/[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 1835 - (show annotations) (download)
Mon Feb 16 17:56:50 2009 UTC (15 years, 1 month ago) by iliev
File size: 132412 byte(s)
* Adapted drivers/Plugin class to be used as a base class for the
  AudioUnit plugin and fixed orphaned pointers when deleting PluginGlobal
* Fixed possible iterator invalidations when resetting the sampler
* Fixed memory leaks when issuing the following LSCP commands:
  GET AUDIO_OUTPUT_DRIVER INFO
  GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO
  GET MIDI_INPUT_DRIVER INFO
  GET MIDI_INPUT_DRIVER_PARAMETER INFO
* Fixed possible compilation error when sqlite is not present

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

  ViewVC Help
Powered by ViewVC