--- linuxsampler/trunk/src/drivers/midi/MidiInputDeviceFactory.cpp 2009/07/09 17:37:41 1933 +++ linuxsampler/trunk/src/drivers/midi/MidiInputDeviceFactory.cpp 2009/07/12 10:35:55 1934 @@ -3,7 +3,7 @@ * LinuxSampler - modular, streaming capable sampler * * * * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * - * Copyright (C) 2005 - 2008 Christian Schoenebeck * + * Copyright (C) 2005 - 2009 Christian Schoenebeck * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -87,24 +87,75 @@ REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceJack, ParameterName); #endif // HAVE_JACK_MIDI + MidiInputDeviceFactory::MidiInputDeviceMap MidiInputDeviceFactory::mMidiInputDevices; + + /** + * Creates a new MIDI input device for the given driver name and + * parameters. Note, this method will also check whether it is actually + * allowed to create an instance of the given driver on its own and throw + * an Exception in case it is not allowed (this is the case for host plugin + * drivers like VST, AU, DSSI, LV2). + * + * @param DriverName - name of the driver of which a new device shall be created + * @param Parameters - device creation parameters which shall be passed to the driver's constructor + * @param pSampler - the sampler instance + * + * @returns pointer to the new device instance + * @throws Exception - in case the device could not be created + * + * @see CreatePrivate() + */ MidiInputDevice* MidiInputDeviceFactory::Create(String DriverName, std::map Parameters, Sampler* pSampler) throw (Exception) { + if (!InnerFactories.count(DriverName)) + throw Exception("There is no midi input driver '" + DriverName + "'."); + if (!InnerFactories[DriverName]->isAutonomousDriver()) + throw Exception("You cannot directly create a new MIDI input device of the '" + DriverName + "' driver!"); + + return CreatePrivate(DriverName, Parameters, pSampler); + } + + /** + * Same as Create(), but this method won't check whether it is allowed to + * create an instance of the given driver on its own. This method is + * usually called by host plugins (e.g. VST, AU, DSSI, LV2) to actually + * create their respective MIDI input devices for the sampler. Usually one + * shouldn't call this method directly, but call Create() instead. + */ + MidiInputDevice* MidiInputDeviceFactory::CreatePrivate(String DriverName, std::map Parameters, Sampler* pSampler) throw (Exception) { if (!InnerFactories.count(DriverName)) throw Exception("There is no midi input driver '" + DriverName + "'."); - //Let's see if we need to create parameters - std::map thisDeviceParams; - DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName]; - if (pParamFactory) { - thisDeviceParams = pParamFactory->CreateAllParams(Parameters); - } else { - //No parameters are registered by the driver. Throw if any parameters were specified. - if (Parameters.size() != 0) throw Exception("Driver '" + DriverName + "' does not have any parameters."); - } - //Now create the device using those parameters - MidiInputDevice* pDevice = InnerFactories[DriverName]->Create(thisDeviceParams, pSampler); - //Now attach all parameters to the newely created device. - for (std::map::iterator iter = thisDeviceParams.begin(); iter != thisDeviceParams.end(); iter++) { - iter->second->Attach(pDevice); - } - return pDevice; + // let's see if we need to create parameters + std::map thisDeviceParams; + DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName]; + if (pParamFactory) { + thisDeviceParams = pParamFactory->CreateAllParams(Parameters); + } else { + // no parameters are registered by the driver. Throw if any parameters were specified. + if (Parameters.size() != 0) throw Exception("Driver '" + DriverName + "' does not have any parameters."); + } + + // get a free device id + int iDeviceId = -1; + for (int i = 0; i >= 0; i++) { // seek for a free place starting from the beginning + if (!mMidiInputDevices[i]) { + iDeviceId = i; + break; + } + } + if (iDeviceId < 0) + throw Exception("Could not retrieve free device ID!"); + + // now create the device using those parameters + MidiInputDevice* pDevice = InnerFactories[DriverName]->Create(thisDeviceParams, pSampler); + pDevice->setDeviceId(iDeviceId); + // now attach all parameters to the newely created device. + for (std::map::iterator iter = thisDeviceParams.begin(); iter != thisDeviceParams.end(); iter++) { + iter->second->Attach(pDevice); + } + + // add new audio device to the audio device list + mMidiInputDevices[iDeviceId] = pDevice; + + return pDevice; } std::vector MidiInputDeviceFactory::AvailableDrivers() { @@ -130,12 +181,12 @@ std::map MidiInputDeviceFactory::GetAvailableDriverParameters(String DriverName) throw (Exception) { if (!InnerFactories.count(DriverName)) throw Exception("There is no midi input driver '" + DriverName + "'."); - std::map thisDeviceParams; - DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName]; - if (pParamFactory) { - thisDeviceParams = pParamFactory->CreateAllParams(); - } - return thisDeviceParams; + std::map thisDeviceParams; + DeviceParameterFactory* pParamFactory = ParameterFactories[DriverName]; + if (pParamFactory) { + thisDeviceParams = pParamFactory->CreateAllParams(); + } + return thisDeviceParams; } DeviceCreationParameter* MidiInputDeviceFactory::GetDriverParameter(String DriverName, String ParameterName) throw (Exception) { @@ -158,4 +209,39 @@ return InnerFactories[DriverName]->Version(); } + std::map MidiInputDeviceFactory::Devices() { + return mMidiInputDevices; + } + + /** + * Destroys the given device. Usually this method shouldn't be called + * directly, Sampler::DestroyMidiInputDevice should be called instead, + * since it also takes care whether some sampler channel is still using + * the device, etc. + */ + void MidiInputDeviceFactory::Destroy(MidiInputDevice* pDevice) throw (Exception) { + if (pDevice && !pDevice->isAutonomousDevice()) + throw Exception("You cannot directly destroy this '" + pDevice->Driver() + "' device!"); + + DestroyPrivate(pDevice); + } + + void MidiInputDeviceFactory::DestroyPrivate(MidiInputDevice* pDevice) throw (Exception) { + MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin(); + for (; iter != mMidiInputDevices.end(); iter++) { + if (iter->second == pDevice) { + // disable device + pDevice->StopListen(); + + // remove device from the device list + mMidiInputDevices.erase(iter); + + // destroy and free device from memory + delete pDevice; + + break; + } + } + } + } // namespace LinuxSampler