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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 420 - (hide annotations) (download)
Thu Mar 3 03:25:17 2005 UTC (19 years, 1 month ago) by schoenebeck
File size: 14739 byte(s)
* fixed some segfaults (which occured on EngineChannel destruction)
* InstrumentResourceManager: recache small samples if their current
  number of silence sample points are not sufficient enough for the used
  audio output device
* src/linuxsampler.cpp: voice / streams statistics on the console is back
  again (can be turned on with command line switch --statistics)

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

  ViewVC Help
Powered by ViewVC