1 /***************************************************************************
2  *                                                                         *
3  *   Copyright (C) 2005 - 2013 Christian Schoenebeck                       *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the Free Software           *
17  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
18  *   MA  02111-1307  USA                                                   *
19  ***************************************************************************/
20 
21 #include "EngineChannelFactory.h"
22 
23 #include <strings.h>
24 
25 #include "gig/EngineChannel.h"
26 
27 #if HAVE_SF2
28 #include "sf2/EngineChannel.h"
29 #endif
30 
31 #include "sfz/EngineChannel.h"
32 
33 namespace LinuxSampler {
34     class LockedChannel {
35         public:
36             const EngineChannel* pChannel;
37             bool bDestroyed;
38 
LockedChannel(const EngineChannel * pChannel)39             LockedChannel(const EngineChannel* pChannel)  {
40                 this->pChannel = pChannel;
41                 bDestroyed = false;
42             }
43     };
44 
45     class LockedChannelList {
46         public:
Add(const EngineChannel * pChannel)47             void Add(const EngineChannel* pChannel) {
48                 vChannelList.push_back(LockedChannel(pChannel));
49             }
50 
IsDestroyed(const EngineChannel * pChannel)51             bool IsDestroyed(const EngineChannel* pChannel) {
52                 LockedChannel* pLockedChannel = get(pChannel);
53                 if (pLockedChannel == NULL) return false;
54                 return pLockedChannel->bDestroyed;
55             }
56 
SetDestroyed(const EngineChannel * pChannel,bool bDestroyed=true)57             void SetDestroyed(const EngineChannel* pChannel, bool bDestroyed = true) {
58                 LockedChannel* pLockedChannel = get(pChannel);
59                 if (pLockedChannel == NULL) return;
60                 pLockedChannel->bDestroyed = bDestroyed;
61             }
62 
Remove(const EngineChannel * pChannel)63             void Remove(const EngineChannel* pChannel) {
64                 std::vector<LockedChannel>::iterator it = vChannelList.begin();
65                 for (; it != vChannelList.end(); it++) {
66                     if ((*it).pChannel == pChannel) {
67                         vChannelList.erase(it);
68                         return;
69                     }
70                 }
71             }
72 
Contains(const EngineChannel * pChannel)73             bool Contains(const EngineChannel* pChannel) {
74                 return get(pChannel) != NULL;
75             }
76 
77         private:
78             std::vector<LockedChannel> vChannelList;
79 
get(const EngineChannel * pChannel)80             LockedChannel* get(const EngineChannel* pChannel) {
81                 for (int i = 0; i < vChannelList.size(); i++) {
82                     if (vChannelList[i].pChannel == pChannel) {
83                         return &vChannelList[i];
84                     }
85                 }
86 
87                 return NULL;
88             }
89     } lockedChannels;
90 
91     Mutex EngineChannelFactory::LockedChannelsMutex;
92     Mutex EngineChannelFactory::EngineChannelsMutex;
93 
SetDeleteEnabled(const EngineChannel * pEngineChannel,bool enable)94     void EngineChannelFactory::SetDeleteEnabled(const EngineChannel* pEngineChannel, bool enable) {
95         if (!enable) {
96             LockGuard lock(LockedChannelsMutex);
97             if (!lockedChannels.Contains(pEngineChannel)) lockedChannels.Add(pEngineChannel);
98         } else {
99             bool b;
100             {
101                 LockGuard lock(LockedChannelsMutex);
102                 b = lockedChannels.IsDestroyed(pEngineChannel);
103                 lockedChannels.Remove(pEngineChannel);
104             }
105             if (b) delete pEngineChannel;
106         }
107     }
108 
109     // all currently existing engine channel instances
110     static std::set<LinuxSampler::EngineChannel*> engineChannels;
111 
Create(String EngineType)112     LinuxSampler::EngineChannel* EngineChannelFactory::Create(String EngineType) throw (Exception) {
113         LinuxSampler::EngineChannel* pEngineChannel;
114         if (!strcasecmp(EngineType.c_str(),"GigEngine") || !strcasecmp(EngineType.c_str(),"gig")) {
115             pEngineChannel = new gig::EngineChannel;
116         } else if (!strcasecmp(EngineType.c_str(),"sf2")) {
117         #if HAVE_SF2
118             pEngineChannel = new sf2::EngineChannel;
119         #else
120             throw Exception("LinuxSampler is not compiled with SF2 support");
121         #endif
122         } else if (!strcasecmp(EngineType.c_str(),"sfz")) {
123             pEngineChannel = new sfz::EngineChannel;
124         } else {
125             throw Exception("Unknown engine type");
126         }
127         LockGuard lock(EngineChannelsMutex);
128         engineChannels.insert(pEngineChannel);
129         return pEngineChannel;
130     }
131 
Destroy(LinuxSampler::EngineChannel * pEngineChannel)132     void EngineChannelFactory::Destroy(LinuxSampler::EngineChannel* pEngineChannel) {
133         pEngineChannel->RemoveAllFxSendCountListeners();
134         {
135             LockGuard lock(EngineChannelsMutex);
136             engineChannels.erase(pEngineChannel);
137         }
138 
139         // Postpone the deletion of the specified EngineChannel if needed (bug #113)
140         {
141             LockGuard lock(LockedChannelsMutex);
142             if (lockedChannels.Contains(pEngineChannel)) {
143                 lockedChannels.SetDestroyed(pEngineChannel);
144                 pEngineChannel->SetSamplerChannel(NULL);
145                 return;
146             }
147         }
148         ///////
149 
150         delete pEngineChannel;
151     }
152 
EngineChannelInstances()153     const std::set<LinuxSampler::EngineChannel*>& EngineChannelFactory::EngineChannelInstances() {
154         return engineChannels;
155     }
156 
157 } // namespace LinuxSampler
158