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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 960 - (hide annotations) (download)
Thu Nov 30 10:39:12 2006 UTC (17 years, 4 months ago) by iliev
File size: 17400 byte(s)
- fixed crash occurring on certain LSCP scripts (Bug 39)

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 schoenebeck 880 * Copyright (C) 2005, 2006 Christian Schoenebeck *
7 schoenebeck 53 * *
8     * This program is free software; you can redistribute it and/or modify *
9     * 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     * This program is distributed in the hope that it will be useful, *
14     * 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     * along with this program; if not, write to the Free Software *
20     * 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 iliev 778 #include "engines/EngineFactory.h"
29 schoenebeck 411 #include "engines/EngineChannelFactory.h"
30 schoenebeck 203 #include "drivers/audio/AudioOutputDeviceFactory.h"
31     #include "drivers/midi/MidiInputDeviceFactory.h"
32 senkov 359 #include "network/lscpserver.h"
33 schoenebeck 53
34     namespace LinuxSampler {
35    
36     // ******************************************************************
37     // * SamplerChannel
38    
39     SamplerChannel::SamplerChannel(Sampler* pS) {
40     pSampler = pS;
41 schoenebeck 411 pEngineChannel = NULL;
42 schoenebeck 675 pAudioOutputDevice = NULL;
43 capela 159 pMidiInputDevice = NULL;
44 schoenebeck 675 iMidiPort = 0;
45     midiChannel = midi_chan_all;
46 schoenebeck 53 iIndex = -1;
47     }
48    
49     SamplerChannel::~SamplerChannel() {
50 schoenebeck 411 if (pEngineChannel) {
51 persson 840 Engine* engine = pEngineChannel->GetEngine();
52     if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(engine);
53    
54 schoenebeck 675 MidiInputPort* pMidiInputPort = (pEngineChannel) ? pEngineChannel->GetMidiInputPort() : __GetMidiInputDevicePort(GetMidiInputChannel());
55 schoenebeck 411 if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel);
56 schoenebeck 420 if (pEngineChannel) {
57     if (pAudioOutputDevice) pEngineChannel->DisconnectAudioOutputDevice();
58 schoenebeck 660 EngineChannelFactory::Destroy(pEngineChannel);
59 persson 840
60     // reconnect engine if it still exists
61     const std::set<Engine*>& engines = EngineFactory::EngineInstances();
62     if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine);
63 schoenebeck 420 }
64 schoenebeck 53 }
65     }
66    
67 schoenebeck 880 void SamplerChannel::SetEngineType(String EngineType) throw (Exception) {
68 schoenebeck 411 dmsg(2,("SamplerChannel: Assigning engine type..."));
69 schoenebeck 53
70 schoenebeck 411 // create new engine channel
71     EngineChannel* pNewEngineChannel = EngineChannelFactory::Create(EngineType);
72 schoenebeck 880 if (!pNewEngineChannel) throw Exception("Unknown engine type");
73 schoenebeck 53
74 schoenebeck 660 //FIXME: hack to allow fast retrieval of engine channel's sampler channel index
75     pNewEngineChannel->iSamplerChannelIndex = Index();
76    
77 capela 159 // dereference midi input port.
78 schoenebeck 675 MidiInputPort* pMidiInputPort = __GetMidiInputDevicePort(GetMidiInputPort());
79     // disconnect old engine channel
80 schoenebeck 411 if (pEngineChannel) {
81 persson 840 Engine* engine = pEngineChannel->GetEngine();
82     if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(engine);
83    
84 schoenebeck 411 if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel);
85 schoenebeck 412 if (pAudioOutputDevice) pEngineChannel->DisconnectAudioOutputDevice();
86 schoenebeck 660 EngineChannelFactory::Destroy(pEngineChannel);
87 persson 840
88     // reconnect engine if it still exists
89     const std::set<Engine*>& engines = EngineFactory::EngineInstances();
90     if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine);
91 schoenebeck 53 }
92    
93 schoenebeck 411 // connect new engine channel
94 schoenebeck 412 if (pAudioOutputDevice) {
95     pNewEngineChannel->Connect(pAudioOutputDevice);
96     pAudioOutputDevice->Connect(pNewEngineChannel->GetEngine());
97     }
98 persson 846 if (pMidiInputPort) pMidiInputPort->Connect(pNewEngineChannel, GetMidiInputChannel());
99 schoenebeck 675 pEngineChannel = pNewEngineChannel;
100    
101     // from now on get MIDI device and port from EngineChannel object
102     this->pMidiInputDevice = NULL;
103     this->iMidiPort = 0;
104    
105 iliev 730 pEngineChannel->StatusChanged(true);
106    
107 schoenebeck 64 dmsg(2,("OK\n"));
108 schoenebeck 53 }
109    
110 schoenebeck 123 void SamplerChannel::SetAudioOutputDevice(AudioOutputDevice* pDevice) {
111 iliev 960 if(pAudioOutputDevice == pDevice) return;
112    
113 schoenebeck 53 // disconnect old device
114 persson 840 if (pAudioOutputDevice && pEngineChannel) {
115     Engine* engine = pEngineChannel->GetEngine();
116     pAudioOutputDevice->Disconnect(engine);
117    
118     pEngineChannel->DisconnectAudioOutputDevice();
119    
120     // reconnect engine if it still exists
121     const std::set<Engine*>& engines = EngineFactory::EngineInstances();
122     if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine);
123     }
124    
125 schoenebeck 53 // connect new device
126     pAudioOutputDevice = pDevice;
127 schoenebeck 412 if (pEngineChannel) {
128     pEngineChannel->Connect(pAudioOutputDevice);
129     pAudioOutputDevice->Connect(pEngineChannel->GetEngine());
130     }
131 schoenebeck 53 }
132    
133 capela 159 void SamplerChannel::SetMidiInputDevice(MidiInputDevice* pDevice) {
134 schoenebeck 675 SetMidiInput(pDevice, 0, GetMidiInputChannel());
135 capela 159 }
136 schoenebeck 203
137 capela 159 void SamplerChannel::SetMidiInputPort(int MidiPort) {
138 schoenebeck 675 SetMidiInput(GetMidiInputDevice(), MidiPort, GetMidiInputChannel());
139 capela 159 }
140 schoenebeck 203
141 schoenebeck 675 void SamplerChannel::SetMidiInputChannel(midi_chan_t MidiChannel) {
142     SetMidiInput(GetMidiInputDevice(), GetMidiInputPort(), MidiChannel);
143 capela 159 }
144 schoenebeck 203
145 schoenebeck 675 void SamplerChannel::SetMidiInput(MidiInputDevice* pDevice, int iMidiPort, midi_chan_t MidiChannel) {
146 schoenebeck 880 if (!pDevice) throw Exception("No MIDI input device assigned.");
147 schoenebeck 675
148     // get old and new midi input port
149     MidiInputPort* pOldMidiInputPort = __GetMidiInputDevicePort(GetMidiInputPort());
150     MidiInputPort* pNewMidiInputPort = pDevice->GetPort(iMidiPort);
151    
152 capela 159 // disconnect old device port
153 schoenebeck 675 if (pOldMidiInputPort && pEngineChannel) pOldMidiInputPort->Disconnect(pEngineChannel);
154     // remember new device, port and channel if not engine channel yet created
155     if (!pEngineChannel) {
156     this->pMidiInputDevice = pDevice;
157     this->iMidiPort = iMidiPort;
158     this->midiChannel = MidiChannel;
159     }
160    
161 capela 159 // connect new device port
162 schoenebeck 675 if (pNewMidiInputPort && pEngineChannel) pNewMidiInputPort->Connect(pEngineChannel, MidiChannel);
163 capela 159 // Ooops.
164 schoenebeck 675 if (pNewMidiInputPort == NULL)
165 schoenebeck 880 throw Exception("There is no MIDI input port with index " + ToString(iMidiPort) + ".");
166 schoenebeck 53 }
167    
168 schoenebeck 411 EngineChannel* SamplerChannel::GetEngineChannel() {
169     return pEngineChannel;
170 schoenebeck 53 }
171    
172 schoenebeck 675 midi_chan_t SamplerChannel::GetMidiInputChannel() {
173     if (pEngineChannel) this->midiChannel = pEngineChannel->MidiChannel();
174 capela 159 return this->midiChannel;
175 schoenebeck 53 }
176    
177 capela 159 int SamplerChannel::GetMidiInputPort() {
178 schoenebeck 675 MidiInputPort* pMidiInputPort = (pEngineChannel) ? pEngineChannel->GetMidiInputPort() : NULL;
179     if (pMidiInputPort) this->iMidiPort = (int) pMidiInputPort->GetPortNumber();
180     return iMidiPort;
181 capela 159 }
182    
183 schoenebeck 53 AudioOutputDevice* SamplerChannel::GetAudioOutputDevice() {
184     return pAudioOutputDevice;
185     }
186    
187 senkov 155 MidiInputDevice* SamplerChannel::GetMidiInputDevice() {
188 schoenebeck 675 if (pEngineChannel)
189     pMidiInputDevice = (pEngineChannel->GetMidiInputPort()) ? pEngineChannel->GetMidiInputPort()->GetDevice() : NULL;
190 capela 159 return pMidiInputDevice;
191 senkov 155 }
192    
193 schoenebeck 53 uint SamplerChannel::Index() {
194     if (iIndex >= 0) return iIndex;
195    
196 schoenebeck 209 Sampler::SamplerChannelMap::iterator iter = pSampler->mSamplerChannels.begin();
197     for (; iter != pSampler->mSamplerChannels.end(); iter++) {
198     if (iter->second == this) {
199     iIndex = iter->first;
200     return iIndex;
201 schoenebeck 53 }
202     }
203    
204 schoenebeck 880 throw Exception("Internal error: SamplerChannel index not found");
205 schoenebeck 53 }
206    
207 schoenebeck 675 MidiInputPort* SamplerChannel::__GetMidiInputDevicePort(int iMidiPort) {
208 schoenebeck 221 MidiInputPort* pMidiInputPort = NULL;
209 schoenebeck 675 MidiInputDevice* pMidiInputDevice = GetMidiInputDevice();
210 capela 159 if (pMidiInputDevice)
211 schoenebeck 221 pMidiInputPort = pMidiInputDevice->GetPort(iMidiPort);
212 capela 159 return pMidiInputPort;
213     }
214 schoenebeck 53
215 schoenebeck 212
216    
217 schoenebeck 53 // ******************************************************************
218     // * Sampler
219    
220     Sampler::Sampler() {
221     }
222    
223     Sampler::~Sampler() {
224 schoenebeck 212 Reset();
225 schoenebeck 53 }
226    
227     uint Sampler::SamplerChannels() {
228 schoenebeck 209 return mSamplerChannels.size();
229 schoenebeck 53 }
230    
231     SamplerChannel* Sampler::AddSamplerChannel() {
232 schoenebeck 209 // if there's no sampler channel yet
233     if (!mSamplerChannels.size()) {
234     SamplerChannel* pChannel = new SamplerChannel(this);
235     mSamplerChannels[0] = pChannel;
236 schoenebeck 556 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, 1));
237 schoenebeck 209 return pChannel;
238     }
239    
240     // get the highest used sampler channel index
241     uint lastIndex = (--(mSamplerChannels.end()))->first;
242    
243     // check if we reached the index limit
244     if (lastIndex + 1 < lastIndex) {
245     // search for an unoccupied sampler channel index starting from 0
246     for (uint i = 0; i < lastIndex; i++) {
247     if (mSamplerChannels.find(i) != mSamplerChannels.end()) continue;
248     // we found an unused index, so insert the new channel there
249     SamplerChannel* pChannel = new SamplerChannel(this);
250     mSamplerChannels[i] = pChannel;
251 schoenebeck 556 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, i));
252 schoenebeck 209 return pChannel;
253     }
254 schoenebeck 880 throw Exception("Internal error: could not find unoccupied sampler channel index.");
255 schoenebeck 209 }
256    
257     // we have not reached the index limit so we just add the channel past the highest index
258 schoenebeck 53 SamplerChannel* pChannel = new SamplerChannel(this);
259 schoenebeck 209 mSamplerChannels[lastIndex + 1] = pChannel;
260 schoenebeck 556 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, lastIndex + 1));
261 schoenebeck 53 return pChannel;
262     }
263    
264     SamplerChannel* Sampler::GetSamplerChannel(uint uiSamplerChannel) {
265 schoenebeck 209 return (mSamplerChannels.find(uiSamplerChannel) != mSamplerChannels.end()) ? mSamplerChannels[uiSamplerChannel] : NULL;
266 schoenebeck 53 }
267    
268 schoenebeck 209 std::map<uint, SamplerChannel*> Sampler::GetSamplerChannels() {
269     return mSamplerChannels;
270     }
271    
272 schoenebeck 53 void Sampler::RemoveSamplerChannel(SamplerChannel* pSamplerChannel) {
273 schoenebeck 209 SamplerChannelMap::iterator iterChan = mSamplerChannels.begin();
274     for (; iterChan != mSamplerChannels.end(); iterChan++) {
275     if (iterChan->second == pSamplerChannel) {
276     mSamplerChannels.erase(iterChan);
277 schoenebeck 53 delete pSamplerChannel;
278 schoenebeck 556 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, mSamplerChannels.size()));
279 schoenebeck 53 return;
280     }
281     }
282     }
283    
284     void Sampler::RemoveSamplerChannel(uint uiSamplerChannel) {
285     SamplerChannel* pChannel = GetSamplerChannel(uiSamplerChannel);
286     if (!pChannel) return;
287     RemoveSamplerChannel(pChannel);
288     }
289    
290 schoenebeck 123 std::vector<String> Sampler::AvailableAudioOutputDrivers() {
291     return AudioOutputDeviceFactory::AvailableDrivers();
292     }
293 schoenebeck 53
294 schoenebeck 900 std::vector<String> Sampler::AvailableMidiInputDrivers() {
295     return MidiInputDeviceFactory::AvailableDrivers();
296     }
297    
298     std::vector<String> Sampler::AvailableEngineTypes() {
299     return EngineFactory::AvailableEngineTypes();
300     }
301    
302 schoenebeck 880 AudioOutputDevice* Sampler::CreateAudioOutputDevice(String AudioDriver, std::map<String,String> Parameters) throw (Exception) {
303 schoenebeck 53 // create new device
304 schoenebeck 123 AudioOutputDevice* pDevice = AudioOutputDeviceFactory::Create(AudioDriver, Parameters);
305 schoenebeck 53
306 schoenebeck 64 // add new audio device to the audio device list
307 schoenebeck 123 for (uint i = 0; ; i++) { // seek for a free place starting from the beginning
308     if (!mAudioOutputDevices[i]) {
309     mAudioOutputDevices[i] = pDevice;
310     break;
311     }
312     }
313 schoenebeck 64
314 schoenebeck 53 return pDevice;
315     }
316    
317 schoenebeck 123 uint Sampler::AudioOutputDevices() {
318     return mAudioOutputDevices.size();
319 schoenebeck 53 }
320    
321 senkov 155 uint Sampler::MidiInputDevices() {
322     return mMidiInputDevices.size();
323     }
324    
325 schoenebeck 123 std::map<uint, AudioOutputDevice*> Sampler::GetAudioOutputDevices() {
326     return mAudioOutputDevices;
327     }
328    
329 senkov 155 std::map<uint, MidiInputDevice*> Sampler::GetMidiInputDevices() {
330     return mMidiInputDevices;
331     }
332    
333 schoenebeck 880 void Sampler::DestroyAudioOutputDevice(AudioOutputDevice* pDevice) throw (Exception) {
334 schoenebeck 123 AudioOutputDeviceMap::iterator iter = mAudioOutputDevices.begin();
335     for (; iter != mAudioOutputDevices.end(); iter++) {
336     if (iter->second == pDevice) {
337     // check if there are still sampler engines connected to this device
338     for (uint i = 0; i < SamplerChannels(); i++)
339 schoenebeck 880 if (GetSamplerChannel(i)->GetAudioOutputDevice() == pDevice) throw Exception("Sampler channel " + ToString(i) + " is still connected to the audio output device.");
340 schoenebeck 123
341     // disable device
342     pDevice->Stop();
343    
344 persson 837 // remove device from the device list
345     mAudioOutputDevices.erase(iter);
346    
347 schoenebeck 123 // destroy and free device from memory
348     delete pDevice;
349 persson 837
350     break;
351 schoenebeck 123 }
352     }
353     }
354    
355 schoenebeck 880 void Sampler::DestroyMidiInputDevice(MidiInputDevice* pDevice) throw (Exception) {
356 senkov 155 MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin();
357     for (; iter != mMidiInputDevices.end(); iter++) {
358     if (iter->second == pDevice) {
359     // check if there are still sampler engines connected to this device
360     for (uint i = 0; i < SamplerChannels(); i++)
361 schoenebeck 880 if (GetSamplerChannel(i)->GetMidiInputDevice() == pDevice) throw Exception("Sampler channel " + ToString(i) + " is still connected to the midi input device.");
362 schoenebeck 53
363 senkov 155 // disable device
364     pDevice->StopListen();
365    
366 persson 837 // remove device from the device list
367     mMidiInputDevices.erase(iter);
368    
369 senkov 155 // destroy and free device from memory
370     delete pDevice;
371 persson 837
372     break;
373 senkov 155 }
374 schoenebeck 53 }
375 senkov 155 }
376 schoenebeck 53
377 schoenebeck 880 MidiInputDevice* Sampler::CreateMidiInputDevice(String MidiDriver, std::map<String,String> Parameters) throw (Exception) {
378 senkov 155 // create new device
379 schoenebeck 551 MidiInputDevice* pDevice = MidiInputDeviceFactory::Create(MidiDriver, Parameters, this);
380 senkov 155
381     // add new device to the midi device list
382     for (uint i = 0; ; i++) { // seek for a free place starting from the beginning
383     if (!mMidiInputDevices[i]) {
384     mMidiInputDevices[i] = pDevice;
385     break;
386     }
387     }
388 schoenebeck 64
389 schoenebeck 53 return pDevice;
390     }
391    
392 iliev 778 int Sampler::GetVoiceCount() {
393     int count = 0;
394     std::set<Engine*>::iterator it = EngineFactory::EngineInstances().begin();
395    
396     for(; it != EngineFactory::EngineInstances().end(); it++) {
397     count += (*it)->VoiceCount();
398     }
399    
400     return count;
401     }
402    
403 schoenebeck 212 void Sampler::Reset() {
404     // delete sampler channels
405     try {
406 senkov 329 while (true) {
407     SamplerChannelMap::iterator iter = mSamplerChannels.begin();
408     if (iter == mSamplerChannels.end()) break;
409     RemoveSamplerChannel(iter->second);
410 schoenebeck 212 }
411     }
412     catch(...) {
413     std::cerr << "Sampler::Reset(): Exception occured while trying to delete all sampler channels, exiting.\n" << std::flush;
414     exit(EXIT_FAILURE);
415     }
416    
417     // delete midi input devices
418     try {
419 senkov 329 while (true) {
420     MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin();
421     if (iter == mMidiInputDevices.end()) break;
422     DestroyMidiInputDevice(iter->second);
423 schoenebeck 212 }
424     }
425     catch(...) {
426     std::cerr << "Sampler::Reset(): Exception occured while trying to delete all MIDI input devices, exiting.\n" << std::flush;
427     exit(EXIT_FAILURE);
428     }
429    
430     // delete audio output devices
431     try {
432 senkov 329 while (true) {
433     AudioOutputDeviceMap::iterator iter = mAudioOutputDevices.begin();
434     if (iter == mAudioOutputDevices.end()) break;
435     DestroyAudioOutputDevice(iter->second);
436 schoenebeck 212 }
437     }
438     catch(...) {
439     std::cerr << "Sampler::Reset(): Exception occured while trying to delete all audio output devices, exiting.\n" << std::flush;
440     exit(EXIT_FAILURE);
441     }
442     }
443    
444 schoenebeck 53 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC