/[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 1848 - (hide annotations) (download)
Sat Feb 28 21:23:06 2009 UTC (15 years, 1 month ago) by iliev
File size: 132657 byte(s)
* close all connections when LSCPServer is deleted

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

  ViewVC Help
Powered by ViewVC