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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2427 - (hide annotations) (download)
Sat Mar 2 07:03:04 2013 UTC (11 years, 1 month ago) by persson
File size: 31753 byte(s)
* code refactoring: added a lock guard class for exception safe mutex
  handling and used it everywhere appropriate

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

  ViewVC Help
Powered by ViewVC