/[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 1337 - (hide annotations) (download)
Sun Sep 9 23:27:23 2007 UTC (16 years, 6 months ago) by iliev
File size: 110268 byte(s)
* fixed a crash which occurs when starting an instrument editor on
  a channel with assigned engine but with no instrument loaded

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

  ViewVC Help
Powered by ViewVC