/[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 1765 - (show annotations) (download)
Sat Sep 6 16:44:42 2008 UTC (15 years, 7 months ago) by persson
File size: 129061 byte(s)
* refactoring: extracted lscp notification from main() to a separate
  function
* added helper function MidiInputPort::DispatchRaw for midi device
  implementations with raw byte data
* fixed a win32 build error (atomic.h is working on windows too)
* code cleanup: moved lscp classes into LinuxSampler namespace

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

  ViewVC Help
Powered by ViewVC