/[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 2427 - (show annotations) (download)
Sat Mar 2 07:03:04 2013 UTC (11 years, 1 month ago) by persson
File size: 154211 byte(s)
* code refactoring: added a lock guard class for exception safe mutex
  handling and used it everywhere appropriate

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

  ViewVC Help
Powered by ViewVC