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