/[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 1403 - (hide annotations) (download)
Fri Oct 12 09:12:22 2007 UTC (16 years, 5 months ago) by iliev
File size: 112786 byte(s)
* _escapeLscpResponse now escapes backslashes
* implemented new method Path::fromDbPath

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

  ViewVC Help
Powered by ViewVC