/[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 2515 - (show annotations) (download)
Wed Feb 5 20:45:18 2014 UTC (10 years, 2 months ago) by schoenebeck
File size: 161006 byte(s)
* WIP: Introducing the LSCP shell: for now, providing color
  highlighting while typing (indicating correct part bold white,
  incorrect part red, and turning green when the command is
  complete. The shell application is implemented as thin client,
  that is the parser work is performed on sampler side and the
  shell application is just providing output formatting.
* Bumped version (1.0.0.svn28).

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

  ViewVC Help
Powered by ViewVC