/[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 3055 - (hide annotations) (download)
Thu Dec 15 13:01:58 2016 UTC (7 years, 5 months ago) by schoenebeck
File size: 166149 byte(s)
- Fixed compile error on Windows.

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

  ViewVC Help
Powered by ViewVC