/[svn]/linuxsampler/trunk/src/network/lscpserver.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/network/lscpserver.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2534 - (hide annotations) (download)
Sun Mar 9 21:34:03 2014 UTC (10 years, 1 month ago) by schoenebeck
File size: 165610 byte(s)
* LSCP shell (WIP): Added initial support for built-in LSCP reference
  documentation, which will automatically show the relevant LSCP reference
  section on screen as soon as one specific LSCP command was detected while
  typing on the command line.
* Bumped version (1.0.0.svn37).

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

  ViewVC Help
Powered by ViewVC