/[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 1695 - (show annotations) (download)
Sat Feb 16 01:09:33 2008 UTC (16 years, 1 month ago) by schoenebeck
File size: 128665 byte(s)
* added new LSCP event "DEVICE_MIDI" which can be used by frontends to
  react on MIDI data arriving on certain MIDI input devices (so far only
  Note-On and Note-Off events are sent via this LSCP event)
* bumped version to 0.5.1.4cvs

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

  ViewVC Help
Powered by ViewVC