/[svn]/linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceFactory.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/drivers/audio/AudioOutputDeviceFactory.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1934 - (hide annotations) (download)
Sun Jul 12 10:35:55 2009 UTC (14 years, 10 months ago) by schoenebeck
File size: 13264 byte(s)
* bugfix: don't allow to create or destroy audio devices and MIDI devices
  of host plugin implementations (e.g VST, AU, DSSI, LV2) on their own,
  as they only exist in the context of the plugin instance and would
  otherwise crash the application

1 schoenebeck 200 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 1889 * Copyright (C) 2005 - 2009 Christian Schoenebeck *
7 schoenebeck 200 * *
8 schoenebeck 838 * This library is free software; you can redistribute it and/or modify *
9 schoenebeck 200 * 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 schoenebeck 838 * This library is distributed in the hope that it will be useful, *
14 schoenebeck 200 * 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 schoenebeck 838 * along with this library; if not, write to the Free Software *
20 schoenebeck 200 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24     #include "AudioOutputDeviceFactory.h"
25    
26 schoenebeck 1424 #include "../../common/global_private.h"
27    
28 schoenebeck 289 #if HAVE_ALSA
29     # include "AudioOutputDeviceAlsa.h"
30     #endif // HAVE_ALSA
31 schoenebeck 288
32 schoenebeck 289 #if HAVE_JACK
33     # include "AudioOutputDeviceJack.h"
34     #endif // HAVE_JACK
35    
36 schoenebeck 838 #if HAVE_ARTS
37     # include "AudioOutputDeviceArts.h"
38     #endif // HAVE_ARTS
39    
40 senoner 1481 #if HAVE_ASIO
41     # include "AudioOutputDeviceAsio.h"
42     #endif // HAVE_ASIO
43 iliev 1829
44     #if HAVE_COREAUDIO
45     # include "AudioOutputDeviceCoreAudio.h"
46     #endif // HAVE_COREAUDIO
47    
48 schoenebeck 200 namespace LinuxSampler {
49    
50     std::map<String, AudioOutputDeviceFactory::InnerFactory*> AudioOutputDeviceFactory::InnerFactories;
51     std::map<String, DeviceParameterFactory*> AudioOutputDeviceFactory::ParameterFactories;
52    
53 schoenebeck 289 #if HAVE_ALSA
54     REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDeviceAlsa);
55     /* Common parameters for now they'll have to be registered here. */
56     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAlsa, ParameterActive);
57     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAlsa, ParameterSampleRate);
58     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAlsa, ParameterChannels);
59     /* Driver specific parameters */
60     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAlsa, ParameterCard);
61     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAlsa, ParameterFragments);
62     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAlsa, ParameterFragmentSize);
63     #endif // HAVE_ALSA
64 schoenebeck 288
65 schoenebeck 289 #if HAVE_JACK
66     REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDeviceJack);
67     /* Common parameters for now they'll have to be registered here. */
68     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterActive);
69 schoenebeck 1604 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterSampleRate);
70 schoenebeck 289 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterChannels);
71 schoenebeck 374 /* Driver specific parameters */
72     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterName);
73 schoenebeck 289 #endif // HAVE_JACK
74    
75 schoenebeck 838 #if HAVE_ARTS
76     REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDeviceArts);
77     /* Common parameters for now they'll have to be registered here. */
78     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceArts, ParameterActive);
79     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceArts, ParameterSampleRate);
80     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceArts, ParameterChannels);
81     /* Driver specific parameters */
82     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceArts, ParameterName);
83     #endif // HAVE_ARTS
84    
85 senoner 1481 #if HAVE_ASIO
86     REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDeviceAsio);
87     /* Common parameters for now they'll have to be registered here. */
88     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAsio, ParameterActive);
89     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAsio, ParameterSampleRate);
90     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAsio, ParameterChannels);
91     /* Driver specific parameters */
92     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAsio, ParameterCard);
93     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceAsio, ParameterFragmentSize);
94     #endif // HAVE_ASIO
95    
96 iliev 1829 #if HAVE_COREAUDIO
97     REGISTER_AUDIO_OUTPUT_DRIVER(AudioOutputDeviceCoreAudio);
98     /* Common parameters for now they'll have to be registered here. */
99     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterActive);
100     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterSampleRate);
101     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterChannels);
102 iliev 1832 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterDevice);
103 iliev 1829 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterBuffers);
104     REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterBufferSize);
105     #endif // HAVE_COREAUDIO
106    
107 schoenebeck 1934 AudioOutputDeviceFactory::AudioOutputDeviceMap AudioOutputDeviceFactory::mAudioOutputDevices;
108    
109     /**
110     * Creates a new audio output device for the given driver name and
111     * parameters. Note, this method will also check whether it is actually
112     * allowed to create an instance of the given driver on its own and throw
113     * an Exception in case it is not allowed (this is the case for host plugin
114     * drivers like VST, AU, DSSI, LV2).
115     *
116     * @param DriverName - name of the driver of which a new device shall be created
117     * @param Parameters - device creation parameters which shall be passed to the driver's constructor
118     *
119     * @returns pointer to the new device instance
120     * @throws Exception - in case the device could not be created
121     *
122     * @see CreatePrivate()
123     */
124 schoenebeck 880 AudioOutputDevice* AudioOutputDeviceFactory::Create(String DriverName, std::map<String,String> Parameters) throw (Exception) {
125 schoenebeck 1934 if (!InnerFactories.count(DriverName))
126     throw Exception("There is no audio output driver '" + DriverName + "'.");
127     if (!InnerFactories[DriverName]->isAutonomousDriver())
128     throw Exception("You cannot directly create a new audio output device of the '" + DriverName + "' driver!");
129    
130     return CreatePrivate(DriverName, Parameters);
131     }
132    
133     /**
134     * Same as Create(), but this method won't check whether it is allowed to
135     * create an instance of the given driver on its own. This method is
136     * usually called by host plugins (e.g. VST, AU, DSSI, LV2) to actually
137     * create their respective audio output devices for the sampler. Usually
138     * one shouldn't call this method directly, but call Create() instead.
139     */
140     AudioOutputDevice* AudioOutputDeviceFactory::CreatePrivate(String DriverName, std::map<String,String> Parameters) throw (Exception) {
141 schoenebeck 880 if (!InnerFactories.count(DriverName)) throw Exception("There is no audio output driver '" + DriverName + "'.");
142 schoenebeck 1934 // let's see if we need to create parameters
143     std::map<String,DeviceCreationParameter*> thisDeviceParams;
144     DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName];
145     if (pParamFactory) {
146     thisDeviceParams = pParamFactory->CreateAllParams(Parameters);
147     } else {
148     // no parameters are registered by the driver. Throw if any parameters were specified.
149     if (Parameters.size() != 0) throw Exception("Driver '" + DriverName + "' does not have any parameters.");
150     }
151    
152     // get a free device id
153     int iDeviceId = -1;
154     for (int i = 0; i >= 0; i++) { // seek for a free place starting from the beginning
155     if (!mAudioOutputDevices[i]) {
156     iDeviceId = i;
157     break;
158     }
159     }
160     if (iDeviceId < 0)
161     throw Exception("Could not retrieve free device ID!");
162    
163     // now create the device using those parameters
164 schoenebeck 200 AudioOutputDevice* pDevice = InnerFactories[DriverName]->Create(thisDeviceParams);
165 schoenebeck 1934 pDevice->setDeviceId(iDeviceId);
166     // now attach all parameters to the newely created device.
167     for (std::map<String,DeviceCreationParameter*>::iterator iter = thisDeviceParams.begin(); iter != thisDeviceParams.end(); iter++) {
168     iter->second->Attach(pDevice);
169     }
170    
171     // add new audio device to the audio device list
172     mAudioOutputDevices[iDeviceId] = pDevice;
173    
174     return pDevice;
175 schoenebeck 200 }
176    
177     std::vector<String> AudioOutputDeviceFactory::AvailableDrivers() {
178     std::vector<String> result;
179     std::map<String, InnerFactory*>::iterator iter = InnerFactories.begin();
180     while (iter != InnerFactories.end()) {
181     result.push_back(iter->first);
182     iter++;
183     }
184     return result;
185     }
186    
187     String AudioOutputDeviceFactory::AvailableDriversAsString() {
188     std::vector<String> drivers = AvailableDrivers();
189     String result;
190     std::vector<String>::iterator iter = drivers.begin();
191     for (; iter != drivers.end(); iter++) {
192     if (result != "") result += ",";
193     result += *iter;
194     }
195     return result;
196     }
197    
198 schoenebeck 880 std::map<String,DeviceCreationParameter*> AudioOutputDeviceFactory::GetAvailableDriverParameters(String DriverName) throw (Exception) {
199     if (!InnerFactories.count(DriverName)) throw Exception("There is no audio output driver '" + DriverName + "'.");
200 schoenebeck 1934 std::map<String,DeviceCreationParameter*> thisDeviceParams;
201     DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName];
202     if (pParamFactory) {
203     thisDeviceParams = pParamFactory->CreateAllParams();
204     }
205 schoenebeck 200 return thisDeviceParams;
206     }
207    
208 schoenebeck 880 DeviceCreationParameter* AudioOutputDeviceFactory::GetDriverParameter(String DriverName, String ParameterName) throw (Exception) {
209 iliev 1835 if (!InnerFactories.count(DriverName)) throw Exception("There is no audio output driver '" + DriverName + "'.");
210     DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName];
211     if (pParamFactory) {
212     try { return pParamFactory->Create(ParameterName); }
213     catch(Exception e) { }
214     }
215     throw Exception("Audio output driver '" + DriverName + "' does not have a parameter '" + ParameterName + "'.");
216 schoenebeck 200 }
217    
218 schoenebeck 880 String AudioOutputDeviceFactory::GetDriverDescription(String DriverName) throw (Exception) {
219     if (!InnerFactories.count(DriverName)) throw Exception("There is no audio output driver '" + DriverName + "'.");
220 schoenebeck 200 return InnerFactories[DriverName]->Description();
221     }
222    
223 schoenebeck 880 String AudioOutputDeviceFactory::GetDriverVersion(String DriverName) throw (Exception) {
224     if (!InnerFactories.count(DriverName)) throw Exception("There is no audio output driver '" + DriverName + "'.");
225 schoenebeck 200 return InnerFactories[DriverName]->Version();
226     }
227    
228 persson 1889 void AudioOutputDeviceFactory::Unregister(String DriverName) {
229     std::map<String, InnerFactory*>::iterator iter = InnerFactories.find(DriverName);
230     if (iter != InnerFactories.end()) {
231     delete iter->second;
232     InnerFactories.erase(iter);
233     }
234    
235     std::map<String, DeviceParameterFactory*>::iterator iterpf = ParameterFactories.find(DriverName);
236     if (iterpf != ParameterFactories.end()) {
237     delete iterpf->second;
238     ParameterFactories.erase(iterpf);
239     }
240     }
241    
242 schoenebeck 1934 std::map<uint, AudioOutputDevice*> AudioOutputDeviceFactory::Devices() {
243     return mAudioOutputDevices;
244     }
245    
246     /**
247     * Destroys the given device. Usually this method shouldn't be called
248     * directly, Sampler::DestroyAudioOutputDevice should be called instead,
249     * since it also takes care whether some sampler channel is still using
250     * the device, etc.
251     */
252     void AudioOutputDeviceFactory::Destroy(AudioOutputDevice* pDevice) throw (Exception) {
253     if (pDevice && !pDevice->isAutonomousDevice())
254     throw Exception("You cannot directly destroy this '" + pDevice->Driver() + "' device!");
255    
256     DestroyPrivate(pDevice);
257     }
258    
259     void AudioOutputDeviceFactory::DestroyPrivate(AudioOutputDevice* pDevice) throw (Exception) {
260     AudioOutputDeviceMap::iterator iter = mAudioOutputDevices.begin();
261     for (; iter != mAudioOutputDevices.end(); iter++) {
262     if (iter->second == pDevice) {
263     // disable device
264     pDevice->Stop();
265     // remove device from the device list
266     mAudioOutputDevices.erase(iter);
267     // destroy and free device from memory
268     delete pDevice;
269    
270     break;
271     }
272     }
273     }
274    
275 schoenebeck 200 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC