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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 209 - (hide annotations) (download)
Sun Jul 18 00:29:39 2004 UTC (19 years, 9 months ago) by schoenebeck
File size: 13567 byte(s)
* src/Sampler.cpp: changed sampler channel index allocation from consistent
channel index allocation to incrementing channel index allocation, that is
it doesn't fill channel index gaps anymore (to avoid race conditions)
* implemented "LIST CHANNELS" LSCP command

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 53 * *
7     * This program is free software; you can redistribute it and/or modify *
8     * it under the terms of the GNU General Public License as published by *
9     * the Free Software Foundation; either version 2 of the License, or *
10     * (at your option) any later version. *
11     * *
12     * This program is distributed in the hope that it will be useful, *
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15     * GNU General Public License for more details. *
16     * *
17     * You should have received a copy of the GNU General Public License *
18     * along with this program; if not, write to the Free Software *
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20     * MA 02111-1307 USA *
21     ***************************************************************************/
22    
23 schoenebeck 123 #include <sstream>
24    
25 schoenebeck 53 #include "Sampler.h"
26    
27 schoenebeck 203 #include "drivers/audio/AudioOutputDeviceFactory.h"
28     #include "drivers/midi/MidiInputDeviceFactory.h"
29 schoenebeck 53 #include "engines/gig/Engine.h"
30    
31     namespace LinuxSampler {
32    
33     // ******************************************************************
34     // * SamplerChannel
35    
36     SamplerChannel::SamplerChannel(Sampler* pS) {
37     pSampler = pS;
38     pEngine = NULL;
39 capela 159 pMidiInputDevice = NULL;
40 schoenebeck 53 pAudioOutputDevice = NULL;
41 capela 159 midiPort = 0;
42     midiChannel = MidiInputDevice::MidiInputPort::midi_chan_all;
43 schoenebeck 53 iIndex = -1;
44     }
45    
46     SamplerChannel::~SamplerChannel() {
47     if (pEngine) {
48 capela 159 MidiInputDevice::MidiInputPort *pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
49 senkov 155 if (pMidiInputPort) pMidiInputPort->Disconnect(pEngine);
50 schoenebeck 53 if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(pEngine);
51     delete pEngine;
52     }
53     }
54    
55 schoenebeck 64 void SamplerChannel::LoadEngine(Engine::type_t EngineType) {
56     dmsg(2,("SamplerChannel: Loading engine..."));
57 schoenebeck 53
58     // create new engine
59     Engine* pNewEngine = NULL;
60     switch (EngineType) {
61 schoenebeck 64 case Engine::type_gig:
62 schoenebeck 53 pNewEngine = new gig::Engine;
63     break;
64     default:
65     throw LinuxSamplerException("Unknown engine type");
66     }
67    
68 capela 159 // dereference midi input port.
69     MidiInputDevice::MidiInputPort *pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
70 schoenebeck 53 // disconnect old engine
71     if (pEngine) {
72 senkov 155 if (pMidiInputPort) pMidiInputPort->Disconnect(pEngine);
73 schoenebeck 53 if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(pEngine);
74     delete pEngine;
75     }
76    
77     // connect new engine
78     pEngine = pNewEngine;
79 capela 159 if (pMidiInputPort) pMidiInputPort->Connect(pNewEngine, this->midiChannel);
80 schoenebeck 53 if (pAudioOutputDevice) pAudioOutputDevice->Connect(pNewEngine);
81 schoenebeck 64 dmsg(2,("OK\n"));
82 schoenebeck 53 }
83    
84 schoenebeck 123 void SamplerChannel::SetAudioOutputDevice(AudioOutputDevice* pDevice) {
85 schoenebeck 53 // disconnect old device
86     if (pAudioOutputDevice && pEngine) pAudioOutputDevice->Disconnect(pEngine);
87     // connect new device
88     pAudioOutputDevice = pDevice;
89     if (pEngine) pAudioOutputDevice->Connect(pEngine);
90     }
91    
92 capela 159 void SamplerChannel::SetMidiInputDevice(MidiInputDevice* pDevice) {
93     SetMidiInput(pDevice, this->midiPort, this->midiChannel);
94     }
95 schoenebeck 203
96 capela 159 void SamplerChannel::SetMidiInputPort(int MidiPort) {
97     SetMidiInput(pMidiInputDevice, MidiPort, this->midiChannel);
98     }
99 schoenebeck 203
100 capela 159 void SamplerChannel::SetMidiInputChannel(MidiInputDevice::MidiInputPort::midi_chan_t MidiChannel) {
101     SetMidiInput(pMidiInputDevice, this->midiPort, MidiChannel);
102     }
103 schoenebeck 203
104 capela 159 void SamplerChannel::SetMidiInput(MidiInputDevice* pDevice, int MidiPort, MidiInputDevice::MidiInputPort::midi_chan_t MidiChannel) {
105     // dereference old midi input port.
106     MidiInputDevice::MidiInputPort *pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
107     // disconnect old device port
108 senkov 155 if (pMidiInputPort && pEngine) pMidiInputPort->Disconnect(pEngine);
109 capela 159 // new device, port and channel
110     pMidiInputDevice = pDevice;
111     this->midiPort = MidiPort;
112     this->midiChannel = MidiChannel;
113     // connect new device port
114     pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
115     if (pMidiInputPort && pEngine) pMidiInputPort->Connect(pEngine, MidiChannel);
116     // Ooops.
117     if (pMidiInputPort == NULL)
118     throw LinuxSamplerException("There is no MIDI input port with index " + ToString(MidiPort) + ".");
119 schoenebeck 53 }
120    
121     Engine* SamplerChannel::GetEngine() {
122     return pEngine;
123     }
124    
125 capela 159 MidiInputDevice::MidiInputPort::midi_chan_t SamplerChannel::GetMidiInputChannel() {
126     return this->midiChannel;
127 schoenebeck 53 }
128    
129 capela 159 int SamplerChannel::GetMidiInputPort() {
130     MidiInputDevice::MidiInputPort *pMidiInputPort = GetMidiInputDevicePort(this->midiPort);
131     return (pMidiInputPort ? (int) pMidiInputPort->GetPortNumber() : -1);
132     }
133    
134 schoenebeck 53 AudioOutputDevice* SamplerChannel::GetAudioOutputDevice() {
135     return pAudioOutputDevice;
136     }
137    
138 senkov 155 MidiInputDevice* SamplerChannel::GetMidiInputDevice() {
139 capela 159 return pMidiInputDevice;
140 senkov 155 }
141    
142 schoenebeck 53 uint SamplerChannel::Index() {
143     if (iIndex >= 0) return iIndex;
144    
145 schoenebeck 209 Sampler::SamplerChannelMap::iterator iter = pSampler->mSamplerChannels.begin();
146     for (; iter != pSampler->mSamplerChannels.end(); iter++) {
147     if (iter->second == this) {
148     iIndex = iter->first;
149     return iIndex;
150 schoenebeck 53 }
151     }
152    
153 schoenebeck 209 throw LinuxSamplerException("Internal error: SamplerChannel index not found");
154 schoenebeck 53 }
155    
156 capela 159 MidiInputDevice::MidiInputPort* SamplerChannel::GetMidiInputDevicePort(int MidiPort) {
157     MidiInputDevice::MidiInputPort *pMidiInputPort = NULL;
158     if (pMidiInputDevice)
159     pMidiInputPort = pMidiInputDevice->GetPort(MidiPort);
160     return pMidiInputPort;
161     }
162 schoenebeck 53
163     // ******************************************************************
164     // * Sampler
165    
166     Sampler::Sampler() {
167     }
168    
169     Sampler::~Sampler() {
170     // delete sampler channels
171     {
172 schoenebeck 209 SamplerChannelMap::iterator iter = mSamplerChannels.begin();
173     for (; iter != mSamplerChannels.end(); iter++) delete iter->second;
174 schoenebeck 53 }
175    
176     // delete midi input devices
177     {
178 senkov 155 MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin();
179     for (; iter != mMidiInputDevices.end(); iter++) {
180 schoenebeck 53 MidiInputDevice* pDevice = iter->second;
181     pDevice->StopListen();
182     delete pDevice;
183     }
184     }
185    
186     // delete audio output devices
187     {
188 schoenebeck 123 AudioOutputDeviceMap::iterator iter = mAudioOutputDevices.begin();
189     for (; iter != mAudioOutputDevices.end(); iter++) {
190 schoenebeck 53 AudioOutputDevice* pDevice = iter->second;
191     pDevice->Stop();
192     delete pDevice;
193     }
194     }
195     }
196    
197     uint Sampler::SamplerChannels() {
198 schoenebeck 209 return mSamplerChannels.size();
199 schoenebeck 53 }
200    
201     SamplerChannel* Sampler::AddSamplerChannel() {
202 schoenebeck 209 // if there's no sampler channel yet
203     if (!mSamplerChannels.size()) {
204     SamplerChannel* pChannel = new SamplerChannel(this);
205     mSamplerChannels[0] = pChannel;
206     return pChannel;
207     }
208    
209     // get the highest used sampler channel index
210     uint lastIndex = (--(mSamplerChannels.end()))->first;
211    
212     // check if we reached the index limit
213     if (lastIndex + 1 < lastIndex) {
214     // search for an unoccupied sampler channel index starting from 0
215     for (uint i = 0; i < lastIndex; i++) {
216     if (mSamplerChannels.find(i) != mSamplerChannels.end()) continue;
217     // we found an unused index, so insert the new channel there
218     SamplerChannel* pChannel = new SamplerChannel(this);
219     mSamplerChannels[i] = pChannel;
220     return pChannel;
221     }
222     throw LinuxSamplerException("Internal error: could not find unoccupied sampler channel index.");
223     }
224    
225     // we have not reached the index limit so we just add the channel past the highest index
226 schoenebeck 53 SamplerChannel* pChannel = new SamplerChannel(this);
227 schoenebeck 209 mSamplerChannels[lastIndex + 1] = pChannel;
228 schoenebeck 53 return pChannel;
229     }
230    
231     SamplerChannel* Sampler::GetSamplerChannel(uint uiSamplerChannel) {
232 schoenebeck 209 return (mSamplerChannels.find(uiSamplerChannel) != mSamplerChannels.end()) ? mSamplerChannels[uiSamplerChannel] : NULL;
233 schoenebeck 53 }
234    
235 schoenebeck 209 std::map<uint, SamplerChannel*> Sampler::GetSamplerChannels() {
236     return mSamplerChannels;
237     }
238    
239 schoenebeck 53 void Sampler::RemoveSamplerChannel(SamplerChannel* pSamplerChannel) {
240 schoenebeck 209 SamplerChannelMap::iterator iterChan = mSamplerChannels.begin();
241     for (; iterChan != mSamplerChannels.end(); iterChan++) {
242     if (iterChan->second == pSamplerChannel) {
243     mSamplerChannels.erase(iterChan);
244 schoenebeck 53 delete pSamplerChannel;
245     return;
246     }
247     }
248     }
249    
250     void Sampler::RemoveSamplerChannel(uint uiSamplerChannel) {
251     SamplerChannel* pChannel = GetSamplerChannel(uiSamplerChannel);
252     if (!pChannel) return;
253     RemoveSamplerChannel(pChannel);
254     }
255    
256 schoenebeck 123 std::vector<String> Sampler::AvailableAudioOutputDrivers() {
257     return AudioOutputDeviceFactory::AvailableDrivers();
258     }
259 schoenebeck 53
260 schoenebeck 123 AudioOutputDevice* Sampler::CreateAudioOutputDevice(String AudioDriver, std::map<String,String> Parameters) throw (LinuxSamplerException) {
261 schoenebeck 53 // create new device
262 schoenebeck 123 AudioOutputDevice* pDevice = AudioOutputDeviceFactory::Create(AudioDriver, Parameters);
263 schoenebeck 53
264 schoenebeck 64 // add new audio device to the audio device list
265 schoenebeck 123 for (uint i = 0; ; i++) { // seek for a free place starting from the beginning
266     if (!mAudioOutputDevices[i]) {
267     mAudioOutputDevices[i] = pDevice;
268     break;
269     }
270     }
271 schoenebeck 64
272 schoenebeck 53 return pDevice;
273     }
274    
275 schoenebeck 123 uint Sampler::AudioOutputDevices() {
276     return mAudioOutputDevices.size();
277 schoenebeck 53 }
278    
279 senkov 155 uint Sampler::MidiInputDevices() {
280     return mMidiInputDevices.size();
281     }
282    
283 schoenebeck 123 std::map<uint, AudioOutputDevice*> Sampler::GetAudioOutputDevices() {
284     return mAudioOutputDevices;
285     }
286    
287 senkov 155 std::map<uint, MidiInputDevice*> Sampler::GetMidiInputDevices() {
288     return mMidiInputDevices;
289     }
290    
291 schoenebeck 123 void Sampler::DestroyAudioOutputDevice(AudioOutputDevice* pDevice) throw (LinuxSamplerException) {
292     AudioOutputDeviceMap::iterator iter = mAudioOutputDevices.begin();
293     for (; iter != mAudioOutputDevices.end(); iter++) {
294     if (iter->second == pDevice) {
295     // check if there are still sampler engines connected to this device
296     for (uint i = 0; i < SamplerChannels(); i++)
297     if (GetSamplerChannel(i)->GetAudioOutputDevice() == pDevice) throw LinuxSamplerException("Sampler channel " + ToString(i) + " is still connected to the audio output device.");
298    
299     // disable device
300     pDevice->Stop();
301    
302     // remove device from the device list
303     mAudioOutputDevices.erase(iter);
304    
305     // destroy and free device from memory
306     delete pDevice;
307     }
308     }
309     }
310    
311 senkov 155 void Sampler::DestroyMidiInputDevice(MidiInputDevice* pDevice) throw (LinuxSamplerException) {
312     MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin();
313     for (; iter != mMidiInputDevices.end(); iter++) {
314     if (iter->second == pDevice) {
315     // check if there are still sampler engines connected to this device
316     for (uint i = 0; i < SamplerChannels(); i++)
317     if (GetSamplerChannel(i)->GetMidiInputDevice() == pDevice) throw LinuxSamplerException("Sampler channel " + ToString(i) + " is still connected to the midi input device.");
318 schoenebeck 53
319 senkov 155 // disable device
320     pDevice->StopListen();
321    
322     // remove device from the device list
323     mMidiInputDevices.erase(iter);
324    
325     // destroy and free device from memory
326     delete pDevice;
327     }
328 schoenebeck 53 }
329 senkov 155 }
330 schoenebeck 53
331 senkov 155 MidiInputDevice* Sampler::CreateMidiInputDevice(String MidiDriver, std::map<String,String> Parameters) throw (LinuxSamplerException) {
332     // create new device
333     MidiInputDevice* pDevice = MidiInputDeviceFactory::Create(MidiDriver, Parameters);
334    
335     // add new device to the midi device list
336     for (uint i = 0; ; i++) { // seek for a free place starting from the beginning
337     if (!mMidiInputDevices[i]) {
338     mMidiInputDevices[i] = pDevice;
339     break;
340     }
341     }
342 schoenebeck 64
343 schoenebeck 53 return pDevice;
344     }
345    
346     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC