/[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 2515 - (hide annotations) (download)
Wed Feb 5 20:45:18 2014 UTC (10 years, 2 months ago) by schoenebeck
File size: 161006 byte(s)
* WIP: Introducing the LSCP shell: for now, providing color
  highlighting while typing (indicating correct part bold white,
  incorrect part red, and turning green when the command is
  complete. The shell application is implemented as thin client,
  that is the parser work is performed on sampler side and the
  shell application is just providing output formatting.
* Bumped version (1.0.0.svn28).

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

  ViewVC Help
Powered by ViewVC