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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1934 - (show annotations) (download)
Sun Jul 12 10:35:55 2009 UTC (14 years, 9 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 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2009 Christian Schoenebeck *
7 * *
8 * This library 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 library 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 library; 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 "AudioOutputDeviceFactory.h"
25
26 #include "../../common/global_private.h"
27
28 #if HAVE_ALSA
29 # include "AudioOutputDeviceAlsa.h"
30 #endif // HAVE_ALSA
31
32 #if HAVE_JACK
33 # include "AudioOutputDeviceJack.h"
34 #endif // HAVE_JACK
35
36 #if HAVE_ARTS
37 # include "AudioOutputDeviceArts.h"
38 #endif // HAVE_ARTS
39
40 #if HAVE_ASIO
41 # include "AudioOutputDeviceAsio.h"
42 #endif // HAVE_ASIO
43
44 #if HAVE_COREAUDIO
45 # include "AudioOutputDeviceCoreAudio.h"
46 #endif // HAVE_COREAUDIO
47
48 namespace LinuxSampler {
49
50 std::map<String, AudioOutputDeviceFactory::InnerFactory*> AudioOutputDeviceFactory::InnerFactories;
51 std::map<String, DeviceParameterFactory*> AudioOutputDeviceFactory::ParameterFactories;
52
53 #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
65 #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 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterSampleRate);
70 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterChannels);
71 /* Driver specific parameters */
72 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceJack, ParameterName);
73 #endif // HAVE_JACK
74
75 #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 #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 #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 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterDevice);
103 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterBuffers);
104 REGISTER_AUDIO_OUTPUT_DRIVER_PARAMETER(AudioOutputDeviceCoreAudio, ParameterBufferSize);
105 #endif // HAVE_COREAUDIO
106
107 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 AudioOutputDevice* AudioOutputDeviceFactory::Create(String DriverName, std::map<String,String> Parameters) throw (Exception) {
125 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 if (!InnerFactories.count(DriverName)) throw Exception("There is no audio output driver '" + DriverName + "'.");
142 // 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 AudioOutputDevice* pDevice = InnerFactories[DriverName]->Create(thisDeviceParams);
165 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 }
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 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 std::map<String,DeviceCreationParameter*> thisDeviceParams;
201 DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName];
202 if (pParamFactory) {
203 thisDeviceParams = pParamFactory->CreateAllParams();
204 }
205 return thisDeviceParams;
206 }
207
208 DeviceCreationParameter* AudioOutputDeviceFactory::GetDriverParameter(String DriverName, String ParameterName) throw (Exception) {
209 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 }
217
218 String AudioOutputDeviceFactory::GetDriverDescription(String DriverName) throw (Exception) {
219 if (!InnerFactories.count(DriverName)) throw Exception("There is no audio output driver '" + DriverName + "'.");
220 return InnerFactories[DriverName]->Description();
221 }
222
223 String AudioOutputDeviceFactory::GetDriverVersion(String DriverName) throw (Exception) {
224 if (!InnerFactories.count(DriverName)) throw Exception("There is no audio output driver '" + DriverName + "'.");
225 return InnerFactories[DriverName]->Version();
226 }
227
228 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 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 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC