/[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 2837 - (hide annotations) (download)
Sun Aug 23 06:14:00 2015 UTC (8 years, 7 months ago) by persson
File size: 166014 byte(s)
* fixed printf type errors (mostly in debug messages)


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 2687 * Copyright (C) 2005 - 2015 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 2535 // Only if the other side (client) is the LSCP shell application:
814     // The following block takes care about automatic correction, auto
815     // completion (and suggestions), LSCP reference documentation, etc.
816     // The "if" statement here is for optimization reasons, so that the
817     // heavy LSCP grammar evaluation algorithm is only executed once for an
818     // entire command line received.
819     if (i == input.size() - 1) {
820     // check the current (incomplete) command line for syntax errors,
821     // possible completions and report everything back to the shell
822     if ((*iter).bShellInteract || (*iter).bShellAutoCorrect) {
823     String s = lscpParserProcessShellInteraction(bufferedCommands[socket], &(*iter), true);
824     if (!s.empty() && (*iter).bShellInteract && i == input.size() - 1)
825     AnswerClient(s + "\n");
826     }
827     // if other side is LSCP shell application, send the relevant LSCP
828     // documentation section of the current command line (if necessary)
829     if ((*iter).bShellSendLSCPDoc && (*iter).bShellInteract) {
830     String s = generateLSCPDocReply(bufferedCommands[socket], &(*iter));
831     if (!s.empty()) AnswerClient(s + "\n");
832     }
833 senoner 1481 }
834 schoenebeck 2528 }
835    
836     // handle network errors ...
837     if (result == 0) { //socket was selected, so 0 here means client has closed the connection
838     CloseConnection(iter);
839     return false;
840     }
841     #if defined(WIN32)
842     if (result == SOCKET_ERROR) {
843     int wsa_lasterror = WSAGetLastError();
844     if (wsa_lasterror == WSAEWOULDBLOCK) //Would block, try again later.
845     return false;
846     dmsg(2,("LSCPScanner: Socket error after recv() Error %d.\n", wsa_lasterror));
847     CloseConnection(iter);
848     return false;
849     }
850     #else
851     if (result == -1) {
852     if (errno == EAGAIN) //Would block, try again later.
853     return false;
854     switch(errno) {
855     case EBADF:
856     dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
857 senkov 170 return false;
858 schoenebeck 2528 case ECONNREFUSED:
859     dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
860     return false;
861     case ENOTCONN:
862     dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
863     return false;
864     case ENOTSOCK:
865     dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
866     return false;
867     case EAGAIN:
868     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"));
869     return false;
870     case EINTR:
871     dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
872     return false;
873     case EFAULT:
874     dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
875     return false;
876     case EINVAL:
877     dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
878     return false;
879     case ENOMEM:
880     dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
881     return false;
882     default:
883     dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
884     return false;
885 senkov 170 }
886 schoenebeck 2528 CloseConnection(iter);
887     return false;
888 senkov 170 }
889 schoenebeck 2528 #endif
890    
891 senkov 170 return false;
892     }
893    
894     /**
895 schoenebeck 35 * Will be called by the parser whenever it wants to send an answer to the
896     * client / frontend.
897     *
898     * @param ReturnMessage - message that will be send to the client
899     */
900     void LSCPServer::AnswerClient(String ReturnMessage) {
901 schoenebeck 2515 dmsg(2,("LSCPServer::AnswerClient(ReturnMessage='%s')", ReturnMessage.c_str()));
902 senkov 170 if (currentSocket != -1) {
903 persson 2427 LockGuard lock(NotifyMutex);
904 schoenebeck 2515
905     // just if other side is LSCP shell: in case respose is a multi-line
906     // one, then inform client about it before sending the actual mult-line
907     // response
908     if (GetCurrentYaccSession()->bShellInteract) {
909     // check if this is a multi-line response
910     int n = 0;
911     for (int i = 0; i < ReturnMessage.size(); ++i)
912     if (ReturnMessage[i] == '\n') ++n;
913     if (n >= 2) {
914     dmsg(2,("LSCP Shell <- expect mult-line response\n"));
915     String s = LSCP_SHK_EXPECT_MULTI_LINE "\r\n";
916 wylder 814 #ifdef MSG_NOSIGNAL
917 schoenebeck 2515 send(currentSocket, s.c_str(), s.size(), MSG_NOSIGNAL);
918     #else
919     send(currentSocket, s.c_str(), s.size(), 0);
920     #endif
921     }
922     }
923    
924     #ifdef MSG_NOSIGNAL
925 iliev 707 send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
926 wylder 814 #else
927     send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
928     #endif
929 senkov 170 }
930 schoenebeck 35 }
931    
932 capela 143 /**
933     * Find a created audio output device index.
934     */
935     int LSCPServer::GetAudioOutputDeviceIndex ( AudioOutputDevice *pDevice )
936     {
937     // Search for the created device to get its index
938     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
939     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
940     for (; iter != devices.end(); iter++) {
941     if (iter->second == pDevice)
942     return iter->first;
943     }
944     // Not found.
945     return -1;
946     }
947    
948 senkov 155 /**
949     * Find a created midi input device index.
950     */
951     int LSCPServer::GetMidiInputDeviceIndex ( MidiInputDevice *pDevice )
952     {
953     // Search for the created device to get its index
954     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
955     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
956     for (; iter != devices.end(); iter++) {
957     if (iter->second == pDevice)
958     return iter->first;
959     }
960     // Not found.
961     return -1;
962     }
963    
964 schoenebeck 123 String LSCPServer::CreateAudioOutputDevice(String Driver, std::map<String,String> Parameters) {
965     dmsg(2,("LSCPServer: CreateAudioOutputDevice(Driver=%s)\n", Driver.c_str()));
966     LSCPResultSet result;
967     try {
968     AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
969     // search for the created device to get its index
970 capela 143 int index = GetAudioOutputDeviceIndex(pDevice);
971 schoenebeck 880 if (index == -1) throw Exception("Internal error: could not find created audio output device.");
972 schoenebeck 123 result = index; // success
973     }
974 schoenebeck 880 catch (Exception e) {
975 schoenebeck 123 result.Error(e);
976     }
977     return result.Produce();
978     }
979    
980 senkov 155 String LSCPServer::CreateMidiInputDevice(String Driver, std::map<String,String> Parameters) {
981     dmsg(2,("LSCPServer: CreateMidiInputDevice(Driver=%s)\n", Driver.c_str()));
982     LSCPResultSet result;
983     try {
984     MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
985     // search for the created device to get its index
986     int index = GetMidiInputDeviceIndex(pDevice);
987 schoenebeck 880 if (index == -1) throw Exception("Internal error: could not find created midi input device.");
988 senkov 155 result = index; // success
989     }
990 schoenebeck 880 catch (Exception e) {
991 senkov 155 result.Error(e);
992     }
993     return result.Produce();
994     }
995    
996 schoenebeck 123 String LSCPServer::DestroyAudioOutputDevice(uint DeviceIndex) {
997     dmsg(2,("LSCPServer: DestroyAudioOutputDevice(DeviceIndex=%d)\n", DeviceIndex));
998     LSCPResultSet result;
999     try {
1000     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1001 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1002 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
1003     pSampler->DestroyAudioOutputDevice(pDevice);
1004     }
1005 schoenebeck 880 catch (Exception e) {
1006 schoenebeck 123 result.Error(e);
1007     }
1008     return result.Produce();
1009     }
1010    
1011 senkov 155 String LSCPServer::DestroyMidiInputDevice(uint DeviceIndex) {
1012     dmsg(2,("LSCPServer: DestroyMidiInputDevice(DeviceIndex=%d)\n", DeviceIndex));
1013     LSCPResultSet result;
1014     try {
1015     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1016 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1017 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1018     pSampler->DestroyMidiInputDevice(pDevice);
1019     }
1020 schoenebeck 880 catch (Exception e) {
1021 senkov 155 result.Error(e);
1022     }
1023     return result.Produce();
1024     }
1025    
1026 iliev 1135 EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
1027     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1028     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1029    
1030     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1031     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1032    
1033 schoenebeck 1252 return pEngineChannel;
1034 iliev 1135 }
1035    
1036 schoenebeck 35 /**
1037     * Will be called by the parser to load an instrument.
1038     */
1039 capela 137 String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel, bool bBackground) {
1040 schoenebeck 53 dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
1041 senkov 120 LSCPResultSet result;
1042 schoenebeck 53 try {
1043     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1044 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1045 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1046 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
1047 schoenebeck 223 if (!pSamplerChannel->GetAudioOutputDevice())
1048 schoenebeck 880 throw Exception("No audio output device connected to sampler channel");
1049 capela 137 if (bBackground) {
1050 schoenebeck 947 InstrumentManager::instrument_id_t id;
1051     id.FileName = Filename;
1052     id.Index = uiInstrument;
1053     InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
1054 capela 137 }
1055 schoenebeck 392 else {
1056 schoenebeck 411 // tell the engine channel which instrument to load
1057     pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrument);
1058 schoenebeck 392 // actually start to load the instrument (blocks until completed)
1059 schoenebeck 411 pEngineChannel->LoadInstrument();
1060 schoenebeck 392 }
1061 schoenebeck 53 }
1062 schoenebeck 880 catch (Exception e) {
1063 senkov 120 result.Error(e);
1064 schoenebeck 53 }
1065 senkov 120 return result.Produce();
1066 schoenebeck 35 }
1067    
1068     /**
1069 schoenebeck 411 * Will be called by the parser to assign a sampler engine type to a
1070     * sampler channel.
1071 schoenebeck 35 */
1072 schoenebeck 411 String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
1073 schoenebeck 705 dmsg(2,("LSCPServer: SetEngineType(EngineName=%s,uiSamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
1074 senkov 120 LSCPResultSet result;
1075 schoenebeck 475 try {
1076 schoenebeck 53 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1077 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1078 persson 2427 LockGuard lock(RTNotifyMutex);
1079 schoenebeck 411 pSamplerChannel->SetEngineType(EngineName);
1080 schoenebeck 705 if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
1081 schoenebeck 53 }
1082 schoenebeck 880 catch (Exception e) {
1083 senkov 120 result.Error(e);
1084 schoenebeck 53 }
1085 senkov 120 return result.Produce();
1086 schoenebeck 35 }
1087    
1088     /**
1089     * Will be called by the parser to get the amount of sampler channels.
1090     */
1091     String LSCPServer::GetChannels() {
1092     dmsg(2,("LSCPServer: GetChannels()\n"));
1093 senkov 120 LSCPResultSet result;
1094     result.Add(pSampler->SamplerChannels());
1095     return result.Produce();
1096 schoenebeck 35 }
1097    
1098     /**
1099 schoenebeck 209 * Will be called by the parser to get the list of sampler channels.
1100     */
1101     String LSCPServer::ListChannels() {
1102     dmsg(2,("LSCPServer: ListChannels()\n"));
1103     String list;
1104     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1105     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1106     for (; iter != channels.end(); iter++) {
1107     if (list != "") list += ",";
1108     list += ToString(iter->first);
1109     }
1110     LSCPResultSet result;
1111     result.Add(list);
1112     return result.Produce();
1113     }
1114    
1115     /**
1116 schoenebeck 35 * Will be called by the parser to add a sampler channel.
1117     */
1118     String LSCPServer::AddChannel() {
1119     dmsg(2,("LSCPServer: AddChannel()\n"));
1120 persson 2427 SamplerChannel* pSamplerChannel;
1121     {
1122     LockGuard lock(RTNotifyMutex);
1123     pSamplerChannel = pSampler->AddSamplerChannel();
1124     }
1125 senkov 120 LSCPResultSet result(pSamplerChannel->Index());
1126     return result.Produce();
1127 schoenebeck 35 }
1128    
1129     /**
1130     * Will be called by the parser to remove a sampler channel.
1131     */
1132 schoenebeck 53 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
1133     dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
1134 senkov 120 LSCPResultSet result;
1135 persson 2427 {
1136     LockGuard lock(RTNotifyMutex);
1137     pSampler->RemoveSamplerChannel(uiSamplerChannel);
1138     }
1139 senkov 120 return result.Produce();
1140 schoenebeck 35 }
1141    
1142     /**
1143 capela 527 * Will be called by the parser to get the amount of all available engines.
1144 schoenebeck 35 */
1145     String LSCPServer::GetAvailableEngines() {
1146     dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
1147 schoenebeck 905 LSCPResultSet result;
1148     try {
1149     int n = EngineFactory::AvailableEngineTypes().size();
1150     result.Add(n);
1151     }
1152     catch (Exception e) {
1153     result.Error(e);
1154     }
1155 senkov 120 return result.Produce();
1156 schoenebeck 35 }
1157    
1158     /**
1159 capela 527 * Will be called by the parser to get a list of all available engines.
1160     */
1161     String LSCPServer::ListAvailableEngines() {
1162     dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
1163 schoenebeck 905 LSCPResultSet result;
1164     try {
1165     String s = EngineFactory::AvailableEngineTypesAsString();
1166     result.Add(s);
1167     }
1168     catch (Exception e) {
1169     result.Error(e);
1170     }
1171 capela 527 return result.Produce();
1172     }
1173    
1174     /**
1175 schoenebeck 411 * Will be called by the parser to get descriptions for a particular
1176     * sampler engine.
1177 schoenebeck 35 */
1178     String LSCPServer::GetEngineInfo(String EngineName) {
1179     dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
1180 senkov 120 LSCPResultSet result;
1181 persson 2427 {
1182     LockGuard lock(RTNotifyMutex);
1183     try {
1184     Engine* pEngine = EngineFactory::Create(EngineName);
1185     result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
1186     result.Add("VERSION", pEngine->Version());
1187     EngineFactory::Destroy(pEngine);
1188     }
1189     catch (Exception e) {
1190     result.Error(e);
1191     }
1192 schoenebeck 53 }
1193 senkov 120 return result.Produce();
1194 schoenebeck 35 }
1195    
1196     /**
1197     * Will be called by the parser to get informations about a particular
1198     * sampler channel.
1199     */
1200 schoenebeck 53 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
1201     dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
1202 senkov 120 LSCPResultSet result;
1203 senkov 113 try {
1204     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1205 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1206 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1207 schoenebeck 123
1208 senkov 117 //Defaults values
1209     String EngineName = "NONE";
1210 schoenebeck 225 float Volume = 0.0f;
1211 senkov 117 String InstrumentFileName = "NONE";
1212 senkov 376 String InstrumentName = "NONE";
1213 capela 133 int InstrumentIndex = -1;
1214     int InstrumentStatus = -1;
1215 schoenebeck 225 int AudioOutputChannels = 0;
1216     String AudioRouting;
1217 schoenebeck 705 int Mute = 0;
1218     bool Solo = false;
1219 iliev 1130 String MidiInstrumentMap = "NONE";
1220 schoenebeck 123
1221 schoenebeck 475 if (pEngineChannel) {
1222     EngineName = pEngineChannel->EngineName();
1223 schoenebeck 411 AudioOutputChannels = pEngineChannel->Channels();
1224     Volume = pEngineChannel->Volume();
1225     InstrumentStatus = pEngineChannel->InstrumentStatus();
1226     InstrumentIndex = pEngineChannel->InstrumentIndex();
1227     if (InstrumentIndex != -1) {
1228     InstrumentFileName = pEngineChannel->InstrumentFileName();
1229     InstrumentName = pEngineChannel->InstrumentName();
1230     }
1231     for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
1232 schoenebeck 225 if (AudioRouting != "") AudioRouting += ",";
1233 schoenebeck 411 AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
1234 schoenebeck 225 }
1235 schoenebeck 705 Mute = pEngineChannel->GetMute();
1236     Solo = pEngineChannel->GetSolo();
1237 schoenebeck 973 if (pEngineChannel->UsesNoMidiInstrumentMap())
1238     MidiInstrumentMap = "NONE";
1239     else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
1240     MidiInstrumentMap = "DEFAULT";
1241     else
1242     MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
1243 senkov 113 }
1244 senkov 117
1245     result.Add("ENGINE_NAME", EngineName);
1246     result.Add("VOLUME", Volume);
1247    
1248 capela 143 //Some not-so-hardcoded stuff to make GUI look good
1249     result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
1250 schoenebeck 225 result.Add("AUDIO_OUTPUT_CHANNELS", AudioOutputChannels);
1251     result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
1252 senkov 113
1253 capela 159 result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
1254     result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
1255 schoenebeck 675 if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
1256 schoenebeck 274 else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
1257 capela 159
1258 schoenebeck 1471 // convert the filename into the correct encoding as defined for LSCP
1259     // (especially in terms of special characters -> escape sequences)
1260     if (InstrumentFileName != "NONE" && InstrumentFileName != "") {
1261     #if WIN32
1262     InstrumentFileName = Path::fromWindows(InstrumentFileName).toLscp();
1263     #else
1264     // assuming POSIX
1265     InstrumentFileName = Path::fromPosix(InstrumentFileName).toLscp();
1266     #endif
1267     }
1268    
1269     result.Add("INSTRUMENT_FILE", InstrumentFileName);
1270 senkov 117 result.Add("INSTRUMENT_NR", InstrumentIndex);
1271 schoenebeck 1399 result.Add("INSTRUMENT_NAME", _escapeLscpResponse(InstrumentName));
1272 capela 133 result.Add("INSTRUMENT_STATUS", InstrumentStatus);
1273 schoenebeck 705 result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
1274     result.Add("SOLO", Solo);
1275 schoenebeck 973 result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
1276 senkov 113 }
1277 schoenebeck 880 catch (Exception e) {
1278 senkov 120 result.Error(e);
1279 senkov 113 }
1280 senkov 120 return result.Produce();
1281 schoenebeck 35 }
1282    
1283     /**
1284     * Will be called by the parser to get the amount of active voices on a
1285     * particular sampler channel.
1286     */
1287 schoenebeck 53 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
1288     dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
1289 senkov 120 LSCPResultSet result;
1290 schoenebeck 53 try {
1291 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1292 schoenebeck 880 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1293 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->VoiceCount());
1294 schoenebeck 53 }
1295 schoenebeck 880 catch (Exception e) {
1296 senkov 120 result.Error(e);
1297 schoenebeck 53 }
1298 senkov 120 return result.Produce();
1299 schoenebeck 35 }
1300    
1301     /**
1302     * Will be called by the parser to get the amount of active disk streams on a
1303     * particular sampler channel.
1304     */
1305 schoenebeck 53 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
1306     dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
1307 senkov 120 LSCPResultSet result;
1308 schoenebeck 53 try {
1309 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1310 schoenebeck 880 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1311 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
1312 schoenebeck 53 }
1313 schoenebeck 880 catch (Exception e) {
1314 senkov 120 result.Error(e);
1315 schoenebeck 53 }
1316 senkov 120 return result.Produce();
1317 schoenebeck 35 }
1318    
1319     /**
1320     * Will be called by the parser to get the buffer fill states of all disk
1321     * streams on a particular sampler channel.
1322     */
1323 schoenebeck 53 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
1324     dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
1325 senkov 120 LSCPResultSet result;
1326 schoenebeck 53 try {
1327 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1328 schoenebeck 880 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1329 schoenebeck 411 if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
1330 senkov 129 else {
1331     switch (ResponseType) {
1332     case fill_response_bytes:
1333 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillBytes());
1334     break;
1335 senkov 129 case fill_response_percentage:
1336 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
1337     break;
1338 senkov 129 default:
1339 schoenebeck 880 throw Exception("Unknown fill response type");
1340 senkov 129 }
1341     }
1342 schoenebeck 53 }
1343 schoenebeck 880 catch (Exception e) {
1344 senkov 120 result.Error(e);
1345 schoenebeck 53 }
1346 senkov 120 return result.Produce();
1347 schoenebeck 35 }
1348    
1349 schoenebeck 123 String LSCPServer::GetAvailableAudioOutputDrivers() {
1350     dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
1351 senkov 120 LSCPResultSet result;
1352 schoenebeck 53 try {
1353 capela 527 int n = AudioOutputDeviceFactory::AvailableDrivers().size();
1354     result.Add(n);
1355     }
1356 schoenebeck 880 catch (Exception e) {
1357 capela 527 result.Error(e);
1358     }
1359     return result.Produce();
1360     }
1361    
1362     String LSCPServer::ListAvailableAudioOutputDrivers() {
1363     dmsg(2,("LSCPServer: ListAvailableAudioOutputDrivers()\n"));
1364     LSCPResultSet result;
1365     try {
1366 schoenebeck 123 String s = AudioOutputDeviceFactory::AvailableDriversAsString();
1367     result.Add(s);
1368 schoenebeck 53 }
1369 schoenebeck 880 catch (Exception e) {
1370 schoenebeck 123 result.Error(e);
1371 schoenebeck 53 }
1372 senkov 120 return result.Produce();
1373 schoenebeck 35 }
1374    
1375 senkov 155 String LSCPServer::GetAvailableMidiInputDrivers() {
1376     dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
1377     LSCPResultSet result;
1378     try {
1379 capela 527 int n = MidiInputDeviceFactory::AvailableDrivers().size();
1380     result.Add(n);
1381     }
1382 schoenebeck 880 catch (Exception e) {
1383 capela 527 result.Error(e);
1384     }
1385     return result.Produce();
1386     }
1387    
1388     String LSCPServer::ListAvailableMidiInputDrivers() {
1389     dmsg(2,("LSCPServer: ListAvailableMidiInputDrivers()\n"));
1390     LSCPResultSet result;
1391     try {
1392 senkov 155 String s = MidiInputDeviceFactory::AvailableDriversAsString();
1393     result.Add(s);
1394     }
1395 schoenebeck 880 catch (Exception e) {
1396 senkov 155 result.Error(e);
1397     }
1398     return result.Produce();
1399     }
1400    
1401     String LSCPServer::GetMidiInputDriverInfo(String Driver) {
1402     dmsg(2,("LSCPServer: GetMidiInputDriverInfo(Driver=%s)\n",Driver.c_str()));
1403     LSCPResultSet result;
1404     try {
1405     result.Add("DESCRIPTION", MidiInputDeviceFactory::GetDriverDescription(Driver));
1406     result.Add("VERSION", MidiInputDeviceFactory::GetDriverVersion(Driver));
1407    
1408     std::map<String,DeviceCreationParameter*> parameters = MidiInputDeviceFactory::GetAvailableDriverParameters(Driver);
1409     if (parameters.size()) { // if there are parameters defined for this driver
1410     String s;
1411     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1412     for (;iter != parameters.end(); iter++) {
1413     if (s != "") s += ",";
1414     s += iter->first;
1415 iliev 1835 delete iter->second;
1416 senkov 155 }
1417     result.Add("PARAMETERS", s);
1418     }
1419     }
1420 schoenebeck 880 catch (Exception e) {
1421 senkov 155 result.Error(e);
1422     }
1423     return result.Produce();
1424     }
1425    
1426 schoenebeck 123 String LSCPServer::GetAudioOutputDriverInfo(String Driver) {
1427     dmsg(2,("LSCPServer: GetAudioOutputDriverInfo(Driver=%s)\n",Driver.c_str()));
1428     LSCPResultSet result;
1429     try {
1430     result.Add("DESCRIPTION", AudioOutputDeviceFactory::GetDriverDescription(Driver));
1431     result.Add("VERSION", AudioOutputDeviceFactory::GetDriverVersion(Driver));
1432    
1433     std::map<String,DeviceCreationParameter*> parameters = AudioOutputDeviceFactory::GetAvailableDriverParameters(Driver);
1434     if (parameters.size()) { // if there are parameters defined for this driver
1435     String s;
1436     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1437     for (;iter != parameters.end(); iter++) {
1438     if (s != "") s += ",";
1439     s += iter->first;
1440 iliev 1835 delete iter->second;
1441 schoenebeck 123 }
1442     result.Add("PARAMETERS", s);
1443     }
1444     }
1445 schoenebeck 880 catch (Exception e) {
1446 schoenebeck 123 result.Error(e);
1447     }
1448     return result.Produce();
1449     }
1450    
1451 senkov 155 String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1452 persson 2837 dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),int(DependencyList.size())));
1453 senkov 155 LSCPResultSet result;
1454     try {
1455     DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
1456     result.Add("TYPE", pParameter->Type());
1457     result.Add("DESCRIPTION", pParameter->Description());
1458 schoenebeck 223 result.Add("MANDATORY", pParameter->Mandatory());
1459     result.Add("FIX", pParameter->Fix());
1460     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1461 schoenebeck 226 optional<String> oDepends = pParameter->Depends();
1462     optional<String> oDefault = pParameter->Default(DependencyList);
1463     optional<String> oRangeMin = pParameter->RangeMin(DependencyList);
1464     optional<String> oRangeMax = pParameter->RangeMax(DependencyList);
1465     optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1466     if (oDepends) result.Add("DEPENDS", *oDepends);
1467     if (oDefault) result.Add("DEFAULT", *oDefault);
1468     if (oRangeMin) result.Add("RANGE_MIN", *oRangeMin);
1469     if (oRangeMax) result.Add("RANGE_MAX", *oRangeMax);
1470     if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1471 iliev 1835 delete pParameter;
1472 senkov 155 }
1473 schoenebeck 880 catch (Exception e) {
1474 senkov 155 result.Error(e);
1475     }
1476     return result.Produce();
1477     }
1478    
1479 schoenebeck 123 String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1480 persson 2837 dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),int(DependencyList.size())));
1481 schoenebeck 123 LSCPResultSet result;
1482     try {
1483     DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
1484     result.Add("TYPE", pParameter->Type());
1485     result.Add("DESCRIPTION", pParameter->Description());
1486 schoenebeck 223 result.Add("MANDATORY", pParameter->Mandatory());
1487     result.Add("FIX", pParameter->Fix());
1488     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1489 schoenebeck 226 optional<String> oDepends = pParameter->Depends();
1490     optional<String> oDefault = pParameter->Default(DependencyList);
1491     optional<String> oRangeMin = pParameter->RangeMin(DependencyList);
1492     optional<String> oRangeMax = pParameter->RangeMax(DependencyList);
1493     optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1494     if (oDepends) result.Add("DEPENDS", *oDepends);
1495     if (oDefault) result.Add("DEFAULT", *oDefault);
1496     if (oRangeMin) result.Add("RANGE_MIN", *oRangeMin);
1497     if (oRangeMax) result.Add("RANGE_MAX", *oRangeMax);
1498     if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1499 iliev 1835 delete pParameter;
1500 schoenebeck 123 }
1501 schoenebeck 880 catch (Exception e) {
1502 schoenebeck 123 result.Error(e);
1503     }
1504     return result.Produce();
1505     }
1506    
1507     String LSCPServer::GetAudioOutputDeviceCount() {
1508     dmsg(2,("LSCPServer: GetAudioOutputDeviceCount()\n"));
1509     LSCPResultSet result;
1510     try {
1511     uint count = pSampler->AudioOutputDevices();
1512 senkov 138 result.Add(count); // success
1513 schoenebeck 123 }
1514 schoenebeck 880 catch (Exception e) {
1515 schoenebeck 123 result.Error(e);
1516     }
1517     return result.Produce();
1518     }
1519    
1520 senkov 155 String LSCPServer::GetMidiInputDeviceCount() {
1521     dmsg(2,("LSCPServer: GetMidiInputDeviceCount()\n"));
1522     LSCPResultSet result;
1523     try {
1524     uint count = pSampler->MidiInputDevices();
1525     result.Add(count); // success
1526     }
1527 schoenebeck 880 catch (Exception e) {
1528 senkov 155 result.Error(e);
1529     }
1530     return result.Produce();
1531     }
1532    
1533 schoenebeck 123 String LSCPServer::GetAudioOutputDevices() {
1534     dmsg(2,("LSCPServer: GetAudioOutputDevices()\n"));
1535     LSCPResultSet result;
1536     try {
1537     String s;
1538     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1539     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1540     for (; iter != devices.end(); iter++) {
1541     if (s != "") s += ",";
1542     s += ToString(iter->first);
1543     }
1544     result.Add(s);
1545     }
1546 schoenebeck 880 catch (Exception e) {
1547 schoenebeck 123 result.Error(e);
1548     }
1549     return result.Produce();
1550     }
1551    
1552 senkov 155 String LSCPServer::GetMidiInputDevices() {
1553     dmsg(2,("LSCPServer: GetMidiInputDevices()\n"));
1554     LSCPResultSet result;
1555     try {
1556     String s;
1557     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1558     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1559     for (; iter != devices.end(); iter++) {
1560     if (s != "") s += ",";
1561     s += ToString(iter->first);
1562     }
1563     result.Add(s);
1564     }
1565 schoenebeck 880 catch (Exception e) {
1566 senkov 155 result.Error(e);
1567     }
1568     return result.Produce();
1569     }
1570    
1571 schoenebeck 123 String LSCPServer::GetAudioOutputDeviceInfo(uint DeviceIndex) {
1572     dmsg(2,("LSCPServer: GetAudioOutputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1573     LSCPResultSet result;
1574     try {
1575     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1576 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1577 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
1578 schoenebeck 221 result.Add("DRIVER", pDevice->Driver());
1579 schoenebeck 123 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1580     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1581     for (; iter != parameters.end(); iter++) {
1582     result.Add(iter->first, iter->second->Value());
1583     }
1584     }
1585 schoenebeck 880 catch (Exception e) {
1586 schoenebeck 123 result.Error(e);
1587     }
1588     return result.Produce();
1589     }
1590    
1591 senkov 155 String LSCPServer::GetMidiInputDeviceInfo(uint DeviceIndex) {
1592     dmsg(2,("LSCPServer: GetMidiInputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1593     LSCPResultSet result;
1594     try {
1595     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1596 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1597 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1598 schoenebeck 221 result.Add("DRIVER", pDevice->Driver());
1599 senkov 155 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1600     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1601     for (; iter != parameters.end(); iter++) {
1602     result.Add(iter->first, iter->second->Value());
1603     }
1604     }
1605 schoenebeck 880 catch (Exception e) {
1606 senkov 155 result.Error(e);
1607     }
1608     return result.Produce();
1609     }
1610     String LSCPServer::GetMidiInputPortInfo(uint DeviceIndex, uint PortIndex) {
1611     dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
1612     LSCPResultSet result;
1613     try {
1614 schoenebeck 223 // get MIDI input device
1615 senkov 155 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1616 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1617 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1618 schoenebeck 223
1619     // get MIDI port
1620 schoenebeck 221 MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1621 schoenebeck 880 if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1622 schoenebeck 223
1623     // return the values of all MIDI port parameters
1624 schoenebeck 221 std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1625     std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1626 senkov 155 for (; iter != parameters.end(); iter++) {
1627     result.Add(iter->first, iter->second->Value());
1628     }
1629     }
1630 schoenebeck 880 catch (Exception e) {
1631 senkov 155 result.Error(e);
1632     }
1633     return result.Produce();
1634     }
1635    
1636 schoenebeck 123 String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
1637 persson 2837 dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%u,ChannelId=%u)\n",DeviceId,ChannelId));
1638 schoenebeck 123 LSCPResultSet result;
1639     try {
1640     // get audio output device
1641     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1642 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1643 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1644    
1645     // get audio channel
1646     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1647 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1648 schoenebeck 123
1649     // return the values of all audio channel parameters
1650     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1651     std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1652     for (; iter != parameters.end(); iter++) {
1653     result.Add(iter->first, iter->second->Value());
1654     }
1655     }
1656 schoenebeck 880 catch (Exception e) {
1657 schoenebeck 123 result.Error(e);
1658     }
1659     return result.Produce();
1660     }
1661    
1662 senkov 185 String LSCPServer::GetMidiInputPortParameterInfo(uint DeviceId, uint PortId, String ParameterName) {
1663     dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
1664     LSCPResultSet result;
1665     try {
1666 schoenebeck 223 // get MIDI input device
1667     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1668 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1669 schoenebeck 223 MidiInputDevice* pDevice = devices[DeviceId];
1670 senkov 185
1671 schoenebeck 221 // get midi port
1672     MidiInputPort* pPort = pDevice->GetPort(PortId);
1673 schoenebeck 880 if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1674 senkov 185
1675 schoenebeck 223 // get desired port parameter
1676     std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1677 schoenebeck 880 if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1678 schoenebeck 223 DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1679 schoenebeck 203
1680 senkov 185 // return all fields of this audio channel parameter
1681     result.Add("TYPE", pParameter->Type());
1682     result.Add("DESCRIPTION", pParameter->Description());
1683     result.Add("FIX", pParameter->Fix());
1684     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1685 schoenebeck 223 if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
1686     if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
1687     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1688 senkov 185 }
1689 schoenebeck 880 catch (Exception e) {
1690 senkov 185 result.Error(e);
1691     }
1692     return result.Produce();
1693     }
1694    
1695 schoenebeck 123 String LSCPServer::GetAudioOutputChannelParameterInfo(uint DeviceId, uint ChannelId, String ParameterName) {
1696     dmsg(2,("LSCPServer: GetAudioOutputChannelParameterInfo(DeviceId=%d,ChannelId=%d,ParameterName=%s)\n",DeviceId,ChannelId,ParameterName.c_str()));
1697     LSCPResultSet result;
1698     try {
1699     // get audio output device
1700     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1701 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1702 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1703    
1704     // get audio channel
1705     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1706 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1707 schoenebeck 123
1708     // get desired audio channel parameter
1709     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1710 schoenebeck 880 if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1711 schoenebeck 123 DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1712    
1713     // return all fields of this audio channel parameter
1714     result.Add("TYPE", pParameter->Type());
1715     result.Add("DESCRIPTION", pParameter->Description());
1716     result.Add("FIX", pParameter->Fix());
1717     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1718 schoenebeck 223 if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
1719     if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
1720     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1721 schoenebeck 123 }
1722 schoenebeck 880 catch (Exception e) {
1723 schoenebeck 123 result.Error(e);
1724     }
1725     return result.Produce();
1726     }
1727    
1728     String LSCPServer::SetAudioOutputChannelParameter(uint DeviceId, uint ChannelId, String ParamKey, String ParamVal) {
1729     dmsg(2,("LSCPServer: SetAudioOutputChannelParameter(DeviceId=%d,ChannelId=%d,ParamKey=%s,ParamVal=%s)\n",DeviceId,ChannelId,ParamKey.c_str(),ParamVal.c_str()));
1730     LSCPResultSet result;
1731     try {
1732     // get audio output device
1733     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1734 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1735 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1736    
1737     // get audio channel
1738     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1739 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1740 schoenebeck 123
1741     // get desired audio channel parameter
1742     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1743 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1744 schoenebeck 123 DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1745    
1746     // set new channel parameter value
1747     pParameter->SetValue(ParamVal);
1748 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1749 schoenebeck 123 }
1750 schoenebeck 880 catch (Exception e) {
1751 schoenebeck 123 result.Error(e);
1752     }
1753     return result.Produce();
1754     }
1755    
1756     String LSCPServer::SetAudioOutputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1757     dmsg(2,("LSCPServer: SetAudioOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1758     LSCPResultSet result;
1759     try {
1760     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1761 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1762 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
1763     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1764 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1765 schoenebeck 123 parameters[ParamKey]->SetValue(ParamVal);
1766 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1767 schoenebeck 123 }
1768 schoenebeck 880 catch (Exception e) {
1769 schoenebeck 123 result.Error(e);
1770     }
1771     return result.Produce();
1772     }
1773    
1774 senkov 155 String LSCPServer::SetMidiInputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1775     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1776     LSCPResultSet result;
1777     try {
1778     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1779 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1780 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1781     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1782 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1783 senkov 155 parameters[ParamKey]->SetValue(ParamVal);
1784 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1785 senkov 155 }
1786 schoenebeck 880 catch (Exception e) {
1787 senkov 155 result.Error(e);
1788     }
1789     return result.Produce();
1790     }
1791    
1792     String LSCPServer::SetMidiInputPortParameter(uint DeviceIndex, uint PortIndex, String ParamKey, String ParamVal) {
1793     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1794     LSCPResultSet result;
1795     try {
1796 schoenebeck 223 // get MIDI input device
1797 senkov 155 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1798 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1799 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1800 schoenebeck 223
1801     // get MIDI port
1802 schoenebeck 221 MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1803 schoenebeck 880 if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1804 schoenebeck 223
1805     // set port parameter value
1806 schoenebeck 221 std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1807 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1808 senkov 155 parameters[ParamKey]->SetValue(ParamVal);
1809 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1810 senkov 155 }
1811 schoenebeck 880 catch (Exception e) {
1812 senkov 155 result.Error(e);
1813     }
1814     return result.Produce();
1815     }
1816    
1817 schoenebeck 35 /**
1818     * Will be called by the parser to change the audio output channel for
1819     * playback on a particular sampler channel.
1820     */
1821 schoenebeck 123 String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1822     dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1823 schoenebeck 225 LSCPResultSet result;
1824     try {
1825     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1826 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1827 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1828 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1829     if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1830 schoenebeck 411 pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1831 schoenebeck 225 }
1832 schoenebeck 880 catch (Exception e) {
1833 schoenebeck 225 result.Error(e);
1834     }
1835     return result.Produce();
1836 schoenebeck 35 }
1837    
1838 capela 159 String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1839     dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1840     LSCPResultSet result;
1841 persson 2427 {
1842     LockGuard lock(RTNotifyMutex);
1843     try {
1844     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1845     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1846     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1847     if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1848     AudioOutputDevice* pDevice = devices[AudioDeviceId];
1849     pSamplerChannel->SetAudioOutputDevice(pDevice);
1850     }
1851     catch (Exception e) {
1852     result.Error(e);
1853     }
1854 capela 159 }
1855     return result.Produce();
1856     }
1857    
1858 capela 143 String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1859     dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1860     LSCPResultSet result;
1861 persson 2427 {
1862     LockGuard lock(RTNotifyMutex);
1863     try {
1864     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1865     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1866     // Driver type name aliasing...
1867     if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1868     if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1869     // Check if there's one audio output device already created
1870     // for the intended audio driver type (AudioOutputDriver)...
1871     AudioOutputDevice *pDevice = NULL;
1872     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1873     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1874     for (; iter != devices.end(); iter++) {
1875     if ((iter->second)->Driver() == AudioOutputDriver) {
1876     pDevice = iter->second;
1877     break;
1878     }
1879 capela 143 }
1880 persson 2427 // If it doesn't exist, create a new one with default parameters...
1881     if (pDevice == NULL) {
1882     std::map<String,String> params;
1883     pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1884     }
1885     // Must have a device...
1886     if (pDevice == NULL)
1887     throw Exception("Internal error: could not create audio output device.");
1888     // Set it as the current channel device...
1889     pSamplerChannel->SetAudioOutputDevice(pDevice);
1890 capela 143 }
1891 persson 2427 catch (Exception e) {
1892     result.Error(e);
1893 capela 143 }
1894     }
1895     return result.Produce();
1896     }
1897    
1898 schoenebeck 2500 String LSCPServer::AddChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId, uint MIDIPort) {
1899     dmsg(2,("LSCPServer: AddChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d, MIDIPort=%d)\n",uiSamplerChannel,MIDIDeviceId,MIDIPort));
1900     LSCPResultSet result;
1901     try {
1902     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1903     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1904    
1905     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1906     if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1907     MidiInputDevice* pDevice = devices[MIDIDeviceId];
1908    
1909     MidiInputPort* pPort = pDevice->GetPort(MIDIPort);
1910     if (!pPort) throw Exception("There is no MIDI input port with index " + ToString(MIDIPort) + " on MIDI input device with index " + ToString(MIDIDeviceId));
1911    
1912     pSamplerChannel->Connect(pPort);
1913     } catch (Exception e) {
1914     result.Error(e);
1915     }
1916     return result.Produce();
1917     }
1918    
1919     String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel) {
1920     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d)\n",uiSamplerChannel));
1921     LSCPResultSet result;
1922     try {
1923     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1924     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1925     pSamplerChannel->DisconnectAllMidiInputPorts();
1926     } catch (Exception e) {
1927     result.Error(e);
1928     }
1929     return result.Produce();
1930     }
1931    
1932     String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId) {
1933     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d)\n",uiSamplerChannel,MIDIDeviceId));
1934     LSCPResultSet result;
1935     try {
1936     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1937     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1938    
1939     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1940     if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1941     MidiInputDevice* pDevice = devices[MIDIDeviceId];
1942    
1943     std::vector<MidiInputPort*> vPorts = pSamplerChannel->GetMidiInputPorts();
1944     for (int i = 0; i < vPorts.size(); ++i)
1945     if (vPorts[i]->GetDevice() == pDevice)
1946     pSamplerChannel->Disconnect(vPorts[i]);
1947    
1948     } catch (Exception e) {
1949     result.Error(e);
1950     }
1951     return result.Produce();
1952     }
1953    
1954     String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId, uint MIDIPort) {
1955     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d, MIDIPort=%d)\n",uiSamplerChannel,MIDIDeviceId,MIDIPort));
1956     LSCPResultSet result;
1957     try {
1958     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1959     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1960    
1961     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1962     if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1963     MidiInputDevice* pDevice = devices[MIDIDeviceId];
1964    
1965     MidiInputPort* pPort = pDevice->GetPort(MIDIPort);
1966     if (!pPort) throw Exception("There is no MIDI input port with index " + ToString(MIDIPort) + " on MIDI input device with index " + ToString(MIDIDeviceId));
1967    
1968     pSamplerChannel->Disconnect(pPort);
1969     } catch (Exception e) {
1970     result.Error(e);
1971     }
1972     return result.Produce();
1973     }
1974    
1975     String LSCPServer::ListChannelMidiInputs(uint uiSamplerChannel) {
1976     dmsg(2,("LSCPServer: ListChannelMidiInputs(uiSamplerChannel=%d)\n",uiSamplerChannel));
1977     LSCPResultSet result;
1978     try {
1979     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1980     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1981     std::vector<MidiInputPort*> vPorts = pSamplerChannel->GetMidiInputPorts();
1982    
1983     String s;
1984     for (int i = 0; i < vPorts.size(); ++i) {
1985     const int iDeviceID = vPorts[i]->GetDevice()->MidiInputDeviceID();
1986     const int iPortNr = vPorts[i]->GetPortNumber();
1987     if (s.size()) s += ",";
1988     s += "{" + ToString(iDeviceID) + ","
1989     + ToString(iPortNr) + "}";
1990     }
1991     result.Add(s);
1992     } catch (Exception e) {
1993     result.Error(e);
1994     }
1995     return result.Produce();
1996     }
1997    
1998 capela 159 String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
1999     dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
2000 senkov 120 LSCPResultSet result;
2001 schoenebeck 53 try {
2002     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2003 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2004 capela 159 pSamplerChannel->SetMidiInputPort(MIDIPort);
2005 schoenebeck 53 }
2006 schoenebeck 880 catch (Exception e) {
2007 senkov 120 result.Error(e);
2008 schoenebeck 53 }
2009 senkov 120 return result.Produce();
2010 schoenebeck 53 }
2011    
2012 capela 159 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
2013     dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
2014 senkov 120 LSCPResultSet result;
2015 senkov 68 try {
2016     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2017 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2018 schoenebeck 675 pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
2019 senkov 68 }
2020 schoenebeck 880 catch (Exception e) {
2021 senkov 120 result.Error(e);
2022 senkov 68 }
2023 senkov 120 return result.Produce();
2024 schoenebeck 35 }
2025    
2026 capela 159 String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
2027     dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
2028 schoenebeck 123 LSCPResultSet result;
2029     try {
2030 capela 159 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2031 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2032 capela 159 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
2033 schoenebeck 880 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
2034 capela 159 MidiInputDevice* pDevice = devices[MIDIDeviceId];
2035     pSamplerChannel->SetMidiInputDevice(pDevice);
2036 schoenebeck 123 }
2037 schoenebeck 880 catch (Exception e) {
2038 schoenebeck 123 result.Error(e);
2039     }
2040     return result.Produce();
2041     }
2042    
2043 capela 159 String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
2044     dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
2045     LSCPResultSet result;
2046     try {
2047     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2048 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2049 capela 159 // Driver type name aliasing...
2050 schoenebeck 226 if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
2051 capela 159 // Check if there's one MIDI input device already created
2052     // for the intended MIDI driver type (MidiInputDriver)...
2053     MidiInputDevice *pDevice = NULL;
2054     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
2055     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
2056     for (; iter != devices.end(); iter++) {
2057     if ((iter->second)->Driver() == MidiInputDriver) {
2058     pDevice = iter->second;
2059     break;
2060     }
2061     }
2062     // If it doesn't exist, create a new one with default parameters...
2063     if (pDevice == NULL) {
2064     std::map<String,String> params;
2065     pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
2066     // Make it with at least one initial port.
2067     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
2068     }
2069     // Must have a device...
2070     if (pDevice == NULL)
2071 schoenebeck 880 throw Exception("Internal error: could not create MIDI input device.");
2072 capela 159 // Set it as the current channel device...
2073     pSamplerChannel->SetMidiInputDevice(pDevice);
2074     }
2075 schoenebeck 880 catch (Exception e) {
2076 capela 159 result.Error(e);
2077     }
2078     return result.Produce();
2079     }
2080    
2081 schoenebeck 35 /**
2082 capela 159 * Will be called by the parser to change the MIDI input device, port and channel on which
2083     * engine of a particular sampler channel should listen to.
2084     */
2085     String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
2086     dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
2087     LSCPResultSet result;
2088     try {
2089     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2090 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2091 capela 159 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
2092 schoenebeck 880 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
2093 capela 159 MidiInputDevice* pDevice = devices[MIDIDeviceId];
2094 schoenebeck 675 pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
2095 capela 159 }
2096 schoenebeck 880 catch (Exception e) {
2097 capela 159 result.Error(e);
2098     }
2099     return result.Produce();
2100     }
2101    
2102     /**
2103 schoenebeck 35 * Will be called by the parser to change the global volume factor on a
2104     * particular sampler channel.
2105     */
2106 schoenebeck 225 String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
2107     dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
2108 senkov 120 LSCPResultSet result;
2109 schoenebeck 53 try {
2110 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2111 schoenebeck 411 pEngineChannel->Volume(dVolume);
2112 schoenebeck 53 }
2113 schoenebeck 880 catch (Exception e) {
2114 senkov 120 result.Error(e);
2115 schoenebeck 53 }
2116 senkov 120 return result.Produce();
2117 schoenebeck 35 }
2118    
2119     /**
2120 schoenebeck 705 * Will be called by the parser to mute/unmute particular sampler channel.
2121     */
2122     String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
2123     dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
2124     LSCPResultSet result;
2125     try {
2126 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2127 schoenebeck 705
2128     if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
2129     else pEngineChannel->SetMute(1);
2130 schoenebeck 880 } catch (Exception e) {
2131 schoenebeck 705 result.Error(e);
2132     }
2133     return result.Produce();
2134     }
2135    
2136     /**
2137     * Will be called by the parser to solo particular sampler channel.
2138     */
2139     String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
2140     dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
2141     LSCPResultSet result;
2142     try {
2143 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2144 schoenebeck 705
2145     bool oldSolo = pEngineChannel->GetSolo();
2146     bool hadSoloChannel = HasSoloChannel();
2147 schoenebeck 1009
2148 schoenebeck 705 pEngineChannel->SetSolo(bSolo);
2149 schoenebeck 1009
2150 schoenebeck 705 if(!oldSolo && bSolo) {
2151     if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
2152     if(!hadSoloChannel) MuteNonSoloChannels();
2153     }
2154 schoenebeck 1009
2155 schoenebeck 705 if(oldSolo && !bSolo) {
2156     if(!HasSoloChannel()) UnmuteChannels();
2157     else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
2158     }
2159 schoenebeck 880 } catch (Exception e) {
2160 schoenebeck 705 result.Error(e);
2161     }
2162     return result.Produce();
2163     }
2164    
2165     /**
2166     * Determines whether there is at least one solo channel in the channel list.
2167     *
2168     * @returns true if there is at least one solo channel in the channel list,
2169     * false otherwise.
2170     */
2171     bool LSCPServer::HasSoloChannel() {
2172     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2173     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2174     for (; iter != channels.end(); iter++) {
2175     EngineChannel* c = iter->second->GetEngineChannel();
2176     if(c && c->GetSolo()) return true;
2177     }
2178    
2179     return false;
2180     }
2181    
2182     /**
2183     * Mutes all unmuted non-solo channels. Notice that the channels are muted
2184     * with -1 which indicates that they are muted because of the presence
2185     * of a solo channel(s). Channels muted with -1 will be automatically unmuted
2186     * when there are no solo channels left.
2187     */
2188     void LSCPServer::MuteNonSoloChannels() {
2189     dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
2190     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2191     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2192     for (; iter != channels.end(); iter++) {
2193     EngineChannel* c = iter->second->GetEngineChannel();
2194     if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
2195     }
2196     }
2197    
2198     /**
2199     * Unmutes all channels that are muted because of the presence
2200     * of a solo channel(s).
2201     */
2202     void LSCPServer::UnmuteChannels() {
2203     dmsg(2,("LSCPServer: UnmuteChannels()\n"));
2204     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2205     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2206     for (; iter != channels.end(); iter++) {
2207     EngineChannel* c = iter->second->GetEngineChannel();
2208     if(c && c->GetMute() == -1) c->SetMute(0);
2209     }
2210     }
2211    
2212 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) {
2213 schoenebeck 947 dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
2214    
2215     midi_prog_index_t idx;
2216 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2217     idx.midi_bank_lsb = MidiBank & 0x7f;
2218 schoenebeck 947 idx.midi_prog = MidiProg;
2219    
2220     MidiInstrumentMapper::entry_t entry;
2221     entry.EngineName = EngineType;
2222     entry.InstrumentFile = InstrumentFile;
2223     entry.InstrumentIndex = InstrumentIndex;
2224     entry.LoadMode = LoadMode;
2225     entry.Volume = Volume;
2226     entry.Name = Name;
2227    
2228     LSCPResultSet result;
2229     try {
2230 schoenebeck 1047 // PERSISTENT mapping commands might block for a long time, so in
2231     // that case we add/replace the mapping in another thread in case
2232     // the NON_MODAL argument was supplied, non persistent mappings
2233     // should return immediately, so we don't need to do that for them
2234     bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
2235 schoenebeck 973 MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
2236 schoenebeck 947 } catch (Exception e) {
2237     result.Error(e);
2238     }
2239     return result.Produce();
2240     }
2241    
2242 schoenebeck 973 String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2243 schoenebeck 947 dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
2244    
2245     midi_prog_index_t idx;
2246 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2247     idx.midi_bank_lsb = MidiBank & 0x7f;
2248 schoenebeck 947 idx.midi_prog = MidiProg;
2249    
2250     LSCPResultSet result;
2251     try {
2252 schoenebeck 973 MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
2253 schoenebeck 947 } catch (Exception e) {
2254     result.Error(e);
2255     }
2256     return result.Produce();
2257     }
2258    
2259 schoenebeck 973 String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
2260     dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
2261 schoenebeck 947 LSCPResultSet result;
2262 schoenebeck 973 try {
2263 iliev 1763 result.Add(MidiInstrumentMapper::GetInstrumentCount(MidiMapID));
2264 schoenebeck 973 } catch (Exception e) {
2265     result.Error(e);
2266     }
2267 schoenebeck 947 return result.Produce();
2268     }
2269    
2270 schoenebeck 973
2271     String LSCPServer::GetAllMidiInstrumentMappings() {
2272     dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
2273     LSCPResultSet result;
2274 iliev 1763 try {
2275     result.Add(MidiInstrumentMapper::GetInstrumentCount());
2276     } catch (Exception e) {
2277     result.Error(e);
2278 schoenebeck 973 }
2279     return result.Produce();
2280     }
2281    
2282     String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2283 schoenebeck 947 dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
2284     LSCPResultSet result;
2285     try {
2286 iliev 1763 MidiInstrumentMapper::entry_t entry = MidiInstrumentMapper::GetEntry(MidiMapID, MidiBank, MidiProg);
2287     // convert the filename into the correct encoding as defined for LSCP
2288     // (especially in terms of special characters -> escape sequences)
2289 schoenebeck 1471 #if WIN32
2290 iliev 1763 const String instrumentFileName = Path::fromWindows(entry.InstrumentFile).toLscp();
2291 schoenebeck 1471 #else
2292 iliev 1763 // assuming POSIX
2293     const String instrumentFileName = Path::fromPosix(entry.InstrumentFile).toLscp();
2294 schoenebeck 1471 #endif
2295    
2296 iliev 1763 result.Add("NAME", _escapeLscpResponse(entry.Name));
2297     result.Add("ENGINE_NAME", entry.EngineName);
2298     result.Add("INSTRUMENT_FILE", instrumentFileName);
2299     result.Add("INSTRUMENT_NR", (int) entry.InstrumentIndex);
2300     String instrumentName;
2301     Engine* pEngine = EngineFactory::Create(entry.EngineName);
2302     if (pEngine) {
2303     if (pEngine->GetInstrumentManager()) {
2304     InstrumentManager::instrument_id_t instrID;
2305     instrID.FileName = entry.InstrumentFile;
2306     instrID.Index = entry.InstrumentIndex;
2307     instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
2308 schoenebeck 947 }
2309 iliev 1763 EngineFactory::Destroy(pEngine);
2310 schoenebeck 947 }
2311 iliev 1763 result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2312     switch (entry.LoadMode) {
2313     case MidiInstrumentMapper::ON_DEMAND:
2314     result.Add("LOAD_MODE", "ON_DEMAND");
2315     break;
2316     case MidiInstrumentMapper::ON_DEMAND_HOLD:
2317     result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2318     break;
2319     case MidiInstrumentMapper::PERSISTENT:
2320     result.Add("LOAD_MODE", "PERSISTENT");
2321     break;
2322     default:
2323     throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2324     }
2325     result.Add("VOLUME", entry.Volume);
2326 schoenebeck 947 } catch (Exception e) {
2327     result.Error(e);
2328     }
2329     return result.Produce();
2330     }
2331    
2332 schoenebeck 973 String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
2333     dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
2334 schoenebeck 947 LSCPResultSet result;
2335     try {
2336     String s;
2337 schoenebeck 973 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
2338 schoenebeck 947 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2339     for (; iter != mappings.end(); iter++) {
2340     if (s.size()) s += ",";
2341 schoenebeck 973 s += "{" + ToString(MidiMapID) + ","
2342 schoenebeck 1007 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2343 schoenebeck 973 + ToString(int(iter->first.midi_prog)) + "}";
2344 schoenebeck 947 }
2345     result.Add(s);
2346     } catch (Exception e) {
2347     result.Error(e);
2348     }
2349     return result.Produce();
2350     }
2351    
2352 schoenebeck 973 String LSCPServer::ListAllMidiInstrumentMappings() {
2353     dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
2354     LSCPResultSet result;
2355     try {
2356     std::vector<int> maps = MidiInstrumentMapper::Maps();
2357     String s;
2358     for (int i = 0; i < maps.size(); i++) {
2359     std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
2360     std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2361     for (; iter != mappings.end(); iter++) {
2362     if (s.size()) s += ",";
2363     s += "{" + ToString(maps[i]) + ","
2364 schoenebeck 1009 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2365 schoenebeck 973 + ToString(int(iter->first.midi_prog)) + "}";
2366     }
2367     }
2368     result.Add(s);
2369     } catch (Exception e) {
2370     result.Error(e);
2371     }
2372     return result.Produce();
2373     }
2374    
2375     String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
2376 schoenebeck 947 dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
2377     LSCPResultSet result;
2378     try {
2379 schoenebeck 973 MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
2380 schoenebeck 947 } catch (Exception e) {
2381     result.Error(e);
2382     }
2383     return result.Produce();
2384     }
2385    
2386 schoenebeck 973 String LSCPServer::ClearAllMidiInstrumentMappings() {
2387     dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
2388     LSCPResultSet result;
2389     try {
2390     std::vector<int> maps = MidiInstrumentMapper::Maps();
2391     for (int i = 0; i < maps.size(); i++)
2392     MidiInstrumentMapper::RemoveAllEntries(maps[i]);
2393     } catch (Exception e) {
2394     result.Error(e);
2395     }
2396     return result.Produce();
2397     }
2398    
2399     String LSCPServer::AddMidiInstrumentMap(String MapName) {
2400     dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
2401     LSCPResultSet result;
2402     try {
2403     int MapID = MidiInstrumentMapper::AddMap(MapName);
2404     result = LSCPResultSet(MapID);
2405     } catch (Exception e) {
2406     result.Error(e);
2407     }
2408     return result.Produce();
2409     }
2410    
2411     String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
2412     dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
2413     LSCPResultSet result;
2414     try {
2415     MidiInstrumentMapper::RemoveMap(MidiMapID);
2416     } catch (Exception e) {
2417     result.Error(e);
2418     }
2419     return result.Produce();
2420     }
2421    
2422     String LSCPServer::RemoveAllMidiInstrumentMaps() {
2423     dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
2424     LSCPResultSet result;
2425     try {
2426     MidiInstrumentMapper::RemoveAllMaps();
2427     } catch (Exception e) {
2428     result.Error(e);
2429     }
2430     return result.Produce();
2431     }
2432    
2433     String LSCPServer::GetMidiInstrumentMaps() {
2434     dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
2435     LSCPResultSet result;
2436     try {
2437     result.Add(MidiInstrumentMapper::Maps().size());
2438     } catch (Exception e) {
2439     result.Error(e);
2440     }
2441     return result.Produce();
2442     }
2443    
2444     String LSCPServer::ListMidiInstrumentMaps() {
2445     dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
2446     LSCPResultSet result;
2447     try {
2448     std::vector<int> maps = MidiInstrumentMapper::Maps();
2449     String sList;
2450     for (int i = 0; i < maps.size(); i++) {
2451     if (sList != "") sList += ",";
2452     sList += ToString(maps[i]);
2453     }
2454     result.Add(sList);
2455     } catch (Exception e) {
2456     result.Error(e);
2457     }
2458     return result.Produce();
2459     }
2460    
2461     String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
2462     dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2463     LSCPResultSet result;
2464     try {
2465 schoenebeck 1399 result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2466 iliev 1135 result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2467 schoenebeck 973 } catch (Exception e) {
2468     result.Error(e);
2469     }
2470     return result.Produce();
2471     }
2472    
2473     String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2474     dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2475     LSCPResultSet result;
2476     try {
2477     MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2478     } catch (Exception e) {
2479     result.Error(e);
2480     }
2481     return result.Produce();
2482     }
2483    
2484 schoenebeck 705 /**
2485 schoenebeck 973 * Set the MIDI instrument map the given sampler channel shall use for
2486     * handling MIDI program change messages. There are the following two
2487     * special (negative) values:
2488     *
2489     * - (-1) : set to NONE (ignore program changes)
2490     * - (-2) : set to DEFAULT map
2491     */
2492     String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2493     dmsg(2,("LSCPServer: SetChannelMap()\n"));
2494     LSCPResultSet result;
2495     try {
2496 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2497 schoenebeck 973
2498     if (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2499     else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2500     else pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2501     } catch (Exception e) {
2502     result.Error(e);
2503     }
2504     return result.Produce();
2505     }
2506    
2507 schoenebeck 1001 String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2508     dmsg(2,("LSCPServer: CreateFxSend()\n"));
2509     LSCPResultSet result;
2510     try {
2511 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2512 schoenebeck 1252
2513 schoenebeck 1001 FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2514     if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2515    
2516     result = LSCPResultSet(pFxSend->Id()); // success
2517     } catch (Exception e) {
2518     result.Error(e);
2519     }
2520     return result.Produce();
2521     }
2522    
2523     String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2524     dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2525     LSCPResultSet result;
2526     try {
2527 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2528 schoenebeck 1001
2529     FxSend* pFxSend = NULL;
2530     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2531     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2532     pFxSend = pEngineChannel->GetFxSend(i);
2533     break;
2534     }
2535     }
2536     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2537     pEngineChannel->RemoveFxSend(pFxSend);
2538     } catch (Exception e) {
2539     result.Error(e);
2540     }
2541     return result.Produce();
2542     }
2543    
2544     String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2545     dmsg(2,("LSCPServer: GetFxSends()\n"));
2546     LSCPResultSet result;
2547     try {
2548 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2549 schoenebeck 1001
2550     result.Add(pEngineChannel->GetFxSendCount());
2551     } catch (Exception e) {
2552     result.Error(e);
2553     }
2554     return result.Produce();
2555     }
2556    
2557     String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2558     dmsg(2,("LSCPServer: ListFxSends()\n"));
2559     LSCPResultSet result;
2560     String list;
2561     try {
2562 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2563 schoenebeck 1001
2564     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2565     FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2566     if (list != "") list += ",";
2567     list += ToString(pFxSend->Id());
2568     }
2569     result.Add(list);
2570     } catch (Exception e) {
2571     result.Error(e);
2572     }
2573     return result.Produce();
2574     }
2575    
2576 iliev 1135 FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2577     EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2578    
2579     FxSend* pFxSend = NULL;
2580     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2581     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2582     pFxSend = pEngineChannel->GetFxSend(i);
2583     break;
2584     }
2585     }
2586     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2587     return pFxSend;
2588     }
2589    
2590 schoenebeck 1001 String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2591     dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2592     LSCPResultSet result;
2593     try {
2594 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2595     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2596 schoenebeck 1252
2597 schoenebeck 1001 // gather audio routing informations
2598     String AudioRouting;
2599     for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2600     if (AudioRouting != "") AudioRouting += ",";
2601     AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2602     }
2603    
2604 schoenebeck 2137 const String sEffectRouting =
2605     (pFxSend->DestinationEffectChain() >= 0 && pFxSend->DestinationEffectChainPosition() >= 0)
2606     ? ToString(pFxSend->DestinationEffectChain()) + "," + ToString(pFxSend->DestinationEffectChainPosition())
2607     : "NONE";
2608    
2609 schoenebeck 1001 // success
2610 schoenebeck 1399 result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2611 schoenebeck 1026 result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2612     result.Add("LEVEL", ToString(pFxSend->Level()));
2613 schoenebeck 1001 result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2614 schoenebeck 2140 result.Add("EFFECT", sEffectRouting);
2615 schoenebeck 1001 } catch (Exception e) {
2616     result.Error(e);
2617     }
2618     return result.Produce();
2619     }
2620    
2621 iliev 1135 String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2622     dmsg(2,("LSCPServer: SetFxSendName()\n"));
2623     LSCPResultSet result;
2624     try {
2625     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2626    
2627     pFxSend->SetName(Name);
2628     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2629     } catch (Exception e) {
2630     result.Error(e);
2631     }
2632     return result.Produce();
2633     }
2634    
2635 schoenebeck 1001 String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2636     dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2637     LSCPResultSet result;
2638     try {
2639 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2640 schoenebeck 1001
2641     pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2642 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2643 schoenebeck 1001 } catch (Exception e) {
2644     result.Error(e);
2645     }
2646     return result.Produce();
2647     }
2648    
2649 schoenebeck 1026 String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2650     dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2651     LSCPResultSet result;
2652     try {
2653 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2654 schoenebeck 1026
2655     pFxSend->SetMidiController(MidiController);
2656 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2657 schoenebeck 1026 } catch (Exception e) {
2658     result.Error(e);
2659     }
2660     return result.Produce();
2661     }
2662    
2663     String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2664     dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2665     LSCPResultSet result;
2666     try {
2667 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2668 schoenebeck 1026
2669     pFxSend->SetLevel((float)dLevel);
2670 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2671 schoenebeck 1026 } catch (Exception e) {
2672     result.Error(e);
2673     }
2674     return result.Produce();
2675     }
2676    
2677 schoenebeck 2137 String LSCPServer::SetFxSendEffect(uint uiSamplerChannel, uint FxSendID, int iSendEffectChain, int iEffectChainPosition) {
2678     dmsg(2,("LSCPServer: SetFxSendEffect(%d,%d)\n", iSendEffectChain, iEffectChainPosition));
2679     LSCPResultSet result;
2680     try {
2681     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2682    
2683     pFxSend->SetDestinationEffect(iSendEffectChain, iEffectChainPosition);
2684     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2685     } catch (Exception e) {
2686     result.Error(e);
2687     }
2688     return result.Produce();
2689     }
2690    
2691 schoenebeck 2135 String LSCPServer::GetAvailableEffects() {
2692     dmsg(2,("LSCPServer: GetAvailableEffects()\n"));
2693     LSCPResultSet result;
2694     try {
2695     int n = EffectFactory::AvailableEffectsCount();
2696     result.Add(n);
2697     }
2698     catch (Exception e) {
2699     result.Error(e);
2700     }
2701     return result.Produce();
2702     }
2703    
2704     String LSCPServer::ListAvailableEffects() {
2705     dmsg(2,("LSCPServer: ListAvailableEffects()\n"));
2706     LSCPResultSet result;
2707     String list;
2708     try {
2709     //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
2710     int n = EffectFactory::AvailableEffectsCount();
2711     for (int i = 0; i < n; i++) {
2712     if (i) list += ",";
2713     list += ToString(i);
2714     }
2715     }
2716     catch (Exception e) {
2717     result.Error(e);
2718     }
2719     result.Add(list);
2720     return result.Produce();
2721     }
2722    
2723     String LSCPServer::GetEffectInfo(int iEffectIndex) {
2724     dmsg(2,("LSCPServer: GetEffectInfo(%d)\n", iEffectIndex));
2725     LSCPResultSet result;
2726     try {
2727     EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2728     if (!pEffectInfo)
2729     throw Exception("There is no effect with index " + ToString(iEffectIndex));
2730    
2731     // convert the filename into the correct encoding as defined for LSCP
2732     // (especially in terms of special characters -> escape sequences)
2733     #if WIN32
2734     const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2735     #else
2736     // assuming POSIX
2737     const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2738     #endif
2739    
2740     result.Add("SYSTEM", pEffectInfo->EffectSystem());
2741     result.Add("MODULE", dllFileName);
2742     result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2743     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2744     }
2745     catch (Exception e) {
2746     result.Error(e);
2747     }
2748     return result.Produce();
2749     }
2750    
2751 schoenebeck 2137 String LSCPServer::GetEffectInstanceInfo(int iEffectInstance) {
2752     dmsg(2,("LSCPServer: GetEffectInstanceInfo(%d)\n", iEffectInstance));
2753 schoenebeck 2135 LSCPResultSet result;
2754     try {
2755 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2756 schoenebeck 2135 if (!pEffect)
2757 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2758 schoenebeck 2135
2759     EffectInfo* pEffectInfo = pEffect->GetEffectInfo();
2760    
2761     // convert the filename into the correct encoding as defined for LSCP
2762     // (especially in terms of special characters -> escape sequences)
2763     #if WIN32
2764     const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2765     #else
2766     // assuming POSIX
2767     const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2768     #endif
2769    
2770     result.Add("SYSTEM", pEffectInfo->EffectSystem());
2771     result.Add("MODULE", dllFileName);
2772     result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2773     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2774     result.Add("INPUT_CONTROLS", ToString(pEffect->InputControlCount()));
2775     }
2776     catch (Exception e) {
2777     result.Error(e);
2778     }
2779     return result.Produce();
2780     }
2781    
2782 schoenebeck 2137 String LSCPServer::GetEffectInstanceInputControlInfo(int iEffectInstance, int iInputControlIndex) {
2783     dmsg(2,("LSCPServer: GetEffectInstanceInputControlInfo(%d,%d)\n", iEffectInstance, iInputControlIndex));
2784 schoenebeck 2135 LSCPResultSet result;
2785     try {
2786 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2787 schoenebeck 2135 if (!pEffect)
2788 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2789 schoenebeck 2135
2790     EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2791     if (!pEffectControl)
2792     throw Exception(
2793 schoenebeck 2137 "Effect instance " + ToString(iEffectInstance) +
2794 schoenebeck 2135 " does not have an input control with index " +
2795     ToString(iInputControlIndex)
2796     );
2797    
2798     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectControl->Description()));
2799     result.Add("VALUE", pEffectControl->Value());
2800     if (pEffectControl->MinValue())
2801     result.Add("RANGE_MIN", *pEffectControl->MinValue());
2802     if (pEffectControl->MaxValue())
2803     result.Add("RANGE_MAX", *pEffectControl->MaxValue());
2804     if (!pEffectControl->Possibilities().empty())
2805     result.Add("POSSIBILITIES", pEffectControl->Possibilities());
2806     if (pEffectControl->DefaultValue())
2807     result.Add("DEFAULT", *pEffectControl->DefaultValue());
2808     } catch (Exception e) {
2809     result.Error(e);
2810     }
2811     return result.Produce();
2812     }
2813    
2814 schoenebeck 2137 String LSCPServer::SetEffectInstanceInputControlValue(int iEffectInstance, int iInputControlIndex, double dValue) {
2815     dmsg(2,("LSCPServer: SetEffectInstanceInputControlValue(%d,%d,%f)\n", iEffectInstance, iInputControlIndex, dValue));
2816 schoenebeck 2135 LSCPResultSet result;
2817     try {
2818 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2819 schoenebeck 2135 if (!pEffect)
2820 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2821 schoenebeck 2135
2822     EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2823     if (!pEffectControl)
2824     throw Exception(
2825 schoenebeck 2137 "Effect instance " + ToString(iEffectInstance) +
2826 schoenebeck 2135 " does not have an input control with index " +
2827     ToString(iInputControlIndex)
2828     );
2829    
2830     pEffectControl->SetValue(dValue);
2831 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_info, iEffectInstance));
2832 schoenebeck 2135 } catch (Exception e) {
2833     result.Error(e);
2834     }
2835     return result.Produce();
2836     }
2837    
2838 schoenebeck 2137 String LSCPServer::CreateEffectInstance(int iEffectIndex) {
2839     dmsg(2,("LSCPServer: CreateEffectInstance(%d)\n", iEffectIndex));
2840 schoenebeck 2135 LSCPResultSet result;
2841     try {
2842 schoenebeck 2137 EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2843 schoenebeck 2135 if (!pEffectInfo)
2844 schoenebeck 2137 throw Exception("There is no effect with index " + ToString(iEffectIndex));
2845 schoenebeck 2135 Effect* pEffect = EffectFactory::Create(pEffectInfo);
2846 schoenebeck 2138 result = pEffect->ID(); // success
2847 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2848 schoenebeck 2135 } catch (Exception e) {
2849     result.Error(e);
2850     }
2851     return result.Produce();
2852     }
2853    
2854     String LSCPServer::CreateEffectInstance(String effectSystem, String module, String effectName) {
2855 schoenebeck 2137 dmsg(2,("LSCPServer: CreateEffectInstance('%s','%s','%s')\n", effectSystem.c_str(), module.c_str(), effectName.c_str()));
2856 schoenebeck 2135 LSCPResultSet result;
2857     try {
2858     // to allow loading the same LSCP session file on different systems
2859     // successfully, probably with different effect plugin DLL paths or even
2860     // running completely different operating systems, we do the following
2861     // for finding the right effect:
2862     //
2863     // first try to search for an exact match of the effect plugin DLL
2864     // (a.k.a 'module'), to avoid picking the wrong DLL with the same
2865     // effect name ...
2866     EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_MATCH_EXACTLY);
2867     // ... if no effect with exactly matchin DLL filename was found, then
2868     // try to lower the restrictions of matching the effect plugin DLL
2869     // filename and try again and again ...
2870     if (!pEffectInfo) {
2871     dmsg(2,("no exact module match, trying MODULE_IGNORE_PATH\n"));
2872     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH);
2873     }
2874     if (!pEffectInfo) {
2875     dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE\n"));
2876     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE);
2877     }
2878     if (!pEffectInfo) {
2879     dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE | MODULE_IGNORE_EXTENSION\n"));
2880     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE | EffectFactory::MODULE_IGNORE_EXTENSION);
2881     }
2882     // ... if there was still no effect found, then completely ignore the
2883     // DLL plugin filename argument and just search for the matching effect
2884     // system type and effect name
2885     if (!pEffectInfo) {
2886     dmsg(2,("no module match, trying MODULE_IGNORE_ALL\n"));
2887     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_ALL);
2888     }
2889     if (!pEffectInfo)
2890     throw Exception("There is no such effect '" + effectSystem + "' '" + module + "' '" + effectName + "'");
2891    
2892     Effect* pEffect = EffectFactory::Create(pEffectInfo);
2893     result = LSCPResultSet(pEffect->ID());
2894 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2895 schoenebeck 2135 } catch (Exception e) {
2896     result.Error(e);
2897     }
2898     return result.Produce();
2899     }
2900    
2901 schoenebeck 2137 String LSCPServer::DestroyEffectInstance(int iEffectInstance) {
2902     dmsg(2,("LSCPServer: DestroyEffectInstance(%d)\n", iEffectInstance));
2903 schoenebeck 2135 LSCPResultSet result;
2904     try {
2905 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2906 schoenebeck 2135 if (!pEffect)
2907 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2908 schoenebeck 2135 EffectFactory::Destroy(pEffect);
2909 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2910 schoenebeck 2135 } catch (Exception e) {
2911     result.Error(e);
2912     }
2913     return result.Produce();
2914     }
2915    
2916     String LSCPServer::GetEffectInstances() {
2917     dmsg(2,("LSCPServer: GetEffectInstances()\n"));
2918     LSCPResultSet result;
2919     try {
2920     int n = EffectFactory::EffectInstancesCount();
2921     result.Add(n);
2922     } catch (Exception e) {
2923     result.Error(e);
2924     }
2925     return result.Produce();
2926     }
2927    
2928     String LSCPServer::ListEffectInstances() {
2929     dmsg(2,("LSCPServer: ListEffectInstances()\n"));
2930     LSCPResultSet result;
2931     String list;
2932     try {
2933     int n = EffectFactory::EffectInstancesCount();
2934     for (int i = 0; i < n; i++) {
2935     Effect* pEffect = EffectFactory::GetEffectInstance(i);
2936     if (i) list += ",";
2937     list += ToString(pEffect->ID());
2938     }
2939     } catch (Exception e) {
2940     result.Error(e);
2941     }
2942     result.Add(list);
2943     return result.Produce();
2944     }
2945    
2946 schoenebeck 2137 String LSCPServer::GetSendEffectChains(int iAudioOutputDevice) {
2947     dmsg(2,("LSCPServer: GetSendEffectChains(%d)\n", iAudioOutputDevice));
2948 schoenebeck 2135 LSCPResultSet result;
2949     try {
2950     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2951     if (!devices.count(iAudioOutputDevice))
2952     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2953     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2954 schoenebeck 2137 int n = pDevice->SendEffectChainCount();
2955 schoenebeck 2135 result.Add(n);
2956     } catch (Exception e) {
2957     result.Error(e);
2958     }
2959     return result.Produce();
2960     }
2961    
2962 schoenebeck 2137 String LSCPServer::ListSendEffectChains(int iAudioOutputDevice) {
2963     dmsg(2,("LSCPServer: ListSendEffectChains(%d)\n", iAudioOutputDevice));
2964 schoenebeck 2135 LSCPResultSet result;
2965     String list;
2966     try {
2967     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2968     if (!devices.count(iAudioOutputDevice))
2969     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2970     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2971 schoenebeck 2137 int n = pDevice->SendEffectChainCount();
2972 schoenebeck 2135 for (int i = 0; i < n; i++) {
2973 schoenebeck 2137 EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2974 schoenebeck 2135 if (i) list += ",";
2975     list += ToString(pEffectChain->ID());
2976     }
2977     } catch (Exception e) {
2978     result.Error(e);
2979     }
2980     result.Add(list);
2981     return result.Produce();
2982     }
2983    
2984 schoenebeck 2137 String LSCPServer::AddSendEffectChain(int iAudioOutputDevice) {
2985     dmsg(2,("LSCPServer: AddSendEffectChain(%d)\n", iAudioOutputDevice));
2986 schoenebeck 2135 LSCPResultSet result;
2987     try {
2988     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2989     if (!devices.count(iAudioOutputDevice))
2990     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2991     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2992 schoenebeck 2137 EffectChain* pEffectChain = pDevice->AddSendEffectChain();
2993 schoenebeck 2138 result = pEffectChain->ID();
2994 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2995 schoenebeck 2135 } catch (Exception e) {
2996     result.Error(e);
2997     }
2998     return result.Produce();
2999     }
3000    
3001 schoenebeck 2137 String LSCPServer::RemoveSendEffectChain(int iAudioOutputDevice, int iSendEffectChain) {
3002     dmsg(2,("LSCPServer: RemoveSendEffectChain(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
3003 schoenebeck 2135 LSCPResultSet result;
3004     try {
3005     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
3006     if (!devices.count(iAudioOutputDevice))
3007     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
3008 iliev 2198
3009     std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
3010     std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
3011     std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
3012     for (; itEngineChannel != itEnd; ++itEngineChannel) {
3013     AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
3014     if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
3015     for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
3016     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
3017     if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain) {
3018     throw Exception("The effect chain is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
3019     }
3020     }
3021     }
3022     }
3023    
3024 schoenebeck 2135 AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
3025 schoenebeck 2137 for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
3026     EffectChain* pEffectChain = pDevice->SendEffectChain(i);
3027     if (pEffectChain->ID() == iSendEffectChain) {
3028     pDevice->RemoveSendEffectChain(i);
3029 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
3030 schoenebeck 2135 return result.Produce();
3031     }
3032     }
3033     throw Exception(
3034 schoenebeck 2137 "There is no send effect chain with ID " +
3035     ToString(iSendEffectChain) + " for audio output device " +
3036 schoenebeck 2135 ToString(iAudioOutputDevice) + "."
3037     );
3038     } catch (Exception e) {
3039     result.Error(e);
3040     }
3041     return result.Produce();
3042     }
3043    
3044 schoenebeck 2137 static EffectChain* _getSendEffectChain(Sampler* pSampler, int iAudioOutputDevice, int iSendEffectChain) throw (Exception) {
3045 schoenebeck 2135 std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
3046     if (!devices.count(iAudioOutputDevice))
3047     throw Exception(
3048     "There is no audio output device with index " +
3049     ToString(iAudioOutputDevice) + "."
3050     );
3051     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
3052 iliev 2198 EffectChain* pEffectChain = pDevice->SendEffectChainByID(iSendEffectChain);
3053     if(pEffectChain != NULL) return pEffectChain;
3054 schoenebeck 2135 throw Exception(
3055 schoenebeck 2137 "There is no send effect chain with ID " +
3056     ToString(iSendEffectChain) + " for audio output device " +
3057 schoenebeck 2135 ToString(iAudioOutputDevice) + "."
3058     );
3059     }
3060    
3061 schoenebeck 2137 String LSCPServer::GetSendEffectChainInfo(int iAudioOutputDevice, int iSendEffectChain) {
3062     dmsg(2,("LSCPServer: GetSendEffectChainInfo(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
3063 schoenebeck 2135 LSCPResultSet result;
3064     try {
3065     EffectChain* pEffectChain =
3066 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3067 schoenebeck 2135 String sEffectSequence;
3068     for (int i = 0; i < pEffectChain->EffectCount(); i++) {
3069     if (i) sEffectSequence += ",";
3070     sEffectSequence += ToString(pEffectChain->GetEffect(i)->ID());
3071     }
3072     result.Add("EFFECT_COUNT", pEffectChain->EffectCount());
3073     result.Add("EFFECT_SEQUENCE", sEffectSequence);
3074     } catch (Exception e) {
3075     result.Error(e);
3076     }
3077     return result.Produce();
3078     }
3079    
3080 schoenebeck 2137 String LSCPServer::AppendSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectInstance) {
3081     dmsg(2,("LSCPServer: AppendSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectInstance));
3082 schoenebeck 2135 LSCPResultSet result;
3083     try {
3084     EffectChain* pEffectChain =
3085 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3086 schoenebeck 2135 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
3087     if (!pEffect)
3088 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
3089 schoenebeck 2135 pEffectChain->AppendEffect(pEffect);
3090 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3091 schoenebeck 2135 } catch (Exception e) {
3092     result.Error(e);
3093     }
3094     return result.Produce();
3095     }
3096    
3097 schoenebeck 2137 String LSCPServer::InsertSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition, int iEffectInstance) {
3098     dmsg(2,("LSCPServer: InsertSendEffectChainEffect(%d,%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition, iEffectInstance));
3099 schoenebeck 2135 LSCPResultSet result;
3100     try {
3101     EffectChain* pEffectChain =
3102 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3103 schoenebeck 2135 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
3104     if (!pEffect)
3105     throw Exception("There is no effect instance with index " + ToString(iEffectInstance));
3106     pEffectChain->InsertEffect(pEffect, iEffectChainPosition);
3107 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3108 schoenebeck 2135 } catch (Exception e) {
3109     result.Error(e);
3110     }
3111     return result.Produce();
3112     }
3113    
3114 schoenebeck 2137 String LSCPServer::RemoveSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition) {
3115     dmsg(2,("LSCPServer: RemoveSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition));
3116 schoenebeck 2135 LSCPResultSet result;
3117     try {
3118     EffectChain* pEffectChain =
3119 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3120 iliev 2198
3121     std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
3122     std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
3123     std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
3124     for (; itEngineChannel != itEnd; ++itEngineChannel) {
3125     AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
3126     if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
3127     for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
3128     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
3129     if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain && fxs->DestinationEffectChainPosition() == iEffectChainPosition) {
3130     throw Exception("The effect instance is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
3131     }
3132     }
3133     }
3134     }
3135    
3136 schoenebeck 2137 pEffectChain->RemoveEffect(iEffectChainPosition);
3137 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3138 schoenebeck 2135 } catch (Exception e) {
3139     result.Error(e);
3140     }
3141     return result.Produce();
3142     }
3143    
3144 schoenebeck 1212 String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
3145     dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
3146     LSCPResultSet result;
3147     try {
3148 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3149 iliev 1337 if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
3150 schoenebeck 1212 Engine* pEngine = pEngineChannel->GetEngine();
3151     InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
3152     if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
3153     InstrumentManager::instrument_id_t instrumentID;
3154     instrumentID.FileName = pEngineChannel->InstrumentFileName();
3155     instrumentID.Index = pEngineChannel->InstrumentIndex();
3156 schoenebeck 2687 pInstrumentManager->LaunchInstrumentEditor(pEngineChannel, instrumentID);
3157 schoenebeck 1212 } catch (Exception e) {
3158     result.Error(e);
3159     }
3160     return result.Produce();
3161     }
3162    
3163 iliev 1771 String LSCPServer::SendChannelMidiData(String MidiMsg, uint uiSamplerChannel, uint Arg1, uint Arg2) {
3164     dmsg(2,("LSCPServer: SendChannelMidiData(MidiMsg=%s,uiSamplerChannel=%d,Arg1=%d,Arg2=%d)\n", MidiMsg.c_str(), uiSamplerChannel, Arg1, Arg2));
3165     LSCPResultSet result;
3166     try {
3167     EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3168    
3169     if (Arg1 > 127 || Arg2 > 127) {
3170     throw Exception("Invalid MIDI message");
3171     }
3172    
3173     VirtualMidiDevice* pMidiDevice = NULL;
3174     std::vector<EventHandler::midi_listener_entry>::iterator iter = eventHandler.channelMidiListeners.begin();
3175     for (; iter != eventHandler.channelMidiListeners.end(); ++iter) {
3176     if ((*iter).pEngineChannel == pEngineChannel) {
3177     pMidiDevice = (*iter).pMidiListener;
3178     break;
3179     }
3180     }
3181    
3182     if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
3183    
3184     if (MidiMsg == "NOTE_ON") {
3185 iliev 1774 pMidiDevice->SendNoteOnToDevice(Arg1, Arg2);
3186 iliev 1771 bool b = pMidiDevice->SendNoteOnToSampler(Arg1, Arg2);
3187     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3188     } else if (MidiMsg == "NOTE_OFF") {
3189 iliev 1774 pMidiDevice->SendNoteOffToDevice(Arg1, Arg2);
3190 iliev 1771 bool b = pMidiDevice->SendNoteOffToSampler(Arg1, Arg2);
3191     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3192 schoenebeck 2025 } else if (MidiMsg == "CC") {
3193     pMidiDevice->SendCCToDevice(Arg1, Arg2);
3194     bool b = pMidiDevice->SendCCToSampler(Arg1, Arg2);
3195     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3196 iliev 1771 } else {
3197     throw Exception("Unknown MIDI message type: " + MidiMsg);
3198     }
3199     } catch (Exception e) {
3200     result.Error(e);
3201     }
3202     return result.Produce();
3203     }
3204    
3205 schoenebeck 973 /**
3206 schoenebeck 35 * Will be called by the parser to reset a particular sampler channel.
3207     */
3208 schoenebeck 53 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
3209     dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
3210 senkov 120 LSCPResultSet result;
3211 schoenebeck 53 try {
3212 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3213 schoenebeck 670 pEngineChannel->Reset();
3214 schoenebeck 53 }
3215 schoenebeck 880 catch (Exception e) {
3216 senkov 120 result.Error(e);
3217 schoenebeck 53 }
3218 senkov 120 return result.Produce();
3219 schoenebeck 35 }
3220    
3221     /**
3222 schoenebeck 212 * Will be called by the parser to reset the whole sampler.
3223     */
3224     String LSCPServer::ResetSampler() {
3225     dmsg(2,("LSCPServer: ResetSampler()\n"));
3226     pSampler->Reset();
3227     LSCPResultSet result;
3228     return result.Produce();
3229     }
3230    
3231     /**
3232 schoenebeck 563 * Will be called by the parser to return general informations about this
3233     * sampler.
3234     */
3235     String LSCPServer::GetServerInfo() {
3236     dmsg(2,("LSCPServer: GetServerInfo()\n"));
3237 schoenebeck 1399 const std::string description =
3238     _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
3239 schoenebeck 563 LSCPResultSet result;
3240 schoenebeck 1399 result.Add("DESCRIPTION", description);
3241 schoenebeck 570 result.Add("VERSION", VERSION);
3242 schoenebeck 947 result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
3243 iliev 1161 #if HAVE_SQLITE3
3244     result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
3245     #else
3246     result.Add("INSTRUMENTS_DB_SUPPORT", "no");
3247     #endif
3248 schoenebeck 1252
3249 schoenebeck 563 return result.Produce();
3250     }
3251    
3252     /**
3253 iliev 1541 * Will be called by the parser to return the current number of all active streams.
3254     */
3255     String LSCPServer::GetTotalStreamCount() {
3256     dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
3257     LSCPResultSet result;
3258     result.Add(pSampler->GetDiskStreamCount());
3259     return result.Produce();
3260     }
3261    
3262     /**
3263 iliev 778 * Will be called by the parser to return the current number of all active voices.
3264     */
3265     String LSCPServer::GetTotalVoiceCount() {
3266     dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
3267     LSCPResultSet result;
3268     result.Add(pSampler->GetVoiceCount());
3269     return result.Produce();
3270     }
3271    
3272     /**
3273     * Will be called by the parser to return the maximum number of voices.
3274     */
3275     String LSCPServer::GetTotalVoiceCountMax() {
3276     dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3277     LSCPResultSet result;
3278 schoenebeck 2375 result.Add(EngineFactory::EngineInstances().size() * pSampler->GetGlobalMaxVoices());
3279 iliev 778 return result.Produce();
3280     }
3281    
3282 schoenebeck 1800 /**
3283     * Will be called by the parser to return the sampler global maximum
3284     * allowed number of voices.
3285     */
3286     String LSCPServer::GetGlobalMaxVoices() {
3287     dmsg(2,("LSCPServer: GetGlobalMaxVoices()\n"));
3288     LSCPResultSet result;
3289 schoenebeck 2375 result.Add(pSampler->GetGlobalMaxVoices());
3290 schoenebeck 1800 return result.Produce();
3291     }
3292    
3293     /**
3294     * Will be called by the parser to set the sampler global maximum number of
3295     * voices.
3296     */
3297     String LSCPServer::SetGlobalMaxVoices(int iVoices) {
3298     dmsg(2,("LSCPServer: SetGlobalMaxVoices(%d)\n", iVoices));
3299     LSCPResultSet result;
3300     try {
3301 schoenebeck 2375 pSampler->SetGlobalMaxVoices(iVoices);
3302     LSCPServer::SendLSCPNotify(
3303     LSCPEvent(LSCPEvent::event_global_info, "VOICES", pSampler->GetGlobalMaxVoices())
3304     );
3305 schoenebeck 1800 } catch (Exception e) {
3306     result.Error(e);
3307     }
3308     return result.Produce();
3309     }
3310    
3311     /**
3312     * Will be called by the parser to return the sampler global maximum
3313     * allowed number of disk streams.
3314     */
3315     String LSCPServer::GetGlobalMaxStreams() {
3316     dmsg(2,("LSCPServer: GetGlobalMaxStreams()\n"));
3317     LSCPResultSet result;
3318 schoenebeck 2375 result.Add(pSampler->GetGlobalMaxStreams());
3319 schoenebeck 1800 return result.Produce();
3320     }
3321    
3322     /**
3323     * Will be called by the parser to set the sampler global maximum number of
3324     * disk streams.
3325     */
3326     String LSCPServer::SetGlobalMaxStreams(int iStreams) {
3327     dmsg(2,("LSCPServer: SetGlobalMaxStreams(%d)\n", iStreams));
3328     LSCPResultSet result;
3329     try {
3330 schoenebeck 2375 pSampler->SetGlobalMaxStreams(iStreams);
3331     LSCPServer::SendLSCPNotify(
3332     LSCPEvent(LSCPEvent::event_global_info, "STREAMS", pSampler->GetGlobalMaxStreams())
3333     );
3334 schoenebeck 1800 } catch (Exception e) {
3335     result.Error(e);
3336     }
3337     return result.Produce();
3338     }
3339    
3340 schoenebeck 1005 String LSCPServer::GetGlobalVolume() {
3341     LSCPResultSet result;
3342     result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
3343     return result.Produce();
3344     }
3345    
3346     String LSCPServer::SetGlobalVolume(double dVolume) {
3347     LSCPResultSet result;
3348     try {
3349     if (dVolume < 0) throw Exception("Volume may not be negative");
3350 schoenebeck 1724 GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3351 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3352 schoenebeck 1005 } catch (Exception e) {
3353     result.Error(e);
3354     }
3355     return result.Produce();
3356     }
3357    
3358 schoenebeck 1525 String LSCPServer::GetFileInstruments(String Filename) {
3359 iliev 1535 dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
3360 schoenebeck 1525 LSCPResultSet result;
3361 iliev 1535 try {
3362     VerifyFile(Filename);
3363     } catch (Exception e) {
3364     result.Error(e);
3365     return result.Produce();
3366     }
3367 schoenebeck 1525 // try to find a sampler engine that can handle the file
3368     bool bFound = false;
3369     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3370     for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3371     Engine* pEngine = NULL;
3372     try {
3373     pEngine = EngineFactory::Create(engineTypes[i]);
3374     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3375     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3376     if (pManager) {
3377     std::vector<InstrumentManager::instrument_id_t> IDs =
3378     pManager->GetInstrumentFileContent(Filename);
3379     // return the amount of instruments in the file
3380     result.Add(IDs.size());
3381     // no more need to ask other engine types
3382     bFound = true;
3383     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3384     } catch (Exception e) {
3385     // NOOP, as exception is thrown if engine doesn't support file
3386     }
3387     if (pEngine) EngineFactory::Destroy(pEngine);
3388     }
3389 iliev 1535
3390     if (!bFound) result.Error("Unknown file format");
3391 schoenebeck 1525 return result.Produce();
3392     }
3393    
3394     String LSCPServer::ListFileInstruments(String Filename) {
3395 iliev 1535 dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
3396 schoenebeck 1525 LSCPResultSet result;
3397 iliev 1535 try {
3398     VerifyFile(Filename);
3399     } catch (Exception e) {
3400     result.Error(e);
3401     return result.Produce();
3402     }
3403 schoenebeck 1525 // try to find a sampler engine that can handle the file
3404     bool bFound = false;
3405     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3406     for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3407     Engine* pEngine = NULL;
3408     try {
3409     pEngine = EngineFactory::Create(engineTypes[i]);
3410     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3411     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3412     if (pManager) {
3413     std::vector<InstrumentManager::instrument_id_t> IDs =
3414     pManager->GetInstrumentFileContent(Filename);
3415     // return a list of IDs of the instruments in the file
3416     String s;
3417     for (int j = 0; j < IDs.size(); j++) {
3418     if (s.size()) s += ",";
3419     s += ToString(IDs[j].Index);
3420     }
3421     result.Add(s);
3422     // no more need to ask other engine types
3423     bFound = true;
3424     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3425     } catch (Exception e) {
3426     // NOOP, as exception is thrown if engine doesn't support file
3427     }
3428     if (pEngine) EngineFactory::Destroy(pEngine);
3429     }
3430 iliev 1535
3431     if (!bFound) result.Error("Unknown file format");
3432 schoenebeck 1525 return result.Produce();
3433     }
3434    
3435     String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
3436 iliev 1535 dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
3437 schoenebeck 1525 LSCPResultSet result;
3438 iliev 1535 try {
3439     VerifyFile(Filename);
3440     } catch (Exception e) {
3441     result.Error(e);
3442     return result.Produce();
3443     }
3444 schoenebeck 1525 InstrumentManager::instrument_id_t id;
3445     id.FileName = Filename;
3446     id.Index = InstrumentID;
3447     // try to find a sampler engine that can handle the file
3448     bool bFound = false;
3449 schoenebeck 1536 bool bFatalErr = false;
3450 schoenebeck 1525 std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3451 schoenebeck 1536 for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
3452 schoenebeck 1525 Engine* pEngine = NULL;
3453     try {
3454     pEngine = EngineFactory::Create(engineTypes[i]);
3455     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3456     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3457     if (pManager) {
3458 schoenebeck 1536 // check if the instrument index is valid
3459     // FIXME: this won't work if an engine only supports parts of the instrument file
3460     std::vector<InstrumentManager::instrument_id_t> IDs =
3461     pManager->GetInstrumentFileContent(Filename);
3462     if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
3463     std::stringstream ss;
3464     ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
3465     bFatalErr = true;
3466     throw Exception(ss.str());
3467     }
3468     // get the info of the requested instrument
3469 schoenebeck 1525 InstrumentManager::instrument_info_t info =
3470     pManager->GetInstrumentInfo(id);
3471     // return detailed informations about the file
3472     result.Add("NAME", info.InstrumentName);
3473 iliev 1535 result.Add("FORMAT_FAMILY", engineTypes[i]);
3474 schoenebeck 1525 result.Add("FORMAT_VERSION", info.FormatVersion);
3475     result.Add("PRODUCT", info.Product);
3476     result.Add("ARTISTS", info.Artists);
3477 iliev 1771
3478     std::stringstream ss;
3479     bool b = false;
3480     for (int i = 0; i < 128; i++) {
3481     if (info.KeyBindings[i]) {
3482     if (b) ss << ',';
3483     ss << i; b = true;
3484     }
3485     }
3486     result.Add("KEY_BINDINGS", ss.str());
3487    
3488 iliev 1774 b = false;
3489 iliev 1771 std::stringstream ss2;
3490     for (int i = 0; i < 128; i++) {
3491     if (info.KeySwitchBindings[i]) {
3492     if (b) ss2 << ',';
3493     ss2 << i; b = true;
3494     }
3495     }
3496     result.Add("KEYSWITCH_BINDINGS", ss2.str());
3497 schoenebeck 1525 // no more need to ask other engine types
3498     bFound = true;
3499     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3500     } catch (Exception e) {
3501 schoenebeck 1536 // usually NOOP, as exception is thrown if engine doesn't support file
3502     if (bFatalErr) result.Error(e);
3503 schoenebeck 1525 }
3504     if (pEngine) EngineFactory::Destroy(pEngine);
3505     }
3506 iliev 1535
3507 schoenebeck 1536 if (!bFound && !bFatalErr) result.Error("Unknown file format");
3508 schoenebeck 1525 return result.Produce();
3509     }
3510    
3511 iliev 1535 void LSCPServer::VerifyFile(String Filename) {
3512 senoner 1537 #if WIN32
3513     WIN32_FIND_DATA win32FileAttributeData;
3514     BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
3515     if (!res) {
3516     std::stringstream ss;
3517     ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
3518     throw Exception(ss.str());
3519     }
3520     if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
3521     throw Exception("Directory is specified");
3522     }
3523 schoenebeck 1551 #else
3524 iliev 1835 File f(Filename);
3525     if(!f.Exist()) throw Exception(f.GetErrorMsg());
3526     if (f.IsDirectory()) throw Exception("Directory is specified");
3527 senoner 1537 #endif
3528 iliev 1535 }
3529    
3530 iliev 778 /**
3531 schoenebeck 35 * Will be called by the parser to subscribe a client (frontend) on the
3532     * server for receiving event messages.
3533     */
3534 senkov 170 String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
3535     dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3536     LSCPResultSet result;
3537 persson 2427 {
3538     LockGuard lock(SubscriptionMutex);
3539     eventSubscriptions[type].push_back(currentSocket);
3540     }
3541 senkov 170 return result.Produce();
3542 schoenebeck 35 }
3543    
3544     /**
3545     * Will be called by the parser to unsubscribe a client on the server
3546     * for not receiving further event messages.
3547     */
3548 senkov 170 String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
3549     dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3550     LSCPResultSet result;
3551 persson 2427 {
3552     LockGuard lock(SubscriptionMutex);
3553     eventSubscriptions[type].remove(currentSocket);
3554     }
3555 senkov 170 return result.Produce();
3556 schoenebeck 35 }
3557 capela 133
3558 iliev 1161 String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3559     dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3560     LSCPResultSet result;
3561     #if HAVE_SQLITE3
3562     try {
3563     InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
3564     } catch (Exception e) {
3565     result.Error(e);
3566     }
3567     #else
3568     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3569     #endif
3570     return result.Produce();
3571 senkov 397 }
3572    
3573 iliev 1161 String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3574     dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3575 senkov 397 LSCPResultSet result;
3576 schoenebeck 401 #if HAVE_SQLITE3
3577 iliev 1161 try {
3578     InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3579     } catch (Exception e) {
3580     result.Error(e);
3581     }
3582     #else
3583     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3584     #endif
3585     return result.Produce();
3586     }
3587 senkov 397
3588 iliev 1187 String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3589     dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3590 iliev 1161 LSCPResultSet result;
3591     #if HAVE_SQLITE3
3592     try {
3593 iliev 1187 result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
3594 iliev 1161 } catch (Exception e) {
3595     result.Error(e);
3596 senkov 397 }
3597 iliev 1161 #else
3598     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3599     #endif
3600     return result.Produce();
3601     }
3602    
3603 iliev 1187 String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
3604     dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3605 iliev 1161 LSCPResultSet result;
3606     #if HAVE_SQLITE3
3607     try {
3608     String list;
3609 iliev 1187 StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
3610 iliev 1161
3611     for (int i = 0; i < dirs->size(); i++) {
3612     if (list != "") list += ",";
3613 iliev 1350 list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
3614 iliev 1161 }
3615    
3616     result.Add(list);
3617     } catch (Exception e) {
3618     result.Error(e);
3619 senkov 397 }
3620     #else
3621 iliev 1161 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3622 senkov 397 #endif
3623     return result.Produce();
3624     }
3625    
3626 iliev 1161 String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
3627     dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
3628     LSCPResultSet result;
3629     #if HAVE_SQLITE3
3630     try {
3631     DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
3632    
3633 iliev 1403 result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3634 iliev 1161 result.Add("CREATED", info.Created);
3635     result.Add("MODIFIED", info.Modified);
3636     } catch (Exception e) {
3637     result.Error(e);
3638     }
3639     #else
3640     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3641     #endif
3642     return result.Produce();
3643     }
3644    
3645     String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
3646     dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
3647     LSCPResultSet result;
3648     #if HAVE_SQLITE3
3649     try {
3650     InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
3651     } catch (Exception e) {
3652     result.Error(e);
3653     }
3654     #else
3655     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3656     #endif
3657     return result.Produce();
3658     }
3659    
3660     String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
3661     dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3662     LSCPResultSet result;
3663     #if HAVE_SQLITE3
3664     try {
3665     InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
3666     } catch (Exception e) {
3667     result.Error(e);
3668     }
3669     #else
3670     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3671     #endif
3672     return result.Produce();
3673     }
3674    
3675 iliev 1187 String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
3676     dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3677     LSCPResultSet result;
3678     #if HAVE_SQLITE3
3679     try {
3680     InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
3681     } catch (Exception e) {
3682     result.Error(e);
3683     }
3684     #else
3685     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3686     #endif
3687     return result.Produce();
3688     }
3689    
3690 iliev 1161 String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3691     dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3692     LSCPResultSet result;
3693     #if HAVE_SQLITE3
3694     try {
3695     InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3696     } catch (Exception e) {
3697     result.Error(e);
3698     }
3699     #else
3700     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3701     #endif
3702     return result.Produce();
3703     }
3704    
3705 iliev 1200 String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3706     dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
3707 iliev 1161 LSCPResultSet result;
3708     #if HAVE_SQLITE3
3709     try {
3710 iliev 1200 int id;
3711     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3712     id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
3713     if (bBackground) result = id;
3714 iliev 1161 } catch (Exception e) {
3715     result.Error(e);
3716     }
3717     #else
3718     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3719     #endif
3720     return result.Produce();
3721     }
3722    
3723 iliev 1781 String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground, bool insDir) {
3724     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));
3725 iliev 1161 LSCPResultSet result;
3726     #if HAVE_SQLITE3
3727     try {
3728 iliev 1200 int id;
3729     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3730     if (ScanMode.compare("RECURSIVE") == 0) {
3731 iliev 1781 id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground, insDir);
3732 iliev 1200 } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
3733 iliev 1781 id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground, insDir);
3734 iliev 1200 } else if (ScanMode.compare("FLAT") == 0) {
3735 iliev 1781 id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground, insDir);
3736 iliev 1200 } else {
3737     throw Exception("Unknown scan mode: " + ScanMode);
3738     }
3739 schoenebeck 1252
3740 iliev 1200 if (bBackground) result = id;
3741 iliev 1161 } catch (Exception e) {
3742     result.Error(e);
3743     }
3744     #else
3745     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3746     #endif
3747     return result.Produce();
3748     }
3749    
3750     String LSCPServer::RemoveDbInstrument(String Instr) {
3751     dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
3752     LSCPResultSet result;
3753     #if HAVE_SQLITE3
3754     try {
3755     InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
3756     } catch (Exception e) {
3757     result.Error(e);
3758     }
3759     #else
3760     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3761     #endif
3762     return result.Produce();
3763     }
3764    
3765 iliev 1187 String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
3766     dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3767 iliev 1161 LSCPResultSet result;
3768     #if HAVE_SQLITE3
3769     try {
3770 iliev 1187 result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
3771 iliev 1161 } catch (Exception e) {
3772     result.Error(e);
3773     }
3774     #else
3775     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3776     #endif
3777     return result.Produce();
3778     }
3779    
3780 iliev 1187 String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
3781     dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3782 iliev 1161 LSCPResultSet result;
3783     #if HAVE_SQLITE3
3784     try {
3785     String list;
3786 iliev 1187 StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
3787 iliev 1161
3788     for (int i = 0; i < instrs->size(); i++) {
3789     if (list != "") list += ",";
3790 iliev 1350 list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
3791 iliev 1161 }
3792    
3793     result.Add(list);
3794     } catch (Exception e) {
3795     result.Error(e);
3796     }
3797     #else
3798     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3799     #endif
3800     return result.Produce();
3801     }
3802    
3803     String LSCPServer::GetDbInstrumentInfo(String Instr) {
3804     dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
3805     LSCPResultSet result;
3806     #if HAVE_SQLITE3
3807     try {
3808     DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
3809    
3810     result.Add("INSTRUMENT_FILE", info.InstrFile);
3811     result.Add("INSTRUMENT_NR", info.InstrNr);
3812     result.Add("FORMAT_FAMILY", info.FormatFamily);
3813     result.Add("FORMAT_VERSION", info.FormatVersion);
3814     result.Add("SIZE", (int)info.Size);
3815     result.Add("CREATED", info.Created);
3816     result.Add("MODIFIED", info.Modified);
3817 iliev 1403 result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3818 iliev 1161 result.Add("IS_DRUM", info.IsDrum);
3819 iliev 1403 result.Add("PRODUCT", _escapeLscpResponse(info.Product));
3820     result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
3821     result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
3822 iliev 1161 } catch (Exception e) {
3823     result.Error(e);
3824     }
3825     #else
3826     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3827     #endif
3828     return result.Produce();
3829     }
3830    
3831 iliev 1200 String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
3832     dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
3833     LSCPResultSet result;
3834     #if HAVE_SQLITE3
3835     try {
3836     ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
3837    
3838     result.Add("FILES_TOTAL", job.FilesTotal);
3839     result.Add("FILES_SCANNED", job.FilesScanned);
3840     result.Add("SCANNING", job.Scanning);
3841     result.Add("STATUS", job.Status);
3842     } catch (Exception e) {
3843     result.Error(e);
3844     }
3845     #else
3846     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3847     #endif
3848     return result.Produce();
3849     }
3850    
3851 iliev 1161 String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
3852     dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
3853     LSCPResultSet result;
3854     #if HAVE_SQLITE3
3855     try {
3856     InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
3857     } catch (Exception e) {
3858     result.Error(e);
3859     }
3860     #else
3861     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3862     #endif
3863     return result.Produce();
3864     }
3865    
3866     String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
3867     dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3868     LSCPResultSet result;
3869     #if HAVE_SQLITE3
3870     try {
3871     InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
3872     } catch (Exception e) {
3873     result.Error(e);
3874     }
3875     #else
3876     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3877     #endif
3878     return result.Produce();
3879     }
3880    
3881 iliev 1187 String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3882     dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3883     LSCPResultSet result;
3884     #if HAVE_SQLITE3
3885     try {
3886     InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3887     } catch (Exception e) {
3888     result.Error(e);
3889     }
3890     #else
3891     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3892     #endif
3893     return result.Produce();
3894     }
3895    
3896 iliev 1161 String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3897     dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3898     LSCPResultSet result;
3899     #if HAVE_SQLITE3
3900     try {
3901     InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3902     } catch (Exception e) {
3903     result.Error(e);
3904     }
3905     #else
3906     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3907     #endif
3908     return result.Produce();
3909     }
3910    
3911 iliev 1727 String LSCPServer::SetDbInstrumentFilePath(String OldPath, String NewPath) {
3912     dmsg(2,("LSCPServer: SetDbInstrumentFilePath(OldPath=%s,NewPath=%s)\n", OldPath.c_str(), NewPath.c_str()));
3913     LSCPResultSet result;
3914     #if HAVE_SQLITE3
3915     try {
3916     InstrumentsDb::GetInstrumentsDb()->SetInstrumentFilePath(OldPath, NewPath);
3917     } catch (Exception e) {
3918     result.Error(e);
3919     }
3920     #else
3921     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3922     #endif
3923     return result.Produce();
3924     }
3925    
3926     String LSCPServer::FindLostDbInstrumentFiles() {
3927     dmsg(2,("LSCPServer: FindLostDbInstrumentFiles()\n"));
3928     LSCPResultSet result;
3929     #if HAVE_SQLITE3
3930     try {
3931     String list;
3932     StringListPtr pLostFiles = InstrumentsDb::GetInstrumentsDb()->FindLostInstrumentFiles();
3933    
3934     for (int i = 0; i < pLostFiles->size(); i++) {
3935     if (list != "") list += ",";
3936     list += "'" + pLostFiles->at(i) + "'";
3937     }
3938    
3939     result.Add(list);
3940     } catch (Exception e) {
3941     result.Error(e);
3942     }
3943     #else
3944     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3945     #endif
3946     return result.Produce();
3947     }
3948    
3949 iliev 1187 String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3950     dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3951     LSCPResultSet result;
3952     #if HAVE_SQLITE3
3953     try {
3954     SearchQuery Query;
3955     std::map<String,String>::iterator iter;
3956     for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3957     if (iter->first.compare("NAME") == 0) {
3958     Query.Name = iter->second;
3959     } else if (iter->first.compare("CREATED") == 0) {
3960     Query.SetCreated(iter->second);
3961     } else if (iter->first.compare("MODIFIED") == 0) {
3962     Query.SetModified(iter->second);
3963     } else if (iter->first.compare("DESCRIPTION") == 0) {
3964     Query.Description = iter->second;
3965     } else {
3966     throw Exception("Unknown search criteria: " + iter->first);
3967     }
3968     }
3969 iliev 1161
3970 iliev 1187 String list;
3971     StringListPtr pDirectories =
3972     InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3973    
3974     for (int i = 0; i < pDirectories->size(); i++) {
3975     if (list != "") list += ",";
3976 iliev 1345 list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3977 iliev 1187 }
3978    
3979     result.Add(list);
3980     } catch (Exception e) {
3981     result.Error(e);
3982     }
3983     #else
3984     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3985     #endif
3986     return result.Produce();
3987     }
3988    
3989     String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
3990     dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
3991     LSCPResultSet result;
3992     #if HAVE_SQLITE3
3993     try {
3994     SearchQuery Query;
3995     std::map<String,String>::iterator iter;
3996     for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3997     if (iter->first.compare("NAME") == 0) {
3998     Query.Name = iter->second;
3999     } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
4000     Query.SetFormatFamilies(iter->second);
4001     } else if (iter->first.compare("SIZE") == 0) {
4002     Query.SetSize(iter->second);
4003     } else if (iter->first.compare("CREATED") == 0) {
4004     Query.SetCreated(iter->second);
4005     } else if (iter->first.compare("MODIFIED") == 0) {
4006     Query.SetModified(iter->second);
4007     } else if (iter->first.compare("DESCRIPTION") == 0) {
4008     Query.Description = iter->second;
4009     } else if (iter->first.compare("IS_DRUM") == 0) {
4010     if (!strcasecmp(iter->second.c_str(), "true")) {
4011     Query.InstrType = SearchQuery::DRUM;
4012     } else {
4013     Query.InstrType = SearchQuery::CHROMATIC;
4014     }
4015     } else if (iter->first.compare("PRODUCT") == 0) {
4016     Query.Product = iter->second;
4017     } else if (iter->first.compare("ARTISTS") == 0) {
4018     Query.Artists = iter->second;
4019     } else if (iter->first.compare("KEYWORDS") == 0) {
4020     Query.Keywords = iter->second;
4021     } else {
4022     throw Exception("Unknown search criteria: " + iter->first);
4023     }
4024     }
4025    
4026     String list;
4027     StringListPtr pInstruments =
4028     InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
4029    
4030     for (int i = 0; i < pInstruments->size(); i++) {
4031     if (list != "") list += ",";
4032 iliev 1345 list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
4033 iliev 1187 }
4034    
4035     result.Add(list);
4036     } catch (Exception e) {
4037     result.Error(e);
4038     }
4039     #else
4040     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
4041     #endif
4042     return result.Produce();
4043     }
4044    
4045 iliev 1353 String LSCPServer::FormatInstrumentsDb() {
4046     dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
4047     LSCPResultSet result;
4048     #if HAVE_SQLITE3
4049     try {
4050     InstrumentsDb::GetInstrumentsDb()->Format();
4051     } catch (Exception e) {
4052     result.Error(e);
4053     }
4054     #else
4055     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
4056     #endif
4057     return result.Produce();
4058     }
4059 iliev 1187
4060 iliev 1353
4061 schoenebeck 210 /**
4062     * Will be called by the parser to enable or disable echo mode; if echo
4063     * mode is enabled, all commands from the client will (immediately) be
4064     * echoed back to the client.
4065     */
4066     String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
4067     dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
4068     LSCPResultSet result;
4069     try {
4070     if (boolean_value == 0) pSession->bVerbose = false;
4071     else if (boolean_value == 1) pSession->bVerbose = true;
4072 schoenebeck 880 else throw Exception("Not a boolean value, must either be 0 or 1");
4073 schoenebeck 210 }
4074 schoenebeck 880 catch (Exception e) {
4075 schoenebeck 210 result.Error(e);
4076     }
4077     return result.Produce();
4078     }
4079 persson 1765
4080 schoenebeck 2515 String LSCPServer::SetShellInteract(yyparse_param_t* pSession, double boolean_value) {
4081     dmsg(2,("LSCPServer: SetShellInteract(val=%f)\n", boolean_value));
4082     LSCPResultSet result;
4083     try {
4084     if (boolean_value == 0) pSession->bShellInteract = false;
4085     else if (boolean_value == 1) pSession->bShellInteract = true;
4086     else throw Exception("Not a boolean value, must either be 0 or 1");
4087     } catch (Exception e) {
4088     result.Error(e);
4089     }
4090     return result.Produce();
4091 persson 1765 }
4092 schoenebeck 2515
4093 schoenebeck 2516 String LSCPServer::SetShellAutoCorrect(yyparse_param_t* pSession, double boolean_value) {
4094     dmsg(2,("LSCPServer: SetShellAutoCorrect(val=%f)\n", boolean_value));
4095     LSCPResultSet result;
4096     try {
4097     if (boolean_value == 0) pSession->bShellAutoCorrect = false;
4098     else if (boolean_value == 1) pSession->bShellAutoCorrect = true;
4099     else throw Exception("Not a boolean value, must either be 0 or 1");
4100     } catch (Exception e) {
4101     result.Error(e);
4102     }
4103     return result.Produce();
4104 schoenebeck 2515 }
4105 schoenebeck 2516
4106 schoenebeck 2534 String LSCPServer::SetShellDoc(yyparse_param_t* pSession, double boolean_value) {
4107     dmsg(2,("LSCPServer: SetShellDoc(val=%f)\n", boolean_value));
4108     LSCPResultSet result;
4109     try {
4110     if (boolean_value == 0) pSession->bShellSendLSCPDoc = false;
4111     else if (boolean_value == 1) pSession->bShellSendLSCPDoc = true;
4112     else throw Exception("Not a boolean value, must either be 0 or 1");
4113     } catch (Exception e) {
4114     result.Error(e);
4115     }
4116     return result.Produce();
4117 schoenebeck 2516 }
4118 schoenebeck 2534
4119     }

  ViewVC Help
Powered by ViewVC