/[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 1835 - (hide annotations) (download)
Mon Feb 16 17:56:50 2009 UTC (15 years, 2 months ago) by iliev
File size: 132412 byte(s)
* Adapted drivers/Plugin class to be used as a base class for the
  AudioUnit plugin and fixed orphaned pointers when deleting PluginGlobal
* Fixed possible iterator invalidations when resetting the sampler
* Fixed memory leaks when issuing the following LSCP commands:
  GET AUDIO_OUTPUT_DRIVER INFO
  GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO
  GET MIDI_INPUT_DRIVER INFO
  GET MIDI_INPUT_DRIVER_PARAMETER INFO
* Fixed possible compilation error when sqlite is not present

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

  ViewVC Help
Powered by ViewVC