--- linuxsampler/trunk/src/Sampler.cpp 2006/02/06 18:07:17 835 +++ linuxsampler/trunk/src/Sampler.cpp 2006/11/30 10:39:12 960 @@ -3,7 +3,7 @@ * LinuxSampler - modular, streaming capable sampler * * * * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * - * Copyright (C) 2005 Christian Schoenebeck * + * Copyright (C) 2005, 2006 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 * @@ -48,21 +48,28 @@ SamplerChannel::~SamplerChannel() { if (pEngineChannel) { + Engine* engine = pEngineChannel->GetEngine(); + if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(engine); + MidiInputPort* pMidiInputPort = (pEngineChannel) ? pEngineChannel->GetMidiInputPort() : __GetMidiInputDevicePort(GetMidiInputChannel()); if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel); if (pEngineChannel) { if (pAudioOutputDevice) pEngineChannel->DisconnectAudioOutputDevice(); EngineChannelFactory::Destroy(pEngineChannel); + + // reconnect engine if it still exists + const std::set& engines = EngineFactory::EngineInstances(); + if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine); } } } - void SamplerChannel::SetEngineType(String EngineType) throw (LinuxSamplerException) { + void SamplerChannel::SetEngineType(String EngineType) throw (Exception) { dmsg(2,("SamplerChannel: Assigning engine type...")); // create new engine channel EngineChannel* pNewEngineChannel = EngineChannelFactory::Create(EngineType); - if (!pNewEngineChannel) throw LinuxSamplerException("Unknown engine type"); + if (!pNewEngineChannel) throw Exception("Unknown engine type"); //FIXME: hack to allow fast retrieval of engine channel's sampler channel index pNewEngineChannel->iSamplerChannelIndex = Index(); @@ -71,17 +78,24 @@ MidiInputPort* pMidiInputPort = __GetMidiInputDevicePort(GetMidiInputPort()); // disconnect old engine channel if (pEngineChannel) { + Engine* engine = pEngineChannel->GetEngine(); + if (pAudioOutputDevice) pAudioOutputDevice->Disconnect(engine); + if (pMidiInputPort) pMidiInputPort->Disconnect(pEngineChannel); if (pAudioOutputDevice) pEngineChannel->DisconnectAudioOutputDevice(); EngineChannelFactory::Destroy(pEngineChannel); + + // reconnect engine if it still exists + const std::set& engines = EngineFactory::EngineInstances(); + if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine); } // connect new engine channel - if (pMidiInputPort) pMidiInputPort->Connect(pNewEngineChannel, GetMidiInputChannel()); if (pAudioOutputDevice) { pNewEngineChannel->Connect(pAudioOutputDevice); pAudioOutputDevice->Connect(pNewEngineChannel->GetEngine()); } + if (pMidiInputPort) pMidiInputPort->Connect(pNewEngineChannel, GetMidiInputChannel()); pEngineChannel = pNewEngineChannel; // from now on get MIDI device and port from EngineChannel object @@ -94,8 +108,20 @@ } void SamplerChannel::SetAudioOutputDevice(AudioOutputDevice* pDevice) { + if(pAudioOutputDevice == pDevice) return; + // disconnect old device - if (pAudioOutputDevice && pEngineChannel) pEngineChannel->DisconnectAudioOutputDevice(); + if (pAudioOutputDevice && pEngineChannel) { + Engine* engine = pEngineChannel->GetEngine(); + pAudioOutputDevice->Disconnect(engine); + + pEngineChannel->DisconnectAudioOutputDevice(); + + // reconnect engine if it still exists + const std::set& engines = EngineFactory::EngineInstances(); + if (engines.find(engine) != engines.end()) pAudioOutputDevice->Connect(engine); + } + // connect new device pAudioOutputDevice = pDevice; if (pEngineChannel) { @@ -117,7 +143,7 @@ } void SamplerChannel::SetMidiInput(MidiInputDevice* pDevice, int iMidiPort, midi_chan_t MidiChannel) { - if (!pDevice) throw LinuxSamplerException("No MIDI input device assigned."); + if (!pDevice) throw Exception("No MIDI input device assigned."); // get old and new midi input port MidiInputPort* pOldMidiInputPort = __GetMidiInputDevicePort(GetMidiInputPort()); @@ -136,7 +162,7 @@ if (pNewMidiInputPort && pEngineChannel) pNewMidiInputPort->Connect(pEngineChannel, MidiChannel); // Ooops. if (pNewMidiInputPort == NULL) - throw LinuxSamplerException("There is no MIDI input port with index " + ToString(iMidiPort) + "."); + throw Exception("There is no MIDI input port with index " + ToString(iMidiPort) + "."); } EngineChannel* SamplerChannel::GetEngineChannel() { @@ -175,7 +201,7 @@ } } - throw LinuxSamplerException("Internal error: SamplerChannel index not found"); + throw Exception("Internal error: SamplerChannel index not found"); } MidiInputPort* SamplerChannel::__GetMidiInputDevicePort(int iMidiPort) { @@ -225,7 +251,7 @@ LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, i)); return pChannel; } - throw LinuxSamplerException("Internal error: could not find unoccupied sampler channel index."); + throw Exception("Internal error: could not find unoccupied sampler channel index."); } // we have not reached the index limit so we just add the channel past the highest index @@ -265,7 +291,15 @@ return AudioOutputDeviceFactory::AvailableDrivers(); } - AudioOutputDevice* Sampler::CreateAudioOutputDevice(String AudioDriver, std::map Parameters) throw (LinuxSamplerException) { + std::vector Sampler::AvailableMidiInputDrivers() { + return MidiInputDeviceFactory::AvailableDrivers(); + } + + std::vector Sampler::AvailableEngineTypes() { + return EngineFactory::AvailableEngineTypes(); + } + + AudioOutputDevice* Sampler::CreateAudioOutputDevice(String AudioDriver, std::map Parameters) throw (Exception) { // create new device AudioOutputDevice* pDevice = AudioOutputDeviceFactory::Create(AudioDriver, Parameters); @@ -296,45 +330,51 @@ return mMidiInputDevices; } - void Sampler::DestroyAudioOutputDevice(AudioOutputDevice* pDevice) throw (LinuxSamplerException) { + void Sampler::DestroyAudioOutputDevice(AudioOutputDevice* pDevice) throw (Exception) { AudioOutputDeviceMap::iterator iter = mAudioOutputDevices.begin(); for (; iter != mAudioOutputDevices.end(); iter++) { if (iter->second == pDevice) { // check if there are still sampler engines connected to this device for (uint i = 0; i < SamplerChannels(); i++) - if (GetSamplerChannel(i)->GetAudioOutputDevice() == pDevice) throw LinuxSamplerException("Sampler channel " + ToString(i) + " is still connected to the audio output device."); + if (GetSamplerChannel(i)->GetAudioOutputDevice() == pDevice) throw Exception("Sampler channel " + ToString(i) + " is still connected to the audio output device."); // disable device pDevice->Stop(); + // remove device from the device list + mAudioOutputDevices.erase(iter); + // destroy and free device from memory delete pDevice; + + break; } } - // remove devices from the device list - mAudioOutputDevices.clear(); } - void Sampler::DestroyMidiInputDevice(MidiInputDevice* pDevice) throw (LinuxSamplerException) { + void Sampler::DestroyMidiInputDevice(MidiInputDevice* pDevice) throw (Exception) { MidiInputDeviceMap::iterator iter = mMidiInputDevices.begin(); for (; iter != mMidiInputDevices.end(); iter++) { if (iter->second == pDevice) { // check if there are still sampler engines connected to this device for (uint i = 0; i < SamplerChannels(); i++) - if (GetSamplerChannel(i)->GetMidiInputDevice() == pDevice) throw LinuxSamplerException("Sampler channel " + ToString(i) + " is still connected to the midi input device."); + if (GetSamplerChannel(i)->GetMidiInputDevice() == pDevice) throw Exception("Sampler channel " + ToString(i) + " is still connected to the midi input device."); // disable device pDevice->StopListen(); + // remove device from the device list + mMidiInputDevices.erase(iter); + // destroy and free device from memory delete pDevice; + + break; } } - // remove devices from the device list - mMidiInputDevices.clear(); } - MidiInputDevice* Sampler::CreateMidiInputDevice(String MidiDriver, std::map Parameters) throw (LinuxSamplerException) { + MidiInputDevice* Sampler::CreateMidiInputDevice(String MidiDriver, std::map Parameters) throw (Exception) { // create new device MidiInputDevice* pDevice = MidiInputDeviceFactory::Create(MidiDriver, Parameters, this);