/[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 2198 - (show annotations) (download)
Sun Jul 3 18:06:51 2011 UTC (12 years, 9 months ago) by iliev
File size: 155011 byte(s)
* bugfix: LSCP command "REMOVE FX_SEND EFFECT" was broken
* fixed a bug in FxSend::SetDestinationEffect
* bugfix: parent was not set when effect instance is appended
* bugfix: was able to remove effect chain while FX send is connected to it
* bugfix: was able to remove effect instance from effect chain while
  FX send is connected to that instance

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

  ViewVC Help
Powered by ViewVC