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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 551 - (show annotations) (download)
Tue May 17 18:16:54 2005 UTC (18 years, 11 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 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 Christian Schoenebeck *
7 * *
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 #include <sstream>
25
26 #include "Sampler.h"
27
28 #include "engines/EngineChannelFactory.h"
29 #include "drivers/audio/AudioOutputDeviceFactory.h"
30 #include "drivers/midi/MidiInputDeviceFactory.h"
31 #include "network/lscpserver.h"
32
33 namespace LinuxSampler {
34
35 // ******************************************************************
36 // * SamplerChannel
37
38 SamplerChannel::SamplerChannel(Sampler* pS) {
39 pSampler = pS;
40 pEngineChannel = NULL;
41 pMidiInputDevice = NULL;
42 pAudioOutputDevice = NULL;
43 midiPort = 0;
44 midiChannel = MidiInputPort::midi_chan_all;
45 iIndex = -1;
46 }
47
48 SamplerChannel::~SamplerChannel() {
49 if (pEngineChannel) {
50 MidiInputPort* pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
51 if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel);
52 if (pEngineChannel) {
53 if (pAudioOutputDevice) pEngineChannel->DisconnectAudioOutputDevice();
54 delete pEngineChannel;
55 }
56 }
57 }
58
59 void SamplerChannel::SetEngineType(String EngineType) throw (LinuxSamplerException) {
60 dmsg(2,("SamplerChannel: Assigning engine type..."));
61
62 // create new engine channel
63 EngineChannel* pNewEngineChannel = EngineChannelFactory::Create(EngineType);
64 if (!pNewEngineChannel) throw LinuxSamplerException("Unknown engine type");
65
66 // dereference midi input port.
67 MidiInputPort* pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
68 // disconnect old engine
69 if (pEngineChannel) {
70 if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel);
71 if (pAudioOutputDevice) pEngineChannel->DisconnectAudioOutputDevice();
72 delete pEngineChannel;
73 }
74
75 // connect new engine channel
76 pEngineChannel = pNewEngineChannel;
77 if (pMidiInputPort) pMidiInputPort->Connect(pNewEngineChannel, this->midiChannel);
78 if (pAudioOutputDevice) {
79 pNewEngineChannel->Connect(pAudioOutputDevice);
80 pAudioOutputDevice->Connect(pNewEngineChannel->GetEngine());
81 }
82 dmsg(2,("OK\n"));
83 }
84
85 void SamplerChannel::SetAudioOutputDevice(AudioOutputDevice* pDevice) {
86 // disconnect old device
87 if (pAudioOutputDevice && pEngineChannel) pEngineChannel->DisconnectAudioOutputDevice();
88 // connect new device
89 pAudioOutputDevice = pDevice;
90 if (pEngineChannel) {
91 pEngineChannel->Connect(pAudioOutputDevice);
92 pAudioOutputDevice->Connect(pEngineChannel->GetEngine());
93 }
94 }
95
96 void SamplerChannel::SetMidiInputDevice(MidiInputDevice* pDevice) {
97 SetMidiInput(pDevice, this->midiPort, this->midiChannel);
98 }
99
100 void SamplerChannel::SetMidiInputPort(int MidiPort) {
101 SetMidiInput(pMidiInputDevice, MidiPort, this->midiChannel);
102 }
103
104 void SamplerChannel::SetMidiInputChannel(MidiInputPort::midi_chan_t MidiChannel) {
105 SetMidiInput(pMidiInputDevice, this->midiPort, MidiChannel);
106 }
107
108 void SamplerChannel::SetMidiInput(MidiInputDevice* pDevice, int iMidiPort, MidiInputPort::midi_chan_t MidiChannel) {
109 // dereference old midi input port.
110 MidiInputPort* pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
111 // disconnect old device port
112 if (pMidiInputPort && pEngineChannel) pMidiInputPort->Disconnect(pEngineChannel);
113 // new device, port and channel
114 pMidiInputDevice = pDevice;
115 this->midiPort = iMidiPort;
116 this->midiChannel = MidiChannel;
117 // connect new device port
118 pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
119 if (pMidiInputPort && pEngineChannel) pMidiInputPort->Connect(pEngineChannel, MidiChannel);
120 // Ooops.
121 if (pMidiInputPort == NULL)
122 throw LinuxSamplerException("There is no MIDI input port with index " + ToString(iMidiPort) + ".");
123 }
124
125 EngineChannel* SamplerChannel::GetEngineChannel() {
126 return pEngineChannel;
127 }
128
129 MidiInputPort::midi_chan_t SamplerChannel::GetMidiInputChannel() {
130 return this->midiChannel;
131 }
132
133 int SamplerChannel::GetMidiInputPort() {
134 MidiInputPort* pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
135 return (pMidiInputPort ? (int) pMidiInputPort->GetPortNumber() : -1);
136 }
137
138 AudioOutputDevice* SamplerChannel::GetAudioOutputDevice() {
139 return pAudioOutputDevice;
140 }
141
142 MidiInputDevice* SamplerChannel::GetMidiInputDevice() {
143 return pMidiInputDevice;
144 }
145
146 uint SamplerChannel::Index() {
147 if (iIndex >= 0) return iIndex;
148
149 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 }
155 }
156
157 throw LinuxSamplerException("Internal error: SamplerChannel index not found");
158 }
159
160 MidiInputPort* SamplerChannel::GetMidiInputDevicePort(int iMidiPort) {
161 MidiInputPort* pMidiInputPort = NULL;
162 if (pMidiInputDevice)
163 pMidiInputPort = pMidiInputDevice->GetPort(iMidiPort);
164 return pMidiInputPort;
165 }
166
167
168
169 // ******************************************************************
170 // * Sampler
171
172 Sampler::Sampler() {
173 }
174
175 Sampler::~Sampler() {
176 Reset();
177 }
178
179 uint Sampler::SamplerChannels() {
180 return mSamplerChannels.size();
181 }
182
183 SamplerChannel* Sampler::AddSamplerChannel() {
184 // if there's no sampler channel yet
185 if (!mSamplerChannels.size()) {
186 SamplerChannel* pChannel = new SamplerChannel(this);
187 mSamplerChannels[0] = pChannel;
188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channels, 1));
189 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 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channels, i));
204 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 SamplerChannel* pChannel = new SamplerChannel(this);
211 mSamplerChannels[lastIndex + 1] = pChannel;
212 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channels, lastIndex + 1));
213 return pChannel;
214 }
215
216 SamplerChannel* Sampler::GetSamplerChannel(uint uiSamplerChannel) {
217 return (mSamplerChannels.find(uiSamplerChannel) != mSamplerChannels.end()) ? mSamplerChannels[uiSamplerChannel] : NULL;
218 }
219
220 std::map<uint, SamplerChannel*> Sampler::GetSamplerChannels() {
221 return mSamplerChannels;
222 }
223
224 void Sampler::RemoveSamplerChannel(SamplerChannel* pSamplerChannel) {
225 SamplerChannelMap::iterator iterChan = mSamplerChannels.begin();
226 for (; iterChan != mSamplerChannels.end(); iterChan++) {
227 if (iterChan->second == pSamplerChannel) {
228 mSamplerChannels.erase(iterChan);
229 delete pSamplerChannel;
230 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channels, mSamplerChannels.size()));
231 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 std::vector<String> Sampler::AvailableAudioOutputDrivers() {
243 return AudioOutputDeviceFactory::AvailableDrivers();
244 }
245
246 AudioOutputDevice* Sampler::CreateAudioOutputDevice(String AudioDriver, std::map<String,String> Parameters) throw (LinuxSamplerException) {
247 // create new device
248 AudioOutputDevice* pDevice = AudioOutputDeviceFactory::Create(AudioDriver, Parameters);
249
250 // add new audio device to the audio device list
251 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
258 return pDevice;
259 }
260
261 uint Sampler::AudioOutputDevices() {
262 return mAudioOutputDevices.size();
263 }
264
265 uint Sampler::MidiInputDevices() {
266 return mMidiInputDevices.size();
267 }
268
269 std::map<uint, AudioOutputDevice*> Sampler::GetAudioOutputDevices() {
270 return mAudioOutputDevices;
271 }
272
273 std::map<uint, MidiInputDevice*> Sampler::GetMidiInputDevices() {
274 return mMidiInputDevices;
275 }
276
277 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 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
305 // 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 }
315 }
316
317 MidiInputDevice* Sampler::CreateMidiInputDevice(String MidiDriver, std::map<String,String> Parameters) throw (LinuxSamplerException) {
318 // create new device
319 MidiInputDevice* pDevice = MidiInputDeviceFactory::Create(MidiDriver, Parameters, this);
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
329 return pDevice;
330 }
331
332 void Sampler::Reset() {
333 // delete sampler channels
334 try {
335 while (true) {
336 SamplerChannelMap::iterator iter = mSamplerChannels.begin();
337 if (iter == mSamplerChannels.end()) break;
338 RemoveSamplerChannel(iter->second);
339 }
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 while (true) {
349 MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin();
350 if (iter == mMidiInputDevices.end()) break;
351 DestroyMidiInputDevice(iter->second);
352 }
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 while (true) {
362 AudioOutputDeviceMap::iterator iter = mAudioOutputDevices.begin();
363 if (iter == mAudioOutputDevices.end()) break;
364 DestroyAudioOutputDevice(iter->second);
365 }
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 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC