--- linuxsampler/trunk/src/network/lscpserver.cpp 2006/11/28 20:55:19 951 +++ linuxsampler/trunk/src/network/lscpserver.cpp 2007/02/19 19:38:04 1047 @@ -3,7 +3,7 @@ * LinuxSampler - modular, streaming capable sampler * * * * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * - * Copyright (C) 2005, 2006 Christian Schoenebeck * + * Copyright (C) 2005 - 2007 Christian Schoenebeck * * * * This library is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -24,7 +24,7 @@ #include "lscpserver.h" #include "lscpresultset.h" #include "lscpevent.h" -//#include "../common/global.h" +#include "../common/global.h" #include @@ -66,11 +66,19 @@ SocketAddress.sin_addr.s_addr = addr; SocketAddress.sin_port = port; this->pSampler = pSampler; + LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT"); + LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO"); + LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT"); + LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO"); LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT"); LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT"); LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT"); LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL"); LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO"); + LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT"); + LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO"); + LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT"); + LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO"); LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS"); LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT"); hSocket = -1; @@ -662,6 +670,7 @@ String AudioRouting; int Mute = 0; bool Solo = false; + String MidiInstrumentMap; if (pEngineChannel) { EngineName = pEngineChannel->EngineName(); @@ -679,6 +688,12 @@ } Mute = pEngineChannel->GetMute(); Solo = pEngineChannel->GetSolo(); + if (pEngineChannel->UsesNoMidiInstrumentMap()) + MidiInstrumentMap = "NONE"; + else if (pEngineChannel->UsesDefaultMidiInstrumentMap()) + MidiInstrumentMap = "DEFAULT"; + else + MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap()); } result.Add("ENGINE_NAME", EngineName); @@ -700,6 +715,7 @@ result.Add("INSTRUMENT_STATUS", InstrumentStatus); result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false")); result.Add("SOLO", Solo); + result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap); } catch (Exception e) { result.Error(e); @@ -1177,6 +1193,7 @@ // set new channel parameter value pParameter->SetValue(ParamVal); + LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId)); } catch (Exception e) { result.Error(e); @@ -1194,6 +1211,7 @@ std::map parameters = pDevice->DeviceParameters(); if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'"); parameters[ParamKey]->SetValue(ParamVal); + LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex)); } catch (Exception e) { result.Error(e); @@ -1211,6 +1229,7 @@ std::map parameters = pDevice->DeviceParameters(); if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'"); parameters[ParamKey]->SetValue(ParamVal); + LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex)); } catch (Exception e) { result.Error(e); @@ -1235,6 +1254,7 @@ std::map parameters = pMidiInputPort->PortParameters(); if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'"); parameters[ParamKey]->SetValue(ParamVal); + LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex)); } catch (Exception e) { result.Error(e); @@ -1482,14 +1502,14 @@ bool oldSolo = pEngineChannel->GetSolo(); bool hadSoloChannel = HasSoloChannel(); - + pEngineChannel->SetSolo(bSolo); - + if(!oldSolo && bSolo) { if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0); if(!hadSoloChannel) MuteNonSoloChannels(); } - + if(oldSolo && !bSolo) { if(!HasSoloChannel()) UnmuteChannels(); else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1); @@ -1547,12 +1567,12 @@ } } -String LSCPServer::AddOrReplaceMIDIInstrumentMapping(uint MidiBankMSB, uint MidiBankLSB, uint MidiProg, String EngineType, String InstrumentFile, uint InstrumentIndex, float Volume, MidiInstrumentMapper::mode_t LoadMode, String Name) { +String LSCPServer::AddOrReplaceMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg, String EngineType, String InstrumentFile, uint InstrumentIndex, float Volume, MidiInstrumentMapper::mode_t LoadMode, String Name, bool bModal) { dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n")); midi_prog_index_t idx; - idx.midi_bank_msb = MidiBankMSB; - idx.midi_bank_lsb = MidiBankLSB; + idx.midi_bank_msb = (MidiBank >> 7) & 0x7f; + idx.midi_bank_lsb = MidiBank & 0x7f; idx.midi_prog = MidiProg; MidiInstrumentMapper::entry_t entry; @@ -1565,50 +1585,71 @@ LSCPResultSet result; try { - // PERSISTENT mapping commands might bloock for a long time, so in - // that case we add/replace the mapping in another thread - bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT); - MidiInstrumentMapper::AddOrReplaceMapping(idx, entry, bInBackground); + // PERSISTENT mapping commands might block for a long time, so in + // that case we add/replace the mapping in another thread in case + // the NON_MODAL argument was supplied, non persistent mappings + // should return immediately, so we don't need to do that for them + bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal); + MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground); } catch (Exception e) { result.Error(e); } return result.Produce(); } -String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiBankMSB, uint MidiBankLSB, uint MidiProg) { +String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) { dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n")); midi_prog_index_t idx; - idx.midi_bank_msb = MidiBankMSB; - idx.midi_bank_lsb = MidiBankLSB; + idx.midi_bank_msb = (MidiBank >> 7) & 0x7f; + idx.midi_bank_lsb = MidiBank & 0x7f; idx.midi_prog = MidiProg; LSCPResultSet result; try { - MidiInstrumentMapper::RemoveMapping(idx); + MidiInstrumentMapper::RemoveEntry(MidiMapID, idx); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) { + dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n")); + LSCPResultSet result; + try { + result.Add(MidiInstrumentMapper::Entries(MidiMapID).size()); } catch (Exception e) { result.Error(e); } return result.Produce(); } -String LSCPServer::GetMidiIstrumentMappings() { - dmsg(2,("LSCPServer: GetMidiIstrumentMappings()\n")); + +String LSCPServer::GetAllMidiInstrumentMappings() { + dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n")); LSCPResultSet result; - result.Add(MidiInstrumentMapper::Mappings().size()); + std::vector maps = MidiInstrumentMapper::Maps(); + int totalMappings = 0; + for (int i = 0; i < maps.size(); i++) { + try { + totalMappings += MidiInstrumentMapper::Entries(maps[i]).size(); + } catch (Exception e) { /*NOOP*/ } + } + result.Add(totalMappings); return result.Produce(); } -String LSCPServer::GetMidiInstrumentMapping(uint MidiBankMSB, uint MidiBankLSB, uint MidiProg) { +String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) { dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n")); LSCPResultSet result; try { midi_prog_index_t idx; - idx.midi_bank_msb = MidiBankMSB; - idx.midi_bank_lsb = MidiBankLSB; + idx.midi_bank_msb = (MidiBank >> 7) & 0x7f; + idx.midi_bank_lsb = MidiBank & 0x7f; idx.midi_prog = MidiProg; - std::map mappings = MidiInstrumentMapper::Mappings(); + std::map mappings = MidiInstrumentMapper::Entries(MidiMapID); std::map::iterator iter = mappings.find(idx); if (iter == mappings.end()) result.Error("there is no map entry with that index"); else { // found @@ -1649,18 +1690,18 @@ return result.Produce(); } -String LSCPServer::ListMidiInstrumentMappings() { - dmsg(2,("LSCPServer: ListMidiIstrumentMappings()\n")); +String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) { + dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n")); LSCPResultSet result; try { String s; - std::map mappings = MidiInstrumentMapper::Mappings(); + std::map mappings = MidiInstrumentMapper::Entries(MidiMapID); std::map::iterator iter = mappings.begin(); for (; iter != mappings.end(); iter++) { if (s.size()) s += ","; - s += "{" + ToString(int(iter->first.midi_bank_msb)) + "," - + ToString(int(iter->first.midi_bank_lsb)) + "," - + ToString(int(iter->first.midi_prog)) + "}"; + s += "{" + ToString(MidiMapID) + "," + + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + "," + + ToString(int(iter->first.midi_prog)) + "}"; } result.Add(s); } catch (Exception e) { @@ -1669,11 +1710,358 @@ return result.Produce(); } -String LSCPServer::ClearMidiInstrumentMappings() { +String LSCPServer::ListAllMidiInstrumentMappings() { + dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n")); + LSCPResultSet result; + try { + std::vector maps = MidiInstrumentMapper::Maps(); + String s; + for (int i = 0; i < maps.size(); i++) { + std::map mappings = MidiInstrumentMapper::Entries(maps[i]); + std::map::iterator iter = mappings.begin(); + for (; iter != mappings.end(); iter++) { + if (s.size()) s += ","; + s += "{" + ToString(maps[i]) + "," + + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + "," + + ToString(int(iter->first.midi_prog)) + "}"; + } + } + result.Add(s); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) { dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n")); LSCPResultSet result; try { - MidiInstrumentMapper::RemoveAllMappings(); + MidiInstrumentMapper::RemoveAllEntries(MidiMapID); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::ClearAllMidiInstrumentMappings() { + dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n")); + LSCPResultSet result; + try { + std::vector maps = MidiInstrumentMapper::Maps(); + for (int i = 0; i < maps.size(); i++) + MidiInstrumentMapper::RemoveAllEntries(maps[i]); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::AddMidiInstrumentMap(String MapName) { + dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n")); + LSCPResultSet result; + try { + int MapID = MidiInstrumentMapper::AddMap(MapName); + result = LSCPResultSet(MapID); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) { + dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n")); + LSCPResultSet result; + try { + MidiInstrumentMapper::RemoveMap(MidiMapID); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::RemoveAllMidiInstrumentMaps() { + dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n")); + LSCPResultSet result; + try { + MidiInstrumentMapper::RemoveAllMaps(); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::GetMidiInstrumentMaps() { + dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n")); + LSCPResultSet result; + try { + result.Add(MidiInstrumentMapper::Maps().size()); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::ListMidiInstrumentMaps() { + dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n")); + LSCPResultSet result; + try { + std::vector maps = MidiInstrumentMapper::Maps(); + String sList; + for (int i = 0; i < maps.size(); i++) { + if (sList != "") sList += ","; + sList += ToString(maps[i]); + } + result.Add(sList); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) { + dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n")); + LSCPResultSet result; + try { + result.Add("NAME", MidiInstrumentMapper::MapName(MidiMapID)); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) { + dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n")); + LSCPResultSet result; + try { + MidiInstrumentMapper::RenameMap(MidiMapID, NewName); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +/** + * Set the MIDI instrument map the given sampler channel shall use for + * handling MIDI program change messages. There are the following two + * special (negative) values: + * + * - (-1) : set to NONE (ignore program changes) + * - (-2) : set to DEFAULT map + */ +String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) { + dmsg(2,("LSCPServer: SetChannelMap()\n")); + LSCPResultSet result; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + if (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone(); + else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault(); + else pEngineChannel->SetMidiInstrumentMap(MidiMapID); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) { + dmsg(2,("LSCPServer: CreateFxSend()\n")); + LSCPResultSet result; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name); + if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)"); + + result = LSCPResultSet(pFxSend->Id()); // success + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) { + dmsg(2,("LSCPServer: DestroyFxSend()\n")); + LSCPResultSet result; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + FxSend* pFxSend = NULL; + for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) { + if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) { + pFxSend = pEngineChannel->GetFxSend(i); + break; + } + } + if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel"); + pEngineChannel->RemoveFxSend(pFxSend); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::GetFxSends(uint uiSamplerChannel) { + dmsg(2,("LSCPServer: GetFxSends()\n")); + LSCPResultSet result; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + result.Add(pEngineChannel->GetFxSendCount()); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::ListFxSends(uint uiSamplerChannel) { + dmsg(2,("LSCPServer: ListFxSends()\n")); + LSCPResultSet result; + String list; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) { + FxSend* pFxSend = pEngineChannel->GetFxSend(i); + if (list != "") list += ","; + list += ToString(pFxSend->Id()); + } + result.Add(list); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) { + dmsg(2,("LSCPServer: GetFxSendInfo()\n")); + LSCPResultSet result; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + FxSend* pFxSend = NULL; + for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) { + if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) { + pFxSend = pEngineChannel->GetFxSend(i); + break; + } + } + if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel"); + + // gather audio routing informations + String AudioRouting; + for (int chan = 0; chan < pEngineChannel->Channels(); chan++) { + if (AudioRouting != "") AudioRouting += ","; + AudioRouting += ToString(pFxSend->DestinationChannel(chan)); + } + + // success + result.Add("NAME", pFxSend->Name()); + result.Add("MIDI_CONTROLLER", pFxSend->MidiController()); + result.Add("LEVEL", ToString(pFxSend->Level())); + result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) { + dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n")); + LSCPResultSet result; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + FxSend* pFxSend = NULL; + for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) { + if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) { + pFxSend = pEngineChannel->GetFxSend(i); + break; + } + } + if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel"); + + pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) { + dmsg(2,("LSCPServer: SetFxSendMidiController()\n")); + LSCPResultSet result; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + FxSend* pFxSend = NULL; + for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) { + if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) { + pFxSend = pEngineChannel->GetFxSend(i); + break; + } + } + if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel"); + + pFxSend->SetMidiController(MidiController); + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + +String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) { + dmsg(2,("LSCPServer: SetFxSendLevel()\n")); + LSCPResultSet result; + try { + SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel); + if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel)); + + EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel(); + if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet"); + + FxSend* pFxSend = NULL; + for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) { + if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) { + pFxSend = pEngineChannel->GetFxSend(i); + break; + } + } + if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel"); + + pFxSend->SetLevel((float)dLevel); } catch (Exception e) { result.Error(e); } @@ -1742,6 +2130,23 @@ return result.Produce(); } +String LSCPServer::GetGlobalVolume() { + LSCPResultSet result; + result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp + return result.Produce(); +} + +String LSCPServer::SetGlobalVolume(double dVolume) { + LSCPResultSet result; + try { + if (dVolume < 0) throw Exception("Volume may not be negative"); + GLOBAL_VOLUME = dVolume; // see common/global.cpp + } catch (Exception e) { + result.Error(e); + } + return result.Produce(); +} + /** * Will be called by the parser to subscribe a client (frontend) on the * server for receiving event messages.