/[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 1850 - (show annotations) (download)
Sun Mar 1 16:33:22 2009 UTC (15 years, 1 month ago) by persson
File size: 132704 byte(s)
* fixed crash when a linuxsampler plugin is unloading

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

  ViewVC Help
Powered by ViewVC