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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 551 - (hide annotations) (download)
Tue May 17 18:16:54 2005 UTC (18 years, 10 months ago) by schoenebeck
File size: 14745 byte(s)
* Implemented MIDI program change as general, engine independant solution.
  The program number will determine the sampler channel to which the MIDI
  device will be connected to and the given MIDI channel defines on which
  MIDI channel that sampler channel should listen to. Also the program
  change will disconnect probably established connection from the previous
  program change event.

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 schoenebeck 551 MidiInputDevice* pDevice = MidiInputDeviceFactory::Create(MidiDriver, Parameters, this);
320 senkov 155
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