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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 411 - (show annotations) (download)
Sat Feb 26 02:01:14 2005 UTC (19 years, 1 month ago) by schoenebeck
File size: 14495 byte(s)
* design change: using now one sampler engine instance and one disk thread
  instance for all sampler channels that are connected to the same audio
  output device (and are using the same engine type of course)
* added EngineFactory / EngineChannelFactory to remove the annoying build
  dependencies e.g. of the lscpserver to the actual sampler engine
  implementations
* bumped version to 0.3.0 (current CVS state is still quite broken,
  previous, stable CVS version was tagged as "v0_2_0" and is also available
  as source tarball)

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

  ViewVC Help
Powered by ViewVC