/[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 3766 - (hide annotations) (download)
Mon Apr 6 12:41:49 2020 UTC (4 years ago) by schoenebeck
File size: 166539 byte(s)
Fixed deadlocks (e.g. when restarting engines).

* Individual thread implementations (e.g. disk thread, etc.):
  Disable thread cancellation on critical sections, e.g. when holding
  mutex locks, to prevent deadlocks if thread is stopped and/or
  restarted.

* Added TestCancel() calls to thread implementations if missing.

* No need to wrap Thread::TestCancel() calls into
  CONFIG_PTHREAD_TESTCANCEL macro conditions (since TestCancel() is
  already a stub on systems which don't have pthread_testcancel()
  available).

* If compiled for debugging: give each thread a human readable name
  to simplify debugging of multi-threading issues.

* DiskThreadBase: TestCancel() and pthread_testcancel() calls are
  per-se redundant, so only call TestCancel().

* Added missing override keywords to silent compiler warnings.

* Bumped version (2.1.1.svn54).

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

  ViewVC Help
Powered by ViewVC