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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 411 - (hide annotations) (download)
Sat Feb 26 02:01:14 2005 UTC (19 years, 2 months 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 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     if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(pEngineChannel);
53     delete pEngineChannel;
54 schoenebeck 53 }
55     }
56    
57 schoenebeck 411 void SamplerChannel::SetEngineType(String EngineType) throw (LinuxSamplerException) {
58     dmsg(2,("SamplerChannel: Assigning engine type..."));
59 schoenebeck 53
60 schoenebeck 411 // create new engine channel
61     EngineChannel* pNewEngineChannel = EngineChannelFactory::Create(EngineType);
62     if (!pNewEngineChannel) throw LinuxSamplerException("Unknown engine type");
63 schoenebeck 53
64 capela 159 // dereference midi input port.
65 schoenebeck 221 MidiInputPort* pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
66 schoenebeck 53 // disconnect old engine
67 schoenebeck 411 if (pEngineChannel) {
68     if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel);
69     if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(pEngineChannel);
70     delete pEngineChannel;
71 schoenebeck 53 }
72    
73 schoenebeck 411 // connect new engine channel
74     pEngineChannel = pNewEngineChannel;
75     if (pMidiInputPort) pMidiInputPort->Connect(pNewEngineChannel, this->midiChannel);
76     if (pAudioOutputDevice) pAudioOutputDevice->Connect(pNewEngineChannel);
77 schoenebeck 64 dmsg(2,("OK\n"));
78 schoenebeck 53 }
79    
80 schoenebeck 123 void SamplerChannel::SetAudioOutputDevice(AudioOutputDevice* pDevice) {
81 schoenebeck 53 // disconnect old device
82 schoenebeck 411 if (pAudioOutputDevice && pEngineChannel) pAudioOutputDevice->Disconnect(pEngineChannel);
83 schoenebeck 53 // connect new device
84     pAudioOutputDevice = pDevice;
85 schoenebeck 411 if (pEngineChannel) pAudioOutputDevice->Connect(pEngineChannel);
86 schoenebeck 53 }
87    
88 capela 159 void SamplerChannel::SetMidiInputDevice(MidiInputDevice* pDevice) {
89     SetMidiInput(pDevice, this->midiPort, this->midiChannel);
90     }
91 schoenebeck 203
92 capela 159 void SamplerChannel::SetMidiInputPort(int MidiPort) {
93     SetMidiInput(pMidiInputDevice, MidiPort, this->midiChannel);
94     }
95 schoenebeck 203
96 schoenebeck 221 void SamplerChannel::SetMidiInputChannel(MidiInputPort::midi_chan_t MidiChannel) {
97 capela 159 SetMidiInput(pMidiInputDevice, this->midiPort, MidiChannel);
98     }
99 schoenebeck 203
100 schoenebeck 221 void SamplerChannel::SetMidiInput(MidiInputDevice* pDevice, int iMidiPort, MidiInputPort::midi_chan_t MidiChannel) {
101 capela 159 // dereference old midi input port.
102 schoenebeck 221 MidiInputPort* pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
103 capela 159 // disconnect old device port
104 schoenebeck 411 if (pMidiInputPort && pEngineChannel) pMidiInputPort->Disconnect(pEngineChannel);
105 capela 159 // new device, port and channel
106     pMidiInputDevice = pDevice;
107 schoenebeck 221 this->midiPort = iMidiPort;
108 capela 159 this->midiChannel = MidiChannel;
109     // connect new device port
110     pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
111 schoenebeck 411 if (pMidiInputPort && pEngineChannel) pMidiInputPort->Connect(pEngineChannel, MidiChannel);
112 capela 159 // Ooops.
113     if (pMidiInputPort == NULL)
114 schoenebeck 221 throw LinuxSamplerException("There is no MIDI input port with index " + ToString(iMidiPort) + ".");
115 schoenebeck 53 }
116    
117 schoenebeck 411 EngineChannel* SamplerChannel::GetEngineChannel() {
118     return pEngineChannel;
119 schoenebeck 53 }
120    
121 schoenebeck 221 MidiInputPort::midi_chan_t SamplerChannel::GetMidiInputChannel() {
122 capela 159 return this->midiChannel;
123 schoenebeck 53 }
124    
125 capela 159 int SamplerChannel::GetMidiInputPort() {
126 schoenebeck 221 MidiInputPort* pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
127 capela 159 return (pMidiInputPort ? (int) pMidiInputPort->GetPortNumber() : -1);
128     }
129    
130 schoenebeck 53 AudioOutputDevice* SamplerChannel::GetAudioOutputDevice() {
131     return pAudioOutputDevice;
132     }
133    
134 senkov 155 MidiInputDevice* SamplerChannel::GetMidiInputDevice() {
135 capela 159 return pMidiInputDevice;
136 senkov 155 }
137    
138 schoenebeck 53 uint SamplerChannel::Index() {
139     if (iIndex >= 0) return iIndex;
140    
141 schoenebeck 209 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 schoenebeck 53 }
147     }
148    
149 schoenebeck 209 throw LinuxSamplerException("Internal error: SamplerChannel index not found");
150 schoenebeck 53 }
151    
152 schoenebeck 221 MidiInputPort* SamplerChannel::GetMidiInputDevicePort(int iMidiPort) {
153     MidiInputPort* pMidiInputPort = NULL;
154 capela 159 if (pMidiInputDevice)
155 schoenebeck 221 pMidiInputPort = pMidiInputDevice->GetPort(iMidiPort);
156 capela 159 return pMidiInputPort;
157     }
158 schoenebeck 53
159 schoenebeck 212
160    
161 schoenebeck 53 // ******************************************************************
162     // * Sampler
163    
164     Sampler::Sampler() {
165     }
166    
167     Sampler::~Sampler() {
168 schoenebeck 212 Reset();
169 schoenebeck 53 }
170    
171     uint Sampler::SamplerChannels() {
172 schoenebeck 209 return mSamplerChannels.size();
173 schoenebeck 53 }
174    
175     SamplerChannel* Sampler::AddSamplerChannel() {
176 schoenebeck 209 // if there's no sampler channel yet
177     if (!mSamplerChannels.size()) {
178     SamplerChannel* pChannel = new SamplerChannel(this);
179     mSamplerChannels[0] = pChannel;
180 senkov 359 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channels, 1));
181 schoenebeck 209 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 senkov 359 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channels, i));
196 schoenebeck 209 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 schoenebeck 53 SamplerChannel* pChannel = new SamplerChannel(this);
203 schoenebeck 209 mSamplerChannels[lastIndex + 1] = pChannel;
204 senkov 359 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channels, lastIndex + 1));
205 schoenebeck 53 return pChannel;
206     }
207    
208     SamplerChannel* Sampler::GetSamplerChannel(uint uiSamplerChannel) {
209 schoenebeck 209 return (mSamplerChannels.find(uiSamplerChannel) != mSamplerChannels.end()) ? mSamplerChannels[uiSamplerChannel] : NULL;
210 schoenebeck 53 }
211    
212 schoenebeck 209 std::map<uint, SamplerChannel*> Sampler::GetSamplerChannels() {
213     return mSamplerChannels;
214     }
215    
216 schoenebeck 53 void Sampler::RemoveSamplerChannel(SamplerChannel* pSamplerChannel) {
217 schoenebeck 209 SamplerChannelMap::iterator iterChan = mSamplerChannels.begin();
218     for (; iterChan != mSamplerChannels.end(); iterChan++) {
219     if (iterChan->second == pSamplerChannel) {
220     mSamplerChannels.erase(iterChan);
221 schoenebeck 53 delete pSamplerChannel;
222 senkov 359 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channels, mSamplerChannels.size()));
223 schoenebeck 53 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 schoenebeck 123 std::vector<String> Sampler::AvailableAudioOutputDrivers() {
235     return AudioOutputDeviceFactory::AvailableDrivers();
236     }
237 schoenebeck 53
238 schoenebeck 123 AudioOutputDevice* Sampler::CreateAudioOutputDevice(String AudioDriver, std::map<String,String> Parameters) throw (LinuxSamplerException) {
239 schoenebeck 53 // create new device
240 schoenebeck 123 AudioOutputDevice* pDevice = AudioOutputDeviceFactory::Create(AudioDriver, Parameters);
241 schoenebeck 53
242 schoenebeck 64 // add new audio device to the audio device list
243 schoenebeck 123 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 schoenebeck 64
250 schoenebeck 53 return pDevice;
251     }
252    
253 schoenebeck 123 uint Sampler::AudioOutputDevices() {
254     return mAudioOutputDevices.size();
255 schoenebeck 53 }
256    
257 senkov 155 uint Sampler::MidiInputDevices() {
258     return mMidiInputDevices.size();
259     }
260    
261 schoenebeck 123 std::map<uint, AudioOutputDevice*> Sampler::GetAudioOutputDevices() {
262     return mAudioOutputDevices;
263     }
264    
265 senkov 155 std::map<uint, MidiInputDevice*> Sampler::GetMidiInputDevices() {
266     return mMidiInputDevices;
267     }
268    
269 schoenebeck 123 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 senkov 155 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 schoenebeck 53
297 senkov 155 // 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 schoenebeck 53 }
307 senkov 155 }
308 schoenebeck 53
309 senkov 155 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 schoenebeck 64
321 schoenebeck 53 return pDevice;
322     }
323    
324 schoenebeck 212 void Sampler::Reset() {
325     // delete sampler channels
326     try {
327 senkov 329 while (true) {
328     SamplerChannelMap::iterator iter = mSamplerChannels.begin();
329     if (iter == mSamplerChannels.end()) break;
330     RemoveSamplerChannel(iter->second);
331 schoenebeck 212 }
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 senkov 329 while (true) {
341     MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin();
342     if (iter == mMidiInputDevices.end()) break;
343     DestroyMidiInputDevice(iter->second);
344 schoenebeck 212 }
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 senkov 329 while (true) {
354     AudioOutputDeviceMap::iterator iter = mAudioOutputDevices.begin();
355     if (iter == mAudioOutputDevices.end()) break;
356     DestroyAudioOutputDevice(iter->second);
357 schoenebeck 212 }
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 schoenebeck 53 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC