/[svn]/linuxsampler/trunk/src/Sampler.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/Sampler.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1937 - (hide annotations) (download)
Sun Jul 12 19:52:20 2009 UTC (14 years, 9 months ago) by schoenebeck
File size: 30380 byte(s)
* bugfix: don't allow to change the audio output device, MIDI input device
  or MIDI input port when using a host plugin implementation
  (e.g VST, AU, DSSI, LV2) as this would go terribly wrong

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 61 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 1897 * Copyright (C) 2005 - 2009 Christian Schoenebeck *
7 schoenebeck 53 * *
8 schoenebeck 1008 * This library is free software; you can redistribute it and/or modify *
9 schoenebeck 53 * it under the terms of the GNU General Public License as published by *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13 schoenebeck 1008 * This library is distributed in the hope that it will be useful, *
14 schoenebeck 53 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19 schoenebeck 1008 * along with this library; if not, write to the Free Software *
20 schoenebeck 53 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24 schoenebeck 123 #include <sstream>
25    
26 schoenebeck 53 #include "Sampler.h"
27    
28 schoenebeck 1424 #include "common/global_private.h"
29 iliev 778 #include "engines/EngineFactory.h"
30 schoenebeck 411 #include "engines/EngineChannelFactory.h"
31 schoenebeck 1375 #include "plugins/InstrumentEditorFactory.h"
32 schoenebeck 203 #include "drivers/audio/AudioOutputDeviceFactory.h"
33     #include "drivers/midi/MidiInputDeviceFactory.h"
34 schoenebeck 1008 #include "drivers/midi/MidiInstrumentMapper.h"
35 schoenebeck 1723 #include "common/Features.h"
36 persson 1765 #include "network/lscpserver.h"
37 schoenebeck 53
38     namespace LinuxSampler {
39    
40     // ******************************************************************
41     // * SamplerChannel
42    
43     SamplerChannel::SamplerChannel(Sampler* pS) {
44     pSampler = pS;
45 schoenebeck 411 pEngineChannel = NULL;
46 schoenebeck 675 pAudioOutputDevice = NULL;
47 capela 159 pMidiInputDevice = NULL;
48 schoenebeck 675 iMidiPort = 0;
49     midiChannel = midi_chan_all;
50 schoenebeck 53 iIndex = -1;
51     }
52    
53     SamplerChannel::~SamplerChannel() {
54 schoenebeck 411 if (pEngineChannel) {
55 persson 840 Engine* engine = pEngineChannel->GetEngine();
56     if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(engine);
57    
58 schoenebeck 675 MidiInputPort* pMidiInputPort = (pEngineChannel) ? pEngineChannel->GetMidiInputPort() : __GetMidiInputDevicePort(GetMidiInputChannel());
59 schoenebeck 411 if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel);
60 schoenebeck 420 if (pEngineChannel) {
61     if (pAudioOutputDevice) pEngineChannel->DisconnectAudioOutputDevice();
62 schoenebeck 660 EngineChannelFactory::Destroy(pEngineChannel);
63 persson 840
64     // reconnect engine if it still exists
65     const std::set<Engine*>& engines = EngineFactory::EngineInstances();
66     if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine);
67 schoenebeck 420 }
68 schoenebeck 53 }
69     }
70    
71 schoenebeck 880 void SamplerChannel::SetEngineType(String EngineType) throw (Exception) {
72 schoenebeck 411 dmsg(2,("SamplerChannel: Assigning engine type..."));
73 schoenebeck 1934
74 iliev 1283 if (pEngineChannel) {
75     if (!strcasecmp(pEngineChannel->EngineName().c_str(), EngineType.c_str())) {
76     dmsg(2,("OK\n"));
77     return;
78     }
79     }
80 schoenebeck 53
81 schoenebeck 1686 fireEngineToBeChanged();
82    
83 schoenebeck 411 // create new engine channel
84     EngineChannel* pNewEngineChannel = EngineChannelFactory::Create(EngineType);
85 schoenebeck 880 if (!pNewEngineChannel) throw Exception("Unknown engine type");
86 schoenebeck 53
87 iliev 1761 pNewEngineChannel->SetSamplerChannel(this);
88 schoenebeck 660
89 capela 159 // dereference midi input port.
90 schoenebeck 675 MidiInputPort* pMidiInputPort = __GetMidiInputDevicePort(GetMidiInputPort());
91     // disconnect old engine channel
92 schoenebeck 411 if (pEngineChannel) {
93 persson 840 Engine* engine = pEngineChannel->GetEngine();
94     if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(engine);
95    
96 schoenebeck 411 if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel);
97 schoenebeck 412 if (pAudioOutputDevice) pEngineChannel->DisconnectAudioOutputDevice();
98 schoenebeck 660 EngineChannelFactory::Destroy(pEngineChannel);
99 persson 840
100     // reconnect engine if it still exists
101     const std::set<Engine*>& engines = EngineFactory::EngineInstances();
102     if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine);
103 schoenebeck 53 }
104    
105 schoenebeck 411 // connect new engine channel
106 schoenebeck 412 if (pAudioOutputDevice) {
107     pNewEngineChannel->Connect(pAudioOutputDevice);
108     pAudioOutputDevice->Connect(pNewEngineChannel->GetEngine());
109     }
110 persson 846 if (pMidiInputPort) pMidiInputPort->Connect(pNewEngineChannel, GetMidiInputChannel());
111 schoenebeck 675 pEngineChannel = pNewEngineChannel;
112    
113     // from now on get MIDI device and port from EngineChannel object
114     this->pMidiInputDevice = NULL;
115     this->iMidiPort = 0;
116    
117 iliev 730 pEngineChannel->StatusChanged(true);
118 iliev 1130 fireEngineChanged();
119 schoenebeck 64 dmsg(2,("OK\n"));
120 schoenebeck 53 }
121    
122 schoenebeck 1937 void SamplerChannel::SetAudioOutputDevice(AudioOutputDevice* pDevice) throw (Exception) {
123 iliev 960 if(pAudioOutputDevice == pDevice) return;
124    
125 schoenebeck 53 // disconnect old device
126 persson 840 if (pAudioOutputDevice && pEngineChannel) {
127 schoenebeck 1937 if (!pAudioOutputDevice->isAutonomousDevice())
128     throw Exception("The audio output device '" + pAudioOutputDevice->Driver() + "' cannot be dropped from this sampler channel!");
129    
130 persson 840 Engine* engine = pEngineChannel->GetEngine();
131     pAudioOutputDevice->Disconnect(engine);
132    
133     pEngineChannel->DisconnectAudioOutputDevice();
134    
135     // reconnect engine if it still exists
136     const std::set<Engine*>& engines = EngineFactory::EngineInstances();
137     if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine);
138     }
139    
140 schoenebeck 53 // connect new device
141     pAudioOutputDevice = pDevice;
142 schoenebeck 412 if (pEngineChannel) {
143     pEngineChannel->Connect(pAudioOutputDevice);
144     pAudioOutputDevice->Connect(pEngineChannel->GetEngine());
145     }
146 schoenebeck 53 }
147    
148 schoenebeck 1937 void SamplerChannel::SetMidiInputDevice(MidiInputDevice* pDevice) throw (Exception) {
149 schoenebeck 675 SetMidiInput(pDevice, 0, GetMidiInputChannel());
150 capela 159 }
151 schoenebeck 203
152 schoenebeck 1937 void SamplerChannel::SetMidiInputPort(int MidiPort) throw (Exception) {
153 schoenebeck 675 SetMidiInput(GetMidiInputDevice(), MidiPort, GetMidiInputChannel());
154 capela 159 }
155 schoenebeck 203
156 schoenebeck 675 void SamplerChannel::SetMidiInputChannel(midi_chan_t MidiChannel) {
157     SetMidiInput(GetMidiInputDevice(), GetMidiInputPort(), MidiChannel);
158 capela 159 }
159 schoenebeck 203
160 schoenebeck 1937 void SamplerChannel::SetMidiInput(MidiInputDevice* pDevice, int iMidiPort, midi_chan_t MidiChannel) throw (Exception) {
161 schoenebeck 880 if (!pDevice) throw Exception("No MIDI input device assigned.");
162 schoenebeck 675
163     // get old and new midi input port
164     MidiInputPort* pOldMidiInputPort = __GetMidiInputDevicePort(GetMidiInputPort());
165     MidiInputPort* pNewMidiInputPort = pDevice->GetPort(iMidiPort);
166    
167 capela 159 // disconnect old device port
168 schoenebeck 1937 if (pOldMidiInputPort && pEngineChannel) {
169     MidiInputDevice* pOldDevice = pOldMidiInputPort->GetDevice();
170     if (pOldMidiInputPort != pNewMidiInputPort &&
171     pOldDevice && !pOldDevice->isAutonomousDevice()
172     ) throw Exception("The MIDI input port '" + pOldDevice->Driver() + "' cannot be altered on this sampler channel!");
173    
174     pOldMidiInputPort->Disconnect(pEngineChannel);
175     }
176    
177 schoenebeck 675 // remember new device, port and channel if not engine channel yet created
178     if (!pEngineChannel) {
179     this->pMidiInputDevice = pDevice;
180     this->iMidiPort = iMidiPort;
181     this->midiChannel = MidiChannel;
182     }
183    
184 capela 159 // connect new device port
185 schoenebeck 675 if (pNewMidiInputPort && pEngineChannel) pNewMidiInputPort->Connect(pEngineChannel, MidiChannel);
186 capela 159 // Ooops.
187 schoenebeck 675 if (pNewMidiInputPort == NULL)
188 schoenebeck 880 throw Exception("There is no MIDI input port with index " + ToString(iMidiPort) + ".");
189 schoenebeck 53 }
190    
191 schoenebeck 411 EngineChannel* SamplerChannel::GetEngineChannel() {
192     return pEngineChannel;
193 schoenebeck 53 }
194    
195 schoenebeck 675 midi_chan_t SamplerChannel::GetMidiInputChannel() {
196     if (pEngineChannel) this->midiChannel = pEngineChannel->MidiChannel();
197 capela 159 return this->midiChannel;
198 schoenebeck 53 }
199    
200 capela 159 int SamplerChannel::GetMidiInputPort() {
201 schoenebeck 675 MidiInputPort* pMidiInputPort = (pEngineChannel) ? pEngineChannel->GetMidiInputPort() : NULL;
202     if (pMidiInputPort) this->iMidiPort = (int) pMidiInputPort->GetPortNumber();
203     return iMidiPort;
204 capela 159 }
205    
206 schoenebeck 53 AudioOutputDevice* SamplerChannel::GetAudioOutputDevice() {
207     return pAudioOutputDevice;
208     }
209    
210 senkov 155 MidiInputDevice* SamplerChannel::GetMidiInputDevice() {
211 schoenebeck 675 if (pEngineChannel)
212     pMidiInputDevice = (pEngineChannel->GetMidiInputPort()) ? pEngineChannel->GetMidiInputPort()->GetDevice() : NULL;
213 capela 159 return pMidiInputDevice;
214 senkov 155 }
215    
216 schoenebeck 53 uint SamplerChannel::Index() {
217     if (iIndex >= 0) return iIndex;
218    
219 schoenebeck 209 Sampler::SamplerChannelMap::iterator iter = pSampler->mSamplerChannels.begin();
220     for (; iter != pSampler->mSamplerChannels.end(); iter++) {
221     if (iter->second == this) {
222     iIndex = iter->first;
223     return iIndex;
224 schoenebeck 53 }
225     }
226    
227 schoenebeck 880 throw Exception("Internal error: SamplerChannel index not found");
228 schoenebeck 53 }
229    
230 iliev 1761 Sampler* SamplerChannel::GetSampler() {
231     return pSampler;
232     }
233    
234 iliev 1130 void SamplerChannel::AddEngineChangeListener(EngineChangeListener* l) {
235     llEngineChangeListeners.AddListener(l);
236     }
237    
238     void SamplerChannel::RemoveEngineChangeListener(EngineChangeListener* l) {
239     llEngineChangeListeners.RemoveListener(l);
240     }
241    
242     void SamplerChannel::RemoveAllEngineChangeListeners() {
243     llEngineChangeListeners.RemoveAllListeners();
244     }
245    
246 schoenebeck 1686 void SamplerChannel::fireEngineToBeChanged() {
247     for (int i = 0; i < llEngineChangeListeners.GetListenerCount(); i++) {
248     llEngineChangeListeners.GetListener(i)->EngineToBeChanged(Index());
249     }
250     }
251    
252 iliev 1130 void SamplerChannel::fireEngineChanged() {
253     for (int i = 0; i < llEngineChangeListeners.GetListenerCount(); i++) {
254     llEngineChangeListeners.GetListener(i)->EngineChanged(Index());
255     }
256     }
257    
258 schoenebeck 675 MidiInputPort* SamplerChannel::__GetMidiInputDevicePort(int iMidiPort) {
259 schoenebeck 221 MidiInputPort* pMidiInputPort = NULL;
260 schoenebeck 675 MidiInputDevice* pMidiInputDevice = GetMidiInputDevice();
261 capela 159 if (pMidiInputDevice)
262 schoenebeck 221 pMidiInputPort = pMidiInputDevice->GetPort(iMidiPort);
263 capela 159 return pMidiInputPort;
264     }
265 schoenebeck 53
266 schoenebeck 212
267    
268 schoenebeck 53 // ******************************************************************
269     // * Sampler
270    
271     Sampler::Sampler() {
272 iliev 1130 eventHandler.SetSampler(this);
273 iliev 1789 uiOldTotalVoiceCount = uiOldTotalStreamCount = 0;
274 schoenebeck 53 }
275    
276     Sampler::~Sampler() {
277 schoenebeck 212 Reset();
278 schoenebeck 53 }
279    
280     uint Sampler::SamplerChannels() {
281 schoenebeck 209 return mSamplerChannels.size();
282 schoenebeck 53 }
283    
284 iliev 1130 void Sampler::AddChannelCountListener(ChannelCountListener* l) {
285     llChannelCountListeners.AddListener(l);
286     }
287    
288     void Sampler::RemoveChannelCountListener(ChannelCountListener* l) {
289     llChannelCountListeners.RemoveListener(l);
290     }
291    
292     void Sampler::fireChannelCountChanged(int NewCount) {
293     for (int i = 0; i < llChannelCountListeners.GetListenerCount(); i++) {
294     llChannelCountListeners.GetListener(i)->ChannelCountChanged(NewCount);
295     }
296     }
297    
298 schoenebeck 1686 void Sampler::fireChannelAdded(SamplerChannel* pChannel) {
299     for (int i = 0; i < llChannelCountListeners.GetListenerCount(); i++) {
300     llChannelCountListeners.GetListener(i)->ChannelAdded(pChannel);
301     }
302     }
303    
304     void Sampler::fireChannelToBeRemoved(SamplerChannel* pChannel) {
305     for (int i = 0; i < llChannelCountListeners.GetListenerCount(); i++) {
306     llChannelCountListeners.GetListener(i)->ChannelToBeRemoved(pChannel);
307     }
308     }
309    
310 iliev 1130 void Sampler::AddAudioDeviceCountListener(AudioDeviceCountListener* l) {
311     llAudioDeviceCountListeners.AddListener(l);
312     }
313    
314     void Sampler::RemoveAudioDeviceCountListener(AudioDeviceCountListener* l) {
315     llAudioDeviceCountListeners.RemoveListener(l);
316     }
317    
318     void Sampler::fireAudioDeviceCountChanged(int NewCount) {
319     for (int i = 0; i < llAudioDeviceCountListeners.GetListenerCount(); i++) {
320     llAudioDeviceCountListeners.GetListener(i)->AudioDeviceCountChanged(NewCount);
321     }
322     }
323    
324     void Sampler::AddMidiDeviceCountListener(MidiDeviceCountListener* l) {
325     llMidiDeviceCountListeners.AddListener(l);
326     }
327    
328     void Sampler::RemoveMidiDeviceCountListener(MidiDeviceCountListener* l) {
329     llMidiDeviceCountListeners.RemoveListener(l);
330     }
331    
332     void Sampler::fireMidiDeviceCountChanged(int NewCount) {
333     for (int i = 0; i < llMidiDeviceCountListeners.GetListenerCount(); i++) {
334     llMidiDeviceCountListeners.GetListener(i)->MidiDeviceCountChanged(NewCount);
335     }
336     }
337    
338 schoenebeck 1695 void Sampler::fireMidiDeviceToBeDestroyed(MidiInputDevice* pDevice) {
339     for (int i = 0; i < llMidiDeviceCountListeners.GetListenerCount(); i++) {
340     llMidiDeviceCountListeners.GetListener(i)->MidiDeviceToBeDestroyed(pDevice);
341     }
342     }
343    
344     void Sampler::fireMidiDeviceCreated(MidiInputDevice* pDevice) {
345     for (int i = 0; i < llMidiDeviceCountListeners.GetListenerCount(); i++) {
346     llMidiDeviceCountListeners.GetListener(i)->MidiDeviceCreated(pDevice);
347     }
348     }
349    
350 iliev 1130 void Sampler::AddVoiceCountListener(VoiceCountListener* l) {
351     llVoiceCountListeners.AddListener(l);
352     }
353    
354     void Sampler::RemoveVoiceCountListener(VoiceCountListener* l) {
355     llVoiceCountListeners.RemoveListener(l);
356     }
357    
358     void Sampler::fireVoiceCountChanged(int ChannelId, int NewCount) {
359 iliev 1789 std::map<uint, uint>::iterator it = mOldVoiceCounts.find(ChannelId);
360     if (it != mOldVoiceCounts.end()) {
361     uint oldCount = it->second;
362     if (NewCount == oldCount) return;
363     }
364    
365     mOldVoiceCounts[ChannelId] = NewCount;
366    
367 iliev 1130 for (int i = 0; i < llVoiceCountListeners.GetListenerCount(); i++) {
368     llVoiceCountListeners.GetListener(i)->VoiceCountChanged(ChannelId, NewCount);
369     }
370     }
371    
372     void Sampler::AddStreamCountListener(StreamCountListener* l) {
373     llStreamCountListeners.AddListener(l);
374     }
375    
376     void Sampler::RemoveStreamCountListener(StreamCountListener* l) {
377     llStreamCountListeners.RemoveListener(l);
378     }
379    
380     void Sampler::fireStreamCountChanged(int ChannelId, int NewCount) {
381 iliev 1789 std::map<uint, uint>::iterator it = mOldStreamCounts.find(ChannelId);
382     if (it != mOldStreamCounts.end()) {
383     uint oldCount = it->second;
384     if (NewCount == oldCount) return;
385     }
386    
387     mOldStreamCounts[ChannelId] = NewCount;
388    
389 iliev 1130 for (int i = 0; i < llStreamCountListeners.GetListenerCount(); i++) {
390     llStreamCountListeners.GetListener(i)->StreamCountChanged(ChannelId, NewCount);
391     }
392     }
393    
394     void Sampler::AddBufferFillListener(BufferFillListener* l) {
395     llBufferFillListeners.AddListener(l);
396     }
397    
398     void Sampler::RemoveBufferFillListener(BufferFillListener* l) {
399     llBufferFillListeners.RemoveListener(l);
400     }
401    
402     void Sampler::fireBufferFillChanged(int ChannelId, String FillData) {
403     for (int i = 0; i < llBufferFillListeners.GetListenerCount(); i++) {
404     llBufferFillListeners.GetListener(i)->BufferFillChanged(ChannelId, FillData);
405     }
406     }
407    
408 iliev 1541 void Sampler::AddTotalStreamCountListener(TotalStreamCountListener* l) {
409     llTotalStreamCountListeners.AddListener(l);
410     }
411    
412     void Sampler::RemoveTotalStreamCountListener(TotalStreamCountListener* l) {
413     llTotalStreamCountListeners.RemoveListener(l);
414     }
415    
416     void Sampler::fireTotalStreamCountChanged(int NewCount) {
417 iliev 1789 if (NewCount == uiOldTotalStreamCount) return;
418     uiOldTotalStreamCount = NewCount;
419    
420 iliev 1541 for (int i = 0; i < llTotalStreamCountListeners.GetListenerCount(); i++) {
421     llTotalStreamCountListeners.GetListener(i)->TotalStreamCountChanged(NewCount);
422     }
423     }
424    
425 iliev 1130 void Sampler::AddTotalVoiceCountListener(TotalVoiceCountListener* l) {
426     llTotalVoiceCountListeners.AddListener(l);
427     }
428    
429     void Sampler::RemoveTotalVoiceCountListener(TotalVoiceCountListener* l) {
430     llTotalVoiceCountListeners.RemoveListener(l);
431     }
432    
433     void Sampler::fireTotalVoiceCountChanged(int NewCount) {
434 iliev 1789 if (NewCount == uiOldTotalVoiceCount) return;
435     uiOldTotalVoiceCount = NewCount;
436    
437 iliev 1130 for (int i = 0; i < llTotalVoiceCountListeners.GetListenerCount(); i++) {
438     llTotalVoiceCountListeners.GetListener(i)->TotalVoiceCountChanged(NewCount);
439     }
440     }
441    
442     void Sampler::AddFxSendCountListener(FxSendCountListener* l) {
443     llFxSendCountListeners.AddListener(l);
444     }
445    
446     void Sampler::RemoveFxSendCountListener(FxSendCountListener* l) {
447     llFxSendCountListeners.RemoveListener(l);
448     }
449    
450     void Sampler::fireFxSendCountChanged(int ChannelId, int NewCount) {
451     for (int i = 0; i < llFxSendCountListeners.GetListenerCount(); i++) {
452     llFxSendCountListeners.GetListener(i)->FxSendCountChanged(ChannelId, NewCount);
453     }
454     }
455    
456 schoenebeck 1686 void Sampler::EventHandler::EngineToBeChanged(int ChannelId) {
457     // nothing to do here
458     }
459    
460 iliev 1130 void Sampler::EventHandler::EngineChanged(int ChannelId) {
461     EngineChannel* engineChannel = pSampler->GetSamplerChannel(ChannelId)->GetEngineChannel();
462     if(engineChannel == NULL) return;
463     engineChannel->AddFxSendCountListener(this);
464     }
465    
466     void Sampler::EventHandler::FxSendCountChanged(int ChannelId, int NewCount) {
467     pSampler->fireFxSendCountChanged(ChannelId, NewCount);
468     }
469    
470    
471 schoenebeck 53 SamplerChannel* Sampler::AddSamplerChannel() {
472 schoenebeck 209 // if there's no sampler channel yet
473     if (!mSamplerChannels.size()) {
474     SamplerChannel* pChannel = new SamplerChannel(this);
475     mSamplerChannels[0] = pChannel;
476 schoenebeck 1686 fireChannelAdded(pChannel);
477 iliev 1130 fireChannelCountChanged(1);
478     pChannel->AddEngineChangeListener(&eventHandler);
479 schoenebeck 209 return pChannel;
480     }
481    
482     // get the highest used sampler channel index
483     uint lastIndex = (--(mSamplerChannels.end()))->first;
484    
485     // check if we reached the index limit
486     if (lastIndex + 1 < lastIndex) {
487     // search for an unoccupied sampler channel index starting from 0
488     for (uint i = 0; i < lastIndex; i++) {
489     if (mSamplerChannels.find(i) != mSamplerChannels.end()) continue;
490     // we found an unused index, so insert the new channel there
491     SamplerChannel* pChannel = new SamplerChannel(this);
492     mSamplerChannels[i] = pChannel;
493 schoenebeck 1686 fireChannelAdded(pChannel);
494 iliev 1130 fireChannelCountChanged(SamplerChannels());
495     pChannel->AddEngineChangeListener(&eventHandler);
496 schoenebeck 209 return pChannel;
497     }
498 schoenebeck 880 throw Exception("Internal error: could not find unoccupied sampler channel index.");
499 schoenebeck 209 }
500    
501     // we have not reached the index limit so we just add the channel past the highest index
502 schoenebeck 53 SamplerChannel* pChannel = new SamplerChannel(this);
503 schoenebeck 209 mSamplerChannels[lastIndex + 1] = pChannel;
504 schoenebeck 1686 fireChannelAdded(pChannel);
505 iliev 1130 fireChannelCountChanged(SamplerChannels());
506     pChannel->AddEngineChangeListener(&eventHandler);
507 schoenebeck 53 return pChannel;
508     }
509    
510     SamplerChannel* Sampler::GetSamplerChannel(uint uiSamplerChannel) {
511 schoenebeck 209 return (mSamplerChannels.find(uiSamplerChannel) != mSamplerChannels.end()) ? mSamplerChannels[uiSamplerChannel] : NULL;
512 schoenebeck 53 }
513    
514 schoenebeck 209 std::map<uint, SamplerChannel*> Sampler::GetSamplerChannels() {
515     return mSamplerChannels;
516     }
517    
518 schoenebeck 53 void Sampler::RemoveSamplerChannel(SamplerChannel* pSamplerChannel) {
519 schoenebeck 209 SamplerChannelMap::iterator iterChan = mSamplerChannels.begin();
520     for (; iterChan != mSamplerChannels.end(); iterChan++) {
521     if (iterChan->second == pSamplerChannel) {
522 schoenebeck 1686 fireChannelToBeRemoved(pSamplerChannel);
523 iliev 1789 mOldVoiceCounts.erase(pSamplerChannel->Index());
524     mOldStreamCounts.erase(pSamplerChannel->Index());
525 iliev 1130 pSamplerChannel->RemoveAllEngineChangeListeners();
526 schoenebeck 209 mSamplerChannels.erase(iterChan);
527 schoenebeck 53 delete pSamplerChannel;
528 iliev 1130 fireChannelCountChanged(SamplerChannels());
529 schoenebeck 53 return;
530     }
531     }
532     }
533    
534     void Sampler::RemoveSamplerChannel(uint uiSamplerChannel) {
535     SamplerChannel* pChannel = GetSamplerChannel(uiSamplerChannel);
536     if (!pChannel) return;
537     RemoveSamplerChannel(pChannel);
538     }
539    
540 iliev 1835 void Sampler::RemoveAllSamplerChannels() {
541     /*
542     * In maps iterator invalidation occurs when the iterator point
543     * to the element that is being erased. So we need to copy the map
544     * by calling GetSamplerChannels() to prevent that.
545     */
546     SamplerChannelMap chns = GetSamplerChannels();
547     SamplerChannelMap::iterator iter = chns.begin();
548     for(; iter != chns.end(); iter++) {
549     RemoveSamplerChannel(iter->second);
550     }
551     }
552    
553 schoenebeck 123 std::vector<String> Sampler::AvailableAudioOutputDrivers() {
554     return AudioOutputDeviceFactory::AvailableDrivers();
555     }
556 schoenebeck 53
557 schoenebeck 900 std::vector<String> Sampler::AvailableMidiInputDrivers() {
558     return MidiInputDeviceFactory::AvailableDrivers();
559     }
560    
561     std::vector<String> Sampler::AvailableEngineTypes() {
562     return EngineFactory::AvailableEngineTypes();
563     }
564    
565 schoenebeck 880 AudioOutputDevice* Sampler::CreateAudioOutputDevice(String AudioDriver, std::map<String,String> Parameters) throw (Exception) {
566 schoenebeck 53 // create new device
567 schoenebeck 123 AudioOutputDevice* pDevice = AudioOutputDeviceFactory::Create(AudioDriver, Parameters);
568 schoenebeck 53
569 iliev 1130 fireAudioDeviceCountChanged(AudioOutputDevices());
570 schoenebeck 53 return pDevice;
571     }
572    
573 schoenebeck 123 uint Sampler::AudioOutputDevices() {
574 schoenebeck 1934 return AudioOutputDeviceFactory::Devices().size();
575 schoenebeck 53 }
576    
577 senkov 155 uint Sampler::MidiInputDevices() {
578 schoenebeck 1934 return MidiInputDeviceFactory::Devices().size();
579 senkov 155 }
580    
581 schoenebeck 123 std::map<uint, AudioOutputDevice*> Sampler::GetAudioOutputDevices() {
582 schoenebeck 1934 return AudioOutputDeviceFactory::Devices();
583 schoenebeck 123 }
584    
585 senkov 155 std::map<uint, MidiInputDevice*> Sampler::GetMidiInputDevices() {
586 schoenebeck 1934 return MidiInputDeviceFactory::Devices();
587 senkov 155 }
588    
589 schoenebeck 880 void Sampler::DestroyAudioOutputDevice(AudioOutputDevice* pDevice) throw (Exception) {
590 schoenebeck 1934 if (pDevice) {
591     // check if there are still sampler engines connected to this device
592     for (SamplerChannelMap::iterator iterChan = mSamplerChannels.begin();
593     iterChan != mSamplerChannels.end(); iterChan++
594     ) if (iterChan->second->GetAudioOutputDevice() == pDevice) throw Exception("Sampler channel " + ToString(iterChan->first) + " is still connected to the audio output device.");
595 schoenebeck 123
596 schoenebeck 1934 //TODO: should we add fireAudioDeviceToBeDestroyed() here ?
597     AudioOutputDeviceFactory::Destroy(pDevice);
598     fireAudioDeviceCountChanged(AudioOutputDevices());
599 schoenebeck 123 }
600     }
601    
602 iliev 1835 void Sampler::DestroyAllAudioOutputDevices() throw (Exception) {
603     /*
604     * In maps iterator invalidation occurs when the iterator point
605     * to the element that is being erased. So we need to copy the map
606     * by calling GetAudioOutputDevices() to prevent that.
607     */
608 schoenebeck 1934 std::map<uint, AudioOutputDevice*> devs = GetAudioOutputDevices();
609     std::map<uint, AudioOutputDevice*>::iterator iter = devs.begin();
610     for (; iter != devs.end(); iter++) {
611     AudioOutputDevice* pDevice = iter->second;
612    
613     // skip non-autonomous devices
614     if (!pDevice->isAutonomousDevice()) continue;
615    
616     DestroyAudioOutputDevice(pDevice);
617 iliev 1835 }
618     }
619    
620 schoenebeck 880 void Sampler::DestroyMidiInputDevice(MidiInputDevice* pDevice) throw (Exception) {
621 schoenebeck 1934 if (pDevice) {
622     // check if there are still sampler engines connected to this device
623     for (SamplerChannelMap::iterator iterChan = mSamplerChannels.begin();
624     iterChan != mSamplerChannels.end(); iterChan++
625     ) if (iterChan->second->GetMidiInputDevice() == pDevice) throw Exception("Sampler channel " + ToString(iterChan->first) + " is still connected to the midi input device.");
626 schoenebeck 53
627 schoenebeck 1934 fireMidiDeviceToBeDestroyed(pDevice);
628     MidiInputDeviceFactory::Destroy(pDevice);
629     fireMidiDeviceCountChanged(MidiInputDevices());
630 schoenebeck 53 }
631 senkov 155 }
632 schoenebeck 53
633 iliev 1835 void Sampler::DestroyAllMidiInputDevices() throw (Exception) {
634     /*
635     * In maps iterator invalidation occurs when the iterator point
636     * to the element that is being erased. So we need to copy the map
637     * by calling GetMidiInputDevices() to prevent that.
638     */
639 schoenebeck 1934 std::map<uint, MidiInputDevice*> devs = GetMidiInputDevices();
640     std::map<uint, MidiInputDevice*>::iterator iter = devs.begin();
641     for (; iter != devs.end(); iter++) {
642     MidiInputDevice* pDevice = iter->second;
643    
644     // skip non-autonomous devices
645     if (!pDevice->isAutonomousDevice()) continue;
646    
647     DestroyMidiInputDevice(pDevice);
648 iliev 1835 }
649     }
650    
651 schoenebeck 880 MidiInputDevice* Sampler::CreateMidiInputDevice(String MidiDriver, std::map<String,String> Parameters) throw (Exception) {
652 senkov 155 // create new device
653 schoenebeck 551 MidiInputDevice* pDevice = MidiInputDeviceFactory::Create(MidiDriver, Parameters, this);
654 senkov 155
655 schoenebeck 1695 fireMidiDeviceCreated(pDevice);
656 iliev 1130 fireMidiDeviceCountChanged(MidiInputDevices());
657 schoenebeck 53 return pDevice;
658     }
659    
660 iliev 1541 int Sampler::GetDiskStreamCount() {
661     int count = 0;
662     std::set<Engine*>::iterator it = EngineFactory::EngineInstances().begin();
663    
664     for(; it != EngineFactory::EngineInstances().end(); it++) {
665     count += (*it)->DiskStreamCount();
666     }
667    
668     return count;
669     }
670    
671 iliev 778 int Sampler::GetVoiceCount() {
672     int count = 0;
673     std::set<Engine*>::iterator it = EngineFactory::EngineInstances().begin();
674    
675     for(; it != EngineFactory::EngineInstances().end(); it++) {
676     count += (*it)->VoiceCount();
677     }
678    
679     return count;
680     }
681    
682 schoenebeck 212 void Sampler::Reset() {
683     // delete sampler channels
684     try {
685 schoenebeck 1934 RemoveAllSamplerChannels();
686 schoenebeck 212 }
687     catch(...) {
688     std::cerr << "Sampler::Reset(): Exception occured while trying to delete all sampler channels, exiting.\n" << std::flush;
689     exit(EXIT_FAILURE);
690     }
691    
692     // delete midi input devices
693     try {
694 schoenebeck 1934 DestroyAllMidiInputDevices();
695 schoenebeck 212 }
696     catch(...) {
697     std::cerr << "Sampler::Reset(): Exception occured while trying to delete all MIDI input devices, exiting.\n" << std::flush;
698     exit(EXIT_FAILURE);
699     }
700    
701     // delete audio output devices
702     try {
703 schoenebeck 1934 DestroyAllAudioOutputDevices();
704 schoenebeck 212 }
705     catch(...) {
706     std::cerr << "Sampler::Reset(): Exception occured while trying to delete all audio output devices, exiting.\n" << std::flush;
707     exit(EXIT_FAILURE);
708     }
709 schoenebeck 1008
710     // delete MIDI instrument maps
711     try {
712     MidiInstrumentMapper::RemoveAllMaps();
713     }
714     catch(...) {
715     std::cerr << "Sampler::Reset(): Exception occured while trying to delete all MIDI instrument maps, exiting.\n" << std::flush;
716     exit(EXIT_FAILURE);
717     }
718 schoenebeck 1212
719     // unload all instrument editor DLLs
720     InstrumentEditorFactory::ClosePlugins();
721 schoenebeck 212 }
722    
723 schoenebeck 1723 bool Sampler::EnableDenormalsAreZeroMode() {
724     Features::detect();
725     return Features::enableDenormalsAreZeroMode();
726     }
727    
728 persson 1765 void Sampler::fireStatistics() {
729     static const LSCPEvent::event_t eventsArr[] = {
730     LSCPEvent::event_voice_count, LSCPEvent::event_stream_count,
731     LSCPEvent::event_buffer_fill, LSCPEvent::event_total_voice_count
732     };
733     static const std::list<LSCPEvent::event_t> events(eventsArr, eventsArr + 4);
734    
735     if (LSCPServer::EventSubscribers(events))
736     {
737     LSCPServer::LockRTNotify();
738     std::map<uint,SamplerChannel*> channels = GetSamplerChannels();
739     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
740     for (; iter != channels.end(); iter++) {
741     SamplerChannel* pSamplerChannel = iter->second;
742     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
743     if (!pEngineChannel) continue;
744     Engine* pEngine = pEngineChannel->GetEngine();
745     if (!pEngine) continue;
746     fireVoiceCountChanged(iter->first, pEngineChannel->GetVoiceCount());
747     fireStreamCountChanged(iter->first, pEngineChannel->GetDiskStreamCount());
748     fireBufferFillChanged(iter->first, pEngine->DiskStreamBufferFillPercentage());
749     }
750 schoenebeck 1934
751 iliev 1789 fireTotalStreamCountChanged(GetDiskStreamCount());
752     fireTotalVoiceCountChanged(GetVoiceCount());
753    
754 persson 1765 LSCPServer::UnlockRTNotify();
755     }
756     }
757    
758 persson 1897 #if defined(WIN32)
759     static HINSTANCE dllInstance = NULL;
760    
761     String Sampler::GetInstallDir() {
762     char buf[MAX_PATH + 1];
763     if (GetModuleFileName(dllInstance, buf, MAX_PATH)) {
764     String s(buf);
765     size_t n = s.rfind('\\');
766     if (n != String::npos) {
767     return s.substr(0, n);
768     }
769     }
770     return "";
771     }
772     #endif
773 schoenebeck 53 } // namespace LinuxSampler
774 persson 1897
775     #if defined(WIN32)
776     extern "C" {
777     BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
778     {
779     switch (reason) {
780     case DLL_PROCESS_ATTACH:
781     LinuxSampler::dllInstance = instance;
782     break;
783     }
784     return TRUE;
785     }
786     }
787     #endif

  ViewVC Help
Powered by ViewVC