1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6  *   Copyright (C) 2005 - 2020 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 <algorithm>
25 #include <string>
26 
27 #include "../common/File.h"
28 #include "lscpserver.h"
29 #include "lscpresultset.h"
30 #include "lscpevent.h"
31 
32 #if defined(WIN32)
33 #include <windows.h>
34 typedef unsigned short in_port_t;
35 typedef unsigned long in_addr_t;
36 #else
37 #include <fcntl.h>
38 #endif
39 
40 #if ! HAVE_SQLITE3
41 #define DOESNT_HAVE_SQLITE3 "No database support. SQLITE3 was not installed when linuxsampler was built."
42 #endif
43 
44 #include "../engines/EngineFactory.h"
45 #include "../engines/EngineChannelFactory.h"
46 #include "../drivers/audio/AudioOutputDeviceFactory.h"
47 #include "../drivers/midi/MidiInputDeviceFactory.h"
48 #include "../effects/EffectFactory.h"
49 
50 namespace LinuxSampler {
51 
52 String lscpParserProcessShellInteraction(String& line, yyparse_param_t* param, bool possibilities);
53 
54 /**
55  * Returns a copy of the given string where all special characters are
56  * replaced by LSCP escape sequences ("\xHH"). This function shall be used
57  * to escape LSCP response fields in case the respective response field is
58  * actually defined as using escape sequences in the LSCP specs.
59  *
60  * @e Caution: DO NOT use this function for escaping path based responses,
61  * use the Path class (src/common/Path.h) for this instead!
62  */
_escapeLscpResponse(String txt)63 static String _escapeLscpResponse(String txt) {
64     for (int i = 0; i < txt.length(); i++) {
65         const char c = txt.c_str()[i];
66         if (
67             !(c >= '0' && c <= '9') &&
68             !(c >= 'a' && c <= 'z') &&
69             !(c >= 'A' && c <= 'Z') &&
70             !(c == ' ') && !(c == '!') && !(c == '#') && !(c == '$') &&
71             !(c == '%') && !(c == '&') && !(c == '(') && !(c == ')') &&
72             !(c == '*') && !(c == '+') && !(c == ',') && !(c == '-') &&
73             !(c == '.') && !(c == '/') && !(c == ':') && !(c == ';') &&
74             !(c == '<') && !(c == '=') && !(c == '>') && !(c == '?') &&
75             !(c == '@') && !(c == '[') && !(c == ']') &&
76             !(c == '^') && !(c == '_') && !(c == '`') && !(c == '{') &&
77             !(c == '|') && !(c == '}') && !(c == '~')
78         ) {
79             // convert the "special" character into a "\xHH" LSCP escape sequence
80             char buf[5];
81             snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
82             txt.replace(i, 1, buf);
83             i += 3;
84         }
85     }
86     return txt;
87 }
88 
89 /**
90  * Below are a few static members of the LSCPServer class.
91  * The big assumption here is that LSCPServer is going to remain a singleton.
92  * These members are used to support client connections.
93  * Class handles multiple connections at the same time using select() and non-blocking recv()
94  * Commands are processed by a single LSCPServer thread.
95  * Notifications are delivered either by the thread that originated them
96  * or (if the resultset is currently in progress) by the LSCPServer thread
97  * after the resultset was sent out.
98  * This makes sure that resultsets can not be interrupted by notifications.
99  * This also makes sure that the thread sending notification is not blocked
100  * by the LSCPServer thread.
101  */
102 fd_set LSCPServer::fdSet;
103 int LSCPServer::currentSocket = -1;
104 std::vector<yyparse_param_t> LSCPServer::Sessions;
105 std::vector<yyparse_param_t>::iterator itCurrentSession;
106 std::map<int,String> LSCPServer::bufferedNotifies;
107 std::map<int,String> LSCPServer::bufferedCommands;
108 std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions;
109 Mutex LSCPServer::NotifyMutex;
110 Mutex LSCPServer::NotifyBufferMutex;
111 Mutex LSCPServer::SubscriptionMutex;
112 Mutex LSCPServer::RTNotifyMutex;
113 
LSCPServer(Sampler * pSampler,long int addr,short int port)114 LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4), eventHandler(this) {
115     SocketAddress.sin_family      = AF_INET;
116     SocketAddress.sin_addr.s_addr = (in_addr_t)addr;
117     SocketAddress.sin_port        = (in_port_t)port;
118     this->pSampler = pSampler;
119     LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT");
120     LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO");
121     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT");
122     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO");
123     LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
124     LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
125     LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
126     LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
127     LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
128     LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_count, "FX_SEND_COUNT");
129     LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_info, "FX_SEND_INFO");
130     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
131     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
132     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
133     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
134     LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_count, "DB_INSTRUMENT_DIRECTORY_COUNT");
135     LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_info, "DB_INSTRUMENT_DIRECTORY_INFO");
136     LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_count, "DB_INSTRUMENT_COUNT");
137     LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_info, "DB_INSTRUMENT_INFO");
138     LSCPEvent::RegisterEvent(LSCPEvent::event_db_instrs_job_info, "DB_INSTRUMENTS_JOB_INFO");
139     LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
140     LSCPEvent::RegisterEvent(LSCPEvent::event_total_stream_count, "TOTAL_STREAM_COUNT");
141     LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
142     LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");
143     LSCPEvent::RegisterEvent(LSCPEvent::event_channel_midi, "CHANNEL_MIDI");
144     LSCPEvent::RegisterEvent(LSCPEvent::event_device_midi, "DEVICE_MIDI");
145     LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_count, "EFFECT_INSTANCE_COUNT");
146     LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_info, "EFFECT_INSTANCE_INFO");
147     LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_count, "SEND_EFFECT_CHAIN_COUNT");
148     LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_info, "SEND_EFFECT_CHAIN_INFO");
149     hSocket = -1;
150 }
151 
~LSCPServer()152 LSCPServer::~LSCPServer() {
153     CloseAllConnections();
154     InstrumentManager::StopBackgroundThread();
155 #if defined(WIN32)
156     if (hSocket >= 0) closesocket(hSocket);
157 #else
158     if (hSocket >= 0) close(hSocket);
159 #endif
160 }
161 
EventHandler(LSCPServer * pParent)162 LSCPServer::EventHandler::EventHandler(LSCPServer* pParent) {
163     this->pParent = pParent;
164 }
165 
~EventHandler()166 LSCPServer::EventHandler::~EventHandler() {
167     std::vector<midi_listener_entry> l = channelMidiListeners;
168     channelMidiListeners.clear();
169     for (int i = 0; i < l.size(); i++)
170         delete l[i].pMidiListener;
171 }
172 
ChannelCountChanged(int NewCount)173 void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {
174     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));
175 }
176 
ChannelAdded(SamplerChannel * pChannel)177 void LSCPServer::EventHandler::ChannelAdded(SamplerChannel* pChannel) {
178     pChannel->AddEngineChangeListener(this);
179 }
180 
ChannelToBeRemoved(SamplerChannel * pChannel)181 void LSCPServer::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) {
182     if (!pChannel->GetEngineChannel()) return;
183     EngineToBeChanged(pChannel->Index());
184 }
185 
EngineToBeChanged(int ChannelId)186 void LSCPServer::EventHandler::EngineToBeChanged(int ChannelId) {
187     SamplerChannel* pSamplerChannel =
188         pParent->pSampler->GetSamplerChannel(ChannelId);
189     if (!pSamplerChannel) return;
190     EngineChannel* pEngineChannel =
191         pSamplerChannel->GetEngineChannel();
192     if (!pEngineChannel) return;
193     for (std::vector<midi_listener_entry>::iterator iter = channelMidiListeners.begin(); iter != channelMidiListeners.end(); ++iter) {
194         if ((*iter).pEngineChannel == pEngineChannel) {
195             VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
196             pEngineChannel->Disconnect(pMidiListener);
197             channelMidiListeners.erase(iter);
198             delete pMidiListener;
199             return;
200         }
201     }
202 }
203 
EngineChanged(int ChannelId)204 void LSCPServer::EventHandler::EngineChanged(int ChannelId) {
205     SamplerChannel* pSamplerChannel =
206         pParent->pSampler->GetSamplerChannel(ChannelId);
207     if (!pSamplerChannel) return;
208     EngineChannel* pEngineChannel =
209         pSamplerChannel->GetEngineChannel();
210     if (!pEngineChannel) return;
211     VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
212     pEngineChannel->Connect(pMidiListener);
213     midi_listener_entry entry = {
214         pSamplerChannel, pEngineChannel, pMidiListener
215     };
216     channelMidiListeners.push_back(entry);
217 }
218 
AudioDeviceCountChanged(int NewCount)219 void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {
220     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));
221 }
222 
MidiDeviceCountChanged(int NewCount)223 void LSCPServer::EventHandler::MidiDeviceCountChanged(int NewCount) {
224     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));
225 }
226 
MidiDeviceToBeDestroyed(MidiInputDevice * pDevice)227 void LSCPServer::EventHandler::MidiDeviceToBeDestroyed(MidiInputDevice* pDevice) {
228     pDevice->RemoveMidiPortCountListener(this);
229     for (int i = 0; i < pDevice->PortCount(); ++i)
230         MidiPortToBeRemoved(pDevice->GetPort(i));
231 }
232 
MidiDeviceCreated(MidiInputDevice * pDevice)233 void LSCPServer::EventHandler::MidiDeviceCreated(MidiInputDevice* pDevice) {
234     pDevice->AddMidiPortCountListener(this);
235     for (int i = 0; i < pDevice->PortCount(); ++i)
236         MidiPortAdded(pDevice->GetPort(i));
237 }
238 
MidiPortCountChanged(int NewCount)239 void LSCPServer::EventHandler::MidiPortCountChanged(int NewCount) {
240     // yet unused
241 }
242 
MidiPortToBeRemoved(MidiInputPort * pPort)243 void LSCPServer::EventHandler::MidiPortToBeRemoved(MidiInputPort* pPort) {
244     for (std::vector<device_midi_listener_entry>::iterator iter = deviceMidiListeners.begin(); iter != deviceMidiListeners.end(); ++iter) {
245         if ((*iter).pPort == pPort) {
246             VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
247             pPort->Disconnect(pMidiListener);
248             deviceMidiListeners.erase(iter);
249             delete pMidiListener;
250             return;
251         }
252     }
253 }
254 
MidiPortAdded(MidiInputPort * pPort)255 void LSCPServer::EventHandler::MidiPortAdded(MidiInputPort* pPort) {
256     // find out the device ID
257     std::map<uint, MidiInputDevice*> devices =
258         pParent->pSampler->GetMidiInputDevices();
259     for (
260         std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
261         iter != devices.end(); ++iter
262     ) {
263         if (iter->second == pPort->GetDevice()) { // found
264             VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
265             pPort->Connect(pMidiListener);
266             device_midi_listener_entry entry = {
267                 pPort, pMidiListener, iter->first
268             };
269             deviceMidiListeners.push_back(entry);
270             return;
271         }
272     }
273 }
274 
MidiInstrumentCountChanged(int MapId,int NewCount)275 void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {
276     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));
277 }
278 
MidiInstrumentInfoChanged(int MapId,int Bank,int Program)279 void LSCPServer::EventHandler::MidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
280     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_info, MapId, Bank, Program));
281 }
282 
MidiInstrumentMapCountChanged(int NewCount)283 void LSCPServer::EventHandler::MidiInstrumentMapCountChanged(int NewCount) {
284     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, NewCount));
285 }
286 
MidiInstrumentMapInfoChanged(int MapId)287 void LSCPServer::EventHandler::MidiInstrumentMapInfoChanged(int MapId) {
288     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_info, MapId));
289 }
290 
FxSendCountChanged(int ChannelId,int NewCount)291 void LSCPServer::EventHandler::FxSendCountChanged(int ChannelId, int NewCount) {
292     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_count, ChannelId, NewCount));
293 }
294 
VoiceCountChanged(int ChannelId,int NewCount)295 void LSCPServer::EventHandler::VoiceCountChanged(int ChannelId, int NewCount) {
296     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, ChannelId, NewCount));
297 }
298 
StreamCountChanged(int ChannelId,int NewCount)299 void LSCPServer::EventHandler::StreamCountChanged(int ChannelId, int NewCount) {
300     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, ChannelId, NewCount));
301 }
302 
BufferFillChanged(int ChannelId,String FillData)303 void LSCPServer::EventHandler::BufferFillChanged(int ChannelId, String FillData) {
304     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, ChannelId, FillData));
305 }
306 
TotalVoiceCountChanged(int NewCount)307 void LSCPServer::EventHandler::TotalVoiceCountChanged(int NewCount) {
308     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));
309 }
310 
TotalStreamCountChanged(int NewCount)311 void LSCPServer::EventHandler::TotalStreamCountChanged(int NewCount) {
312     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_stream_count, NewCount));
313 }
314 
315 #if HAVE_SQLITE3
DirectoryCountChanged(String Dir)316 void LSCPServer::DbInstrumentsEventHandler::DirectoryCountChanged(String Dir) {
317     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_count, InstrumentsDb::toEscapedPath(Dir)));
318 }
319 
DirectoryInfoChanged(String Dir)320 void LSCPServer::DbInstrumentsEventHandler::DirectoryInfoChanged(String Dir) {
321     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, InstrumentsDb::toEscapedPath(Dir)));
322 }
323 
DirectoryNameChanged(String Dir,String NewName)324 void LSCPServer::DbInstrumentsEventHandler::DirectoryNameChanged(String Dir, String NewName) {
325     Dir = "'" + InstrumentsDb::toEscapedPath(Dir) + "'";
326     NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
327     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, "NAME", Dir, NewName));
328 }
329 
InstrumentCountChanged(String Dir)330 void LSCPServer::DbInstrumentsEventHandler::InstrumentCountChanged(String Dir) {
331     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_count, InstrumentsDb::toEscapedPath(Dir)));
332 }
333 
InstrumentInfoChanged(String Instr)334 void LSCPServer::DbInstrumentsEventHandler::InstrumentInfoChanged(String Instr) {
335     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, InstrumentsDb::toEscapedPath(Instr)));
336 }
337 
InstrumentNameChanged(String Instr,String NewName)338 void LSCPServer::DbInstrumentsEventHandler::InstrumentNameChanged(String Instr, String NewName) {
339     Instr = "'" + InstrumentsDb::toEscapedPath(Instr) + "'";
340     NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
341     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, "NAME", Instr, NewName));
342 }
343 
JobStatusChanged(int JobId)344 void LSCPServer::DbInstrumentsEventHandler::JobStatusChanged(int JobId) {
345     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instrs_job_info, JobId));
346 }
347 #endif // HAVE_SQLITE3
348 
RemoveListeners()349 void LSCPServer::RemoveListeners() {
350     pSampler->RemoveChannelCountListener(&eventHandler);
351     pSampler->RemoveAudioDeviceCountListener(&eventHandler);
352     pSampler->RemoveMidiDeviceCountListener(&eventHandler);
353     pSampler->RemoveVoiceCountListener(&eventHandler);
354     pSampler->RemoveStreamCountListener(&eventHandler);
355     pSampler->RemoveBufferFillListener(&eventHandler);
356     pSampler->RemoveTotalStreamCountListener(&eventHandler);
357     pSampler->RemoveTotalVoiceCountListener(&eventHandler);
358     pSampler->RemoveFxSendCountListener(&eventHandler);
359     MidiInstrumentMapper::RemoveMidiInstrumentCountListener(&eventHandler);
360     MidiInstrumentMapper::RemoveMidiInstrumentInfoListener(&eventHandler);
361     MidiInstrumentMapper::RemoveMidiInstrumentMapCountListener(&eventHandler);
362     MidiInstrumentMapper::RemoveMidiInstrumentMapInfoListener(&eventHandler);
363 #if HAVE_SQLITE3
364     InstrumentsDb::GetInstrumentsDb()->RemoveInstrumentsDbListener(&dbInstrumentsEventHandler);
365 #endif
366 }
367 
368 /**
369  * Blocks the calling thread until the LSCP Server is initialized and
370  * accepting socket connections, if the server is already initialized then
371  * this method will return immediately.
372  * @param TimeoutSeconds     - optional: max. wait time in seconds
373  *                             (default: 0s)
374  * @param TimeoutNanoSeconds - optional: max wait time in nano seconds
375  *                             (default: 0ns)
376  * @returns  0 on success, a value less than 0 if timeout exceeded
377  */
WaitUntilInitialized(long TimeoutSeconds,long TimeoutNanoSeconds)378 int LSCPServer::WaitUntilInitialized(long TimeoutSeconds, long TimeoutNanoSeconds) {
379     return Initialized.WaitAndUnlockIf(false, TimeoutSeconds, TimeoutNanoSeconds);
380 }
381 
Main()382 int LSCPServer::Main() {
383     #if DEBUG
384     Thread::setNameOfCaller("LSCPServer");
385     #endif
386 
387 	#if defined(WIN32)
388 	WSADATA wsaData;
389 	int iResult;
390 	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
391 	if (iResult != 0) {
392 		std::cerr << "LSCPServer: WSAStartup failed: " << iResult << "\n";
393 		exit(EXIT_FAILURE);
394 	}
395 	#endif
396     hSocket = socket(AF_INET, SOCK_STREAM, 0);
397     if (hSocket < 0) {
398         std::cerr << "LSCPServer: Could not create server socket." << std::endl;
399         //return -1;
400         exit(EXIT_FAILURE);
401     }
402 
403     if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
404         std::cerr << "LSCPServer: Could not bind server socket, retrying for " << ToString(LSCP_SERVER_BIND_TIMEOUT) << " seconds...";
405         for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds
406             if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
407                 if (trial > LSCP_SERVER_BIND_TIMEOUT) {
408                     std::cerr << "gave up!" << std::endl;
409                     #if defined(WIN32)
410                     closesocket(hSocket);
411                     #else
412                     close(hSocket);
413                     #endif
414                     //return -1;
415                     exit(EXIT_FAILURE);
416                 }
417                 else sleep(1); // sleep 1s
418             }
419             else break; // success
420         }
421     }
422 
423     listen(hSocket, 1);
424     Initialized.Set(true);
425 
426     // Registering event listeners
427     pSampler->AddChannelCountListener(&eventHandler);
428     pSampler->AddAudioDeviceCountListener(&eventHandler);
429     pSampler->AddMidiDeviceCountListener(&eventHandler);
430     pSampler->AddVoiceCountListener(&eventHandler);
431     pSampler->AddStreamCountListener(&eventHandler);
432     pSampler->AddBufferFillListener(&eventHandler);
433     pSampler->AddTotalStreamCountListener(&eventHandler);
434     pSampler->AddTotalVoiceCountListener(&eventHandler);
435     pSampler->AddFxSendCountListener(&eventHandler);
436     MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);
437     MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);
438     MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);
439     MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);
440 #if HAVE_SQLITE3
441     InstrumentsDb::GetInstrumentsDb()->AddInstrumentsDbListener(&dbInstrumentsEventHandler);
442 #endif
443     // now wait for client connections and handle their requests
444     sockaddr_in client;
445     int length = sizeof(client);
446     FD_ZERO(&fdSet);
447     FD_SET(hSocket, &fdSet);
448     int maxSessions = hSocket;
449 
450     timeval timeout;
451 
452     while (true) {
453 
454 		TestCancel();
455 
456         // prevent thread from being cancelled
457         // (e.g. to prevent deadlocks while holding mutex lock(s))
458         pushCancelable(false);
459 
460         // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
461         {
462             LockGuard lock(EngineChannelFactory::EngineChannelsMutex);
463             std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
464             std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
465             std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
466             for (; itEngineChannel != itEnd; ++itEngineChannel) {
467                 if ((*itEngineChannel)->StatusChanged()) {
468                     SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->GetSamplerChannel()->Index()));
469                 }
470 
471                 for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
472                     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
473                     if(fxs != NULL && fxs->IsInfoChanged()) {
474                         int chn = (*itEngineChannel)->GetSamplerChannel()->Index();
475                         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));
476                         fxs->SetInfoChanged(false);
477                     }
478                 }
479             }
480         }
481 
482         // check if MIDI data arrived on some engine channel
483         for (int i = 0; i < eventHandler.channelMidiListeners.size(); ++i) {
484             const EventHandler::midi_listener_entry entry =
485                 eventHandler.channelMidiListeners[i];
486             VirtualMidiDevice* pMidiListener = entry.pMidiListener;
487             if (pMidiListener->NotesChanged()) {
488                 for (int iNote = 0; iNote < 128; iNote++) {
489                     if (pMidiListener->NoteChanged(iNote)) {
490                         const bool bActive = pMidiListener->NoteIsActive(iNote);
491                         LSCPServer::SendLSCPNotify(
492                             LSCPEvent(
493                                 LSCPEvent::event_channel_midi,
494                                 entry.pSamplerChannel->Index(),
495                                 std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
496                                 iNote,
497                                 bActive ? pMidiListener->NoteOnVelocity(iNote)
498                                         : pMidiListener->NoteOffVelocity(iNote)
499                             )
500                         );
501                     }
502                 }
503             }
504         }
505 
506         // check if MIDI data arrived on some MIDI device
507         for (int i = 0; i < eventHandler.deviceMidiListeners.size(); ++i) {
508             const EventHandler::device_midi_listener_entry entry =
509                 eventHandler.deviceMidiListeners[i];
510             VirtualMidiDevice* pMidiListener = entry.pMidiListener;
511             if (pMidiListener->NotesChanged()) {
512                 for (int iNote = 0; iNote < 128; iNote++) {
513                     if (pMidiListener->NoteChanged(iNote)) {
514                         const bool bActive = pMidiListener->NoteIsActive(iNote);
515                         LSCPServer::SendLSCPNotify(
516                             LSCPEvent(
517                                 LSCPEvent::event_device_midi,
518                                 entry.uiDeviceID,
519                                 entry.pPort->GetPortNumber(),
520                                 std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
521                                 iNote,
522                                 bActive ? pMidiListener->NoteOnVelocity(iNote)
523                                         : pMidiListener->NoteOffVelocity(iNote)
524                             )
525                         );
526                     }
527                 }
528             }
529         }
530 
531         //Now let's deliver late notifies (if any)
532         {
533             LockGuard lock(NotifyBufferMutex);
534             for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
535 #ifdef MSG_NOSIGNAL
536                 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
537 #else
538                 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
539 #endif
540             }
541             bufferedNotifies.clear();
542         }
543 
544         // now allow thread being cancelled again
545         // (since all mutexes are now unlocked)
546         popCancelable();
547 
548         fd_set selectSet = fdSet;
549         timeout.tv_sec  = 0;
550         timeout.tv_usec = 100000;
551 
552         int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
553 
554 	if (retval == 0 || (retval == -1 && errno == EINTR))
555 		continue; //Nothing try again
556 	if (retval == -1) {
557 		std::cerr << "LSCPServer: Socket select error." << std::endl;
558 		#if defined(WIN32)
559 		closesocket(hSocket);
560 		#else
561 		close(hSocket);
562 		#endif
563 		exit(EXIT_FAILURE);
564 	}
565 
566 	//Accept new connections now (if any)
567 	if (FD_ISSET(hSocket, &selectSet)) {
568 		int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
569 		if (socket < 0) {
570 			std::cerr << "LSCPServer: Client connection failed." << std::endl;
571 			exit(EXIT_FAILURE);
572 		}
573 
574 		#if defined(WIN32)
575 		u_long nonblock_io = 1;
576 		if( ioctlsocket(socket, FIONBIO, &nonblock_io) ) {
577 		  std::cerr << "LSCPServer: ioctlsocket: set FIONBIO failed. Error " << WSAGetLastError() << std::endl;
578 		  exit(EXIT_FAILURE);
579 		}
580         #else
581                 struct linger linger;
582                 linger.l_onoff = 1;
583                 linger.l_linger = 0;
584                 if(setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))) {
585                     std::cerr << "LSCPServer: Failed to set SO_LINGER\n";
586                 }
587 
588 		if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
589 			std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
590 			exit(EXIT_FAILURE);
591 		}
592 		#endif
593 
594                 // Parser initialization
595                 yyparse_param_t yyparse_param;
596                 yyparse_param.pServer  = this;
597                 yyparse_param.hSession = socket;
598 
599 		Sessions.push_back(yyparse_param);
600 		FD_SET(socket, &fdSet);
601 		if (socket > maxSessions)
602 			maxSessions = socket;
603 		dmsg(1,("LSCPServer: Client connection established on socket:%d.\n", socket));
604 		LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection established on socket", socket));
605 		continue; //Maybe this was the only selected socket, better select again
606 	}
607 
608 	//Something was selected and it was not the hSocket, so it must be some command(s) coming.
609 	for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
610 		if (FD_ISSET((*iter).hSession, &selectSet)) {	//Was it this socket?
611 			currentSocket = (*iter).hSession;  //a hack
612 			if (GetLSCPCommand(iter)) {	//Have we read the entire command?
613 				dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
614                                 int dummy; // just a temporary hack to fulfill the restart() function prototype
615                                 restart(NULL, dummy); // restart the 'scanner'
616 				itCurrentSession = iter; // another hack
617 				dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
618                                 if ((*iter).bVerbose) { // if echo mode enabled
619                                     AnswerClient(bufferedCommands[currentSocket]);
620                                 }
621 				int result = yyparse(&(*iter));
622 				currentSocket = -1;	//continuation of a hack
623 				itCurrentSession = Sessions.end(); // hack as well
624 				dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
625 				if (result == LSCP_QUIT) { //Was it a quit command by any chance?
626 					CloseConnection(iter);
627 				}
628 			}
629 			currentSocket = -1;	//continuation of a hack
630 			//socket may have been closed, iter may be invalid, get out of the loop for now.
631 			//we'll be back if there is data.
632 			break;
633 		}
634 	}
635     }
636 }
637 
CloseConnection(std::vector<yyparse_param_t>::iterator iter)638 void LSCPServer::CloseConnection( std::vector<yyparse_param_t>::iterator iter ) {
639 	int socket = (*iter).hSession;
640 	dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));
641 	LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
642 	Sessions.erase(iter);
643 	FD_CLR(socket,  &fdSet);
644 	{
645             LockGuard lock(SubscriptionMutex);
646             // Must unsubscribe this socket from all events (if any)
647             for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
648                 iter->second.remove(socket);
649             }
650         }
651 	LockGuard lock(NotifyMutex);
652 	bufferedCommands.erase(socket);
653 	bufferedNotifies.erase(socket);
654 	#if defined(WIN32)
655 	closesocket(socket);
656 	#else
657 	close(socket);
658 	#endif
659 }
660 
CloseAllConnections()661 void LSCPServer::CloseAllConnections() {
662     std::vector<yyparse_param_t>::iterator iter = Sessions.begin();
663     while(iter != Sessions.end()) {
664         CloseConnection(iter);
665         iter = Sessions.begin();
666     }
667 }
668 
EventSubscribers(std::list<LSCPEvent::event_t> events)669 int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {
670 	int subs = 0;
671 	LockGuard lock(SubscriptionMutex);
672 	for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();
673 			iter != events.end(); iter++)
674 	{
675 		subs += eventSubscriptions.count(*iter);
676 	}
677 	return subs;
678 }
679 
SendLSCPNotify(LSCPEvent event)680 void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
681 	LockGuard lock(SubscriptionMutex);
682 	if (eventSubscriptions.count(event.GetType()) == 0) {
683 		// Nobody is subscribed to this event
684 		return;
685 	}
686 	std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();
687 	std::list<int>::iterator end = eventSubscriptions[event.GetType()].end();
688 	String notify = event.Produce();
689 
690 	while (true) {
691 		if (NotifyMutex.Trylock()) {
692 			for(;iter != end; iter++)
693 #ifdef MSG_NOSIGNAL
694 				send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
695 #else
696 				send(*iter, notify.c_str(), notify.size(), 0);
697 #endif
698 			NotifyMutex.Unlock();
699 			break;
700 		} else {
701 			if (NotifyBufferMutex.Trylock()) {
702 				for(;iter != end; iter++)
703 					bufferedNotifies[*iter] += notify;
704 				NotifyBufferMutex.Unlock();
705 				break;
706 			}
707 		}
708 	}
709 }
710 
GetLSCPCommand(void * buf,int max_size)711 extern int GetLSCPCommand( void *buf, int max_size ) {
712 	String command = LSCPServer::bufferedCommands[LSCPServer::currentSocket];
713 	if (command.size() == 0) { 		//Parser wants input but we have nothing.
714 		strcpy((char*) buf, "\n"); 	//So give it an empty command
715 		return 1;			//to keep it happy.
716 	}
717 
718 	if (max_size < command.size()) {
719 		std::cerr << "getLSCPCommand: Flex buffer too small, ignoring the command." << std::endl;
720 		return 0;	//This will never happen
721 	}
722 
723 	strcpy((char*) buf, command.c_str());
724 	LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);
725 	return (int) command.size();
726 }
727 
GetCurrentYaccSession()728 extern yyparse_param_t* GetCurrentYaccSession() {
729     return &(*itCurrentSession);
730 }
731 
732 /**
733  * Generate the relevant LSCP documentation reference section if necessary.
734  * The documentation section for the currently active command on the LSCP
735  * shell's command line will be encoded in a special format, specifically for
736  * the LSCP shell application.
737  *
738  * @param line - current LSCP command line
739  * @param param - reentrant Bison parser parameters
740  *
741  * @return encoded reference string or empty string if nothing shall be sent
742  *         to LSCP shell (client) at this point
743  */
generateLSCPDocReply(const String & line,yyparse_param_t * param)744 String LSCPServer::generateLSCPDocReply(const String& line, yyparse_param_t* param) {
745     String result;
746     lscp_ref_entry_t* ref = lscp_reference_for_command(line.c_str());
747     // Pointer comparison works here, since the function above always
748     // returns the same constant pointer for the respective LSCP
749     // command ... Only send the LSCP reference section to the client if
750     // another LSCP reference section became relevant now:
751     if (ref != param->pLSCPDocRef) {
752         param->pLSCPDocRef = ref;
753         if (ref) { // send a new LSCP doc section to client ...
754             result += "SHD:" + ToString(LSCP_SHD_MATCH) + ":" + String(ref->name) + "\n";
755             result += String(ref->section) + "\n";
756             result += "."; // dot line marks the end of the text for client
757         } else { // inform client that no LSCP doc section matches right now ...
758             result = "SHD:" + ToString(LSCP_SHD_NO_MATCH);
759         }
760     }
761     dmsg(4,("LSCP doc reply -> '%s'\n", result.c_str()));
762     return result;
763 }
764 
765 /**
766  * Will be called to try to read the command from the socket
767  * If command is read, it will return true. Otherwise false is returned.
768  * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.
769  */
GetLSCPCommand(std::vector<yyparse_param_t>::iterator iter)770 bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
771 	int socket = (*iter).hSession;
772 	int result;
773 	char c;
774 	std::vector<char> input;
775 
776 	// first get as many character as possible and add it to the 'input' buffer
777 	while (true) {
778 		#if defined(WIN32)
779 		result = (int)recv(socket, (char*)&c, 1, 0); //Read one character at a time for now
780 		#else
781 		result = (int)recv(socket, (void*)&c, 1, 0); //Read one character at a time for now
782 		#endif
783 		if (result == 1) input.push_back(c);
784 		else break; // end of input or some error
785 		if (c == '\n') break; // process line by line
786 	}
787 
788 	// process input buffer
789 	for (int i = 0; i < input.size(); ++i) {
790 		c = input[i];
791 		if (c == '\r') continue; //Ignore CR
792 		if (c == '\n') {
793 			// only if the other side is the LSCP shell application:
794 			// check the current (incomplete) command line for syntax errors,
795 			// possible completions and report everything back to the shell
796 			if ((*iter).bShellInteract || (*iter).bShellAutoCorrect) {
797 				String s = lscpParserProcessShellInteraction(bufferedCommands[socket], &(*iter), false);
798 				if (!s.empty() && (*iter).bShellInteract) AnswerClient(s + "\n");
799 			}
800 			// if other side is LSCP shell application, send the relevant LSCP
801 			// documentation section of the current command line (if necessary)
802 			if ((*iter).bShellSendLSCPDoc && (*iter).bShellInteract) {
803 				String s = generateLSCPDocReply(bufferedCommands[socket], &(*iter));
804 				if (!s.empty()) AnswerClient(s + "\n");
805 			}
806 			LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
807 			bufferedCommands[socket] += "\r\n";
808 			return true; //Complete command was read
809 		} else if (c == 2) { // custom ASCII code usage for moving cursor left (LSCP shell)
810 			if (iter->iCursorOffset + bufferedCommands[socket].size() > 0)
811 				iter->iCursorOffset--;
812 		} else if (c == 3) { // custom ASCII code usage for moving cursor right (LSCP shell)
813 			if (iter->iCursorOffset < 0) iter->iCursorOffset++;
814 		} else {
815 			ssize_t cursorPos = bufferedCommands[socket].size() + iter->iCursorOffset;
816 			// backspace character - should only happen with shell
817 			if (c == '\b') {
818 				if (!bufferedCommands[socket].empty() && cursorPos > 0)
819 					bufferedCommands[socket].erase(cursorPos - 1, 1);
820 			} else { // append (or insert) new character (at current cursor position) ...
821 				if (cursorPos >= 0)
822 					bufferedCommands[socket].insert(cursorPos, String(1,c)); // insert
823 				else
824 					bufferedCommands[socket] += c; // append
825 			}
826 		}
827 		// Only if the other side (client) is the LSCP shell application:
828 		// The following block takes care about automatic correction, auto
829 		// completion (and suggestions), LSCP reference documentation, etc.
830 		// The "if" statement here is for optimization reasons, so that the
831 		// heavy LSCP grammar evaluation algorithm is only executed once for an
832 		// entire command line received.
833 		if (i == input.size() - 1) {
834 			// check the current (incomplete) command line for syntax errors,
835 			// possible completions and report everything back to the shell
836 			if ((*iter).bShellInteract || (*iter).bShellAutoCorrect) {
837 				String s = lscpParserProcessShellInteraction(bufferedCommands[socket], &(*iter), true);
838 				if (!s.empty() && (*iter).bShellInteract && i == input.size() - 1)
839 					AnswerClient(s + "\n");
840 			}
841 			// if other side is LSCP shell application, send the relevant LSCP
842 			// documentation section of the current command line (if necessary)
843 			if ((*iter).bShellSendLSCPDoc && (*iter).bShellInteract) {
844 				String s = generateLSCPDocReply(bufferedCommands[socket], &(*iter));
845 				if (!s.empty()) AnswerClient(s + "\n");
846 			}
847 		}
848 	}
849 
850 	// handle network errors ...
851 	if (result == 0) { //socket was selected, so 0 here means client has closed the connection
852 		CloseConnection(iter);
853 		return false;
854 	}
855 	#if defined(WIN32)
856 	if (result == SOCKET_ERROR) {
857 		int wsa_lasterror = WSAGetLastError();
858 		if (wsa_lasterror == WSAEWOULDBLOCK) //Would block, try again later.
859 			return false;
860 		dmsg(2,("LSCPScanner: Socket error after recv() Error %d.\n", wsa_lasterror));
861 		CloseConnection(iter);
862 		return false;
863 	}
864 	#else
865 	if (result == -1) {
866 		switch(errno) {
867 			case EBADF:
868 				dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
869 				break; // close connection
870 			case ECONNREFUSED:
871 				dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
872 				break; // close connection
873 			case ENOTCONN:
874 				dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
875 				break; // close connection
876 			case ENOTSOCK:
877 				dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
878 				break; // close connection
879 			case EAGAIN:
880 				dmsg(2,("LSCPScanner: The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.\n"));
881 				return false; // don't close connection, try again later
882 			case EINTR:
883 				dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
884 				break; // close connection
885 			case EFAULT:
886 				dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
887 				break; // close connection
888 			case EINVAL:
889 				dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
890 				break; // close connection
891 			case ENOMEM:
892 				dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
893 				break; // close connection
894 			default:
895 				dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
896 				break; // close connection
897 		}
898 		CloseConnection(iter);
899 		return false;
900 	}
901 	#endif
902 
903 	return false;
904 }
905 
906 /**
907  * Will be called by the parser whenever it wants to send an answer to the
908  * client / frontend.
909  *
910  * @param ReturnMessage - message that will be send to the client
911  */
AnswerClient(String ReturnMessage)912 void LSCPServer::AnswerClient(String ReturnMessage) {
913     dmsg(2,("LSCPServer::AnswerClient(ReturnMessage='%s')", ReturnMessage.c_str()));
914     if (currentSocket != -1) {
915 	    LockGuard lock(NotifyMutex);
916 
917         // just if other side is LSCP shell: in case respose is a multi-line
918         // one, then inform client about it before sending the actual mult-line
919         // response
920         if (GetCurrentYaccSession()->bShellInteract) {
921             // check if this is a multi-line response
922             int n = 0;
923             for (int i = 0; i < ReturnMessage.size(); ++i)
924                 if (ReturnMessage[i] == '\n') ++n;
925             if (n >= 2) {
926                 dmsg(2,("LSCP Shell <- expect mult-line response\n"));
927                 String s = LSCP_SHK_EXPECT_MULTI_LINE "\r\n";
928 #ifdef MSG_NOSIGNAL
929                 send(currentSocket, s.c_str(), s.size(), MSG_NOSIGNAL);
930 #else
931                 send(currentSocket, s.c_str(), s.size(), 0);
932 #endif
933             }
934         }
935 
936 #ifdef MSG_NOSIGNAL
937 	    send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
938 #else
939 	    send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
940 #endif
941     }
942 }
943 
944 /**
945  * Find a created audio output device index.
946  */
GetAudioOutputDeviceIndex(AudioOutputDevice * pDevice)947 int LSCPServer::GetAudioOutputDeviceIndex ( AudioOutputDevice *pDevice )
948 {
949     // Search for the created device to get its index
950     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
951     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
952     for (; iter != devices.end(); iter++) {
953         if (iter->second == pDevice)
954             return iter->first;
955     }
956     // Not found.
957     return -1;
958 }
959 
960 /**
961  * Find a created midi input device index.
962  */
GetMidiInputDeviceIndex(MidiInputDevice * pDevice)963 int LSCPServer::GetMidiInputDeviceIndex ( MidiInputDevice *pDevice )
964 {
965     // Search for the created device to get its index
966     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
967     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
968     for (; iter != devices.end(); iter++) {
969         if (iter->second == pDevice)
970             return iter->first;
971     }
972     // Not found.
973     return -1;
974 }
975 
CreateAudioOutputDevice(String Driver,std::map<String,String> Parameters)976 String LSCPServer::CreateAudioOutputDevice(String Driver, std::map<String,String> Parameters) {
977     dmsg(2,("LSCPServer: CreateAudioOutputDevice(Driver=%s)\n", Driver.c_str()));
978     LSCPResultSet result;
979     try {
980         AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
981         // search for the created device to get its index
982         int index = GetAudioOutputDeviceIndex(pDevice);
983         if (index == -1) throw Exception("Internal error: could not find created audio output device.");
984         result = index; // success
985     }
986     catch (Exception e) {
987         result.Error(e);
988     }
989     return result.Produce();
990 }
991 
CreateMidiInputDevice(String Driver,std::map<String,String> Parameters)992 String LSCPServer::CreateMidiInputDevice(String Driver, std::map<String,String> Parameters) {
993     dmsg(2,("LSCPServer: CreateMidiInputDevice(Driver=%s)\n", Driver.c_str()));
994     LSCPResultSet result;
995     try {
996         MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
997         // search for the created device to get its index
998         int index = GetMidiInputDeviceIndex(pDevice);
999         if (index == -1) throw Exception("Internal error: could not find created midi input device.");
1000         result = index; // success
1001     }
1002     catch (Exception e) {
1003         result.Error(e);
1004     }
1005     return result.Produce();
1006 }
1007 
DestroyAudioOutputDevice(uint DeviceIndex)1008 String LSCPServer::DestroyAudioOutputDevice(uint DeviceIndex) {
1009     dmsg(2,("LSCPServer: DestroyAudioOutputDevice(DeviceIndex=%d)\n", DeviceIndex));
1010     LSCPResultSet result;
1011     try {
1012         std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1013         if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1014         AudioOutputDevice* pDevice = devices[DeviceIndex];
1015         pSampler->DestroyAudioOutputDevice(pDevice);
1016     }
1017     catch (Exception e) {
1018         result.Error(e);
1019     }
1020     return result.Produce();
1021 }
1022 
DestroyMidiInputDevice(uint DeviceIndex)1023 String LSCPServer::DestroyMidiInputDevice(uint DeviceIndex) {
1024     dmsg(2,("LSCPServer: DestroyMidiInputDevice(DeviceIndex=%d)\n", DeviceIndex));
1025     LSCPResultSet result;
1026     try {
1027         std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1028         if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1029         MidiInputDevice* pDevice = devices[DeviceIndex];
1030         pSampler->DestroyMidiInputDevice(pDevice);
1031     }
1032     catch (Exception e) {
1033         result.Error(e);
1034     }
1035     return result.Produce();
1036 }
1037 
GetEngineChannel(uint uiSamplerChannel)1038 EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
1039     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1040     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1041 
1042     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1043     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1044 
1045     return pEngineChannel;
1046 }
1047 
1048 /**
1049  * Will be called by the parser to load an instrument.
1050  */
LoadInstrument(String Filename,uint uiInstrument,uint uiSamplerChannel,bool bBackground)1051 String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel, bool bBackground) {
1052     dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
1053     LSCPResultSet result;
1054     try {
1055         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1056         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1057         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1058         if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
1059         if (!pSamplerChannel->GetAudioOutputDevice())
1060             throw Exception("No audio output device connected to sampler channel");
1061         if (bBackground) {
1062             InstrumentManager::instrument_id_t id;
1063             id.FileName = Filename;
1064             id.Index    = uiInstrument;
1065             InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
1066         }
1067         else {
1068             // tell the engine channel which instrument to load
1069             pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrument);
1070             // actually start to load the instrument (blocks until completed)
1071             pEngineChannel->LoadInstrument();
1072         }
1073     }
1074     catch (Exception e) {
1075          result.Error(e);
1076     }
1077     return result.Produce();
1078 }
1079 
1080 /**
1081  * Will be called by the parser to assign a sampler engine type to a
1082  * sampler channel.
1083  */
SetEngineType(String EngineName,uint uiSamplerChannel)1084 String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
1085     dmsg(2,("LSCPServer: SetEngineType(EngineName=%s,uiSamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
1086     LSCPResultSet result;
1087     try {
1088         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1089         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1090 	LockGuard lock(RTNotifyMutex);
1091         pSamplerChannel->SetEngineType(EngineName);
1092         if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
1093     }
1094     catch (Exception e) {
1095          result.Error(e);
1096     }
1097     return result.Produce();
1098 }
1099 
1100 /**
1101  * Will be called by the parser to get the amount of sampler channels.
1102  */
GetChannels()1103 String LSCPServer::GetChannels() {
1104     dmsg(2,("LSCPServer: GetChannels()\n"));
1105     LSCPResultSet result;
1106     result.Add(pSampler->SamplerChannels());
1107     return result.Produce();
1108 }
1109 
1110 /**
1111  * Will be called by the parser to get the list of sampler channels.
1112  */
ListChannels()1113 String LSCPServer::ListChannels() {
1114     dmsg(2,("LSCPServer: ListChannels()\n"));
1115     String list;
1116     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1117     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1118     for (; iter != channels.end(); iter++) {
1119         if (list != "") list += ",";
1120         list += ToString(iter->first);
1121     }
1122     LSCPResultSet result;
1123     result.Add(list);
1124     return result.Produce();
1125 }
1126 
1127 /**
1128  * Will be called by the parser to add a sampler channel.
1129  */
AddChannel()1130 String LSCPServer::AddChannel() {
1131     dmsg(2,("LSCPServer: AddChannel()\n"));
1132     SamplerChannel* pSamplerChannel;
1133     {
1134         LockGuard lock(RTNotifyMutex);
1135         pSamplerChannel = pSampler->AddSamplerChannel();
1136     }
1137     LSCPResultSet result(pSamplerChannel->Index());
1138     return result.Produce();
1139 }
1140 
1141 /**
1142  * Will be called by the parser to remove a sampler channel.
1143  */
RemoveChannel(uint uiSamplerChannel)1144 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
1145     dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
1146     LSCPResultSet result;
1147     {
1148         LockGuard lock(RTNotifyMutex);
1149         pSampler->RemoveSamplerChannel(uiSamplerChannel);
1150     }
1151     return result.Produce();
1152 }
1153 
1154 /**
1155  * Will be called by the parser to get the amount of all available engines.
1156  */
GetAvailableEngines()1157 String LSCPServer::GetAvailableEngines() {
1158     dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
1159     LSCPResultSet result;
1160     try {
1161         int n = (int)EngineFactory::AvailableEngineTypes().size();
1162         result.Add(n);
1163     }
1164     catch (Exception e) {
1165         result.Error(e);
1166     }
1167     return result.Produce();
1168 }
1169 
1170 /**
1171  * Will be called by the parser to get a list of all available engines.
1172  */
ListAvailableEngines()1173 String LSCPServer::ListAvailableEngines() {
1174     dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
1175     LSCPResultSet result;
1176     try {
1177         String s = EngineFactory::AvailableEngineTypesAsString();
1178         result.Add(s);
1179     }
1180     catch (Exception e) {
1181         result.Error(e);
1182     }
1183     return result.Produce();
1184 }
1185 
1186 /**
1187  * Will be called by the parser to get descriptions for a particular
1188  * sampler engine.
1189  */
GetEngineInfo(String EngineName)1190 String LSCPServer::GetEngineInfo(String EngineName) {
1191     dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
1192     LSCPResultSet result;
1193     {
1194         LockGuard lock(RTNotifyMutex);
1195         try {
1196             Engine* pEngine = EngineFactory::Create(EngineName);
1197             result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
1198             result.Add("VERSION",     pEngine->Version());
1199             EngineFactory::Destroy(pEngine);
1200         }
1201         catch (Exception e) {
1202             result.Error(e);
1203         }
1204     }
1205     return result.Produce();
1206 }
1207 
1208 /**
1209  * Will be called by the parser to get informations about a particular
1210  * sampler channel.
1211  */
GetChannelInfo(uint uiSamplerChannel)1212 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
1213     dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
1214     LSCPResultSet result;
1215     try {
1216         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1217         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1218         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1219 
1220 	//Defaults values
1221 	String EngineName = "NONE";
1222         float Volume = 0.0f;
1223 	String InstrumentFileName = "NONE";
1224 	String InstrumentName = "NONE";
1225 	int InstrumentIndex = -1;
1226 	int InstrumentStatus = -1;
1227         int AudioOutputChannels = 0;
1228         String AudioRouting;
1229         int Mute = 0;
1230         bool Solo = false;
1231         String MidiInstrumentMap = "NONE";
1232 
1233         if (pEngineChannel) {
1234             EngineName          = pEngineChannel->EngineName();
1235             AudioOutputChannels = pEngineChannel->Channels();
1236             Volume              = pEngineChannel->Volume();
1237             InstrumentStatus    = pEngineChannel->InstrumentStatus();
1238             InstrumentIndex     = pEngineChannel->InstrumentIndex();
1239             if (InstrumentIndex != -1) {
1240                 InstrumentFileName = pEngineChannel->InstrumentFileName();
1241                 InstrumentName     = pEngineChannel->InstrumentName();
1242             }
1243             for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
1244                 if (AudioRouting != "") AudioRouting += ",";
1245                 AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
1246             }
1247             Mute = pEngineChannel->GetMute();
1248             Solo = pEngineChannel->GetSolo();
1249             if (pEngineChannel->UsesNoMidiInstrumentMap())
1250                 MidiInstrumentMap = "NONE";
1251             else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
1252                 MidiInstrumentMap = "DEFAULT";
1253             else
1254                 MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
1255 	}
1256 
1257         result.Add("ENGINE_NAME", EngineName);
1258         result.Add("VOLUME", Volume);
1259 
1260 	//Some not-so-hardcoded stuff to make GUI look good
1261         result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
1262         result.Add("AUDIO_OUTPUT_CHANNELS", AudioOutputChannels);
1263         result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
1264 
1265         result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
1266         result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
1267         if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
1268         else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
1269 
1270         // convert the filename into the correct encoding as defined for LSCP
1271         // (especially in terms of special characters -> escape sequences)
1272         if (InstrumentFileName != "NONE" && InstrumentFileName != "") {
1273 #if WIN32
1274             InstrumentFileName = Path::fromWindows(InstrumentFileName).toLscp();
1275 #else
1276             // assuming POSIX
1277             InstrumentFileName = Path::fromPosix(InstrumentFileName).toLscp();
1278 #endif
1279         }
1280 
1281         result.Add("INSTRUMENT_FILE", InstrumentFileName);
1282         result.Add("INSTRUMENT_NR", InstrumentIndex);
1283         result.Add("INSTRUMENT_NAME", _escapeLscpResponse(InstrumentName));
1284         result.Add("INSTRUMENT_STATUS", InstrumentStatus);
1285         result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
1286         result.Add("SOLO", Solo);
1287         result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
1288     }
1289     catch (Exception e) {
1290          result.Error(e);
1291     }
1292     return result.Produce();
1293 }
1294 
1295 /**
1296  * Will be called by the parser to get the amount of active voices on a
1297  * particular sampler channel.
1298  */
GetVoiceCount(uint uiSamplerChannel)1299 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
1300     dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
1301     LSCPResultSet result;
1302     try {
1303         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1304         if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1305 	result.Add(pEngineChannel->GetEngine()->VoiceCount());
1306     }
1307     catch (Exception e) {
1308          result.Error(e);
1309     }
1310     return result.Produce();
1311 }
1312 
1313 /**
1314  * Will be called by the parser to get the amount of active disk streams on a
1315  * particular sampler channel.
1316  */
GetStreamCount(uint uiSamplerChannel)1317 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
1318     dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
1319     LSCPResultSet result;
1320     try {
1321         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1322         if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1323         result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
1324     }
1325     catch (Exception e) {
1326          result.Error(e);
1327     }
1328     return result.Produce();
1329 }
1330 
1331 /**
1332  * Will be called by the parser to get the buffer fill states of all disk
1333  * streams on a particular sampler channel.
1334  */
GetBufferFill(fill_response_t ResponseType,uint uiSamplerChannel)1335 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
1336     dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
1337     LSCPResultSet result;
1338     try {
1339         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1340         if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1341         if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
1342         else {
1343             switch (ResponseType) {
1344                 case fill_response_bytes:
1345                     result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillBytes());
1346                     break;
1347                 case fill_response_percentage:
1348                     result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
1349                     break;
1350                 default:
1351                     throw Exception("Unknown fill response type");
1352             }
1353 	}
1354     }
1355     catch (Exception e) {
1356          result.Error(e);
1357     }
1358     return result.Produce();
1359 }
1360 
GetAvailableAudioOutputDrivers()1361 String LSCPServer::GetAvailableAudioOutputDrivers() {
1362     dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
1363     LSCPResultSet result;
1364     try {
1365         int n = (int) AudioOutputDeviceFactory::AvailableDrivers().size();
1366         result.Add(n);
1367     }
1368     catch (Exception e) {
1369         result.Error(e);
1370     }
1371     return result.Produce();
1372 }
1373 
ListAvailableAudioOutputDrivers()1374 String LSCPServer::ListAvailableAudioOutputDrivers() {
1375     dmsg(2,("LSCPServer: ListAvailableAudioOutputDrivers()\n"));
1376     LSCPResultSet result;
1377     try {
1378         String s = AudioOutputDeviceFactory::AvailableDriversAsString();
1379         result.Add(s);
1380     }
1381     catch (Exception e) {
1382         result.Error(e);
1383     }
1384     return result.Produce();
1385 }
1386 
GetAvailableMidiInputDrivers()1387 String LSCPServer::GetAvailableMidiInputDrivers() {
1388     dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
1389     LSCPResultSet result;
1390     try {
1391         int n = (int)MidiInputDeviceFactory::AvailableDrivers().size();
1392         result.Add(n);
1393     }
1394     catch (Exception e) {
1395         result.Error(e);
1396     }
1397     return result.Produce();
1398 }
1399 
ListAvailableMidiInputDrivers()1400 String LSCPServer::ListAvailableMidiInputDrivers() {
1401     dmsg(2,("LSCPServer: ListAvailableMidiInputDrivers()\n"));
1402     LSCPResultSet result;
1403     try {
1404         String s = MidiInputDeviceFactory::AvailableDriversAsString();
1405         result.Add(s);
1406     }
1407     catch (Exception e) {
1408         result.Error(e);
1409     }
1410     return result.Produce();
1411 }
1412 
GetMidiInputDriverInfo(String Driver)1413 String LSCPServer::GetMidiInputDriverInfo(String Driver) {
1414     dmsg(2,("LSCPServer: GetMidiInputDriverInfo(Driver=%s)\n",Driver.c_str()));
1415     LSCPResultSet result;
1416     try {
1417         result.Add("DESCRIPTION", MidiInputDeviceFactory::GetDriverDescription(Driver));
1418         result.Add("VERSION",     MidiInputDeviceFactory::GetDriverVersion(Driver));
1419 
1420         std::map<String,DeviceCreationParameter*> parameters = MidiInputDeviceFactory::GetAvailableDriverParameters(Driver);
1421         if (parameters.size()) { // if there are parameters defined for this driver
1422             String s;
1423             std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1424             for (;iter != parameters.end(); iter++) {
1425                 if (s != "") s += ",";
1426                 s += iter->first;
1427                 delete iter->second;
1428             }
1429             result.Add("PARAMETERS", s);
1430         }
1431     }
1432     catch (Exception e) {
1433         result.Error(e);
1434     }
1435     return result.Produce();
1436 }
1437 
GetAudioOutputDriverInfo(String Driver)1438 String LSCPServer::GetAudioOutputDriverInfo(String Driver) {
1439     dmsg(2,("LSCPServer: GetAudioOutputDriverInfo(Driver=%s)\n",Driver.c_str()));
1440     LSCPResultSet result;
1441     try {
1442         result.Add("DESCRIPTION", AudioOutputDeviceFactory::GetDriverDescription(Driver));
1443         result.Add("VERSION",     AudioOutputDeviceFactory::GetDriverVersion(Driver));
1444 
1445         std::map<String,DeviceCreationParameter*> parameters = AudioOutputDeviceFactory::GetAvailableDriverParameters(Driver);
1446         if (parameters.size()) { // if there are parameters defined for this driver
1447             String s;
1448             std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1449             for (;iter != parameters.end(); iter++) {
1450                 if (s != "") s += ",";
1451                 s += iter->first;
1452                 delete iter->second;
1453             }
1454             result.Add("PARAMETERS", s);
1455         }
1456     }
1457     catch (Exception e) {
1458         result.Error(e);
1459     }
1460     return result.Produce();
1461 }
1462 
GetMidiInputDriverParameterInfo(String Driver,String Parameter,std::map<String,String> DependencyList)1463 String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1464     dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),int(DependencyList.size())));
1465     LSCPResultSet result;
1466     try {
1467         DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
1468         result.Add("TYPE",         pParameter->Type());
1469         result.Add("DESCRIPTION",  pParameter->Description());
1470         result.Add("MANDATORY",    pParameter->Mandatory());
1471         result.Add("FIX",          pParameter->Fix());
1472         result.Add("MULTIPLICITY", pParameter->Multiplicity());
1473         optional<String> oDepends       = pParameter->Depends();
1474         optional<String> oDefault       = pParameter->Default(DependencyList);
1475         optional<String> oRangeMin      = pParameter->RangeMin(DependencyList);
1476         optional<String> oRangeMax      = pParameter->RangeMax(DependencyList);
1477         optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1478         if (oDepends)       result.Add("DEPENDS",       *oDepends);
1479         if (oDefault)       result.Add("DEFAULT",       *oDefault);
1480         if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1481         if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1482         if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1483         delete pParameter;
1484     }
1485     catch (Exception e) {
1486         result.Error(e);
1487     }
1488     return result.Produce();
1489 }
1490 
GetAudioOutputDriverParameterInfo(String Driver,String Parameter,std::map<String,String> DependencyList)1491 String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1492     dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),int(DependencyList.size())));
1493     LSCPResultSet result;
1494     try {
1495         DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
1496         result.Add("TYPE",         pParameter->Type());
1497         result.Add("DESCRIPTION",  pParameter->Description());
1498         result.Add("MANDATORY",    pParameter->Mandatory());
1499         result.Add("FIX",          pParameter->Fix());
1500         result.Add("MULTIPLICITY", pParameter->Multiplicity());
1501         optional<String> oDepends       = pParameter->Depends();
1502         optional<String> oDefault       = pParameter->Default(DependencyList);
1503         optional<String> oRangeMin      = pParameter->RangeMin(DependencyList);
1504         optional<String> oRangeMax      = pParameter->RangeMax(DependencyList);
1505         optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1506         if (oDepends)       result.Add("DEPENDS",       *oDepends);
1507         if (oDefault)       result.Add("DEFAULT",       *oDefault);
1508         if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1509         if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1510         if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1511         delete pParameter;
1512     }
1513     catch (Exception e) {
1514         result.Error(e);
1515     }
1516     return result.Produce();
1517 }
1518 
GetAudioOutputDeviceCount()1519 String LSCPServer::GetAudioOutputDeviceCount() {
1520     dmsg(2,("LSCPServer: GetAudioOutputDeviceCount()\n"));
1521     LSCPResultSet result;
1522     try {
1523         uint count = pSampler->AudioOutputDevices();
1524         result.Add(count); // success
1525     }
1526     catch (Exception e) {
1527         result.Error(e);
1528     }
1529     return result.Produce();
1530 }
1531 
GetMidiInputDeviceCount()1532 String LSCPServer::GetMidiInputDeviceCount() {
1533     dmsg(2,("LSCPServer: GetMidiInputDeviceCount()\n"));
1534     LSCPResultSet result;
1535     try {
1536         uint count = pSampler->MidiInputDevices();
1537         result.Add(count); // success
1538     }
1539     catch (Exception e) {
1540         result.Error(e);
1541     }
1542     return result.Produce();
1543 }
1544 
GetAudioOutputDevices()1545 String LSCPServer::GetAudioOutputDevices() {
1546     dmsg(2,("LSCPServer: GetAudioOutputDevices()\n"));
1547     LSCPResultSet result;
1548     try {
1549         String s;
1550         std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1551         std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1552         for (; iter != devices.end(); iter++) {
1553             if (s != "") s += ",";
1554             s += ToString(iter->first);
1555         }
1556         result.Add(s);
1557     }
1558     catch (Exception e) {
1559         result.Error(e);
1560     }
1561     return result.Produce();
1562 }
1563 
GetMidiInputDevices()1564 String LSCPServer::GetMidiInputDevices() {
1565     dmsg(2,("LSCPServer: GetMidiInputDevices()\n"));
1566     LSCPResultSet result;
1567     try {
1568         String s;
1569         std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1570         std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1571         for (; iter != devices.end(); iter++) {
1572             if (s != "") s += ",";
1573             s += ToString(iter->first);
1574         }
1575         result.Add(s);
1576     }
1577     catch (Exception e) {
1578         result.Error(e);
1579     }
1580     return result.Produce();
1581 }
1582 
GetAudioOutputDeviceInfo(uint DeviceIndex)1583 String LSCPServer::GetAudioOutputDeviceInfo(uint DeviceIndex) {
1584     dmsg(2,("LSCPServer: GetAudioOutputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1585     LSCPResultSet result;
1586     try {
1587         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1588         if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1589         AudioOutputDevice* pDevice = devices[DeviceIndex];
1590         result.Add("DRIVER", pDevice->Driver());
1591         std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1592         std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1593         for (; iter != parameters.end(); iter++) {
1594             result.Add(iter->first, iter->second->Value());
1595         }
1596     }
1597     catch (Exception e) {
1598         result.Error(e);
1599     }
1600     return result.Produce();
1601 }
1602 
GetMidiInputDeviceInfo(uint DeviceIndex)1603 String LSCPServer::GetMidiInputDeviceInfo(uint DeviceIndex) {
1604     dmsg(2,("LSCPServer: GetMidiInputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1605     LSCPResultSet result;
1606     try {
1607         std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1608         if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1609         MidiInputDevice* pDevice = devices[DeviceIndex];
1610         result.Add("DRIVER", pDevice->Driver());
1611         std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1612         std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1613         for (; iter != parameters.end(); iter++) {
1614             result.Add(iter->first, iter->second->Value());
1615         }
1616     }
1617     catch (Exception e) {
1618         result.Error(e);
1619     }
1620     return result.Produce();
1621 }
GetMidiInputPortInfo(uint DeviceIndex,uint PortIndex)1622 String LSCPServer::GetMidiInputPortInfo(uint DeviceIndex, uint PortIndex) {
1623     dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
1624     LSCPResultSet result;
1625     try {
1626         // get MIDI input device
1627         std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1628         if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1629         MidiInputDevice* pDevice = devices[DeviceIndex];
1630 
1631         // get MIDI port
1632         MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1633         if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1634 
1635         // return the values of all MIDI port parameters
1636         std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1637         std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1638         for (; iter != parameters.end(); iter++) {
1639             result.Add(iter->first, iter->second->Value());
1640         }
1641     }
1642     catch (Exception e) {
1643         result.Error(e);
1644     }
1645     return result.Produce();
1646 }
1647 
GetAudioOutputChannelInfo(uint DeviceId,uint ChannelId)1648 String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
1649     dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%u,ChannelId=%u)\n",DeviceId,ChannelId));
1650     LSCPResultSet result;
1651     try {
1652         // get audio output device
1653         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1654         if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1655         AudioOutputDevice* pDevice = devices[DeviceId];
1656 
1657         // get audio channel
1658         AudioChannel* pChannel = pDevice->Channel(ChannelId);
1659         if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1660 
1661         // return the values of all audio channel parameters
1662         std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1663         std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1664         for (; iter != parameters.end(); iter++) {
1665             result.Add(iter->first, iter->second->Value());
1666         }
1667     }
1668     catch (Exception e) {
1669         result.Error(e);
1670     }
1671     return result.Produce();
1672 }
1673 
GetMidiInputPortParameterInfo(uint DeviceId,uint PortId,String ParameterName)1674 String LSCPServer::GetMidiInputPortParameterInfo(uint DeviceId, uint PortId, String ParameterName) {
1675     dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
1676     LSCPResultSet result;
1677     try {
1678         // get MIDI input device
1679         std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1680         if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1681         MidiInputDevice* pDevice = devices[DeviceId];
1682 
1683         // get midi port
1684         MidiInputPort* pPort = pDevice->GetPort(PortId);
1685         if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1686 
1687         // get desired port parameter
1688         std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1689         if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1690         DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1691 
1692         // return all fields of this audio channel parameter
1693         result.Add("TYPE",         pParameter->Type());
1694         result.Add("DESCRIPTION",  pParameter->Description());
1695         result.Add("FIX",          pParameter->Fix());
1696         result.Add("MULTIPLICITY", pParameter->Multiplicity());
1697         if (pParameter->RangeMin())      result.Add("RANGE_MIN",     *pParameter->RangeMin());
1698         if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1699         if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1700     }
1701     catch (Exception e) {
1702         result.Error(e);
1703     }
1704     return result.Produce();
1705 }
1706 
GetAudioOutputChannelParameterInfo(uint DeviceId,uint ChannelId,String ParameterName)1707 String LSCPServer::GetAudioOutputChannelParameterInfo(uint DeviceId, uint ChannelId, String ParameterName) {
1708     dmsg(2,("LSCPServer: GetAudioOutputChannelParameterInfo(DeviceId=%d,ChannelId=%d,ParameterName=%s)\n",DeviceId,ChannelId,ParameterName.c_str()));
1709     LSCPResultSet result;
1710     try {
1711         // get audio output device
1712         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1713         if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1714         AudioOutputDevice* pDevice = devices[DeviceId];
1715 
1716         // get audio channel
1717         AudioChannel* pChannel = pDevice->Channel(ChannelId);
1718         if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1719 
1720         // get desired audio channel parameter
1721         std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1722         if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1723         DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1724 
1725         // return all fields of this audio channel parameter
1726         result.Add("TYPE",         pParameter->Type());
1727         result.Add("DESCRIPTION",  pParameter->Description());
1728         result.Add("FIX",          pParameter->Fix());
1729         result.Add("MULTIPLICITY", pParameter->Multiplicity());
1730         if (pParameter->RangeMin())      result.Add("RANGE_MIN",     *pParameter->RangeMin());
1731         if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1732         if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1733     }
1734     catch (Exception e) {
1735         result.Error(e);
1736     }
1737     return result.Produce();
1738 }
1739 
SetAudioOutputChannelParameter(uint DeviceId,uint ChannelId,String ParamKey,String ParamVal)1740 String LSCPServer::SetAudioOutputChannelParameter(uint DeviceId, uint ChannelId, String ParamKey, String ParamVal) {
1741     dmsg(2,("LSCPServer: SetAudioOutputChannelParameter(DeviceId=%d,ChannelId=%d,ParamKey=%s,ParamVal=%s)\n",DeviceId,ChannelId,ParamKey.c_str(),ParamVal.c_str()));
1742     LSCPResultSet result;
1743     try {
1744         // get audio output device
1745         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1746         if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1747         AudioOutputDevice* pDevice = devices[DeviceId];
1748 
1749         // get audio channel
1750         AudioChannel* pChannel = pDevice->Channel(ChannelId);
1751         if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1752 
1753         // get desired audio channel parameter
1754         std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1755         if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1756         DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1757 
1758         // set new channel parameter value
1759         pParameter->SetValue(ParamVal);
1760         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1761     }
1762     catch (Exception e) {
1763         result.Error(e);
1764     }
1765     return result.Produce();
1766 }
1767 
SetAudioOutputDeviceParameter(uint DeviceIndex,String ParamKey,String ParamVal)1768 String LSCPServer::SetAudioOutputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1769     dmsg(2,("LSCPServer: SetAudioOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1770     LSCPResultSet result;
1771     try {
1772         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1773         if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1774         AudioOutputDevice* pDevice = devices[DeviceIndex];
1775         std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1776         if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1777         parameters[ParamKey]->SetValue(ParamVal);
1778         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1779     }
1780     catch (Exception e) {
1781         result.Error(e);
1782     }
1783     return result.Produce();
1784 }
1785 
SetMidiInputDeviceParameter(uint DeviceIndex,String ParamKey,String ParamVal)1786 String LSCPServer::SetMidiInputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1787     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1788     LSCPResultSet result;
1789     try {
1790         std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1791         if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1792         MidiInputDevice* pDevice = devices[DeviceIndex];
1793         std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1794         if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1795         parameters[ParamKey]->SetValue(ParamVal);
1796         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1797     }
1798     catch (Exception e) {
1799         result.Error(e);
1800     }
1801     return result.Produce();
1802 }
1803 
SetMidiInputPortParameter(uint DeviceIndex,uint PortIndex,String ParamKey,String ParamVal)1804 String LSCPServer::SetMidiInputPortParameter(uint DeviceIndex, uint PortIndex, String ParamKey, String ParamVal) {
1805     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1806     LSCPResultSet result;
1807     try {
1808         // get MIDI input device
1809         std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1810         if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1811         MidiInputDevice* pDevice = devices[DeviceIndex];
1812 
1813         // get MIDI port
1814         MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1815         if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1816 
1817         // set port parameter value
1818         std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1819         if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1820         parameters[ParamKey]->SetValue(ParamVal);
1821         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1822     }
1823     catch (Exception e) {
1824         result.Error(e);
1825     }
1826     return result.Produce();
1827 }
1828 
1829 /**
1830  * Will be called by the parser to change the audio output channel for
1831  * playback on a particular sampler channel.
1832  */
SetAudioOutputChannel(uint ChannelAudioOutputChannel,uint AudioOutputDeviceInputChannel,uint uiSamplerChannel)1833 String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1834     dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1835     LSCPResultSet result;
1836     try {
1837         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1838         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1839         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1840         if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1841         if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1842         pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1843     }
1844     catch (Exception e) {
1845          result.Error(e);
1846     }
1847     return result.Produce();
1848 }
1849 
SetAudioOutputDevice(uint AudioDeviceId,uint uiSamplerChannel)1850 String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1851     dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1852     LSCPResultSet result;
1853     {
1854         LockGuard lock(RTNotifyMutex);
1855         try {
1856             SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1857             if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1858             std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1859             if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1860             AudioOutputDevice* pDevice = devices[AudioDeviceId];
1861             pSamplerChannel->SetAudioOutputDevice(pDevice);
1862         }
1863         catch (Exception e) {
1864             result.Error(e);
1865         }
1866     }
1867     return result.Produce();
1868 }
1869 
SetAudioOutputType(String AudioOutputDriver,uint uiSamplerChannel)1870 String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1871     dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1872     LSCPResultSet result;
1873     {
1874         LockGuard lock(RTNotifyMutex);
1875         try {
1876             SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1877             if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1878             // Driver type name aliasing...
1879             if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1880             if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1881             // Check if there's one audio output device already created
1882             // for the intended audio driver type (AudioOutputDriver)...
1883             AudioOutputDevice *pDevice = NULL;
1884             std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1885             std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1886             for (; iter != devices.end(); iter++) {
1887                 if ((iter->second)->Driver() == AudioOutputDriver) {
1888                     pDevice = iter->second;
1889                     break;
1890                 }
1891             }
1892             // If it doesn't exist, create a new one with default parameters...
1893             if (pDevice == NULL) {
1894                 std::map<String,String> params;
1895                 pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1896             }
1897             // Must have a device...
1898             if (pDevice == NULL)
1899                 throw Exception("Internal error: could not create audio output device.");
1900             // Set it as the current channel device...
1901             pSamplerChannel->SetAudioOutputDevice(pDevice);
1902         }
1903         catch (Exception e) {
1904             result.Error(e);
1905         }
1906     }
1907     return result.Produce();
1908 }
1909 
AddChannelMidiInput(uint uiSamplerChannel,uint MIDIDeviceId,uint MIDIPort)1910 String LSCPServer::AddChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId, uint MIDIPort) {
1911     dmsg(2,("LSCPServer: AddChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d, MIDIPort=%d)\n",uiSamplerChannel,MIDIDeviceId,MIDIPort));
1912     LSCPResultSet result;
1913     try {
1914         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1915         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1916 
1917         std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1918         if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1919         MidiInputDevice* pDevice = devices[MIDIDeviceId];
1920 
1921         MidiInputPort* pPort = pDevice->GetPort(MIDIPort);
1922         if (!pPort) throw Exception("There is no MIDI input port with index " + ToString(MIDIPort) + " on MIDI input device with index " + ToString(MIDIDeviceId));
1923 
1924         pSamplerChannel->Connect(pPort);
1925     } catch (Exception e) {
1926         result.Error(e);
1927     }
1928     return result.Produce();
1929 }
1930 
RemoveChannelMidiInput(uint uiSamplerChannel)1931 String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel) {
1932     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d)\n",uiSamplerChannel));
1933     LSCPResultSet result;
1934     try {
1935         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1936         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1937         pSamplerChannel->DisconnectAllMidiInputPorts();
1938     } catch (Exception e) {
1939         result.Error(e);
1940     }
1941     return result.Produce();
1942 }
1943 
RemoveChannelMidiInput(uint uiSamplerChannel,uint MIDIDeviceId)1944 String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId) {
1945     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d)\n",uiSamplerChannel,MIDIDeviceId));
1946     LSCPResultSet result;
1947     try {
1948         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1949         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1950 
1951         std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1952         if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1953         MidiInputDevice* pDevice = devices[MIDIDeviceId];
1954 
1955         std::vector<MidiInputPort*> vPorts = pSamplerChannel->GetMidiInputPorts();
1956         for (int i = 0; i < vPorts.size(); ++i)
1957             if (vPorts[i]->GetDevice() == pDevice)
1958                 pSamplerChannel->Disconnect(vPorts[i]);
1959 
1960     } catch (Exception e) {
1961         result.Error(e);
1962     }
1963     return result.Produce();
1964 }
1965 
RemoveChannelMidiInput(uint uiSamplerChannel,uint MIDIDeviceId,uint MIDIPort)1966 String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId, uint MIDIPort) {
1967     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d, MIDIPort=%d)\n",uiSamplerChannel,MIDIDeviceId,MIDIPort));
1968     LSCPResultSet result;
1969     try {
1970         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1971         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1972 
1973         std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1974         if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1975         MidiInputDevice* pDevice = devices[MIDIDeviceId];
1976 
1977         MidiInputPort* pPort = pDevice->GetPort(MIDIPort);
1978         if (!pPort) throw Exception("There is no MIDI input port with index " + ToString(MIDIPort) + " on MIDI input device with index " + ToString(MIDIDeviceId));
1979 
1980         pSamplerChannel->Disconnect(pPort);
1981     } catch (Exception e) {
1982         result.Error(e);
1983     }
1984     return result.Produce();
1985 }
1986 
ListChannelMidiInputs(uint uiSamplerChannel)1987 String LSCPServer::ListChannelMidiInputs(uint uiSamplerChannel) {
1988     dmsg(2,("LSCPServer: ListChannelMidiInputs(uiSamplerChannel=%d)\n",uiSamplerChannel));
1989     LSCPResultSet result;
1990     try {
1991         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1992         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1993         std::vector<MidiInputPort*> vPorts = pSamplerChannel->GetMidiInputPorts();
1994 
1995         String s;
1996         for (int i = 0; i < vPorts.size(); ++i) {
1997             const int iDeviceID = vPorts[i]->GetDevice()->MidiInputDeviceID();
1998             const int iPortNr   = vPorts[i]->GetPortNumber();
1999             if (s.size()) s += ",";
2000             s += "{" + ToString(iDeviceID) + ","
2001                      + ToString(iPortNr) + "}";
2002         }
2003         result.Add(s);
2004     } catch (Exception e) {
2005         result.Error(e);
2006     }
2007     return result.Produce();
2008 }
2009 
SetMIDIInputPort(uint MIDIPort,uint uiSamplerChannel)2010 String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
2011     dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
2012     LSCPResultSet result;
2013     try {
2014         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2015         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2016         pSamplerChannel->SetMidiInputPort(MIDIPort);
2017     }
2018     catch (Exception e) {
2019          result.Error(e);
2020     }
2021     return result.Produce();
2022 }
2023 
SetMIDIInputChannel(uint MIDIChannel,uint uiSamplerChannel)2024 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
2025     dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
2026     LSCPResultSet result;
2027     try {
2028         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2029         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2030         pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
2031     }
2032     catch (Exception e) {
2033          result.Error(e);
2034     }
2035     return result.Produce();
2036 }
2037 
SetMIDIInputDevice(uint MIDIDeviceId,uint uiSamplerChannel)2038 String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
2039     dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
2040     LSCPResultSet result;
2041     try {
2042         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2043         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2044         std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
2045         if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
2046         MidiInputDevice* pDevice = devices[MIDIDeviceId];
2047         pSamplerChannel->SetMidiInputDevice(pDevice);
2048     }
2049     catch (Exception e) {
2050          result.Error(e);
2051     }
2052     return result.Produce();
2053 }
2054 
SetMIDIInputType(String MidiInputDriver,uint uiSamplerChannel)2055 String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
2056     dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
2057     LSCPResultSet result;
2058     try {
2059         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2060         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2061         // Driver type name aliasing...
2062         if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
2063         // Check if there's one MIDI input device already created
2064         // for the intended MIDI driver type (MidiInputDriver)...
2065         MidiInputDevice *pDevice = NULL;
2066         std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
2067         std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
2068         for (; iter != devices.end(); iter++) {
2069             if ((iter->second)->Driver() == MidiInputDriver) {
2070                 pDevice = iter->second;
2071                 break;
2072             }
2073         }
2074         // If it doesn't exist, create a new one with default parameters...
2075         if (pDevice == NULL) {
2076             std::map<String,String> params;
2077             pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
2078             // Make it with at least one initial port.
2079             std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
2080         }
2081         // Must have a device...
2082         if (pDevice == NULL)
2083             throw Exception("Internal error: could not create MIDI input device.");
2084         // Set it as the current channel device...
2085         pSamplerChannel->SetMidiInputDevice(pDevice);
2086     }
2087     catch (Exception e) {
2088          result.Error(e);
2089     }
2090     return result.Produce();
2091 }
2092 
2093 /**
2094  * Will be called by the parser to change the MIDI input device, port and channel on which
2095  * engine of a particular sampler channel should listen to.
2096  */
SetMIDIInput(uint MIDIDeviceId,uint MIDIPort,uint MIDIChannel,uint uiSamplerChannel)2097 String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
2098     dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
2099     LSCPResultSet result;
2100     try {
2101         SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2102         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2103         std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();
2104         if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
2105         MidiInputDevice* pDevice = devices[MIDIDeviceId];
2106         pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
2107     }
2108     catch (Exception e) {
2109          result.Error(e);
2110     }
2111     return result.Produce();
2112 }
2113 
2114 /**
2115  * Will be called by the parser to change the global volume factor on a
2116  * particular sampler channel.
2117  */
SetVolume(double dVolume,uint uiSamplerChannel)2118 String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
2119     dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
2120     LSCPResultSet result;
2121     try {
2122         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2123         pEngineChannel->Volume(dVolume);
2124     }
2125     catch (Exception e) {
2126          result.Error(e);
2127     }
2128     return result.Produce();
2129 }
2130 
2131 /**
2132  * Will be called by the parser to mute/unmute particular sampler channel.
2133  */
SetChannelMute(bool bMute,uint uiSamplerChannel)2134 String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
2135     dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
2136     LSCPResultSet result;
2137     try {
2138         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2139 
2140         if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
2141         else pEngineChannel->SetMute(1);
2142     } catch (Exception e) {
2143         result.Error(e);
2144     }
2145     return result.Produce();
2146 }
2147 
2148 /**
2149  * Will be called by the parser to solo particular sampler channel.
2150  */
SetChannelSolo(bool bSolo,uint uiSamplerChannel)2151 String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
2152     dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
2153     LSCPResultSet result;
2154     try {
2155         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2156 
2157         bool oldSolo = pEngineChannel->GetSolo();
2158         bool hadSoloChannel = HasSoloChannel();
2159 
2160         pEngineChannel->SetSolo(bSolo);
2161 
2162         if(!oldSolo && bSolo) {
2163             if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
2164             if(!hadSoloChannel) MuteNonSoloChannels();
2165         }
2166 
2167         if(oldSolo && !bSolo) {
2168             if(!HasSoloChannel()) UnmuteChannels();
2169             else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
2170         }
2171     } catch (Exception e) {
2172         result.Error(e);
2173     }
2174     return result.Produce();
2175 }
2176 
2177 /**
2178  * Determines whether there is at least one solo channel in the channel list.
2179  *
2180  * @returns true if there is at least one solo channel in the channel list,
2181  * false otherwise.
2182  */
HasSoloChannel()2183 bool LSCPServer::HasSoloChannel() {
2184     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2185     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2186     for (; iter != channels.end(); iter++) {
2187         EngineChannel* c = iter->second->GetEngineChannel();
2188         if(c && c->GetSolo()) return true;
2189     }
2190 
2191     return false;
2192 }
2193 
2194 /**
2195  * Mutes all unmuted non-solo channels. Notice that the channels are muted
2196  * with -1 which indicates that they are muted because of the presence
2197  * of a solo channel(s). Channels muted with -1 will be automatically unmuted
2198  * when there are no solo channels left.
2199  */
MuteNonSoloChannels()2200 void LSCPServer::MuteNonSoloChannels() {
2201     dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
2202     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2203     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2204     for (; iter != channels.end(); iter++) {
2205         EngineChannel* c = iter->second->GetEngineChannel();
2206         if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
2207     }
2208 }
2209 
2210 /**
2211  * Unmutes all channels that are muted because of the presence
2212  * of a solo channel(s).
2213  */
UnmuteChannels()2214 void  LSCPServer::UnmuteChannels() {
2215     dmsg(2,("LSCPServer: UnmuteChannels()\n"));
2216     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2217     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2218     for (; iter != channels.end(); iter++) {
2219         EngineChannel* c = iter->second->GetEngineChannel();
2220         if(c && c->GetMute() == -1) c->SetMute(0);
2221     }
2222 }
2223 
AddOrReplaceMIDIInstrumentMapping(uint MidiMapID,uint MidiBank,uint MidiProg,String EngineType,String InstrumentFile,uint InstrumentIndex,float Volume,MidiInstrumentMapper::mode_t LoadMode,String Name,bool bModal)2224 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) {
2225     dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
2226 
2227     midi_prog_index_t idx;
2228     idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2229     idx.midi_bank_lsb = MidiBank & 0x7f;
2230     idx.midi_prog     = MidiProg;
2231 
2232     MidiInstrumentMapper::entry_t entry;
2233     entry.EngineName      = EngineType;
2234     entry.InstrumentFile  = InstrumentFile;
2235     entry.InstrumentIndex = InstrumentIndex;
2236     entry.LoadMode        = LoadMode;
2237     entry.Volume          = Volume;
2238     entry.Name            = Name;
2239 
2240     LSCPResultSet result;
2241     try {
2242         // PERSISTENT mapping commands might block for a long time, so in
2243         // that case we add/replace the mapping in another thread in case
2244         // the NON_MODAL argument was supplied, non persistent mappings
2245         // should return immediately, so we don't need to do that for them
2246         bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
2247         MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
2248     } catch (Exception e) {
2249         result.Error(e);
2250     }
2251     return result.Produce();
2252 }
2253 
RemoveMIDIInstrumentMapping(uint MidiMapID,uint MidiBank,uint MidiProg)2254 String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2255     dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
2256 
2257     midi_prog_index_t idx;
2258     idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2259     idx.midi_bank_lsb = MidiBank & 0x7f;
2260     idx.midi_prog     = MidiProg;
2261 
2262     LSCPResultSet result;
2263     try {
2264         MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
2265     } catch (Exception e) {
2266         result.Error(e);
2267     }
2268     return result.Produce();
2269 }
2270 
GetMidiInstrumentMappings(uint MidiMapID)2271 String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
2272     dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
2273     LSCPResultSet result;
2274     try {
2275         result.Add(MidiInstrumentMapper::GetInstrumentCount(MidiMapID));
2276     } catch (Exception e) {
2277         result.Error(e);
2278     }
2279     return result.Produce();
2280 }
2281 
2282 
GetAllMidiInstrumentMappings()2283 String LSCPServer::GetAllMidiInstrumentMappings() {
2284     dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
2285     LSCPResultSet result;
2286     try {
2287         result.Add(MidiInstrumentMapper::GetInstrumentCount());
2288     } catch (Exception e) {
2289         result.Error(e);
2290     }
2291     return result.Produce();
2292 }
2293 
GetMidiInstrumentMapping(uint MidiMapID,uint MidiBank,uint MidiProg)2294 String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2295     dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
2296     LSCPResultSet result;
2297     try {
2298         MidiInstrumentMapper::entry_t entry = MidiInstrumentMapper::GetEntry(MidiMapID, MidiBank, MidiProg);
2299         // convert the filename into the correct encoding as defined for LSCP
2300         // (especially in terms of special characters -> escape sequences)
2301 #if WIN32
2302         const String instrumentFileName = Path::fromWindows(entry.InstrumentFile).toLscp();
2303 #else
2304         // assuming POSIX
2305         const String instrumentFileName = Path::fromPosix(entry.InstrumentFile).toLscp();
2306 #endif
2307 
2308         result.Add("NAME", _escapeLscpResponse(entry.Name));
2309         result.Add("ENGINE_NAME", entry.EngineName);
2310         result.Add("INSTRUMENT_FILE", instrumentFileName);
2311         result.Add("INSTRUMENT_NR", (int) entry.InstrumentIndex);
2312         String instrumentName;
2313         Engine* pEngine = EngineFactory::Create(entry.EngineName);
2314         if (pEngine) {
2315             if (pEngine->GetInstrumentManager()) {
2316                 InstrumentManager::instrument_id_t instrID;
2317                 instrID.FileName = entry.InstrumentFile;
2318                 instrID.Index    = entry.InstrumentIndex;
2319                 instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
2320             }
2321             EngineFactory::Destroy(pEngine);
2322         }
2323         result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2324         switch (entry.LoadMode) {
2325             case MidiInstrumentMapper::ON_DEMAND:
2326                 result.Add("LOAD_MODE", "ON_DEMAND");
2327                 break;
2328             case MidiInstrumentMapper::ON_DEMAND_HOLD:
2329                 result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2330                 break;
2331             case MidiInstrumentMapper::PERSISTENT:
2332                 result.Add("LOAD_MODE", "PERSISTENT");
2333                 break;
2334             default:
2335                 throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2336         }
2337         result.Add("VOLUME", entry.Volume);
2338     } catch (Exception e) {
2339         result.Error(e);
2340     }
2341     return result.Produce();
2342 }
2343 
ListMidiInstrumentMappings(uint MidiMapID)2344 String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
2345     dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
2346     LSCPResultSet result;
2347     try {
2348         String s;
2349         std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
2350         std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2351         for (; iter != mappings.end(); iter++) {
2352             if (s.size()) s += ",";
2353             s += "{" + ToString(MidiMapID) + ","
2354                      + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2355                      + ToString(int(iter->first.midi_prog)) + "}";
2356         }
2357         result.Add(s);
2358     } catch (Exception e) {
2359         result.Error(e);
2360     }
2361     return result.Produce();
2362 }
2363 
ListAllMidiInstrumentMappings()2364 String LSCPServer::ListAllMidiInstrumentMappings() {
2365     dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
2366     LSCPResultSet result;
2367     try {
2368         std::vector<int> maps = MidiInstrumentMapper::Maps();
2369         String s;
2370         for (int i = 0; i < maps.size(); i++) {
2371             std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
2372             std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2373             for (; iter != mappings.end(); iter++) {
2374                 if (s.size()) s += ",";
2375                 s += "{" + ToString(maps[i]) + ","
2376                          + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2377                          + ToString(int(iter->first.midi_prog)) + "}";
2378             }
2379         }
2380         result.Add(s);
2381     } catch (Exception e) {
2382         result.Error(e);
2383     }
2384     return result.Produce();
2385 }
2386 
ClearMidiInstrumentMappings(uint MidiMapID)2387 String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
2388     dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
2389     LSCPResultSet result;
2390     try {
2391         MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
2392     } catch (Exception e) {
2393         result.Error(e);
2394     }
2395     return result.Produce();
2396 }
2397 
ClearAllMidiInstrumentMappings()2398 String LSCPServer::ClearAllMidiInstrumentMappings() {
2399     dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
2400     LSCPResultSet result;
2401     try {
2402         std::vector<int> maps = MidiInstrumentMapper::Maps();
2403         for (int i = 0; i < maps.size(); i++)
2404             MidiInstrumentMapper::RemoveAllEntries(maps[i]);
2405     } catch (Exception e) {
2406         result.Error(e);
2407     }
2408     return result.Produce();
2409 }
2410 
AddMidiInstrumentMap(String MapName)2411 String LSCPServer::AddMidiInstrumentMap(String MapName) {
2412     dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
2413     LSCPResultSet result;
2414     try {
2415         int MapID = MidiInstrumentMapper::AddMap(MapName);
2416         result = LSCPResultSet(MapID);
2417     } catch (Exception e) {
2418         result.Error(e);
2419     }
2420     return result.Produce();
2421 }
2422 
RemoveMidiInstrumentMap(uint MidiMapID)2423 String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
2424     dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
2425     LSCPResultSet result;
2426     try {
2427         MidiInstrumentMapper::RemoveMap(MidiMapID);
2428     } catch (Exception e) {
2429         result.Error(e);
2430     }
2431     return result.Produce();
2432 }
2433 
RemoveAllMidiInstrumentMaps()2434 String LSCPServer::RemoveAllMidiInstrumentMaps() {
2435     dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
2436     LSCPResultSet result;
2437     try {
2438         MidiInstrumentMapper::RemoveAllMaps();
2439     } catch (Exception e) {
2440         result.Error(e);
2441     }
2442     return result.Produce();
2443 }
2444 
GetMidiInstrumentMaps()2445 String LSCPServer::GetMidiInstrumentMaps() {
2446     dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
2447     LSCPResultSet result;
2448     try {
2449         result.Add(int(MidiInstrumentMapper::Maps().size()));
2450     } catch (Exception e) {
2451         result.Error(e);
2452     }
2453     return result.Produce();
2454 }
2455 
ListMidiInstrumentMaps()2456 String LSCPServer::ListMidiInstrumentMaps() {
2457     dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
2458     LSCPResultSet result;
2459     try {
2460         std::vector<int> maps = MidiInstrumentMapper::Maps();
2461         String sList;
2462         for (int i = 0; i < maps.size(); i++) {
2463             if (sList != "") sList += ",";
2464             sList += ToString(maps[i]);
2465         }
2466         result.Add(sList);
2467     } catch (Exception e) {
2468         result.Error(e);
2469     }
2470     return result.Produce();
2471 }
2472 
GetMidiInstrumentMap(uint MidiMapID)2473 String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
2474     dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2475     LSCPResultSet result;
2476     try {
2477         result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2478         result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2479     } catch (Exception e) {
2480         result.Error(e);
2481     }
2482     return result.Produce();
2483 }
2484 
SetMidiInstrumentMapName(uint MidiMapID,String NewName)2485 String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2486     dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2487     LSCPResultSet result;
2488     try {
2489         MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2490     } catch (Exception e) {
2491         result.Error(e);
2492     }
2493     return result.Produce();
2494 }
2495 
2496 /**
2497  * Set the MIDI instrument map the given sampler channel shall use for
2498  * handling MIDI program change messages. There are the following two
2499  * special (negative) values:
2500  *
2501  *    - (-1) :  set to NONE (ignore program changes)
2502  *    - (-2) :  set to DEFAULT map
2503  */
SetChannelMap(uint uiSamplerChannel,int MidiMapID)2504 String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2505     dmsg(2,("LSCPServer: SetChannelMap()\n"));
2506     LSCPResultSet result;
2507     try {
2508         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2509 
2510         if      (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2511         else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2512         else                      pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2513     } catch (Exception e) {
2514         result.Error(e);
2515     }
2516     return result.Produce();
2517 }
2518 
CreateFxSend(uint uiSamplerChannel,uint MidiCtrl,String Name)2519 String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2520     dmsg(2,("LSCPServer: CreateFxSend()\n"));
2521     LSCPResultSet result;
2522     try {
2523         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2524 
2525         FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2526         if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2527 
2528         result = LSCPResultSet(pFxSend->Id()); // success
2529     } catch (Exception e) {
2530         result.Error(e);
2531     }
2532     return result.Produce();
2533 }
2534 
DestroyFxSend(uint uiSamplerChannel,uint FxSendID)2535 String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2536     dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2537     LSCPResultSet result;
2538     try {
2539         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2540 
2541         FxSend* pFxSend = NULL;
2542         for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2543             if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2544                 pFxSend = pEngineChannel->GetFxSend(i);
2545                 break;
2546             }
2547         }
2548         if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2549         pEngineChannel->RemoveFxSend(pFxSend);
2550     } catch (Exception e) {
2551         result.Error(e);
2552     }
2553     return result.Produce();
2554 }
2555 
GetFxSends(uint uiSamplerChannel)2556 String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2557     dmsg(2,("LSCPServer: GetFxSends()\n"));
2558     LSCPResultSet result;
2559     try {
2560         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2561 
2562         result.Add(pEngineChannel->GetFxSendCount());
2563     } catch (Exception e) {
2564         result.Error(e);
2565     }
2566     return result.Produce();
2567 }
2568 
ListFxSends(uint uiSamplerChannel)2569 String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2570     dmsg(2,("LSCPServer: ListFxSends()\n"));
2571     LSCPResultSet result;
2572     String list;
2573     try {
2574         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2575 
2576         for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2577             FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2578             if (list != "") list += ",";
2579             list += ToString(pFxSend->Id());
2580         }
2581         result.Add(list);
2582     } catch (Exception e) {
2583         result.Error(e);
2584     }
2585     return result.Produce();
2586 }
2587 
GetFxSend(uint uiSamplerChannel,uint FxSendID)2588 FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2589     EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2590 
2591     FxSend* pFxSend = NULL;
2592     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2593         if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2594             pFxSend = pEngineChannel->GetFxSend(i);
2595             break;
2596         }
2597     }
2598     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2599     return pFxSend;
2600 }
2601 
GetFxSendInfo(uint uiSamplerChannel,uint FxSendID)2602 String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2603     dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2604     LSCPResultSet result;
2605     try {
2606         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2607         FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2608 
2609         // gather audio routing informations
2610         String AudioRouting;
2611         for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2612             if (AudioRouting != "") AudioRouting += ",";
2613             AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2614         }
2615 
2616         const String sEffectRouting =
2617             (pFxSend->DestinationEffectChain() >= 0 && pFxSend->DestinationEffectChainPosition() >= 0)
2618                 ? ToString(pFxSend->DestinationEffectChain()) + "," + ToString(pFxSend->DestinationEffectChainPosition())
2619                 : "NONE";
2620 
2621         // success
2622         result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2623         result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2624         result.Add("LEVEL", ToString(pFxSend->Level()));
2625         result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2626         result.Add("EFFECT", sEffectRouting);
2627     } catch (Exception e) {
2628         result.Error(e);
2629     }
2630     return result.Produce();
2631 }
2632 
SetFxSendName(uint uiSamplerChannel,uint FxSendID,String Name)2633 String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2634     dmsg(2,("LSCPServer: SetFxSendName()\n"));
2635     LSCPResultSet result;
2636     try {
2637         FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2638 
2639         pFxSend->SetName(Name);
2640         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2641     } catch (Exception e) {
2642         result.Error(e);
2643     }
2644     return result.Produce();
2645 }
2646 
SetFxSendAudioOutputChannel(uint uiSamplerChannel,uint FxSendID,uint FxSendChannel,uint DeviceChannel)2647 String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2648     dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2649     LSCPResultSet result;
2650     try {
2651         FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2652 
2653         pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2654         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2655     } catch (Exception e) {
2656         result.Error(e);
2657     }
2658     return result.Produce();
2659 }
2660 
SetFxSendMidiController(uint uiSamplerChannel,uint FxSendID,uint MidiController)2661 String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2662     dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2663     LSCPResultSet result;
2664     try {
2665         FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2666 
2667         pFxSend->SetMidiController(MidiController);
2668         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2669     } catch (Exception e) {
2670         result.Error(e);
2671     }
2672     return result.Produce();
2673 }
2674 
SetFxSendLevel(uint uiSamplerChannel,uint FxSendID,double dLevel)2675 String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2676     dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2677     LSCPResultSet result;
2678     try {
2679         FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2680 
2681         pFxSend->SetLevel((float)dLevel);
2682         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2683     } catch (Exception e) {
2684         result.Error(e);
2685     }
2686     return result.Produce();
2687 }
2688 
SetFxSendEffect(uint uiSamplerChannel,uint FxSendID,int iSendEffectChain,int iEffectChainPosition)2689 String LSCPServer::SetFxSendEffect(uint uiSamplerChannel, uint FxSendID, int iSendEffectChain, int iEffectChainPosition) {
2690     dmsg(2,("LSCPServer: SetFxSendEffect(%d,%d)\n", iSendEffectChain, iEffectChainPosition));
2691     LSCPResultSet result;
2692     try {
2693         FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2694 
2695         pFxSend->SetDestinationEffect(iSendEffectChain, iEffectChainPosition);
2696         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2697     } catch (Exception e) {
2698         result.Error(e);
2699     }
2700     return result.Produce();
2701 }
2702 
GetAvailableEffects()2703 String LSCPServer::GetAvailableEffects() {
2704     dmsg(2,("LSCPServer: GetAvailableEffects()\n"));
2705     LSCPResultSet result;
2706     try {
2707         int n = EffectFactory::AvailableEffectsCount();
2708         result.Add(n);
2709     }
2710     catch (Exception e) {
2711         result.Error(e);
2712     }
2713     return result.Produce();
2714 }
2715 
ListAvailableEffects()2716 String LSCPServer::ListAvailableEffects() {
2717     dmsg(2,("LSCPServer: ListAvailableEffects()\n"));
2718     LSCPResultSet result;
2719     String list;
2720     try {
2721         //FIXME: for now we simply enumerate from 0 .. EffectFactory::AvailableEffectsCount() here, in future we should use unique IDs for effects during the whole sampler session. This issue comes into game when the user forces a reload of available effect plugins
2722         int n = EffectFactory::AvailableEffectsCount();
2723         for (int i = 0; i < n; i++) {
2724             if (i) list += ",";
2725             list += ToString(i);
2726         }
2727     }
2728     catch (Exception e) {
2729         result.Error(e);
2730     }
2731     result.Add(list);
2732     return result.Produce();
2733 }
2734 
GetEffectInfo(int iEffectIndex)2735 String LSCPServer::GetEffectInfo(int iEffectIndex) {
2736     dmsg(2,("LSCPServer: GetEffectInfo(%d)\n", iEffectIndex));
2737     LSCPResultSet result;
2738     try {
2739         EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2740         if (!pEffectInfo)
2741             throw Exception("There is no effect with index " + ToString(iEffectIndex));
2742 
2743         // convert the filename into the correct encoding as defined for LSCP
2744         // (especially in terms of special characters -> escape sequences)
2745 #if WIN32
2746         const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2747 #else
2748         // assuming POSIX
2749         const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2750 #endif
2751 
2752         result.Add("SYSTEM", pEffectInfo->EffectSystem());
2753         result.Add("MODULE", dllFileName);
2754         result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2755         result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2756     }
2757     catch (Exception e) {
2758         result.Error(e);
2759     }
2760     return result.Produce();
2761 }
2762 
GetEffectInstanceInfo(int iEffectInstance)2763 String LSCPServer::GetEffectInstanceInfo(int iEffectInstance) {
2764     dmsg(2,("LSCPServer: GetEffectInstanceInfo(%d)\n", iEffectInstance));
2765     LSCPResultSet result;
2766     try {
2767         Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2768         if (!pEffect)
2769             throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2770 
2771         EffectInfo* pEffectInfo = pEffect->GetEffectInfo();
2772 
2773         // convert the filename into the correct encoding as defined for LSCP
2774         // (especially in terms of special characters -> escape sequences)
2775 #if WIN32
2776         const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2777 #else
2778         // assuming POSIX
2779         const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2780 #endif
2781 
2782         result.Add("SYSTEM", pEffectInfo->EffectSystem());
2783         result.Add("MODULE", dllFileName);
2784         result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2785         result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2786         result.Add("INPUT_CONTROLS", ToString(pEffect->InputControlCount()));
2787     }
2788     catch (Exception e) {
2789         result.Error(e);
2790     }
2791     return result.Produce();
2792 }
2793 
GetEffectInstanceInputControlInfo(int iEffectInstance,int iInputControlIndex)2794 String LSCPServer::GetEffectInstanceInputControlInfo(int iEffectInstance, int iInputControlIndex) {
2795     dmsg(2,("LSCPServer: GetEffectInstanceInputControlInfo(%d,%d)\n", iEffectInstance, iInputControlIndex));
2796     LSCPResultSet result;
2797     try {
2798         Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2799         if (!pEffect)
2800             throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2801 
2802         EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2803         if (!pEffectControl)
2804             throw Exception(
2805                 "Effect instance " + ToString(iEffectInstance) +
2806                 " does not have an input control with index " +
2807                 ToString(iInputControlIndex)
2808             );
2809 
2810         result.Add("DESCRIPTION", _escapeLscpResponse(pEffectControl->Description()));
2811         result.Add("VALUE", pEffectControl->Value());
2812         if (pEffectControl->MinValue())
2813              result.Add("RANGE_MIN", *pEffectControl->MinValue());
2814         if (pEffectControl->MaxValue())
2815              result.Add("RANGE_MAX", *pEffectControl->MaxValue());
2816         if (!pEffectControl->Possibilities().empty())
2817              result.Add("POSSIBILITIES", pEffectControl->Possibilities());
2818         if (pEffectControl->DefaultValue())
2819              result.Add("DEFAULT", *pEffectControl->DefaultValue());
2820     } catch (Exception e) {
2821         result.Error(e);
2822     }
2823     return result.Produce();
2824 }
2825 
SetEffectInstanceInputControlValue(int iEffectInstance,int iInputControlIndex,double dValue)2826 String LSCPServer::SetEffectInstanceInputControlValue(int iEffectInstance, int iInputControlIndex, double dValue) {
2827     dmsg(2,("LSCPServer: SetEffectInstanceInputControlValue(%d,%d,%f)\n", iEffectInstance, iInputControlIndex, dValue));
2828     LSCPResultSet result;
2829     try {
2830         Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2831         if (!pEffect)
2832             throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2833 
2834         EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2835         if (!pEffectControl)
2836             throw Exception(
2837                 "Effect instance " + ToString(iEffectInstance) +
2838                 " does not have an input control with index " +
2839                 ToString(iInputControlIndex)
2840             );
2841 
2842         pEffectControl->SetValue(dValue);
2843         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_info, iEffectInstance));
2844     } catch (Exception e) {
2845         result.Error(e);
2846     }
2847     return result.Produce();
2848 }
2849 
CreateEffectInstance(int iEffectIndex)2850 String LSCPServer::CreateEffectInstance(int iEffectIndex) {
2851     dmsg(2,("LSCPServer: CreateEffectInstance(%d)\n", iEffectIndex));
2852     LSCPResultSet result;
2853     try {
2854         EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2855         if (!pEffectInfo)
2856             throw Exception("There is no effect with index " + ToString(iEffectIndex));
2857         Effect* pEffect = EffectFactory::Create(pEffectInfo);
2858         result = pEffect->ID(); // success
2859         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2860     } catch (Exception e) {
2861         result.Error(e);
2862     }
2863     return result.Produce();
2864 }
2865 
CreateEffectInstance(String effectSystem,String module,String effectName)2866 String LSCPServer::CreateEffectInstance(String effectSystem, String module, String effectName) {
2867     dmsg(2,("LSCPServer: CreateEffectInstance('%s','%s','%s')\n", effectSystem.c_str(), module.c_str(), effectName.c_str()));
2868     LSCPResultSet result;
2869     try {
2870         // to allow loading the same LSCP session file on different systems
2871         // successfully, probably with different effect plugin DLL paths or even
2872         // running completely different operating systems, we do the following
2873         // for finding the right effect:
2874         //
2875         // first try to search for an exact match of the effect plugin DLL
2876         // (a.k.a 'module'), to avoid picking the wrong DLL with the same
2877         // effect name ...
2878         EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_MATCH_EXACTLY);
2879         // ... if no effect with exactly matchin DLL filename was found, then
2880         // try to lower the restrictions of matching the effect plugin DLL
2881         // filename and try again and again ...
2882         if (!pEffectInfo) {
2883             dmsg(2,("no exact module match, trying MODULE_IGNORE_PATH\n"));
2884             pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH);
2885         }
2886         if (!pEffectInfo) {
2887             dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE\n"));
2888             pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE);
2889         }
2890         if (!pEffectInfo) {
2891             dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE | MODULE_IGNORE_EXTENSION\n"));
2892             pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE | EffectFactory::MODULE_IGNORE_EXTENSION);
2893         }
2894         // ... if there was still no effect found, then completely ignore the
2895         // DLL plugin filename argument and just search for the matching effect
2896         // system type and effect name
2897         if (!pEffectInfo) {
2898             dmsg(2,("no module match, trying MODULE_IGNORE_ALL\n"));
2899             pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_ALL);
2900         }
2901         if (!pEffectInfo)
2902             throw Exception("There is no such effect '" + effectSystem + "' '" + module + "' '" + effectName + "'");
2903 
2904         Effect* pEffect = EffectFactory::Create(pEffectInfo);
2905         result = LSCPResultSet(pEffect->ID());
2906         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2907     } catch (Exception e) {
2908         result.Error(e);
2909     }
2910     return result.Produce();
2911 }
2912 
DestroyEffectInstance(int iEffectInstance)2913 String LSCPServer::DestroyEffectInstance(int iEffectInstance) {
2914     dmsg(2,("LSCPServer: DestroyEffectInstance(%d)\n", iEffectInstance));
2915     LSCPResultSet result;
2916     try {
2917         Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2918         if (!pEffect)
2919             throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2920         EffectFactory::Destroy(pEffect);
2921         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2922     } catch (Exception e) {
2923         result.Error(e);
2924     }
2925     return result.Produce();
2926 }
2927 
GetEffectInstances()2928 String LSCPServer::GetEffectInstances() {
2929     dmsg(2,("LSCPServer: GetEffectInstances()\n"));
2930     LSCPResultSet result;
2931     try {
2932         int n = EffectFactory::EffectInstancesCount();
2933         result.Add(n);
2934     } catch (Exception e) {
2935         result.Error(e);
2936     }
2937     return result.Produce();
2938 }
2939 
ListEffectInstances()2940 String LSCPServer::ListEffectInstances() {
2941     dmsg(2,("LSCPServer: ListEffectInstances()\n"));
2942     LSCPResultSet result;
2943     String list;
2944     try {
2945         int n = EffectFactory::EffectInstancesCount();
2946         for (int i = 0; i < n; i++) {
2947             Effect* pEffect = EffectFactory::GetEffectInstance(i);
2948             if (i) list += ",";
2949             list += ToString(pEffect->ID());
2950         }
2951     } catch (Exception e) {
2952         result.Error(e);
2953     }
2954     result.Add(list);
2955     return result.Produce();
2956 }
2957 
GetSendEffectChains(int iAudioOutputDevice)2958 String LSCPServer::GetSendEffectChains(int iAudioOutputDevice) {
2959     dmsg(2,("LSCPServer: GetSendEffectChains(%d)\n", iAudioOutputDevice));
2960     LSCPResultSet result;
2961     try {
2962         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2963         if (!devices.count(iAudioOutputDevice))
2964             throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2965         AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2966         int n = pDevice->SendEffectChainCount();
2967         result.Add(n);
2968     } catch (Exception e) {
2969         result.Error(e);
2970     }
2971     return result.Produce();
2972 }
2973 
ListSendEffectChains(int iAudioOutputDevice)2974 String LSCPServer::ListSendEffectChains(int iAudioOutputDevice) {
2975     dmsg(2,("LSCPServer: ListSendEffectChains(%d)\n", iAudioOutputDevice));
2976     LSCPResultSet result;
2977     String list;
2978     try {
2979         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2980         if (!devices.count(iAudioOutputDevice))
2981             throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2982         AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2983         int n = pDevice->SendEffectChainCount();
2984         for (int i = 0; i < n; i++) {
2985             EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2986             if (i) list += ",";
2987             list += ToString(pEffectChain->ID());
2988         }
2989     } catch (Exception e) {
2990         result.Error(e);
2991     }
2992     result.Add(list);
2993     return result.Produce();
2994 }
2995 
AddSendEffectChain(int iAudioOutputDevice)2996 String LSCPServer::AddSendEffectChain(int iAudioOutputDevice) {
2997     dmsg(2,("LSCPServer: AddSendEffectChain(%d)\n", iAudioOutputDevice));
2998     LSCPResultSet result;
2999     try {
3000         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
3001         if (!devices.count(iAudioOutputDevice))
3002             throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
3003         AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
3004         EffectChain* pEffectChain = pDevice->AddSendEffectChain();
3005         result = pEffectChain->ID();
3006         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
3007     } catch (Exception e) {
3008         result.Error(e);
3009     }
3010     return result.Produce();
3011 }
3012 
RemoveSendEffectChain(int iAudioOutputDevice,int iSendEffectChain)3013 String LSCPServer::RemoveSendEffectChain(int iAudioOutputDevice, int iSendEffectChain) {
3014     dmsg(2,("LSCPServer: RemoveSendEffectChain(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
3015     LSCPResultSet result;
3016     try {
3017         std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
3018         if (!devices.count(iAudioOutputDevice))
3019             throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
3020 
3021         std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
3022         std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
3023         std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
3024         for (; itEngineChannel != itEnd; ++itEngineChannel) {
3025             AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
3026             if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
3027                 for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
3028                     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
3029                     if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain) {
3030                         throw Exception("The effect chain is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
3031                     }
3032                 }
3033             }
3034         }
3035 
3036         AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
3037         for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
3038             EffectChain* pEffectChain = pDevice->SendEffectChain(i);
3039             if (pEffectChain->ID() == iSendEffectChain) {
3040                 pDevice->RemoveSendEffectChain(i);
3041                 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
3042                 return result.Produce();
3043             }
3044         }
3045         throw Exception(
3046             "There is no send effect chain with ID " +
3047             ToString(iSendEffectChain) + " for audio output device " +
3048             ToString(iAudioOutputDevice) + "."
3049         );
3050     } catch (Exception e) {
3051         result.Error(e);
3052     }
3053     return result.Produce();
3054 }
3055 
_getSendEffectChain(Sampler * pSampler,int iAudioOutputDevice,int iSendEffectChain)3056 static EffectChain* _getSendEffectChain(Sampler* pSampler, int iAudioOutputDevice, int iSendEffectChain) throw (Exception) {
3057     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
3058     if (!devices.count(iAudioOutputDevice))
3059         throw Exception(
3060             "There is no audio output device with index " +
3061             ToString(iAudioOutputDevice) + "."
3062         );
3063     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
3064     EffectChain* pEffectChain = pDevice->SendEffectChainByID(iSendEffectChain);
3065     if(pEffectChain != NULL) return pEffectChain;
3066     throw Exception(
3067         "There is no send effect chain with ID " +
3068         ToString(iSendEffectChain) + " for audio output device " +
3069         ToString(iAudioOutputDevice) + "."
3070     );
3071 }
3072 
GetSendEffectChainInfo(int iAudioOutputDevice,int iSendEffectChain)3073 String LSCPServer::GetSendEffectChainInfo(int iAudioOutputDevice, int iSendEffectChain) {
3074     dmsg(2,("LSCPServer: GetSendEffectChainInfo(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
3075     LSCPResultSet result;
3076     try {
3077         EffectChain* pEffectChain =
3078             _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3079         String sEffectSequence;
3080         for (int i = 0; i < pEffectChain->EffectCount(); i++) {
3081             if (i) sEffectSequence += ",";
3082             sEffectSequence += ToString(pEffectChain->GetEffect(i)->ID());
3083         }
3084         result.Add("EFFECT_COUNT", pEffectChain->EffectCount());
3085         result.Add("EFFECT_SEQUENCE", sEffectSequence);
3086     } catch (Exception e) {
3087         result.Error(e);
3088     }
3089     return result.Produce();
3090 }
3091 
AppendSendEffectChainEffect(int iAudioOutputDevice,int iSendEffectChain,int iEffectInstance)3092 String LSCPServer::AppendSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectInstance) {
3093     dmsg(2,("LSCPServer: AppendSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectInstance));
3094     LSCPResultSet result;
3095     try {
3096         EffectChain* pEffectChain =
3097             _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3098         Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
3099         if (!pEffect)
3100             throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
3101         pEffectChain->AppendEffect(pEffect);
3102         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3103     } catch (Exception e) {
3104         result.Error(e);
3105     }
3106     return result.Produce();
3107 }
3108 
InsertSendEffectChainEffect(int iAudioOutputDevice,int iSendEffectChain,int iEffectChainPosition,int iEffectInstance)3109 String LSCPServer::InsertSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition, int iEffectInstance) {
3110     dmsg(2,("LSCPServer: InsertSendEffectChainEffect(%d,%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition, iEffectInstance));
3111     LSCPResultSet result;
3112     try {
3113         EffectChain* pEffectChain =
3114             _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3115         Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
3116         if (!pEffect)
3117             throw Exception("There is no effect instance with index " + ToString(iEffectInstance));
3118         pEffectChain->InsertEffect(pEffect, iEffectChainPosition);
3119         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3120     } catch (Exception e) {
3121         result.Error(e);
3122     }
3123     return result.Produce();
3124 }
3125 
RemoveSendEffectChainEffect(int iAudioOutputDevice,int iSendEffectChain,int iEffectChainPosition)3126 String LSCPServer::RemoveSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition) {
3127     dmsg(2,("LSCPServer: RemoveSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition));
3128     LSCPResultSet result;
3129     try {
3130         EffectChain* pEffectChain =
3131             _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3132 
3133         std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
3134         std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
3135         std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
3136         for (; itEngineChannel != itEnd; ++itEngineChannel) {
3137             AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
3138             if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
3139                 for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
3140                     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
3141                     if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain && fxs->DestinationEffectChainPosition() == iEffectChainPosition) {
3142                         throw Exception("The effect instance is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
3143                     }
3144                 }
3145             }
3146         }
3147 
3148         pEffectChain->RemoveEffect(iEffectChainPosition);
3149         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3150     } catch (Exception e) {
3151         result.Error(e);
3152     }
3153     return result.Produce();
3154 }
3155 
EditSamplerChannelInstrument(uint uiSamplerChannel)3156 String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
3157     dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
3158     LSCPResultSet result;
3159     try {
3160         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3161         if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
3162         Engine* pEngine = pEngineChannel->GetEngine();
3163         InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
3164         if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
3165         InstrumentManager::instrument_id_t instrumentID;
3166         instrumentID.FileName = pEngineChannel->InstrumentFileName();
3167         instrumentID.Index    = pEngineChannel->InstrumentIndex();
3168         pInstrumentManager->LaunchInstrumentEditor(pEngineChannel, instrumentID);
3169     } catch (Exception e) {
3170         result.Error(e);
3171     }
3172     return result.Produce();
3173 }
3174 
SendChannelMidiData(String MidiMsg,uint uiSamplerChannel,uint Arg1,uint Arg2)3175 String LSCPServer::SendChannelMidiData(String MidiMsg, uint uiSamplerChannel, uint Arg1, uint Arg2) {
3176     dmsg(2,("LSCPServer: SendChannelMidiData(MidiMsg=%s,uiSamplerChannel=%d,Arg1=%d,Arg2=%d)\n", MidiMsg.c_str(), uiSamplerChannel, Arg1, Arg2));
3177     LSCPResultSet result;
3178     try {
3179         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3180 
3181         if (Arg1 > 127 || Arg2 > 127) {
3182             throw Exception("Invalid MIDI message");
3183         }
3184 
3185         VirtualMidiDevice* pMidiDevice = NULL;
3186         std::vector<EventHandler::midi_listener_entry>::iterator iter = eventHandler.channelMidiListeners.begin();
3187         for (; iter != eventHandler.channelMidiListeners.end(); ++iter) {
3188             if ((*iter).pEngineChannel == pEngineChannel) {
3189                 pMidiDevice = (*iter).pMidiListener;
3190                 break;
3191             }
3192         }
3193 
3194         if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
3195 
3196         if (MidiMsg == "NOTE_ON") {
3197             pMidiDevice->SendNoteOnToDevice(Arg1, Arg2);
3198             bool b = pMidiDevice->SendNoteOnToSampler(Arg1, Arg2);
3199             if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3200         } else if (MidiMsg == "NOTE_OFF") {
3201             pMidiDevice->SendNoteOffToDevice(Arg1, Arg2);
3202             bool b = pMidiDevice->SendNoteOffToSampler(Arg1, Arg2);
3203             if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3204         } else if (MidiMsg == "CC") {
3205             pMidiDevice->SendCCToDevice(Arg1, Arg2);
3206             bool b = pMidiDevice->SendCCToSampler(Arg1, Arg2);
3207             if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3208         } else {
3209             throw Exception("Unknown MIDI message type: " + MidiMsg);
3210         }
3211     } catch (Exception e) {
3212         result.Error(e);
3213     }
3214     return result.Produce();
3215 }
3216 
3217 /**
3218  * Will be called by the parser to reset a particular sampler channel.
3219  */
ResetChannel(uint uiSamplerChannel)3220 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
3221     dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
3222     LSCPResultSet result;
3223     try {
3224         EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3225         pEngineChannel->Reset();
3226     }
3227     catch (Exception e) {
3228          result.Error(e);
3229     }
3230     return result.Produce();
3231 }
3232 
3233 /**
3234  * Will be called by the parser to reset the whole sampler.
3235  */
ResetSampler()3236 String LSCPServer::ResetSampler() {
3237     dmsg(2,("LSCPServer: ResetSampler()\n"));
3238     pSampler->Reset();
3239     LSCPResultSet result;
3240     return result.Produce();
3241 }
3242 
3243 /**
3244  * Will be called by the parser to return general informations about this
3245  * sampler.
3246  */
GetServerInfo()3247 String LSCPServer::GetServerInfo() {
3248     dmsg(2,("LSCPServer: GetServerInfo()\n"));
3249     const std::string description =
3250         _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
3251     LSCPResultSet result;
3252     result.Add("DESCRIPTION", description);
3253     result.Add("VERSION", VERSION);
3254     result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
3255 #if HAVE_SQLITE3
3256     result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
3257 #else
3258     result.Add("INSTRUMENTS_DB_SUPPORT", "no");
3259 #endif
3260 
3261     return result.Produce();
3262 }
3263 
3264 /**
3265  * Will be called by the parser to return the current number of all active streams.
3266  */
GetTotalStreamCount()3267 String LSCPServer::GetTotalStreamCount() {
3268     dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
3269     LSCPResultSet result;
3270     result.Add(pSampler->GetDiskStreamCount());
3271     return result.Produce();
3272 }
3273 
3274 /**
3275  * Will be called by the parser to return the current number of all active voices.
3276  */
GetTotalVoiceCount()3277 String LSCPServer::GetTotalVoiceCount() {
3278     dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
3279     LSCPResultSet result;
3280     result.Add(pSampler->GetVoiceCount());
3281     return result.Produce();
3282 }
3283 
3284 /**
3285  * Will be called by the parser to return the maximum number of voices.
3286  */
GetTotalVoiceCountMax()3287 String LSCPServer::GetTotalVoiceCountMax() {
3288     dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3289     LSCPResultSet result;
3290     result.Add(int(EngineFactory::EngineInstances().size() * pSampler->GetGlobalMaxVoices()));
3291     return result.Produce();
3292 }
3293 
3294 /**
3295  * Will be called by the parser to return the sampler global maximum
3296  * allowed number of voices.
3297  */
GetGlobalMaxVoices()3298 String LSCPServer::GetGlobalMaxVoices() {
3299     dmsg(2,("LSCPServer: GetGlobalMaxVoices()\n"));
3300     LSCPResultSet result;
3301     result.Add(pSampler->GetGlobalMaxVoices());
3302     return result.Produce();
3303 }
3304 
3305 /**
3306  * Will be called by the parser to set the sampler global maximum number of
3307  * voices.
3308  */
SetGlobalMaxVoices(int iVoices)3309 String LSCPServer::SetGlobalMaxVoices(int iVoices) {
3310     dmsg(2,("LSCPServer: SetGlobalMaxVoices(%d)\n", iVoices));
3311     LSCPResultSet result;
3312     try {
3313         pSampler->SetGlobalMaxVoices(iVoices);
3314         LSCPServer::SendLSCPNotify(
3315             LSCPEvent(LSCPEvent::event_global_info, "VOICES", pSampler->GetGlobalMaxVoices())
3316         );
3317     } catch (Exception e) {
3318         result.Error(e);
3319     }
3320     return result.Produce();
3321 }
3322 
3323 /**
3324  * Will be called by the parser to return the sampler global maximum
3325  * allowed number of disk streams.
3326  */
GetGlobalMaxStreams()3327 String LSCPServer::GetGlobalMaxStreams() {
3328     dmsg(2,("LSCPServer: GetGlobalMaxStreams()\n"));
3329     LSCPResultSet result;
3330     result.Add(pSampler->GetGlobalMaxStreams());
3331     return result.Produce();
3332 }
3333 
3334 /**
3335  * Will be called by the parser to set the sampler global maximum number of
3336  * disk streams.
3337  */
SetGlobalMaxStreams(int iStreams)3338 String LSCPServer::SetGlobalMaxStreams(int iStreams) {
3339     dmsg(2,("LSCPServer: SetGlobalMaxStreams(%d)\n", iStreams));
3340     LSCPResultSet result;
3341     try {
3342         pSampler->SetGlobalMaxStreams(iStreams);
3343         LSCPServer::SendLSCPNotify(
3344             LSCPEvent(LSCPEvent::event_global_info, "STREAMS", pSampler->GetGlobalMaxStreams())
3345         );
3346     } catch (Exception e) {
3347         result.Error(e);
3348     }
3349     return result.Produce();
3350 }
3351 
GetGlobalVolume()3352 String LSCPServer::GetGlobalVolume() {
3353     LSCPResultSet result;
3354     result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
3355     return result.Produce();
3356 }
3357 
SetGlobalVolume(double dVolume)3358 String LSCPServer::SetGlobalVolume(double dVolume) {
3359     LSCPResultSet result;
3360     try {
3361         if (dVolume < 0) throw Exception("Volume may not be negative");
3362         GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3363         LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3364     } catch (Exception e) {
3365         result.Error(e);
3366     }
3367     return result.Produce();
3368 }
3369 
GetFileInstruments(String Filename)3370 String LSCPServer::GetFileInstruments(String Filename) {
3371     dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
3372     LSCPResultSet result;
3373     try {
3374         VerifyFile(Filename);
3375     } catch (Exception e) {
3376         result.Error(e);
3377         return result.Produce();
3378     }
3379     // try to find a sampler engine that can handle the file
3380     bool bFound = false;
3381     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3382     for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3383         Engine* pEngine = NULL;
3384         try {
3385             pEngine = EngineFactory::Create(engineTypes[i]);
3386             if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3387             InstrumentManager* pManager = pEngine->GetInstrumentManager();
3388             if (pManager) {
3389                 std::vector<InstrumentManager::instrument_id_t> IDs =
3390                     pManager->GetInstrumentFileContent(Filename);
3391                 // return the amount of instruments in the file
3392                 result.Add((int)IDs.size());
3393                 // no more need to ask other engine types
3394                 bFound = true;
3395             } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3396         } catch (Exception e) {
3397             // NOOP, as exception is thrown if engine doesn't support file
3398         }
3399         if (pEngine) EngineFactory::Destroy(pEngine);
3400     }
3401 
3402     if (!bFound) result.Error("Unknown file format");
3403     return result.Produce();
3404 }
3405 
ListFileInstruments(String Filename)3406 String LSCPServer::ListFileInstruments(String Filename) {
3407     dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
3408     LSCPResultSet result;
3409     try {
3410         VerifyFile(Filename);
3411     } catch (Exception e) {
3412         result.Error(e);
3413         return result.Produce();
3414     }
3415     // try to find a sampler engine that can handle the file
3416     bool bFound = false;
3417     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3418     for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3419         Engine* pEngine = NULL;
3420         try {
3421             pEngine = EngineFactory::Create(engineTypes[i]);
3422             if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3423             InstrumentManager* pManager = pEngine->GetInstrumentManager();
3424             if (pManager) {
3425                 std::vector<InstrumentManager::instrument_id_t> IDs =
3426                     pManager->GetInstrumentFileContent(Filename);
3427                 // return a list of IDs of the instruments in the file
3428                 String s;
3429                 for (int j = 0; j < IDs.size(); j++) {
3430                     if (s.size()) s += ",";
3431                     s += ToString(IDs[j].Index);
3432                 }
3433                 result.Add(s);
3434                 // no more need to ask other engine types
3435                 bFound = true;
3436             } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3437         } catch (Exception e) {
3438             // NOOP, as exception is thrown if engine doesn't support file
3439         }
3440         if (pEngine) EngineFactory::Destroy(pEngine);
3441     }
3442 
3443     if (!bFound) result.Error("Unknown file format");
3444     return result.Produce();
3445 }
3446 
GetFileInstrumentInfo(String Filename,uint InstrumentID)3447 String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
3448     dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
3449     LSCPResultSet result;
3450     try {
3451         VerifyFile(Filename);
3452     } catch (Exception e) {
3453         result.Error(e);
3454         return result.Produce();
3455     }
3456     InstrumentManager::instrument_id_t id;
3457     id.FileName = Filename;
3458     id.Index    = InstrumentID;
3459     // try to find a sampler engine that can handle the file
3460     bool bFound = false;
3461     bool bFatalErr = false;
3462     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3463     for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
3464         Engine* pEngine = NULL;
3465         try {
3466             pEngine = EngineFactory::Create(engineTypes[i]);
3467             if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3468             InstrumentManager* pManager = pEngine->GetInstrumentManager();
3469             if (pManager) {
3470                 // check if the instrument index is valid
3471                 // FIXME: this won't work if an engine only supports parts of the instrument file
3472                 std::vector<InstrumentManager::instrument_id_t> IDs =
3473                     pManager->GetInstrumentFileContent(Filename);
3474                 if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
3475                     std::stringstream ss;
3476                     ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
3477                     bFatalErr = true;
3478                     throw Exception(ss.str());
3479                 }
3480                 // get the info of the requested instrument
3481                 InstrumentManager::instrument_info_t info =
3482                     pManager->GetInstrumentInfo(id);
3483                 // return detailed informations about the file
3484                 result.Add("NAME", info.InstrumentName);
3485                 result.Add("FORMAT_FAMILY", engineTypes[i]);
3486                 result.Add("FORMAT_VERSION", info.FormatVersion);
3487                 result.Add("PRODUCT", info.Product);
3488                 result.Add("ARTISTS", info.Artists);
3489 
3490                 std::stringstream ss;
3491                 bool b = false;
3492                 for (int i = 0; i < 128; i++) {
3493                     if (info.KeyBindings[i]) {
3494                         if (b) ss << ',';
3495                         ss << i; b = true;
3496                     }
3497                 }
3498                 result.Add("KEY_BINDINGS", ss.str());
3499 
3500                 b = false;
3501                 std::stringstream ss2;
3502                 for (int i = 0; i < 128; i++) {
3503                     if (info.KeySwitchBindings[i]) {
3504                         if (b) ss2 << ',';
3505                         ss2 << i; b = true;
3506                     }
3507                 }
3508                 result.Add("KEYSWITCH_BINDINGS", ss2.str());
3509                 // no more need to ask other engine types
3510                 bFound = true;
3511             } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3512         } catch (Exception e) {
3513             // usually NOOP, as exception is thrown if engine doesn't support file
3514             if (bFatalErr) result.Error(e);
3515         }
3516         if (pEngine) EngineFactory::Destroy(pEngine);
3517     }
3518 
3519     if (!bFound && !bFatalErr) result.Error("Unknown file format");
3520     return result.Produce();
3521 }
3522 
VerifyFile(String Filename)3523 void LSCPServer::VerifyFile(String Filename) {
3524     #if WIN32
3525     WIN32_FIND_DATA win32FileAttributeData;
3526     BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
3527     if (!res) {
3528         std::stringstream ss;
3529         ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
3530         throw Exception(ss.str());
3531     }
3532     if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
3533         throw Exception("Directory is specified");
3534     }
3535     #else
3536     File f(Filename);
3537     if(!f.Exist()) throw Exception(f.GetErrorMsg());
3538     if (f.IsDirectory()) throw Exception("Directory is specified");
3539     #endif
3540 }
3541 
3542 /**
3543  * Will be called by the parser to subscribe a client (frontend) on the
3544  * server for receiving event messages.
3545  */
SubscribeNotification(LSCPEvent::event_t type)3546 String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
3547     dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3548     LSCPResultSet result;
3549     {
3550         LockGuard lock(SubscriptionMutex);
3551         eventSubscriptions[type].push_back(currentSocket);
3552     }
3553     return result.Produce();
3554 }
3555 
3556 /**
3557  * Will be called by the parser to unsubscribe a client on the server
3558  * for not receiving further event messages.
3559  */
UnsubscribeNotification(LSCPEvent::event_t type)3560 String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
3561     dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3562     LSCPResultSet result;
3563     {
3564         LockGuard lock(SubscriptionMutex);
3565         eventSubscriptions[type].remove(currentSocket);
3566     }
3567     return result.Produce();
3568 }
3569 
AddDbInstrumentDirectory(String Dir)3570 String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3571     dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3572     LSCPResultSet result;
3573 #if HAVE_SQLITE3
3574     try {
3575         InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
3576     } catch (Exception e) {
3577          result.Error(e);
3578     }
3579 #else
3580     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3581 #endif
3582     return result.Produce();
3583 }
3584 
RemoveDbInstrumentDirectory(String Dir,bool Force)3585 String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3586     dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3587     LSCPResultSet result;
3588 #if HAVE_SQLITE3
3589     try {
3590         InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3591     } catch (Exception e) {
3592          result.Error(e);
3593     }
3594 #else
3595     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3596 #endif
3597     return result.Produce();
3598 }
3599 
GetDbInstrumentDirectoryCount(String Dir,bool Recursive)3600 String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3601     dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3602     LSCPResultSet result;
3603 #if HAVE_SQLITE3
3604     try {
3605         result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
3606     } catch (Exception e) {
3607          result.Error(e);
3608     }
3609 #else
3610     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3611 #endif
3612     return result.Produce();
3613 }
3614 
GetDbInstrumentDirectories(String Dir,bool Recursive)3615 String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
3616     dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3617     LSCPResultSet result;
3618 #if HAVE_SQLITE3
3619     try {
3620         String list;
3621         StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
3622 
3623         for (int i = 0; i < dirs->size(); i++) {
3624             if (list != "") list += ",";
3625             list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
3626         }
3627 
3628         result.Add(list);
3629     } catch (Exception e) {
3630          result.Error(e);
3631     }
3632 #else
3633     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3634 #endif
3635     return result.Produce();
3636 }
3637 
GetDbInstrumentDirectoryInfo(String Dir)3638 String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
3639     dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
3640     LSCPResultSet result;
3641 #if HAVE_SQLITE3
3642     try {
3643         DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
3644 
3645         result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3646         result.Add("CREATED", info.Created);
3647         result.Add("MODIFIED", info.Modified);
3648     } catch (Exception e) {
3649          result.Error(e);
3650     }
3651 #else
3652     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3653 #endif
3654     return result.Produce();
3655 }
3656 
SetDbInstrumentDirectoryName(String Dir,String Name)3657 String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
3658     dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
3659     LSCPResultSet result;
3660 #if HAVE_SQLITE3
3661     try {
3662         InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
3663     } catch (Exception e) {
3664          result.Error(e);
3665     }
3666 #else
3667     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3668 #endif
3669     return result.Produce();
3670 }
3671 
MoveDbInstrumentDirectory(String Dir,String Dst)3672 String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
3673     dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3674     LSCPResultSet result;
3675 #if HAVE_SQLITE3
3676     try {
3677         InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
3678     } catch (Exception e) {
3679          result.Error(e);
3680     }
3681 #else
3682     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3683 #endif
3684     return result.Produce();
3685 }
3686 
CopyDbInstrumentDirectory(String Dir,String Dst)3687 String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
3688     dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3689     LSCPResultSet result;
3690 #if HAVE_SQLITE3
3691     try {
3692         InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
3693     } catch (Exception e) {
3694          result.Error(e);
3695     }
3696 #else
3697     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3698 #endif
3699     return result.Produce();
3700 }
3701 
SetDbInstrumentDirectoryDescription(String Dir,String Desc)3702 String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3703     dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3704     LSCPResultSet result;
3705 #if HAVE_SQLITE3
3706     try {
3707         InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3708     } catch (Exception e) {
3709          result.Error(e);
3710     }
3711 #else
3712     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3713 #endif
3714     return result.Produce();
3715 }
3716 
AddDbInstruments(String DbDir,String FilePath,int Index,bool bBackground)3717 String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3718     dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
3719     LSCPResultSet result;
3720 #if HAVE_SQLITE3
3721     try {
3722         int id;
3723         InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3724         id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
3725         if (bBackground) result = id;
3726     } catch (Exception e) {
3727          result.Error(e);
3728     }
3729 #else
3730     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3731 #endif
3732     return result.Produce();
3733 }
3734 
AddDbInstruments(String ScanMode,String DbDir,String FsDir,bool bBackground,bool insDir)3735 String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground, bool insDir) {
3736     dmsg(2,("LSCPServer: AddDbInstruments(ScanMode=%s,DbDir=%s,FsDir=%s,bBackground=%d,insDir=%d)\n", ScanMode.c_str(), DbDir.c_str(), FsDir.c_str(), bBackground, insDir));
3737     LSCPResultSet result;
3738 #if HAVE_SQLITE3
3739     try {
3740         int id;
3741         InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3742         if (ScanMode.compare("RECURSIVE") == 0) {
3743             id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground, insDir);
3744         } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
3745             id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground, insDir);
3746         } else if (ScanMode.compare("FLAT") == 0) {
3747             id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground, insDir);
3748         } else {
3749             throw Exception("Unknown scan mode: " + ScanMode);
3750         }
3751 
3752         if (bBackground) result = id;
3753     } catch (Exception e) {
3754          result.Error(e);
3755     }
3756 #else
3757     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3758 #endif
3759     return result.Produce();
3760 }
3761 
RemoveDbInstrument(String Instr)3762 String LSCPServer::RemoveDbInstrument(String Instr) {
3763     dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
3764     LSCPResultSet result;
3765 #if HAVE_SQLITE3
3766     try {
3767         InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
3768     } catch (Exception e) {
3769          result.Error(e);
3770     }
3771 #else
3772     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3773 #endif
3774     return result.Produce();
3775 }
3776 
GetDbInstrumentCount(String Dir,bool Recursive)3777 String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
3778     dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3779     LSCPResultSet result;
3780 #if HAVE_SQLITE3
3781     try {
3782         result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
3783     } catch (Exception e) {
3784          result.Error(e);
3785     }
3786 #else
3787     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3788 #endif
3789     return result.Produce();
3790 }
3791 
GetDbInstruments(String Dir,bool Recursive)3792 String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
3793     dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3794     LSCPResultSet result;
3795 #if HAVE_SQLITE3
3796     try {
3797         String list;
3798         StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
3799 
3800         for (int i = 0; i < instrs->size(); i++) {
3801             if (list != "") list += ",";
3802             list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
3803         }
3804 
3805         result.Add(list);
3806     } catch (Exception e) {
3807          result.Error(e);
3808     }
3809 #else
3810     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3811 #endif
3812     return result.Produce();
3813 }
3814 
GetDbInstrumentInfo(String Instr)3815 String LSCPServer::GetDbInstrumentInfo(String Instr) {
3816     dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
3817     LSCPResultSet result;
3818 #if HAVE_SQLITE3
3819     try {
3820         DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
3821 
3822         result.Add("INSTRUMENT_FILE", info.InstrFile);
3823         result.Add("INSTRUMENT_NR", info.InstrNr);
3824         result.Add("FORMAT_FAMILY", info.FormatFamily);
3825         result.Add("FORMAT_VERSION", info.FormatVersion);
3826         result.Add("SIZE", (int)info.Size);
3827         result.Add("CREATED", info.Created);
3828         result.Add("MODIFIED", info.Modified);
3829         result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3830         result.Add("IS_DRUM", info.IsDrum);
3831         result.Add("PRODUCT", _escapeLscpResponse(info.Product));
3832         result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
3833         result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
3834     } catch (Exception e) {
3835          result.Error(e);
3836     }
3837 #else
3838     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3839 #endif
3840     return result.Produce();
3841 }
3842 
GetDbInstrumentsJobInfo(int JobId)3843 String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
3844     dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
3845     LSCPResultSet result;
3846 #if HAVE_SQLITE3
3847     try {
3848         ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
3849 
3850         result.Add("FILES_TOTAL", job.FilesTotal);
3851         result.Add("FILES_SCANNED", job.FilesScanned);
3852         result.Add("SCANNING", job.Scanning);
3853         result.Add("STATUS", job.Status);
3854     } catch (Exception e) {
3855          result.Error(e);
3856     }
3857 #else
3858     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3859 #endif
3860     return result.Produce();
3861 }
3862 
SetDbInstrumentName(String Instr,String Name)3863 String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
3864     dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
3865     LSCPResultSet result;
3866 #if HAVE_SQLITE3
3867     try {
3868         InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
3869     } catch (Exception e) {
3870          result.Error(e);
3871     }
3872 #else
3873     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3874 #endif
3875     return result.Produce();
3876 }
3877 
MoveDbInstrument(String Instr,String Dst)3878 String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
3879     dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3880     LSCPResultSet result;
3881 #if HAVE_SQLITE3
3882     try {
3883         InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
3884     } catch (Exception e) {
3885          result.Error(e);
3886     }
3887 #else
3888     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3889 #endif
3890     return result.Produce();
3891 }
3892 
CopyDbInstrument(String Instr,String Dst)3893 String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3894     dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3895     LSCPResultSet result;
3896 #if HAVE_SQLITE3
3897     try {
3898         InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3899     } catch (Exception e) {
3900          result.Error(e);
3901     }
3902 #else
3903     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3904 #endif
3905     return result.Produce();
3906 }
3907 
SetDbInstrumentDescription(String Instr,String Desc)3908 String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3909     dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3910     LSCPResultSet result;
3911 #if HAVE_SQLITE3
3912     try {
3913         InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3914     } catch (Exception e) {
3915          result.Error(e);
3916     }
3917 #else
3918     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3919 #endif
3920     return result.Produce();
3921 }
3922 
SetDbInstrumentFilePath(String OldPath,String NewPath)3923 String LSCPServer::SetDbInstrumentFilePath(String OldPath, String NewPath) {
3924     dmsg(2,("LSCPServer: SetDbInstrumentFilePath(OldPath=%s,NewPath=%s)\n", OldPath.c_str(), NewPath.c_str()));
3925     LSCPResultSet result;
3926 #if HAVE_SQLITE3
3927     try {
3928         InstrumentsDb::GetInstrumentsDb()->SetInstrumentFilePath(OldPath, NewPath);
3929     } catch (Exception e) {
3930          result.Error(e);
3931     }
3932 #else
3933     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3934 #endif
3935     return result.Produce();
3936 }
3937 
FindLostDbInstrumentFiles()3938 String LSCPServer::FindLostDbInstrumentFiles() {
3939     dmsg(2,("LSCPServer: FindLostDbInstrumentFiles()\n"));
3940     LSCPResultSet result;
3941 #if HAVE_SQLITE3
3942     try {
3943         String list;
3944         StringListPtr pLostFiles = InstrumentsDb::GetInstrumentsDb()->FindLostInstrumentFiles();
3945 
3946         for (int i = 0; i < pLostFiles->size(); i++) {
3947             if (list != "") list += ",";
3948             list += "'" + pLostFiles->at(i) + "'";
3949         }
3950 
3951         result.Add(list);
3952     } catch (Exception e) {
3953          result.Error(e);
3954     }
3955 #else
3956     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3957 #endif
3958     return result.Produce();
3959 }
3960 
FindDbInstrumentDirectories(String Dir,std::map<String,String> Parameters,bool Recursive)3961 String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3962     dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3963     LSCPResultSet result;
3964 #if HAVE_SQLITE3
3965     try {
3966         SearchQuery Query;
3967         std::map<String,String>::iterator iter;
3968         for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3969             if (iter->first.compare("NAME") == 0) {
3970                 Query.Name = iter->second;
3971             } else if (iter->first.compare("CREATED") == 0) {
3972                 Query.SetCreated(iter->second);
3973             } else if (iter->first.compare("MODIFIED") == 0) {
3974                 Query.SetModified(iter->second);
3975             } else if (iter->first.compare("DESCRIPTION") == 0) {
3976                 Query.Description = iter->second;
3977             } else {
3978                 throw Exception("Unknown search criteria: " + iter->first);
3979             }
3980         }
3981 
3982         String list;
3983         StringListPtr pDirectories =
3984             InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3985 
3986         for (int i = 0; i < pDirectories->size(); i++) {
3987             if (list != "") list += ",";
3988             list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3989         }
3990 
3991         result.Add(list);
3992     } catch (Exception e) {
3993          result.Error(e);
3994     }
3995 #else
3996     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3997 #endif
3998     return result.Produce();
3999 }
4000 
FindDbInstruments(String Dir,std::map<String,String> Parameters,bool Recursive)4001 String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
4002     dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
4003     LSCPResultSet result;
4004 #if HAVE_SQLITE3
4005     try {
4006         SearchQuery Query;
4007         std::map<String,String>::iterator iter;
4008         for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
4009             if (iter->first.compare("NAME") == 0) {
4010                 Query.Name = iter->second;
4011             } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
4012                 Query.SetFormatFamilies(iter->second);
4013             } else if (iter->first.compare("SIZE") == 0) {
4014                 Query.SetSize(iter->second);
4015             } else if (iter->first.compare("CREATED") == 0) {
4016                 Query.SetCreated(iter->second);
4017             } else if (iter->first.compare("MODIFIED") == 0) {
4018                 Query.SetModified(iter->second);
4019             } else if (iter->first.compare("DESCRIPTION") == 0) {
4020                 Query.Description = iter->second;
4021             } else if (iter->first.compare("IS_DRUM") == 0) {
4022                 if (!strcasecmp(iter->second.c_str(), "true")) {
4023                     Query.InstrType = SearchQuery::DRUM;
4024                 } else {
4025                     Query.InstrType = SearchQuery::CHROMATIC;
4026                 }
4027             } else if (iter->first.compare("PRODUCT") == 0) {
4028                  Query.Product = iter->second;
4029             } else if (iter->first.compare("ARTISTS") == 0) {
4030                  Query.Artists = iter->second;
4031             } else if (iter->first.compare("KEYWORDS") == 0) {
4032                  Query.Keywords = iter->second;
4033             } else {
4034                 throw Exception("Unknown search criteria: " + iter->first);
4035             }
4036         }
4037 
4038         String list;
4039         StringListPtr pInstruments =
4040             InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
4041 
4042         for (int i = 0; i < pInstruments->size(); i++) {
4043             if (list != "") list += ",";
4044             list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
4045         }
4046 
4047         result.Add(list);
4048     } catch (Exception e) {
4049          result.Error(e);
4050     }
4051 #else
4052     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
4053 #endif
4054     return result.Produce();
4055 }
4056 
FormatInstrumentsDb()4057 String LSCPServer::FormatInstrumentsDb() {
4058     dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
4059     LSCPResultSet result;
4060 #if HAVE_SQLITE3
4061     try {
4062         InstrumentsDb::GetInstrumentsDb()->Format();
4063     } catch (Exception e) {
4064          result.Error(e);
4065     }
4066 #else
4067     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
4068 #endif
4069     return result.Produce();
4070 }
4071 
4072 
4073 /**
4074  * Will be called by the parser to enable or disable echo mode; if echo
4075  * mode is enabled, all commands from the client will (immediately) be
4076  * echoed back to the client.
4077  */
SetEcho(yyparse_param_t * pSession,double boolean_value)4078 String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
4079     dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
4080     LSCPResultSet result;
4081     try {
4082         if      (boolean_value == 0) pSession->bVerbose = false;
4083         else if (boolean_value == 1) pSession->bVerbose = true;
4084         else throw Exception("Not a boolean value, must either be 0 or 1");
4085     }
4086     catch (Exception e) {
4087          result.Error(e);
4088     }
4089     return result.Produce();
4090 }
4091 
SetShellInteract(yyparse_param_t * pSession,double boolean_value)4092 String LSCPServer::SetShellInteract(yyparse_param_t* pSession, double boolean_value) {
4093     dmsg(2,("LSCPServer: SetShellInteract(val=%f)\n", boolean_value));
4094     LSCPResultSet result;
4095     try {
4096         if      (boolean_value == 0) pSession->bShellInteract = false;
4097         else if (boolean_value == 1) pSession->bShellInteract = true;
4098         else throw Exception("Not a boolean value, must either be 0 or 1");
4099     } catch (Exception e) {
4100         result.Error(e);
4101     }
4102     return result.Produce();
4103 }
4104 
SetShellAutoCorrect(yyparse_param_t * pSession,double boolean_value)4105 String LSCPServer::SetShellAutoCorrect(yyparse_param_t* pSession, double boolean_value) {
4106     dmsg(2,("LSCPServer: SetShellAutoCorrect(val=%f)\n", boolean_value));
4107     LSCPResultSet result;
4108     try {
4109         if      (boolean_value == 0) pSession->bShellAutoCorrect = false;
4110         else if (boolean_value == 1) pSession->bShellAutoCorrect = true;
4111         else throw Exception("Not a boolean value, must either be 0 or 1");
4112     } catch (Exception e) {
4113         result.Error(e);
4114     }
4115     return result.Produce();
4116 }
4117 
SetShellDoc(yyparse_param_t * pSession,double boolean_value)4118 String LSCPServer::SetShellDoc(yyparse_param_t* pSession, double boolean_value) {
4119     dmsg(2,("LSCPServer: SetShellDoc(val=%f)\n", boolean_value));
4120     LSCPResultSet result;
4121     try {
4122         if      (boolean_value == 0) pSession->bShellSendLSCPDoc = false;
4123         else if (boolean_value == 1) pSession->bShellSendLSCPDoc = true;
4124         else throw Exception("Not a boolean value, must either be 0 or 1");
4125     } catch (Exception e) {
4126         result.Error(e);
4127     }
4128     return result.Produce();
4129 }
4130 
4131 }
4132