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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 660 - (hide annotations) (download)
Fri Jun 17 19:49:30 2005 UTC (18 years, 10 months ago) by schoenebeck
File size: 14961 byte(s)
* LSCP server: fixed LSCP event "CHANNEL_INFO" notification
  (e.g. did not notify on volume changes)

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

  ViewVC Help
Powered by ViewVC