/[svn]/linuxsampler/trunk/src/drivers/midi/MidiInputDeviceFactory.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/midi/MidiInputDeviceFactory.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2201 - (show annotations) (download)
Thu Jul 7 19:19:09 2011 UTC (12 years, 9 months ago) by iliev
File size: 11324 byte(s)
* Fixed possible crashes due to corrupted MIDI/audio device list
  after MIDI/audio device creation failure

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 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 #include "MidiInputDeviceFactory.h"
25
26 #include "../../common/global_private.h"
27
28 #if HAVE_ALSA
29 # include "MidiInputDeviceAlsa.h"
30 #endif // HAVE_ALSA
31
32 #if HAVE_COREMIDI
33 # include "MidiInputDeviceCoreMidi.h"
34 #endif // HAVE_CORE_MIDI
35
36 #if HAVE_MIDISHARE
37 # include "MidiInputDeviceMidiShare.h"
38 #endif // HAVE_MIDISHARE
39
40 #if HAVE_MME_MIDI
41 # include "MidiInputDeviceMme.h"
42 #endif // HAVE_MME_MIDI
43
44 #if HAVE_JACK_MIDI
45 # include "MidiInputDeviceJack.h"
46 #endif // HAVE_JACK_MIDI
47
48 namespace LinuxSampler {
49
50 std::map<String, MidiInputDeviceFactory::InnerFactory*> MidiInputDeviceFactory::InnerFactories;
51 std::map<String, DeviceParameterFactory*> MidiInputDeviceFactory::ParameterFactories;
52
53 #if HAVE_ALSA
54 REGISTER_MIDI_INPUT_DRIVER(MidiInputDeviceAlsa);
55 /* Common parameters */
56 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterActive);
57 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterPorts);
58 /* Driver specific parameters */
59 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterName);
60 #endif // HAVE_ALSA
61
62 #if HAVE_COREMIDI
63 REGISTER_MIDI_INPUT_DRIVER(MidiInputDeviceCoreMidi);
64 /* Common parameters */
65 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceCoreMidi, ParameterActive);
66 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceCoreMidi, ParameterPorts);
67 #endif // HAVE_COREMIDI
68
69 #if HAVE_MIDISHARE
70 REGISTER_MIDI_INPUT_DRIVER(MidiInputDeviceMidiShare);
71 /* Common parameters */
72 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceMidiShare, ParameterActive);
73 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceMidiShare, ParameterPorts);
74 #endif // HAVE_MIDISHARE
75
76 #if HAVE_MME_MIDI
77 REGISTER_MIDI_INPUT_DRIVER(MidiInputDeviceMme);
78 /* Common parameters */
79 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceMme, ParameterActive);
80 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceMme, ParameterPorts);
81 #endif // HAVE_MME_MIDI
82
83 #if HAVE_JACK_MIDI
84 REGISTER_MIDI_INPUT_DRIVER(MidiInputDeviceJack);
85 /* Common parameters */
86 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceJack, ParameterActive);
87 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceJack, ParameterPorts);
88 /* Driver specific parameters */
89 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceJack, ParameterName);
90 #endif // HAVE_JACK_MIDI
91
92 MidiInputDeviceFactory::MidiInputDeviceMap MidiInputDeviceFactory::mMidiInputDevices;
93
94 /**
95 * Creates a new MIDI input device for the given driver name and
96 * parameters. Note, this method will also check whether it is actually
97 * allowed to create an instance of the given driver on its own and throw
98 * an Exception in case it is not allowed (this is the case for host plugin
99 * drivers like VST, AU, DSSI, LV2).
100 *
101 * @param DriverName - name of the driver of which a new device shall be created
102 * @param Parameters - device creation parameters which shall be passed to the driver's constructor
103 * @param pSampler - the sampler instance
104 *
105 * @returns pointer to the new device instance
106 * @throws Exception - in case the device could not be created
107 *
108 * @see CreatePrivate()
109 */
110 MidiInputDevice* MidiInputDeviceFactory::Create(String DriverName, std::map<String,String> Parameters, Sampler* pSampler) throw (Exception) {
111 if (!InnerFactories.count(DriverName))
112 throw Exception("There is no midi input driver '" + DriverName + "'.");
113 if (!InnerFactories[DriverName]->isAutonomousDriver())
114 throw Exception("You cannot directly create a new MIDI input device of the '" + DriverName + "' driver!");
115
116 return CreatePrivate(DriverName, Parameters, pSampler);
117 }
118
119 /**
120 * Same as Create(), but this method won't check whether it is allowed to
121 * create an instance of the given driver on its own. This method is
122 * usually called by host plugins (e.g. VST, AU, DSSI, LV2) to actually
123 * create their respective MIDI input devices for the sampler. Usually one
124 * shouldn't call this method directly, but call Create() instead.
125 */
126 MidiInputDevice* MidiInputDeviceFactory::CreatePrivate(String DriverName, std::map<String,String> Parameters, Sampler* pSampler) throw (Exception) {
127 if (!InnerFactories.count(DriverName)) throw Exception("There is no midi input driver '" + DriverName + "'.");
128 // let's see if we need to create parameters
129 std::map<String,DeviceCreationParameter*> thisDeviceParams;
130 DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName];
131 if (pParamFactory) {
132 thisDeviceParams = pParamFactory->CreateAllParams(Parameters);
133 } else {
134 // no parameters are registered by the driver. Throw if any parameters were specified.
135 if (Parameters.size() != 0) throw Exception("Driver '" + DriverName + "' does not have any parameters.");
136 }
137
138 // get a free device id
139 int iDeviceId = -1;
140 for (int i = 0; i >= 0; i++) { // seek for a free place starting from the beginning
141 if (!mMidiInputDevices[i]) {
142 iDeviceId = i;
143 mMidiInputDevices.erase(i);
144 break;
145 }
146 }
147 if (iDeviceId < 0)
148 throw Exception("Could not retrieve free device ID!");
149
150 // now create the device using those parameters
151 MidiInputDevice* pDevice = InnerFactories[DriverName]->Create(thisDeviceParams, pSampler);
152 pDevice->setDeviceId(iDeviceId);
153 // now attach all parameters to the newly created device.
154 for (std::map<String,DeviceCreationParameter*>::iterator iter = thisDeviceParams.begin(); iter != thisDeviceParams.end(); iter++) {
155 iter->second->Attach(pDevice);
156 }
157
158 // add new audio device to the audio device list
159 mMidiInputDevices[iDeviceId] = pDevice;
160
161 return pDevice;
162 }
163
164 std::vector<String> MidiInputDeviceFactory::AvailableDrivers() {
165 std::vector<String> result;
166 std::map<String, InnerFactory*>::iterator iter = InnerFactories.begin();
167 while (iter != InnerFactories.end()) {
168 result.push_back(iter->first);
169 iter++;
170 }
171 return result;
172 }
173
174 String MidiInputDeviceFactory::AvailableDriversAsString() {
175 std::vector<String> drivers = AvailableDrivers();
176 String result;
177 std::vector<String>::iterator iter = drivers.begin();
178 for (; iter != drivers.end(); iter++) {
179 if (result != "") result += ",";
180 result += *iter;
181 }
182 return result;
183 }
184
185 std::map<String,DeviceCreationParameter*> MidiInputDeviceFactory::GetAvailableDriverParameters(String DriverName) throw (Exception) {
186 if (!InnerFactories.count(DriverName)) throw Exception("There is no midi input driver '" + DriverName + "'.");
187 std::map<String,DeviceCreationParameter*> thisDeviceParams;
188 DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName];
189 if (pParamFactory) {
190 thisDeviceParams = pParamFactory->CreateAllParams();
191 }
192 return thisDeviceParams;
193 }
194
195 DeviceCreationParameter* MidiInputDeviceFactory::GetDriverParameter(String DriverName, String ParameterName) throw (Exception) {
196 if (!InnerFactories.count(DriverName)) throw Exception("There is no midi input driver '" + DriverName + "'.");
197 DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName];
198 if (pParamFactory) {
199 try { return pParamFactory->Create(ParameterName); }
200 catch(Exception e) { }
201 }
202 throw Exception("Midi input driver '" + DriverName + "' does not have a parameter '" + ParameterName + "'.");
203 }
204
205 String MidiInputDeviceFactory::GetDriverDescription(String DriverName) throw (Exception) {
206 if (!InnerFactories.count(DriverName)) throw Exception("There is no midi input driver '" + DriverName + "'.");
207 return InnerFactories[DriverName]->Description();
208 }
209
210 String MidiInputDeviceFactory::GetDriverVersion(String DriverName) throw (Exception) {
211 if (!InnerFactories.count(DriverName)) throw Exception("There is no midi input driver '" + DriverName + "'.");
212 return InnerFactories[DriverName]->Version();
213 }
214
215 std::map<uint, MidiInputDevice*> MidiInputDeviceFactory::Devices() {
216 return mMidiInputDevices;
217 }
218
219 /**
220 * Destroys the given device. Usually this method shouldn't be called
221 * directly, Sampler::DestroyMidiInputDevice should be called instead,
222 * since it also takes care whether some sampler channel is still using
223 * the device, etc.
224 */
225 void MidiInputDeviceFactory::Destroy(MidiInputDevice* pDevice) throw (Exception) {
226 if (pDevice && !pDevice->isAutonomousDevice())
227 throw Exception("You cannot directly destroy this '" + pDevice->Driver() + "' device!");
228
229 DestroyPrivate(pDevice);
230 }
231
232 void MidiInputDeviceFactory::DestroyPrivate(MidiInputDevice* pDevice) throw (Exception) {
233 MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin();
234 for (; iter != mMidiInputDevices.end(); iter++) {
235 if (iter->second == pDevice) {
236 // disable device
237 pDevice->StopListen();
238
239 // remove device from the device list
240 mMidiInputDevices.erase(iter);
241
242 // destroy and free device from memory
243 delete pDevice;
244
245 break;
246 }
247 }
248 }
249
250 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC