/[svn]/linuxsampler/trunk/src/network/lscpserver.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/network/lscpserver.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1399 - (show annotations) (download)
Thu Oct 11 18:53:29 2007 UTC (16 years, 5 months ago) by schoenebeck
File size: 112847 byte(s)
* the following LSCP command return escape sequences in at least one
  of their LSCP response fields: "GET ENGINE INFO", "GET CHANNEL INFO",
  "GET MIDI_INSTRUMENT INFO", "GET MIDI_INSTRUMENT_MAP INFO",
  "GET FX_SEND INFO", "GET SERVER INFO"
* listed all LSCP commands in the LSCP specs which may use escape
  sequences in at least on of their response fields
* hide instrument editor related debug messages in the gig::Engine when
  using the default debug level (which is 1)
* bumped version to 0.4.0.8cvs

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * Copyright (C) 2005 - 2007 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 "lscpserver.h"
25 #include "lscpresultset.h"
26 #include "lscpevent.h"
27
28 #include <fcntl.h>
29
30 #if ! HAVE_SQLITE3
31 #define DOESNT_HAVE_SQLITE3 "No database support. SQLITE3 was not installed when linuxsampler was built."
32 #endif
33
34 #include "../engines/EngineFactory.h"
35 #include "../engines/EngineChannelFactory.h"
36 #include "../drivers/audio/AudioOutputDeviceFactory.h"
37 #include "../drivers/midi/MidiInputDeviceFactory.h"
38
39
40 /**
41 * Returns a copy of the given string where all special characters are
42 * replaced by LSCP escape sequences ("\xHH"). This function shall be used
43 * to escape LSCP response fields in case the respective response field is
44 * actually defined as using escape sequences in the LSCP specs.
45 *
46 * @e Caution: DO NOT use this function for escaping path based responses,
47 * use the Path class (src/common/Path.h) for this instead!
48 */
49 static String _escapeLscpResponse(String txt) {
50 for (int i = 0; i < txt.length(); i++) {
51 const char c = txt.c_str()[i];
52 if (
53 !(c >= '0' && c <= '9') &&
54 !(c >= 'a' && c <= 'z') &&
55 !(c >= 'A' && c <= 'Z') &&
56 !(c == ' ') && !(c == '!') && !(c == '#') && !(c == '$') &&
57 !(c == '%') && !(c == '&') && !(c == '(') && !(c == ')') &&
58 !(c == '*') && !(c == '+') && !(c == ',') && !(c == '-') &&
59 !(c == '.') && !(c == '/') && !(c == ':') && !(c == ';') &&
60 !(c == '<') && !(c == '=') && !(c == '>') && !(c == '?') &&
61 !(c == '@') && !(c == '[') && !(c == '\\') && !(c == ']') &&
62 !(c == '^') && !(c == '_') && !(c == '`') && !(c == '{') &&
63 !(c == '|') && !(c == '}') && !(c == '~')
64 ) {
65 // convert the "special" character into a "\xHH" LSCP escape sequence
66 char buf[5];
67 snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
68 txt.replace(i, 1, buf);
69 i += 3;
70 }
71 }
72 return txt;
73 }
74
75 /**
76 * Below are a few static members of the LSCPServer class.
77 * The big assumption here is that LSCPServer is going to remain a singleton.
78 * These members are used to support client connections.
79 * Class handles multiple connections at the same time using select() and non-blocking recv()
80 * Commands are processed by a single LSCPServer thread.
81 * Notifications are delivered either by the thread that originated them
82 * or (if the resultset is currently in progress) by the LSCPServer thread
83 * after the resultset was sent out.
84 * This makes sure that resultsets can not be interrupted by notifications.
85 * This also makes sure that the thread sending notification is not blocked
86 * by the LSCPServer thread.
87 */
88 fd_set LSCPServer::fdSet;
89 int LSCPServer::currentSocket = -1;
90 std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();
91 std::vector<yyparse_param_t>::iterator itCurrentSession = std::vector<yyparse_param_t>::iterator();
92 std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();
93 std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();
94 std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();
95 Mutex LSCPServer::NotifyMutex = Mutex();
96 Mutex LSCPServer::NotifyBufferMutex = Mutex();
97 Mutex LSCPServer::SubscriptionMutex = Mutex();
98 Mutex LSCPServer::RTNotifyMutex = Mutex();
99
100 LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4) {
101 SocketAddress.sin_family = AF_INET;
102 SocketAddress.sin_addr.s_addr = addr;
103 SocketAddress.sin_port = port;
104 this->pSampler = pSampler;
105 LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT");
106 LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO");
107 LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT");
108 LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO");
109 LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
110 LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
111 LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
112 LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
113 LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
114 LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_count, "FX_SEND_COUNT");
115 LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_info, "FX_SEND_INFO");
116 LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
117 LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
118 LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
119 LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
120 LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_count, "DB_INSTRUMENT_DIRECTORY_COUNT");
121 LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_info, "DB_INSTRUMENT_DIRECTORY_INFO");
122 LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_count, "DB_INSTRUMENT_COUNT");
123 LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_info, "DB_INSTRUMENT_INFO");
124 LSCPEvent::RegisterEvent(LSCPEvent::event_db_instrs_job_info, "DB_INSTRUMENTS_JOB_INFO");
125 LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
126 LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
127 LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");
128 hSocket = -1;
129 }
130
131 LSCPServer::~LSCPServer() {
132 if (hSocket >= 0) close(hSocket);
133 }
134
135 void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {
136 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));
137 }
138
139 void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {
140 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));
141 }
142
143 void LSCPServer::EventHandler::MidiDeviceCountChanged(int NewCount) {
144 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));
145 }
146
147 void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {
148 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));
149 }
150
151 void LSCPServer::EventHandler::MidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
152 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_info, MapId, Bank, Program));
153 }
154
155 void LSCPServer::EventHandler::MidiInstrumentMapCountChanged(int NewCount) {
156 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, NewCount));
157 }
158
159 void LSCPServer::EventHandler::MidiInstrumentMapInfoChanged(int MapId) {
160 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_info, MapId));
161 }
162
163 void LSCPServer::EventHandler::FxSendCountChanged(int ChannelId, int NewCount) {
164 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_count, ChannelId, NewCount));
165 }
166
167 void LSCPServer::EventHandler::VoiceCountChanged(int ChannelId, int NewCount) {
168 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, ChannelId, NewCount));
169 }
170
171 void LSCPServer::EventHandler::StreamCountChanged(int ChannelId, int NewCount) {
172 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, ChannelId, NewCount));
173 }
174
175 void LSCPServer::EventHandler::BufferFillChanged(int ChannelId, String FillData) {
176 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, ChannelId, FillData));
177 }
178
179 void LSCPServer::EventHandler::TotalVoiceCountChanged(int NewCount) {
180 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));
181 }
182
183 #if HAVE_SQLITE3
184 void LSCPServer::DbInstrumentsEventHandler::DirectoryCountChanged(String Dir) {
185 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_count, InstrumentsDb::toEscapedPath(Dir)));
186 }
187
188 void LSCPServer::DbInstrumentsEventHandler::DirectoryInfoChanged(String Dir) {
189 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, InstrumentsDb::toEscapedPath(Dir)));
190 }
191
192 void LSCPServer::DbInstrumentsEventHandler::DirectoryNameChanged(String Dir, String NewName) {
193 Dir = "'" + InstrumentsDb::toEscapedPath(Dir) + "'";
194 NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
195 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, "NAME", Dir, NewName));
196 }
197
198 void LSCPServer::DbInstrumentsEventHandler::InstrumentCountChanged(String Dir) {
199 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_count, InstrumentsDb::toEscapedPath(Dir)));
200 }
201
202 void LSCPServer::DbInstrumentsEventHandler::InstrumentInfoChanged(String Instr) {
203 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, InstrumentsDb::toEscapedPath(Instr)));
204 }
205
206 void LSCPServer::DbInstrumentsEventHandler::InstrumentNameChanged(String Instr, String NewName) {
207 Instr = "'" + InstrumentsDb::toEscapedPath(Instr) + "'";
208 NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
209 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, "NAME", Instr, NewName));
210 }
211
212 void LSCPServer::DbInstrumentsEventHandler::JobStatusChanged(int JobId) {
213 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instrs_job_info, JobId));
214 }
215 #endif // HAVE_SQLITE3
216
217
218 /**
219 * Blocks the calling thread until the LSCP Server is initialized and
220 * accepting socket connections, if the server is already initialized then
221 * this method will return immediately.
222 * @param TimeoutSeconds - optional: max. wait time in seconds
223 * (default: 0s)
224 * @param TimeoutNanoSeconds - optional: max wait time in nano seconds
225 * (default: 0ns)
226 * @returns 0 on success, a value less than 0 if timeout exceeded
227 */
228 int LSCPServer::WaitUntilInitialized(long TimeoutSeconds, long TimeoutNanoSeconds) {
229 return Initialized.WaitAndUnlockIf(false, TimeoutSeconds, TimeoutNanoSeconds);
230 }
231
232 int LSCPServer::Main() {
233 hSocket = socket(AF_INET, SOCK_STREAM, 0);
234 if (hSocket < 0) {
235 std::cerr << "LSCPServer: Could not create server socket." << std::endl;
236 //return -1;
237 exit(EXIT_FAILURE);
238 }
239
240 if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
241 std::cerr << "LSCPServer: Could not bind server socket, retrying for " << ToString(LSCP_SERVER_BIND_TIMEOUT) << " seconds...";
242 for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds
243 if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
244 if (trial > LSCP_SERVER_BIND_TIMEOUT) {
245 std::cerr << "gave up!" << std::endl;
246 close(hSocket);
247 //return -1;
248 exit(EXIT_FAILURE);
249 }
250 else sleep(1); // sleep 1s
251 }
252 else break; // success
253 }
254 }
255
256 listen(hSocket, 1);
257 Initialized.Set(true);
258
259 // Registering event listeners
260 pSampler->AddChannelCountListener(&eventHandler);
261 pSampler->AddAudioDeviceCountListener(&eventHandler);
262 pSampler->AddMidiDeviceCountListener(&eventHandler);
263 pSampler->AddVoiceCountListener(&eventHandler);
264 pSampler->AddStreamCountListener(&eventHandler);
265 pSampler->AddBufferFillListener(&eventHandler);
266 pSampler->AddTotalVoiceCountListener(&eventHandler);
267 pSampler->AddFxSendCountListener(&eventHandler);
268 MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);
269 MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);
270 MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);
271 MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);
272 #if HAVE_SQLITE3
273 InstrumentsDb::GetInstrumentsDb()->AddInstrumentsDbListener(&dbInstrumentsEventHandler);
274 #endif
275 // now wait for client connections and handle their requests
276 sockaddr_in client;
277 int length = sizeof(client);
278 FD_ZERO(&fdSet);
279 FD_SET(hSocket, &fdSet);
280 int maxSessions = hSocket;
281
282 timeval timeout;
283
284 while (true) {
285 // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
286 {
287 std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
288 std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
289 std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
290 for (; itEngineChannel != itEnd; ++itEngineChannel) {
291 if ((*itEngineChannel)->StatusChanged()) {
292 SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->iSamplerChannelIndex));
293 }
294
295 for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
296 FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
297 if(fxs != NULL && fxs->IsInfoChanged()) {
298 int chn = (*itEngineChannel)->iSamplerChannelIndex;
299 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));
300 fxs->SetInfoChanged(false);
301 }
302 }
303 }
304 }
305
306 //Now let's deliver late notifies (if any)
307 NotifyBufferMutex.Lock();
308 for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
309 #ifdef MSG_NOSIGNAL
310 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
311 #else
312 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
313 #endif
314 }
315 bufferedNotifies.clear();
316 NotifyBufferMutex.Unlock();
317
318 fd_set selectSet = fdSet;
319 timeout.tv_sec = 0;
320 timeout.tv_usec = 100000;
321
322 int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
323
324 if (retval == 0)
325 continue; //Nothing try again
326 if (retval == -1) {
327 std::cerr << "LSCPServer: Socket select error." << std::endl;
328 close(hSocket);
329 exit(EXIT_FAILURE);
330 }
331
332 //Accept new connections now (if any)
333 if (FD_ISSET(hSocket, &selectSet)) {
334 int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
335 if (socket < 0) {
336 std::cerr << "LSCPServer: Client connection failed." << std::endl;
337 exit(EXIT_FAILURE);
338 }
339
340 if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
341 std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
342 exit(EXIT_FAILURE);
343 }
344
345 // Parser initialization
346 yyparse_param_t yyparse_param;
347 yyparse_param.pServer = this;
348 yyparse_param.hSession = socket;
349
350 Sessions.push_back(yyparse_param);
351 FD_SET(socket, &fdSet);
352 if (socket > maxSessions)
353 maxSessions = socket;
354 dmsg(1,("LSCPServer: Client connection established on socket:%d.\n", socket));
355 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection established on socket", socket));
356 continue; //Maybe this was the only selected socket, better select again
357 }
358
359 //Something was selected and it was not the hSocket, so it must be some command(s) coming.
360 for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
361 if (FD_ISSET((*iter).hSession, &selectSet)) { //Was it this socket?
362 if (GetLSCPCommand(iter)) { //Have we read the entire command?
363 dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
364 int dummy; // just a temporary hack to fulfill the restart() function prototype
365 restart(NULL, dummy); // restart the 'scanner'
366 currentSocket = (*iter).hSession; //a hack
367 itCurrentSession = iter; // another hack
368 dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
369 if ((*iter).bVerbose) { // if echo mode enabled
370 AnswerClient(bufferedCommands[currentSocket]);
371 }
372 int result = yyparse(&(*iter));
373 currentSocket = -1; //continuation of a hack
374 itCurrentSession = Sessions.end(); // hack as well
375 dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
376 if (result == LSCP_QUIT) { //Was it a quit command by any chance?
377 CloseConnection(iter);
378 }
379 }
380 //socket may have been closed, iter may be invalid, get out of the loop for now.
381 //we'll be back if there is data.
382 break;
383 }
384 }
385 }
386 }
387
388 void LSCPServer::CloseConnection( std::vector<yyparse_param_t>::iterator iter ) {
389 int socket = (*iter).hSession;
390 dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));
391 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
392 Sessions.erase(iter);
393 FD_CLR(socket, &fdSet);
394 SubscriptionMutex.Lock(); //Must unsubscribe this socket from all events (if any)
395 for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
396 iter->second.remove(socket);
397 }
398 SubscriptionMutex.Unlock();
399 NotifyMutex.Lock();
400 bufferedCommands.erase(socket);
401 bufferedNotifies.erase(socket);
402 close(socket);
403 NotifyMutex.Unlock();
404 }
405
406 int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {
407 int subs = 0;
408 SubscriptionMutex.Lock();
409 for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();
410 iter != events.end(); iter++)
411 {
412 subs += eventSubscriptions.count(*iter);
413 }
414 SubscriptionMutex.Unlock();
415 return subs;
416 }
417
418 void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
419 SubscriptionMutex.Lock();
420 if (eventSubscriptions.count(event.GetType()) == 0) {
421 SubscriptionMutex.Unlock(); //Nobody is subscribed to this event
422 return;
423 }
424 std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();
425 std::list<int>::iterator end = eventSubscriptions[event.GetType()].end();
426 String notify = event.Produce();
427
428 while (true) {
429 if (NotifyMutex.Trylock()) {
430 for(;iter != end; iter++)
431 #ifdef MSG_NOSIGNAL
432 send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
433 #else
434 send(*iter, notify.c_str(), notify.size(), 0);
435 #endif
436 NotifyMutex.Unlock();
437 break;
438 } else {
439 if (NotifyBufferMutex.Trylock()) {
440 for(;iter != end; iter++)
441 bufferedNotifies[*iter] += notify;
442 NotifyBufferMutex.Unlock();
443 break;
444 }
445 }
446 }
447 SubscriptionMutex.Unlock();
448 }
449
450 extern int GetLSCPCommand( void *buf, int max_size ) {
451 String command = LSCPServer::bufferedCommands[LSCPServer::currentSocket];
452 if (command.size() == 0) { //Parser wants input but we have nothing.
453 strcpy((char*) buf, "\n"); //So give it an empty command
454 return 1; //to keep it happy.
455 }
456
457 if (max_size < command.size()) {
458 std::cerr << "getLSCPCommand: Flex buffer too small, ignoring the command." << std::endl;
459 return 0; //This will never happen
460 }
461
462 strcpy((char*) buf, command.c_str());
463 LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);
464 return command.size();
465 }
466
467 extern yyparse_param_t* GetCurrentYaccSession() {
468 return &(*itCurrentSession);
469 }
470
471 /**
472 * Will be called to try to read the command from the socket
473 * If command is read, it will return true. Otherwise false is returned.
474 * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.
475 */
476 bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
477 int socket = (*iter).hSession;
478 char c;
479 int i = 0;
480 while (true) {
481 int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now
482 if (result == 0) { //socket was selected, so 0 here means client has closed the connection
483 CloseConnection(iter);
484 break;
485 }
486 if (result == 1) {
487 if (c == '\r')
488 continue; //Ignore CR
489 if (c == '\n') {
490 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
491 bufferedCommands[socket] += "\r\n";
492 return true; //Complete command was read
493 }
494 bufferedCommands[socket] += c;
495 }
496 if (result == -1) {
497 if (errno == EAGAIN) //Would block, try again later.
498 return false;
499 switch(errno) {
500 case EBADF:
501 dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
502 break;
503 case ECONNREFUSED:
504 dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
505 break;
506 case ENOTCONN:
507 dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
508 break;
509 case ENOTSOCK:
510 dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
511 break;
512 case EAGAIN:
513 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"));
514 break;
515 case EINTR:
516 dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
517 break;
518 case EFAULT:
519 dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
520 break;
521 case EINVAL:
522 dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
523 break;
524 case ENOMEM:
525 dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
526 break;
527 default:
528 dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
529 break;
530 }
531 CloseConnection(iter);
532 break;
533 }
534 }
535 return false;
536 }
537
538 /**
539 * Will be called by the parser whenever it wants to send an answer to the
540 * client / frontend.
541 *
542 * @param ReturnMessage - message that will be send to the client
543 */
544 void LSCPServer::AnswerClient(String ReturnMessage) {
545 dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
546 if (currentSocket != -1) {
547 NotifyMutex.Lock();
548 #ifdef MSG_NOSIGNAL
549 send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
550 #else
551 send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
552 #endif
553 NotifyMutex.Unlock();
554 }
555 }
556
557 /**
558 * Find a created audio output device index.
559 */
560 int LSCPServer::GetAudioOutputDeviceIndex ( AudioOutputDevice *pDevice )
561 {
562 // Search for the created device to get its index
563 std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
564 std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
565 for (; iter != devices.end(); iter++) {
566 if (iter->second == pDevice)
567 return iter->first;
568 }
569 // Not found.
570 return -1;
571 }
572
573 /**
574 * Find a created midi input device index.
575 */
576 int LSCPServer::GetMidiInputDeviceIndex ( MidiInputDevice *pDevice )
577 {
578 // Search for the created device to get its index
579 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
580 std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
581 for (; iter != devices.end(); iter++) {
582 if (iter->second == pDevice)
583 return iter->first;
584 }
585 // Not found.
586 return -1;
587 }
588
589 String LSCPServer::CreateAudioOutputDevice(String Driver, std::map<String,String> Parameters) {
590 dmsg(2,("LSCPServer: CreateAudioOutputDevice(Driver=%s)\n", Driver.c_str()));
591 LSCPResultSet result;
592 try {
593 AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
594 // search for the created device to get its index
595 int index = GetAudioOutputDeviceIndex(pDevice);
596 if (index == -1) throw Exception("Internal error: could not find created audio output device.");
597 result = index; // success
598 }
599 catch (Exception e) {
600 result.Error(e);
601 }
602 return result.Produce();
603 }
604
605 String LSCPServer::CreateMidiInputDevice(String Driver, std::map<String,String> Parameters) {
606 dmsg(2,("LSCPServer: CreateMidiInputDevice(Driver=%s)\n", Driver.c_str()));
607 LSCPResultSet result;
608 try {
609 MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
610 // search for the created device to get its index
611 int index = GetMidiInputDeviceIndex(pDevice);
612 if (index == -1) throw Exception("Internal error: could not find created midi input device.");
613 result = index; // success
614 }
615 catch (Exception e) {
616 result.Error(e);
617 }
618 return result.Produce();
619 }
620
621 String LSCPServer::DestroyAudioOutputDevice(uint DeviceIndex) {
622 dmsg(2,("LSCPServer: DestroyAudioOutputDevice(DeviceIndex=%d)\n", DeviceIndex));
623 LSCPResultSet result;
624 try {
625 std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
626 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
627 AudioOutputDevice* pDevice = devices[DeviceIndex];
628 pSampler->DestroyAudioOutputDevice(pDevice);
629 }
630 catch (Exception e) {
631 result.Error(e);
632 }
633 return result.Produce();
634 }
635
636 String LSCPServer::DestroyMidiInputDevice(uint DeviceIndex) {
637 dmsg(2,("LSCPServer: DestroyMidiInputDevice(DeviceIndex=%d)\n", DeviceIndex));
638 LSCPResultSet result;
639 try {
640 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
641 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
642 MidiInputDevice* pDevice = devices[DeviceIndex];
643 pSampler->DestroyMidiInputDevice(pDevice);
644 }
645 catch (Exception e) {
646 result.Error(e);
647 }
648 return result.Produce();
649 }
650
651 EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
652 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
653 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
654
655 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
656 if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
657
658 return pEngineChannel;
659 }
660
661 /**
662 * Will be called by the parser to load an instrument.
663 */
664 String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel, bool bBackground) {
665 dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
666 LSCPResultSet result;
667 try {
668 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
669 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
670 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
671 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
672 if (!pSamplerChannel->GetAudioOutputDevice())
673 throw Exception("No audio output device connected to sampler channel");
674 if (bBackground) {
675 InstrumentManager::instrument_id_t id;
676 id.FileName = Filename;
677 id.Index = uiInstrument;
678 InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
679 }
680 else {
681 // tell the engine channel which instrument to load
682 pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrument);
683 // actually start to load the instrument (blocks until completed)
684 pEngineChannel->LoadInstrument();
685 }
686 }
687 catch (Exception e) {
688 result.Error(e);
689 }
690 return result.Produce();
691 }
692
693 /**
694 * Will be called by the parser to assign a sampler engine type to a
695 * sampler channel.
696 */
697 String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
698 dmsg(2,("LSCPServer: SetEngineType(EngineName=%s,uiSamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
699 LSCPResultSet result;
700 try {
701 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
702 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
703 LockRTNotify();
704 pSamplerChannel->SetEngineType(EngineName);
705 if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
706 UnlockRTNotify();
707 }
708 catch (Exception e) {
709 result.Error(e);
710 }
711 return result.Produce();
712 }
713
714 /**
715 * Will be called by the parser to get the amount of sampler channels.
716 */
717 String LSCPServer::GetChannels() {
718 dmsg(2,("LSCPServer: GetChannels()\n"));
719 LSCPResultSet result;
720 result.Add(pSampler->SamplerChannels());
721 return result.Produce();
722 }
723
724 /**
725 * Will be called by the parser to get the list of sampler channels.
726 */
727 String LSCPServer::ListChannels() {
728 dmsg(2,("LSCPServer: ListChannels()\n"));
729 String list;
730 std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
731 std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
732 for (; iter != channels.end(); iter++) {
733 if (list != "") list += ",";
734 list += ToString(iter->first);
735 }
736 LSCPResultSet result;
737 result.Add(list);
738 return result.Produce();
739 }
740
741 /**
742 * Will be called by the parser to add a sampler channel.
743 */
744 String LSCPServer::AddChannel() {
745 dmsg(2,("LSCPServer: AddChannel()\n"));
746 LockRTNotify();
747 SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
748 UnlockRTNotify();
749 LSCPResultSet result(pSamplerChannel->Index());
750 return result.Produce();
751 }
752
753 /**
754 * Will be called by the parser to remove a sampler channel.
755 */
756 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
757 dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
758 LSCPResultSet result;
759 LockRTNotify();
760 pSampler->RemoveSamplerChannel(uiSamplerChannel);
761 UnlockRTNotify();
762 return result.Produce();
763 }
764
765 /**
766 * Will be called by the parser to get the amount of all available engines.
767 */
768 String LSCPServer::GetAvailableEngines() {
769 dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
770 LSCPResultSet result;
771 try {
772 int n = EngineFactory::AvailableEngineTypes().size();
773 result.Add(n);
774 }
775 catch (Exception e) {
776 result.Error(e);
777 }
778 return result.Produce();
779 }
780
781 /**
782 * Will be called by the parser to get a list of all available engines.
783 */
784 String LSCPServer::ListAvailableEngines() {
785 dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
786 LSCPResultSet result;
787 try {
788 String s = EngineFactory::AvailableEngineTypesAsString();
789 result.Add(s);
790 }
791 catch (Exception e) {
792 result.Error(e);
793 }
794 return result.Produce();
795 }
796
797 /**
798 * Will be called by the parser to get descriptions for a particular
799 * sampler engine.
800 */
801 String LSCPServer::GetEngineInfo(String EngineName) {
802 dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
803 LSCPResultSet result;
804 LockRTNotify();
805 try {
806 Engine* pEngine = EngineFactory::Create(EngineName);
807 result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
808 result.Add("VERSION", pEngine->Version());
809 EngineFactory::Destroy(pEngine);
810 }
811 catch (Exception e) {
812 result.Error(e);
813 }
814 UnlockRTNotify();
815 return result.Produce();
816 }
817
818 /**
819 * Will be called by the parser to get informations about a particular
820 * sampler channel.
821 */
822 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
823 dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
824 LSCPResultSet result;
825 try {
826 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
827 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
828 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
829
830 //Defaults values
831 String EngineName = "NONE";
832 float Volume = 0.0f;
833 String InstrumentFileName = "NONE";
834 String InstrumentName = "NONE";
835 int InstrumentIndex = -1;
836 int InstrumentStatus = -1;
837 int AudioOutputChannels = 0;
838 String AudioRouting;
839 int Mute = 0;
840 bool Solo = false;
841 String MidiInstrumentMap = "NONE";
842
843 if (pEngineChannel) {
844 EngineName = pEngineChannel->EngineName();
845 AudioOutputChannels = pEngineChannel->Channels();
846 Volume = pEngineChannel->Volume();
847 InstrumentStatus = pEngineChannel->InstrumentStatus();
848 InstrumentIndex = pEngineChannel->InstrumentIndex();
849 if (InstrumentIndex != -1) {
850 InstrumentFileName = pEngineChannel->InstrumentFileName();
851 InstrumentName = pEngineChannel->InstrumentName();
852 }
853 for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
854 if (AudioRouting != "") AudioRouting += ",";
855 AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
856 }
857 Mute = pEngineChannel->GetMute();
858 Solo = pEngineChannel->GetSolo();
859 if (pEngineChannel->UsesNoMidiInstrumentMap())
860 MidiInstrumentMap = "NONE";
861 else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
862 MidiInstrumentMap = "DEFAULT";
863 else
864 MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
865 }
866
867 result.Add("ENGINE_NAME", EngineName);
868 result.Add("VOLUME", Volume);
869
870 //Some not-so-hardcoded stuff to make GUI look good
871 result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
872 result.Add("AUDIO_OUTPUT_CHANNELS", AudioOutputChannels);
873 result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
874
875 result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
876 result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
877 if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
878 else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
879
880 result.Add("INSTRUMENT_FILE",
881 (InstrumentFileName != "NONE" && InstrumentFileName != "") ?
882 Path::fromPosix(InstrumentFileName).toLscp() : // TODO: assuming POSIX
883 InstrumentFileName
884 );
885 result.Add("INSTRUMENT_NR", InstrumentIndex);
886 result.Add("INSTRUMENT_NAME", _escapeLscpResponse(InstrumentName));
887 result.Add("INSTRUMENT_STATUS", InstrumentStatus);
888 result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
889 result.Add("SOLO", Solo);
890 result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
891 }
892 catch (Exception e) {
893 result.Error(e);
894 }
895 return result.Produce();
896 }
897
898 /**
899 * Will be called by the parser to get the amount of active voices on a
900 * particular sampler channel.
901 */
902 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
903 dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
904 LSCPResultSet result;
905 try {
906 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
907 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
908 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
909 if (!pEngineChannel) throw Exception("No engine loaded on sampler channel");
910 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
911 result.Add(pEngineChannel->GetEngine()->VoiceCount());
912 }
913 catch (Exception e) {
914 result.Error(e);
915 }
916 return result.Produce();
917 }
918
919 /**
920 * Will be called by the parser to get the amount of active disk streams on a
921 * particular sampler channel.
922 */
923 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
924 dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
925 LSCPResultSet result;
926 try {
927 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
928 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
929 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
930 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
931 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
932 result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
933 }
934 catch (Exception e) {
935 result.Error(e);
936 }
937 return result.Produce();
938 }
939
940 /**
941 * Will be called by the parser to get the buffer fill states of all disk
942 * streams on a particular sampler channel.
943 */
944 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
945 dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
946 LSCPResultSet result;
947 try {
948 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
949 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
950 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
951 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
952 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
953 if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
954 else {
955 switch (ResponseType) {
956 case fill_response_bytes:
957 result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillBytes());
958 break;
959 case fill_response_percentage:
960 result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
961 break;
962 default:
963 throw Exception("Unknown fill response type");
964 }
965 }
966 }
967 catch (Exception e) {
968 result.Error(e);
969 }
970 return result.Produce();
971 }
972
973 String LSCPServer::GetAvailableAudioOutputDrivers() {
974 dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
975 LSCPResultSet result;
976 try {
977 int n = AudioOutputDeviceFactory::AvailableDrivers().size();
978 result.Add(n);
979 }
980 catch (Exception e) {
981 result.Error(e);
982 }
983 return result.Produce();
984 }
985
986 String LSCPServer::ListAvailableAudioOutputDrivers() {
987 dmsg(2,("LSCPServer: ListAvailableAudioOutputDrivers()\n"));
988 LSCPResultSet result;
989 try {
990 String s = AudioOutputDeviceFactory::AvailableDriversAsString();
991 result.Add(s);
992 }
993 catch (Exception e) {
994 result.Error(e);
995 }
996 return result.Produce();
997 }
998
999 String LSCPServer::GetAvailableMidiInputDrivers() {
1000 dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
1001 LSCPResultSet result;
1002 try {
1003 int n = MidiInputDeviceFactory::AvailableDrivers().size();
1004 result.Add(n);
1005 }
1006 catch (Exception e) {
1007 result.Error(e);
1008 }
1009 return result.Produce();
1010 }
1011
1012 String LSCPServer::ListAvailableMidiInputDrivers() {
1013 dmsg(2,("LSCPServer: ListAvailableMidiInputDrivers()\n"));
1014 LSCPResultSet result;
1015 try {
1016 String s = MidiInputDeviceFactory::AvailableDriversAsString();
1017 result.Add(s);
1018 }
1019 catch (Exception e) {
1020 result.Error(e);
1021 }
1022 return result.Produce();
1023 }
1024
1025 String LSCPServer::GetMidiInputDriverInfo(String Driver) {
1026 dmsg(2,("LSCPServer: GetMidiInputDriverInfo(Driver=%s)\n",Driver.c_str()));
1027 LSCPResultSet result;
1028 try {
1029 result.Add("DESCRIPTION", MidiInputDeviceFactory::GetDriverDescription(Driver));
1030 result.Add("VERSION", MidiInputDeviceFactory::GetDriverVersion(Driver));
1031
1032 std::map<String,DeviceCreationParameter*> parameters = MidiInputDeviceFactory::GetAvailableDriverParameters(Driver);
1033 if (parameters.size()) { // if there are parameters defined for this driver
1034 String s;
1035 std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1036 for (;iter != parameters.end(); iter++) {
1037 if (s != "") s += ",";
1038 s += iter->first;
1039 }
1040 result.Add("PARAMETERS", s);
1041 }
1042 }
1043 catch (Exception e) {
1044 result.Error(e);
1045 }
1046 return result.Produce();
1047 }
1048
1049 String LSCPServer::GetAudioOutputDriverInfo(String Driver) {
1050 dmsg(2,("LSCPServer: GetAudioOutputDriverInfo(Driver=%s)\n",Driver.c_str()));
1051 LSCPResultSet result;
1052 try {
1053 result.Add("DESCRIPTION", AudioOutputDeviceFactory::GetDriverDescription(Driver));
1054 result.Add("VERSION", AudioOutputDeviceFactory::GetDriverVersion(Driver));
1055
1056 std::map<String,DeviceCreationParameter*> parameters = AudioOutputDeviceFactory::GetAvailableDriverParameters(Driver);
1057 if (parameters.size()) { // if there are parameters defined for this driver
1058 String s;
1059 std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1060 for (;iter != parameters.end(); iter++) {
1061 if (s != "") s += ",";
1062 s += iter->first;
1063 }
1064 result.Add("PARAMETERS", s);
1065 }
1066 }
1067 catch (Exception e) {
1068 result.Error(e);
1069 }
1070 return result.Produce();
1071 }
1072
1073 String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1074 dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
1075 LSCPResultSet result;
1076 try {
1077 DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
1078 result.Add("TYPE", pParameter->Type());
1079 result.Add("DESCRIPTION", pParameter->Description());
1080 result.Add("MANDATORY", pParameter->Mandatory());
1081 result.Add("FIX", pParameter->Fix());
1082 result.Add("MULTIPLICITY", pParameter->Multiplicity());
1083 optional<String> oDepends = pParameter->Depends();
1084 optional<String> oDefault = pParameter->Default(DependencyList);
1085 optional<String> oRangeMin = pParameter->RangeMin(DependencyList);
1086 optional<String> oRangeMax = pParameter->RangeMax(DependencyList);
1087 optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1088 if (oDepends) result.Add("DEPENDS", *oDepends);
1089 if (oDefault) result.Add("DEFAULT", *oDefault);
1090 if (oRangeMin) result.Add("RANGE_MIN", *oRangeMin);
1091 if (oRangeMax) result.Add("RANGE_MAX", *oRangeMax);
1092 if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1093 }
1094 catch (Exception e) {
1095 result.Error(e);
1096 }
1097 return result.Produce();
1098 }
1099
1100 String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1101 dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
1102 LSCPResultSet result;
1103 try {
1104 DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
1105 result.Add("TYPE", pParameter->Type());
1106 result.Add("DESCRIPTION", pParameter->Description());
1107 result.Add("MANDATORY", pParameter->Mandatory());
1108 result.Add("FIX", pParameter->Fix());
1109 result.Add("MULTIPLICITY", pParameter->Multiplicity());
1110 optional<String> oDepends = pParameter->Depends();
1111 optional<String> oDefault = pParameter->Default(DependencyList);
1112 optional<String> oRangeMin = pParameter->RangeMin(DependencyList);
1113 optional<String> oRangeMax = pParameter->RangeMax(DependencyList);
1114 optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1115 if (oDepends) result.Add("DEPENDS", *oDepends);
1116 if (oDefault) result.Add("DEFAULT", *oDefault);
1117 if (oRangeMin) result.Add("RANGE_MIN", *oRangeMin);
1118 if (oRangeMax) result.Add("RANGE_MAX", *oRangeMax);
1119 if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1120 }
1121 catch (Exception e) {
1122 result.Error(e);
1123 }
1124 return result.Produce();
1125 }
1126
1127 String LSCPServer::GetAudioOutputDeviceCount() {
1128 dmsg(2,("LSCPServer: GetAudioOutputDeviceCount()\n"));
1129 LSCPResultSet result;
1130 try {
1131 uint count = pSampler->AudioOutputDevices();
1132 result.Add(count); // success
1133 }
1134 catch (Exception e) {
1135 result.Error(e);
1136 }
1137 return result.Produce();
1138 }
1139
1140 String LSCPServer::GetMidiInputDeviceCount() {
1141 dmsg(2,("LSCPServer: GetMidiInputDeviceCount()\n"));
1142 LSCPResultSet result;
1143 try {
1144 uint count = pSampler->MidiInputDevices();
1145 result.Add(count); // success
1146 }
1147 catch (Exception e) {
1148 result.Error(e);
1149 }
1150 return result.Produce();
1151 }
1152
1153 String LSCPServer::GetAudioOutputDevices() {
1154 dmsg(2,("LSCPServer: GetAudioOutputDevices()\n"));
1155 LSCPResultSet result;
1156 try {
1157 String s;
1158 std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1159 std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1160 for (; iter != devices.end(); iter++) {
1161 if (s != "") s += ",";
1162 s += ToString(iter->first);
1163 }
1164 result.Add(s);
1165 }
1166 catch (Exception e) {
1167 result.Error(e);
1168 }
1169 return result.Produce();
1170 }
1171
1172 String LSCPServer::GetMidiInputDevices() {
1173 dmsg(2,("LSCPServer: GetMidiInputDevices()\n"));
1174 LSCPResultSet result;
1175 try {
1176 String s;
1177 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1178 std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1179 for (; iter != devices.end(); iter++) {
1180 if (s != "") s += ",";
1181 s += ToString(iter->first);
1182 }
1183 result.Add(s);
1184 }
1185 catch (Exception e) {
1186 result.Error(e);
1187 }
1188 return result.Produce();
1189 }
1190
1191 String LSCPServer::GetAudioOutputDeviceInfo(uint DeviceIndex) {
1192 dmsg(2,("LSCPServer: GetAudioOutputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1193 LSCPResultSet result;
1194 try {
1195 std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1196 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1197 AudioOutputDevice* pDevice = devices[DeviceIndex];
1198 result.Add("DRIVER", pDevice->Driver());
1199 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1200 std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1201 for (; iter != parameters.end(); iter++) {
1202 result.Add(iter->first, iter->second->Value());
1203 }
1204 }
1205 catch (Exception e) {
1206 result.Error(e);
1207 }
1208 return result.Produce();
1209 }
1210
1211 String LSCPServer::GetMidiInputDeviceInfo(uint DeviceIndex) {
1212 dmsg(2,("LSCPServer: GetMidiInputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1213 LSCPResultSet result;
1214 try {
1215 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1216 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1217 MidiInputDevice* pDevice = devices[DeviceIndex];
1218 result.Add("DRIVER", pDevice->Driver());
1219 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1220 std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1221 for (; iter != parameters.end(); iter++) {
1222 result.Add(iter->first, iter->second->Value());
1223 }
1224 }
1225 catch (Exception e) {
1226 result.Error(e);
1227 }
1228 return result.Produce();
1229 }
1230 String LSCPServer::GetMidiInputPortInfo(uint DeviceIndex, uint PortIndex) {
1231 dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
1232 LSCPResultSet result;
1233 try {
1234 // get MIDI input device
1235 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1236 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1237 MidiInputDevice* pDevice = devices[DeviceIndex];
1238
1239 // get MIDI port
1240 MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1241 if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1242
1243 // return the values of all MIDI port parameters
1244 std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1245 std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1246 for (; iter != parameters.end(); iter++) {
1247 result.Add(iter->first, iter->second->Value());
1248 }
1249 }
1250 catch (Exception e) {
1251 result.Error(e);
1252 }
1253 return result.Produce();
1254 }
1255
1256 String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
1257 dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%d,ChannelId)\n",DeviceId,ChannelId));
1258 LSCPResultSet result;
1259 try {
1260 // get audio output device
1261 std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1262 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1263 AudioOutputDevice* pDevice = devices[DeviceId];
1264
1265 // get audio channel
1266 AudioChannel* pChannel = pDevice->Channel(ChannelId);
1267 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1268
1269 // return the values of all audio channel parameters
1270 std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1271 std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1272 for (; iter != parameters.end(); iter++) {
1273 result.Add(iter->first, iter->second->Value());
1274 }
1275 }
1276 catch (Exception e) {
1277 result.Error(e);
1278 }
1279 return result.Produce();
1280 }
1281
1282 String LSCPServer::GetMidiInputPortParameterInfo(uint DeviceId, uint PortId, String ParameterName) {
1283 dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
1284 LSCPResultSet result;
1285 try {
1286 // get MIDI input device
1287 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1288 if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1289 MidiInputDevice* pDevice = devices[DeviceId];
1290
1291 // get midi port
1292 MidiInputPort* pPort = pDevice->GetPort(PortId);
1293 if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1294
1295 // get desired port parameter
1296 std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1297 if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1298 DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1299
1300 // return all fields of this audio channel parameter
1301 result.Add("TYPE", pParameter->Type());
1302 result.Add("DESCRIPTION", pParameter->Description());
1303 result.Add("FIX", pParameter->Fix());
1304 result.Add("MULTIPLICITY", pParameter->Multiplicity());
1305 if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
1306 if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
1307 if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1308 }
1309 catch (Exception e) {
1310 result.Error(e);
1311 }
1312 return result.Produce();
1313 }
1314
1315 String LSCPServer::GetAudioOutputChannelParameterInfo(uint DeviceId, uint ChannelId, String ParameterName) {
1316 dmsg(2,("LSCPServer: GetAudioOutputChannelParameterInfo(DeviceId=%d,ChannelId=%d,ParameterName=%s)\n",DeviceId,ChannelId,ParameterName.c_str()));
1317 LSCPResultSet result;
1318 try {
1319 // get audio output device
1320 std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1321 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1322 AudioOutputDevice* pDevice = devices[DeviceId];
1323
1324 // get audio channel
1325 AudioChannel* pChannel = pDevice->Channel(ChannelId);
1326 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1327
1328 // get desired audio channel parameter
1329 std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1330 if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1331 DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1332
1333 // return all fields of this audio channel parameter
1334 result.Add("TYPE", pParameter->Type());
1335 result.Add("DESCRIPTION", pParameter->Description());
1336 result.Add("FIX", pParameter->Fix());
1337 result.Add("MULTIPLICITY", pParameter->Multiplicity());
1338 if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
1339 if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
1340 if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1341 }
1342 catch (Exception e) {
1343 result.Error(e);
1344 }
1345 return result.Produce();
1346 }
1347
1348 String LSCPServer::SetAudioOutputChannelParameter(uint DeviceId, uint ChannelId, String ParamKey, String ParamVal) {
1349 dmsg(2,("LSCPServer: SetAudioOutputChannelParameter(DeviceId=%d,ChannelId=%d,ParamKey=%s,ParamVal=%s)\n",DeviceId,ChannelId,ParamKey.c_str(),ParamVal.c_str()));
1350 LSCPResultSet result;
1351 try {
1352 // get audio output device
1353 std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1354 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1355 AudioOutputDevice* pDevice = devices[DeviceId];
1356
1357 // get audio channel
1358 AudioChannel* pChannel = pDevice->Channel(ChannelId);
1359 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1360
1361 // get desired audio channel parameter
1362 std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1363 if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1364 DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1365
1366 // set new channel parameter value
1367 pParameter->SetValue(ParamVal);
1368 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1369 }
1370 catch (Exception e) {
1371 result.Error(e);
1372 }
1373 return result.Produce();
1374 }
1375
1376 String LSCPServer::SetAudioOutputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1377 dmsg(2,("LSCPServer: SetAudioOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1378 LSCPResultSet result;
1379 try {
1380 std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1381 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1382 AudioOutputDevice* pDevice = devices[DeviceIndex];
1383 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1384 if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1385 parameters[ParamKey]->SetValue(ParamVal);
1386 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1387 }
1388 catch (Exception e) {
1389 result.Error(e);
1390 }
1391 return result.Produce();
1392 }
1393
1394 String LSCPServer::SetMidiInputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1395 dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1396 LSCPResultSet result;
1397 try {
1398 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1399 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1400 MidiInputDevice* pDevice = devices[DeviceIndex];
1401 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1402 if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1403 parameters[ParamKey]->SetValue(ParamVal);
1404 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1405 }
1406 catch (Exception e) {
1407 result.Error(e);
1408 }
1409 return result.Produce();
1410 }
1411
1412 String LSCPServer::SetMidiInputPortParameter(uint DeviceIndex, uint PortIndex, String ParamKey, String ParamVal) {
1413 dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1414 LSCPResultSet result;
1415 try {
1416 // get MIDI input device
1417 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1418 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1419 MidiInputDevice* pDevice = devices[DeviceIndex];
1420
1421 // get MIDI port
1422 MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1423 if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1424
1425 // set port parameter value
1426 std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1427 if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1428 parameters[ParamKey]->SetValue(ParamVal);
1429 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1430 }
1431 catch (Exception e) {
1432 result.Error(e);
1433 }
1434 return result.Produce();
1435 }
1436
1437 /**
1438 * Will be called by the parser to change the audio output channel for
1439 * playback on a particular sampler channel.
1440 */
1441 String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1442 dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1443 LSCPResultSet result;
1444 try {
1445 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1446 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1447 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1448 if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1449 if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1450 pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1451 }
1452 catch (Exception e) {
1453 result.Error(e);
1454 }
1455 return result.Produce();
1456 }
1457
1458 String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1459 dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1460 LSCPResultSet result;
1461 LockRTNotify();
1462 try {
1463 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1464 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1465 std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1466 if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1467 AudioOutputDevice* pDevice = devices[AudioDeviceId];
1468 pSamplerChannel->SetAudioOutputDevice(pDevice);
1469 }
1470 catch (Exception e) {
1471 result.Error(e);
1472 }
1473 UnlockRTNotify();
1474 return result.Produce();
1475 }
1476
1477 String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1478 dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1479 LSCPResultSet result;
1480 LockRTNotify();
1481 try {
1482 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1483 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1484 // Driver type name aliasing...
1485 if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1486 if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1487 // Check if there's one audio output device already created
1488 // for the intended audio driver type (AudioOutputDriver)...
1489 AudioOutputDevice *pDevice = NULL;
1490 std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1491 std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1492 for (; iter != devices.end(); iter++) {
1493 if ((iter->second)->Driver() == AudioOutputDriver) {
1494 pDevice = iter->second;
1495 break;
1496 }
1497 }
1498 // If it doesn't exist, create a new one with default parameters...
1499 if (pDevice == NULL) {
1500 std::map<String,String> params;
1501 pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1502 }
1503 // Must have a device...
1504 if (pDevice == NULL)
1505 throw Exception("Internal error: could not create audio output device.");
1506 // Set it as the current channel device...
1507 pSamplerChannel->SetAudioOutputDevice(pDevice);
1508 }
1509 catch (Exception e) {
1510 result.Error(e);
1511 }
1512 UnlockRTNotify();
1513 return result.Produce();
1514 }
1515
1516 String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
1517 dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
1518 LSCPResultSet result;
1519 try {
1520 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1521 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1522 pSamplerChannel->SetMidiInputPort(MIDIPort);
1523 }
1524 catch (Exception e) {
1525 result.Error(e);
1526 }
1527 return result.Produce();
1528 }
1529
1530 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
1531 dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
1532 LSCPResultSet result;
1533 try {
1534 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1535 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1536 pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
1537 }
1538 catch (Exception e) {
1539 result.Error(e);
1540 }
1541 return result.Produce();
1542 }
1543
1544 String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
1545 dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
1546 LSCPResultSet result;
1547 try {
1548 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1549 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1550 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1551 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1552 MidiInputDevice* pDevice = devices[MIDIDeviceId];
1553 pSamplerChannel->SetMidiInputDevice(pDevice);
1554 }
1555 catch (Exception e) {
1556 result.Error(e);
1557 }
1558 return result.Produce();
1559 }
1560
1561 String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
1562 dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
1563 LSCPResultSet result;
1564 try {
1565 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1566 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1567 // Driver type name aliasing...
1568 if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
1569 // Check if there's one MIDI input device already created
1570 // for the intended MIDI driver type (MidiInputDriver)...
1571 MidiInputDevice *pDevice = NULL;
1572 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1573 std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1574 for (; iter != devices.end(); iter++) {
1575 if ((iter->second)->Driver() == MidiInputDriver) {
1576 pDevice = iter->second;
1577 break;
1578 }
1579 }
1580 // If it doesn't exist, create a new one with default parameters...
1581 if (pDevice == NULL) {
1582 std::map<String,String> params;
1583 pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1584 // Make it with at least one initial port.
1585 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1586 parameters["PORTS"]->SetValue("1");
1587 }
1588 // Must have a device...
1589 if (pDevice == NULL)
1590 throw Exception("Internal error: could not create MIDI input device.");
1591 // Set it as the current channel device...
1592 pSamplerChannel->SetMidiInputDevice(pDevice);
1593 }
1594 catch (Exception e) {
1595 result.Error(e);
1596 }
1597 return result.Produce();
1598 }
1599
1600 /**
1601 * Will be called by the parser to change the MIDI input device, port and channel on which
1602 * engine of a particular sampler channel should listen to.
1603 */
1604 String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
1605 dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
1606 LSCPResultSet result;
1607 try {
1608 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1609 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1610 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1611 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1612 MidiInputDevice* pDevice = devices[MIDIDeviceId];
1613 pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
1614 }
1615 catch (Exception e) {
1616 result.Error(e);
1617 }
1618 return result.Produce();
1619 }
1620
1621 /**
1622 * Will be called by the parser to change the global volume factor on a
1623 * particular sampler channel.
1624 */
1625 String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
1626 dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
1627 LSCPResultSet result;
1628 try {
1629 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1630 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1631 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1632 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1633 pEngineChannel->Volume(dVolume);
1634 }
1635 catch (Exception e) {
1636 result.Error(e);
1637 }
1638 return result.Produce();
1639 }
1640
1641 /**
1642 * Will be called by the parser to mute/unmute particular sampler channel.
1643 */
1644 String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
1645 dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
1646 LSCPResultSet result;
1647 try {
1648 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1649 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1650
1651 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1652 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1653
1654 if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
1655 else pEngineChannel->SetMute(1);
1656 } catch (Exception e) {
1657 result.Error(e);
1658 }
1659 return result.Produce();
1660 }
1661
1662 /**
1663 * Will be called by the parser to solo particular sampler channel.
1664 */
1665 String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
1666 dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
1667 LSCPResultSet result;
1668 try {
1669 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1670 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1671
1672 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1673 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1674
1675 bool oldSolo = pEngineChannel->GetSolo();
1676 bool hadSoloChannel = HasSoloChannel();
1677
1678 pEngineChannel->SetSolo(bSolo);
1679
1680 if(!oldSolo && bSolo) {
1681 if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
1682 if(!hadSoloChannel) MuteNonSoloChannels();
1683 }
1684
1685 if(oldSolo && !bSolo) {
1686 if(!HasSoloChannel()) UnmuteChannels();
1687 else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
1688 }
1689 } catch (Exception e) {
1690 result.Error(e);
1691 }
1692 return result.Produce();
1693 }
1694
1695 /**
1696 * Determines whether there is at least one solo channel in the channel list.
1697 *
1698 * @returns true if there is at least one solo channel in the channel list,
1699 * false otherwise.
1700 */
1701 bool LSCPServer::HasSoloChannel() {
1702 std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1703 std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1704 for (; iter != channels.end(); iter++) {
1705 EngineChannel* c = iter->second->GetEngineChannel();
1706 if(c && c->GetSolo()) return true;
1707 }
1708
1709 return false;
1710 }
1711
1712 /**
1713 * Mutes all unmuted non-solo channels. Notice that the channels are muted
1714 * with -1 which indicates that they are muted because of the presence
1715 * of a solo channel(s). Channels muted with -1 will be automatically unmuted
1716 * when there are no solo channels left.
1717 */
1718 void LSCPServer::MuteNonSoloChannels() {
1719 dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
1720 std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1721 std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1722 for (; iter != channels.end(); iter++) {
1723 EngineChannel* c = iter->second->GetEngineChannel();
1724 if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
1725 }
1726 }
1727
1728 /**
1729 * Unmutes all channels that are muted because of the presence
1730 * of a solo channel(s).
1731 */
1732 void LSCPServer::UnmuteChannels() {
1733 dmsg(2,("LSCPServer: UnmuteChannels()\n"));
1734 std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1735 std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1736 for (; iter != channels.end(); iter++) {
1737 EngineChannel* c = iter->second->GetEngineChannel();
1738 if(c && c->GetMute() == -1) c->SetMute(0);
1739 }
1740 }
1741
1742 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) {
1743 dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
1744
1745 midi_prog_index_t idx;
1746 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1747 idx.midi_bank_lsb = MidiBank & 0x7f;
1748 idx.midi_prog = MidiProg;
1749
1750 MidiInstrumentMapper::entry_t entry;
1751 entry.EngineName = EngineType;
1752 entry.InstrumentFile = InstrumentFile;
1753 entry.InstrumentIndex = InstrumentIndex;
1754 entry.LoadMode = LoadMode;
1755 entry.Volume = Volume;
1756 entry.Name = Name;
1757
1758 LSCPResultSet result;
1759 try {
1760 // PERSISTENT mapping commands might block for a long time, so in
1761 // that case we add/replace the mapping in another thread in case
1762 // the NON_MODAL argument was supplied, non persistent mappings
1763 // should return immediately, so we don't need to do that for them
1764 bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
1765 MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
1766 } catch (Exception e) {
1767 result.Error(e);
1768 }
1769 return result.Produce();
1770 }
1771
1772 String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
1773 dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
1774
1775 midi_prog_index_t idx;
1776 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1777 idx.midi_bank_lsb = MidiBank & 0x7f;
1778 idx.midi_prog = MidiProg;
1779
1780 LSCPResultSet result;
1781 try {
1782 MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
1783 } catch (Exception e) {
1784 result.Error(e);
1785 }
1786 return result.Produce();
1787 }
1788
1789 String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
1790 dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
1791 LSCPResultSet result;
1792 try {
1793 result.Add(MidiInstrumentMapper::Entries(MidiMapID).size());
1794 } catch (Exception e) {
1795 result.Error(e);
1796 }
1797 return result.Produce();
1798 }
1799
1800
1801 String LSCPServer::GetAllMidiInstrumentMappings() {
1802 dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
1803 LSCPResultSet result;
1804 std::vector<int> maps = MidiInstrumentMapper::Maps();
1805 int totalMappings = 0;
1806 for (int i = 0; i < maps.size(); i++) {
1807 try {
1808 totalMappings += MidiInstrumentMapper::Entries(maps[i]).size();
1809 } catch (Exception e) { /*NOOP*/ }
1810 }
1811 result.Add(totalMappings);
1812 return result.Produce();
1813 }
1814
1815 String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
1816 dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
1817 LSCPResultSet result;
1818 try {
1819 midi_prog_index_t idx;
1820 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1821 idx.midi_bank_lsb = MidiBank & 0x7f;
1822 idx.midi_prog = MidiProg;
1823
1824 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
1825 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.find(idx);
1826 if (iter == mappings.end()) result.Error("there is no map entry with that index");
1827 else { // found
1828 result.Add("NAME", _escapeLscpResponse(iter->second.Name));
1829 result.Add("ENGINE_NAME", iter->second.EngineName);
1830 result.Add("INSTRUMENT_FILE", Path::fromPosix(iter->second.InstrumentFile).toLscp()); //TODO: assuming POSIX
1831 result.Add("INSTRUMENT_NR", (int) iter->second.InstrumentIndex);
1832 String instrumentName;
1833 Engine* pEngine = EngineFactory::Create(iter->second.EngineName);
1834 if (pEngine) {
1835 if (pEngine->GetInstrumentManager()) {
1836 InstrumentManager::instrument_id_t instrID;
1837 instrID.FileName = iter->second.InstrumentFile;
1838 instrID.Index = iter->second.InstrumentIndex;
1839 instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
1840 }
1841 EngineFactory::Destroy(pEngine);
1842 }
1843 result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
1844 switch (iter->second.LoadMode) {
1845 case MidiInstrumentMapper::ON_DEMAND:
1846 result.Add("LOAD_MODE", "ON_DEMAND");
1847 break;
1848 case MidiInstrumentMapper::ON_DEMAND_HOLD:
1849 result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
1850 break;
1851 case MidiInstrumentMapper::PERSISTENT:
1852 result.Add("LOAD_MODE", "PERSISTENT");
1853 break;
1854 default:
1855 throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
1856 }
1857 result.Add("VOLUME", iter->second.Volume);
1858 }
1859 } catch (Exception e) {
1860 result.Error(e);
1861 }
1862 return result.Produce();
1863 }
1864
1865 String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
1866 dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
1867 LSCPResultSet result;
1868 try {
1869 String s;
1870 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
1871 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
1872 for (; iter != mappings.end(); iter++) {
1873 if (s.size()) s += ",";
1874 s += "{" + ToString(MidiMapID) + ","
1875 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
1876 + ToString(int(iter->first.midi_prog)) + "}";
1877 }
1878 result.Add(s);
1879 } catch (Exception e) {
1880 result.Error(e);
1881 }
1882 return result.Produce();
1883 }
1884
1885 String LSCPServer::ListAllMidiInstrumentMappings() {
1886 dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
1887 LSCPResultSet result;
1888 try {
1889 std::vector<int> maps = MidiInstrumentMapper::Maps();
1890 String s;
1891 for (int i = 0; i < maps.size(); i++) {
1892 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
1893 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
1894 for (; iter != mappings.end(); iter++) {
1895 if (s.size()) s += ",";
1896 s += "{" + ToString(maps[i]) + ","
1897 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
1898 + ToString(int(iter->first.midi_prog)) + "}";
1899 }
1900 }
1901 result.Add(s);
1902 } catch (Exception e) {
1903 result.Error(e);
1904 }
1905 return result.Produce();
1906 }
1907
1908 String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
1909 dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
1910 LSCPResultSet result;
1911 try {
1912 MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
1913 } catch (Exception e) {
1914 result.Error(e);
1915 }
1916 return result.Produce();
1917 }
1918
1919 String LSCPServer::ClearAllMidiInstrumentMappings() {
1920 dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
1921 LSCPResultSet result;
1922 try {
1923 std::vector<int> maps = MidiInstrumentMapper::Maps();
1924 for (int i = 0; i < maps.size(); i++)
1925 MidiInstrumentMapper::RemoveAllEntries(maps[i]);
1926 } catch (Exception e) {
1927 result.Error(e);
1928 }
1929 return result.Produce();
1930 }
1931
1932 String LSCPServer::AddMidiInstrumentMap(String MapName) {
1933 dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
1934 LSCPResultSet result;
1935 try {
1936 int MapID = MidiInstrumentMapper::AddMap(MapName);
1937 result = LSCPResultSet(MapID);
1938 } catch (Exception e) {
1939 result.Error(e);
1940 }
1941 return result.Produce();
1942 }
1943
1944 String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
1945 dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
1946 LSCPResultSet result;
1947 try {
1948 MidiInstrumentMapper::RemoveMap(MidiMapID);
1949 } catch (Exception e) {
1950 result.Error(e);
1951 }
1952 return result.Produce();
1953 }
1954
1955 String LSCPServer::RemoveAllMidiInstrumentMaps() {
1956 dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
1957 LSCPResultSet result;
1958 try {
1959 MidiInstrumentMapper::RemoveAllMaps();
1960 } catch (Exception e) {
1961 result.Error(e);
1962 }
1963 return result.Produce();
1964 }
1965
1966 String LSCPServer::GetMidiInstrumentMaps() {
1967 dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
1968 LSCPResultSet result;
1969 try {
1970 result.Add(MidiInstrumentMapper::Maps().size());
1971 } catch (Exception e) {
1972 result.Error(e);
1973 }
1974 return result.Produce();
1975 }
1976
1977 String LSCPServer::ListMidiInstrumentMaps() {
1978 dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
1979 LSCPResultSet result;
1980 try {
1981 std::vector<int> maps = MidiInstrumentMapper::Maps();
1982 String sList;
1983 for (int i = 0; i < maps.size(); i++) {
1984 if (sList != "") sList += ",";
1985 sList += ToString(maps[i]);
1986 }
1987 result.Add(sList);
1988 } catch (Exception e) {
1989 result.Error(e);
1990 }
1991 return result.Produce();
1992 }
1993
1994 String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
1995 dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
1996 LSCPResultSet result;
1997 try {
1998 result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
1999 result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2000 } catch (Exception e) {
2001 result.Error(e);
2002 }
2003 return result.Produce();
2004 }
2005
2006 String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2007 dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2008 LSCPResultSet result;
2009 try {
2010 MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2011 } catch (Exception e) {
2012 result.Error(e);
2013 }
2014 return result.Produce();
2015 }
2016
2017 /**
2018 * Set the MIDI instrument map the given sampler channel shall use for
2019 * handling MIDI program change messages. There are the following two
2020 * special (negative) values:
2021 *
2022 * - (-1) : set to NONE (ignore program changes)
2023 * - (-2) : set to DEFAULT map
2024 */
2025 String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2026 dmsg(2,("LSCPServer: SetChannelMap()\n"));
2027 LSCPResultSet result;
2028 try {
2029 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2030 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2031
2032 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2033 if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
2034
2035 if (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2036 else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2037 else pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2038 } catch (Exception e) {
2039 result.Error(e);
2040 }
2041 return result.Produce();
2042 }
2043
2044 String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2045 dmsg(2,("LSCPServer: CreateFxSend()\n"));
2046 LSCPResultSet result;
2047 try {
2048 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2049
2050 FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2051 if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2052
2053 result = LSCPResultSet(pFxSend->Id()); // success
2054 } catch (Exception e) {
2055 result.Error(e);
2056 }
2057 return result.Produce();
2058 }
2059
2060 String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2061 dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2062 LSCPResultSet result;
2063 try {
2064 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2065
2066 FxSend* pFxSend = NULL;
2067 for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2068 if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2069 pFxSend = pEngineChannel->GetFxSend(i);
2070 break;
2071 }
2072 }
2073 if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2074 pEngineChannel->RemoveFxSend(pFxSend);
2075 } catch (Exception e) {
2076 result.Error(e);
2077 }
2078 return result.Produce();
2079 }
2080
2081 String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2082 dmsg(2,("LSCPServer: GetFxSends()\n"));
2083 LSCPResultSet result;
2084 try {
2085 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2086
2087 result.Add(pEngineChannel->GetFxSendCount());
2088 } catch (Exception e) {
2089 result.Error(e);
2090 }
2091 return result.Produce();
2092 }
2093
2094 String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2095 dmsg(2,("LSCPServer: ListFxSends()\n"));
2096 LSCPResultSet result;
2097 String list;
2098 try {
2099 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2100
2101 for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2102 FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2103 if (list != "") list += ",";
2104 list += ToString(pFxSend->Id());
2105 }
2106 result.Add(list);
2107 } catch (Exception e) {
2108 result.Error(e);
2109 }
2110 return result.Produce();
2111 }
2112
2113 FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2114 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2115
2116 FxSend* pFxSend = NULL;
2117 for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2118 if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2119 pFxSend = pEngineChannel->GetFxSend(i);
2120 break;
2121 }
2122 }
2123 if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2124 return pFxSend;
2125 }
2126
2127 String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2128 dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2129 LSCPResultSet result;
2130 try {
2131 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2132 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2133
2134 // gather audio routing informations
2135 String AudioRouting;
2136 for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2137 if (AudioRouting != "") AudioRouting += ",";
2138 AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2139 }
2140
2141 // success
2142 result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2143 result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2144 result.Add("LEVEL", ToString(pFxSend->Level()));
2145 result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2146 } catch (Exception e) {
2147 result.Error(e);
2148 }
2149 return result.Produce();
2150 }
2151
2152 String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2153 dmsg(2,("LSCPServer: SetFxSendName()\n"));
2154 LSCPResultSet result;
2155 try {
2156 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2157
2158 pFxSend->SetName(Name);
2159 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2160 } catch (Exception e) {
2161 result.Error(e);
2162 }
2163 return result.Produce();
2164 }
2165
2166 String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2167 dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2168 LSCPResultSet result;
2169 try {
2170 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2171
2172 pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2173 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2174 } catch (Exception e) {
2175 result.Error(e);
2176 }
2177 return result.Produce();
2178 }
2179
2180 String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2181 dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2182 LSCPResultSet result;
2183 try {
2184 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2185
2186 pFxSend->SetMidiController(MidiController);
2187 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2188 } catch (Exception e) {
2189 result.Error(e);
2190 }
2191 return result.Produce();
2192 }
2193
2194 String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2195 dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2196 LSCPResultSet result;
2197 try {
2198 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2199
2200 pFxSend->SetLevel((float)dLevel);
2201 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2202 } catch (Exception e) {
2203 result.Error(e);
2204 }
2205 return result.Produce();
2206 }
2207
2208 String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
2209 dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
2210 LSCPResultSet result;
2211 try {
2212 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2213 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2214 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2215 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
2216 if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
2217 Engine* pEngine = pEngineChannel->GetEngine();
2218 InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
2219 if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
2220 InstrumentManager::instrument_id_t instrumentID;
2221 instrumentID.FileName = pEngineChannel->InstrumentFileName();
2222 instrumentID.Index = pEngineChannel->InstrumentIndex();
2223 pInstrumentManager->LaunchInstrumentEditor(instrumentID);
2224 } catch (Exception e) {
2225 result.Error(e);
2226 }
2227 return result.Produce();
2228 }
2229
2230 /**
2231 * Will be called by the parser to reset a particular sampler channel.
2232 */
2233 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
2234 dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
2235 LSCPResultSet result;
2236 try {
2237 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2238 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2239 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2240 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
2241 pEngineChannel->Reset();
2242 }
2243 catch (Exception e) {
2244 result.Error(e);
2245 }
2246 return result.Produce();
2247 }
2248
2249 /**
2250 * Will be called by the parser to reset the whole sampler.
2251 */
2252 String LSCPServer::ResetSampler() {
2253 dmsg(2,("LSCPServer: ResetSampler()\n"));
2254 pSampler->Reset();
2255 LSCPResultSet result;
2256 return result.Produce();
2257 }
2258
2259 /**
2260 * Will be called by the parser to return general informations about this
2261 * sampler.
2262 */
2263 String LSCPServer::GetServerInfo() {
2264 dmsg(2,("LSCPServer: GetServerInfo()\n"));
2265 const std::string description =
2266 _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
2267 LSCPResultSet result;
2268 result.Add("DESCRIPTION", description);
2269 result.Add("VERSION", VERSION);
2270 result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
2271 #if HAVE_SQLITE3
2272 result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
2273 #else
2274 result.Add("INSTRUMENTS_DB_SUPPORT", "no");
2275 #endif
2276
2277 return result.Produce();
2278 }
2279
2280 /**
2281 * Will be called by the parser to return the current number of all active voices.
2282 */
2283 String LSCPServer::GetTotalVoiceCount() {
2284 dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
2285 LSCPResultSet result;
2286 result.Add(pSampler->GetVoiceCount());
2287 return result.Produce();
2288 }
2289
2290 /**
2291 * Will be called by the parser to return the maximum number of voices.
2292 */
2293 String LSCPServer::GetTotalVoiceCountMax() {
2294 dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
2295 LSCPResultSet result;
2296 result.Add(EngineFactory::EngineInstances().size() * CONFIG_MAX_VOICES);
2297 return result.Produce();
2298 }
2299
2300 String LSCPServer::GetGlobalVolume() {
2301 LSCPResultSet result;
2302 result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
2303 return result.Produce();
2304 }
2305
2306 String LSCPServer::SetGlobalVolume(double dVolume) {
2307 LSCPResultSet result;
2308 try {
2309 if (dVolume < 0) throw Exception("Volume may not be negative");
2310 GLOBAL_VOLUME = dVolume; // see common/global.cpp
2311 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
2312 } catch (Exception e) {
2313 result.Error(e);
2314 }
2315 return result.Produce();
2316 }
2317
2318 /**
2319 * Will be called by the parser to subscribe a client (frontend) on the
2320 * server for receiving event messages.
2321 */
2322 String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
2323 dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
2324 LSCPResultSet result;
2325 SubscriptionMutex.Lock();
2326 eventSubscriptions[type].push_back(currentSocket);
2327 SubscriptionMutex.Unlock();
2328 return result.Produce();
2329 }
2330
2331 /**
2332 * Will be called by the parser to unsubscribe a client on the server
2333 * for not receiving further event messages.
2334 */
2335 String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
2336 dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
2337 LSCPResultSet result;
2338 SubscriptionMutex.Lock();
2339 eventSubscriptions[type].remove(currentSocket);
2340 SubscriptionMutex.Unlock();
2341 return result.Produce();
2342 }
2343
2344 String LSCPServer::AddDbInstrumentDirectory(String Dir) {
2345 dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
2346 LSCPResultSet result;
2347 #if HAVE_SQLITE3
2348 try {
2349 InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
2350 } catch (Exception e) {
2351 result.Error(e);
2352 }
2353 #else
2354 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2355 #endif
2356 return result.Produce();
2357 }
2358
2359 String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
2360 dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
2361 LSCPResultSet result;
2362 #if HAVE_SQLITE3
2363 try {
2364 InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
2365 } catch (Exception e) {
2366 result.Error(e);
2367 }
2368 #else
2369 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2370 #endif
2371 return result.Produce();
2372 }
2373
2374 String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
2375 dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
2376 LSCPResultSet result;
2377 #if HAVE_SQLITE3
2378 try {
2379 result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
2380 } catch (Exception e) {
2381 result.Error(e);
2382 }
2383 #else
2384 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2385 #endif
2386 return result.Produce();
2387 }
2388
2389 String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
2390 dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
2391 LSCPResultSet result;
2392 #if HAVE_SQLITE3
2393 try {
2394 String list;
2395 StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
2396
2397 for (int i = 0; i < dirs->size(); i++) {
2398 if (list != "") list += ",";
2399 list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
2400 }
2401
2402 result.Add(list);
2403 } catch (Exception e) {
2404 result.Error(e);
2405 }
2406 #else
2407 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2408 #endif
2409 return result.Produce();
2410 }
2411
2412 String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
2413 dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
2414 LSCPResultSet result;
2415 #if HAVE_SQLITE3
2416 try {
2417 DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
2418
2419 result.Add("DESCRIPTION", InstrumentsDb::toEscapedText(info.Description));
2420 result.Add("CREATED", info.Created);
2421 result.Add("MODIFIED", info.Modified);
2422 } catch (Exception e) {
2423 result.Error(e);
2424 }
2425 #else
2426 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2427 #endif
2428 return result.Produce();
2429 }
2430
2431 String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
2432 dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
2433 LSCPResultSet result;
2434 #if HAVE_SQLITE3
2435 try {
2436 InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
2437 } catch (Exception e) {
2438 result.Error(e);
2439 }
2440 #else
2441 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2442 #endif
2443 return result.Produce();
2444 }
2445
2446 String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
2447 dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
2448 LSCPResultSet result;
2449 #if HAVE_SQLITE3
2450 try {
2451 InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
2452 } catch (Exception e) {
2453 result.Error(e);
2454 }
2455 #else
2456 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2457 #endif
2458 return result.Produce();
2459 }
2460
2461 String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
2462 dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
2463 LSCPResultSet result;
2464 #if HAVE_SQLITE3
2465 try {
2466 InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
2467 } catch (Exception e) {
2468 result.Error(e);
2469 }
2470 #else
2471 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2472 #endif
2473 return result.Produce();
2474 }
2475
2476 String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
2477 dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
2478 LSCPResultSet result;
2479 #if HAVE_SQLITE3
2480 try {
2481 InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
2482 } catch (Exception e) {
2483 result.Error(e);
2484 }
2485 #else
2486 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2487 #endif
2488 return result.Produce();
2489 }
2490
2491 String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
2492 dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
2493 LSCPResultSet result;
2494 #if HAVE_SQLITE3
2495 try {
2496 int id;
2497 InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
2498 id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
2499 if (bBackground) result = id;
2500 } catch (Exception e) {
2501 result.Error(e);
2502 }
2503 #else
2504 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2505 #endif
2506 return result.Produce();
2507 }
2508
2509 String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground) {
2510 dmsg(2,("LSCPServer: AddDbInstruments(ScanMode=%s,DbDir=%s,FsDir=%s,bBackground=%d)\n", ScanMode.c_str(), DbDir.c_str(), FsDir.c_str(), bBackground));
2511 LSCPResultSet result;
2512 #if HAVE_SQLITE3
2513 try {
2514 int id;
2515 InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
2516 if (ScanMode.compare("RECURSIVE") == 0) {
2517 id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground);
2518 } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
2519 id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground);
2520 } else if (ScanMode.compare("FLAT") == 0) {
2521 id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground);
2522 } else {
2523 throw Exception("Unknown scan mode: " + ScanMode);
2524 }
2525
2526 if (bBackground) result = id;
2527 } catch (Exception e) {
2528 result.Error(e);
2529 }
2530 #else
2531 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2532 #endif
2533 return result.Produce();
2534 }
2535
2536 String LSCPServer::RemoveDbInstrument(String Instr) {
2537 dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
2538 LSCPResultSet result;
2539 #if HAVE_SQLITE3
2540 try {
2541 InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
2542 } catch (Exception e) {
2543 result.Error(e);
2544 }
2545 #else
2546 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2547 #endif
2548 return result.Produce();
2549 }
2550
2551 String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
2552 dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
2553 LSCPResultSet result;
2554 #if HAVE_SQLITE3
2555 try {
2556 result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
2557 } catch (Exception e) {
2558 result.Error(e);
2559 }
2560 #else
2561 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2562 #endif
2563 return result.Produce();
2564 }
2565
2566 String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
2567 dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
2568 LSCPResultSet result;
2569 #if HAVE_SQLITE3
2570 try {
2571 String list;
2572 StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
2573
2574 for (int i = 0; i < instrs->size(); i++) {
2575 if (list != "") list += ",";
2576 list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
2577 }
2578
2579 result.Add(list);
2580 } catch (Exception e) {
2581 result.Error(e);
2582 }
2583 #else
2584 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2585 #endif
2586 return result.Produce();
2587 }
2588
2589 String LSCPServer::GetDbInstrumentInfo(String Instr) {
2590 dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
2591 LSCPResultSet result;
2592 #if HAVE_SQLITE3
2593 try {
2594 DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
2595
2596 result.Add("INSTRUMENT_FILE", info.InstrFile);
2597 result.Add("INSTRUMENT_NR", info.InstrNr);
2598 result.Add("FORMAT_FAMILY", info.FormatFamily);
2599 result.Add("FORMAT_VERSION", info.FormatVersion);
2600 result.Add("SIZE", (int)info.Size);
2601 result.Add("CREATED", info.Created);
2602 result.Add("MODIFIED", info.Modified);
2603 result.Add("DESCRIPTION", InstrumentsDb::toEscapedText(info.Description));
2604 result.Add("IS_DRUM", info.IsDrum);
2605 result.Add("PRODUCT", InstrumentsDb::toEscapedText(info.Product));
2606 result.Add("ARTISTS", InstrumentsDb::toEscapedText(info.Artists));
2607 result.Add("KEYWORDS", InstrumentsDb::toEscapedText(info.Keywords));
2608 } catch (Exception e) {
2609 result.Error(e);
2610 }
2611 #else
2612 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2613 #endif
2614 return result.Produce();
2615 }
2616
2617 String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
2618 dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
2619 LSCPResultSet result;
2620 #if HAVE_SQLITE3
2621 try {
2622 ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
2623
2624 result.Add("FILES_TOTAL", job.FilesTotal);
2625 result.Add("FILES_SCANNED", job.FilesScanned);
2626 result.Add("SCANNING", job.Scanning);
2627 result.Add("STATUS", job.Status);
2628 } catch (Exception e) {
2629 result.Error(e);
2630 }
2631 #else
2632 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2633 #endif
2634 return result.Produce();
2635 }
2636
2637 String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
2638 dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
2639 LSCPResultSet result;
2640 #if HAVE_SQLITE3
2641 try {
2642 InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
2643 } catch (Exception e) {
2644 result.Error(e);
2645 }
2646 #else
2647 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2648 #endif
2649 return result.Produce();
2650 }
2651
2652 String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
2653 dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
2654 LSCPResultSet result;
2655 #if HAVE_SQLITE3
2656 try {
2657 InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
2658 } catch (Exception e) {
2659 result.Error(e);
2660 }
2661 #else
2662 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2663 #endif
2664 return result.Produce();
2665 }
2666
2667 String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
2668 dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
2669 LSCPResultSet result;
2670 #if HAVE_SQLITE3
2671 try {
2672 InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
2673 } catch (Exception e) {
2674 result.Error(e);
2675 }
2676 #else
2677 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2678 #endif
2679 return result.Produce();
2680 }
2681
2682 String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
2683 dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
2684 LSCPResultSet result;
2685 #if HAVE_SQLITE3
2686 try {
2687 InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
2688 } catch (Exception e) {
2689 result.Error(e);
2690 }
2691 #else
2692 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2693 #endif
2694 return result.Produce();
2695 }
2696
2697 String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
2698 dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
2699 LSCPResultSet result;
2700 #if HAVE_SQLITE3
2701 try {
2702 SearchQuery Query;
2703 std::map<String,String>::iterator iter;
2704 for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
2705 if (iter->first.compare("NAME") == 0) {
2706 Query.Name = iter->second;
2707 } else if (iter->first.compare("CREATED") == 0) {
2708 Query.SetCreated(iter->second);
2709 } else if (iter->first.compare("MODIFIED") == 0) {
2710 Query.SetModified(iter->second);
2711 } else if (iter->first.compare("DESCRIPTION") == 0) {
2712 Query.Description = iter->second;
2713 } else {
2714 throw Exception("Unknown search criteria: " + iter->first);
2715 }
2716 }
2717
2718 String list;
2719 StringListPtr pDirectories =
2720 InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
2721
2722 for (int i = 0; i < pDirectories->size(); i++) {
2723 if (list != "") list += ",";
2724 list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
2725 }
2726
2727 result.Add(list);
2728 } catch (Exception e) {
2729 result.Error(e);
2730 }
2731 #else
2732 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2733 #endif
2734 return result.Produce();
2735 }
2736
2737 String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
2738 dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
2739 LSCPResultSet result;
2740 #if HAVE_SQLITE3
2741 try {
2742 SearchQuery Query;
2743 std::map<String,String>::iterator iter;
2744 for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
2745 if (iter->first.compare("NAME") == 0) {
2746 Query.Name = iter->second;
2747 } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
2748 Query.SetFormatFamilies(iter->second);
2749 } else if (iter->first.compare("SIZE") == 0) {
2750 Query.SetSize(iter->second);
2751 } else if (iter->first.compare("CREATED") == 0) {
2752 Query.SetCreated(iter->second);
2753 } else if (iter->first.compare("MODIFIED") == 0) {
2754 Query.SetModified(iter->second);
2755 } else if (iter->first.compare("DESCRIPTION") == 0) {
2756 Query.Description = iter->second;
2757 } else if (iter->first.compare("IS_DRUM") == 0) {
2758 if (!strcasecmp(iter->second.c_str(), "true")) {
2759 Query.InstrType = SearchQuery::DRUM;
2760 } else {
2761 Query.InstrType = SearchQuery::CHROMATIC;
2762 }
2763 } else if (iter->first.compare("PRODUCT") == 0) {
2764 Query.Product = iter->second;
2765 } else if (iter->first.compare("ARTISTS") == 0) {
2766 Query.Artists = iter->second;
2767 } else if (iter->first.compare("KEYWORDS") == 0) {
2768 Query.Keywords = iter->second;
2769 } else {
2770 throw Exception("Unknown search criteria: " + iter->first);
2771 }
2772 }
2773
2774 String list;
2775 StringListPtr pInstruments =
2776 InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
2777
2778 for (int i = 0; i < pInstruments->size(); i++) {
2779 if (list != "") list += ",";
2780 list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
2781 }
2782
2783 result.Add(list);
2784 } catch (Exception e) {
2785 result.Error(e);
2786 }
2787 #else
2788 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2789 #endif
2790 return result.Produce();
2791 }
2792
2793 String LSCPServer::FormatInstrumentsDb() {
2794 dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
2795 LSCPResultSet result;
2796 #if HAVE_SQLITE3
2797 try {
2798 InstrumentsDb::GetInstrumentsDb()->Format();
2799 } catch (Exception e) {
2800 result.Error(e);
2801 }
2802 #else
2803 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2804 #endif
2805 return result.Produce();
2806 }
2807
2808
2809 /**
2810 * Will be called by the parser to enable or disable echo mode; if echo
2811 * mode is enabled, all commands from the client will (immediately) be
2812 * echoed back to the client.
2813 */
2814 String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
2815 dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
2816 LSCPResultSet result;
2817 try {
2818 if (boolean_value == 0) pSession->bVerbose = false;
2819 else if (boolean_value == 1) pSession->bVerbose = true;
2820 else throw Exception("Not a boolean value, must either be 0 or 1");
2821 }
2822 catch (Exception e) {
2823 result.Error(e);
2824 }
2825 return result.Produce();
2826 }

  ViewVC Help
Powered by ViewVC