/[svn]/linuxsampler/trunk/src/network/lscpserver.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/network/lscpserver.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 121 by senkov, Sat Jun 12 07:46:02 2004 UTC revision 1005 by schoenebeck, Fri Dec 29 20:06:14 2006 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005, 2006 Christian Schoenebeck                        *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   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     *   *   the Free Software Foundation; either version 2 of the License, or     *
11   *   (at your option) any later version.                                   *   *   (at your option) any later version.                                   *
12   *                                                                         *   *                                                                         *
13   *   This program is distributed in the hope that it will be useful,       *   *   This library is distributed in the hope that it will be useful,       *
14   *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *   *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16   *   GNU General Public License for more details.                          *   *   GNU General Public License for more details.                          *
17   *                                                                         *   *                                                                         *
18   *   You should have received a copy of the GNU General Public License     *   *   You should have received a copy of the GNU General Public License     *
19   *   along with this program; if not, write to the Free Software           *   *   along with this library; if not, write to the Free Software           *
20   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
24  #include "lscpserver.h"  #include "lscpserver.h"
25  #include "lscpresultset.h"  #include "lscpresultset.h"
26    #include "lscpevent.h"
27    #include "../common/global.h"
28    
29  #include "../engines/gig/Engine.h"  #include <fcntl.h>
30    
31  LSCPServer::LSCPServer(Sampler* pSampler) : Thread(false, 0, -4) {  #if HAVE_SQLITE3
32    # include "sqlite3.h"
33    #endif
34    
35    #include "../engines/EngineFactory.h"
36    #include "../engines/EngineChannelFactory.h"
37    #include "../drivers/audio/AudioOutputDeviceFactory.h"
38    #include "../drivers/midi/MidiInputDeviceFactory.h"
39    
40    /**
41     * Below are a few static members of the LSCPServer class.
42     * The big assumption here is that LSCPServer is going to remain a singleton.
43     * These members are used to support client connections.
44     * Class handles multiple connections at the same time using select() and non-blocking recv()
45     * Commands are processed by a single LSCPServer thread.
46     * Notifications are delivered either by the thread that originated them
47     * or (if the resultset is currently in progress) by the LSCPServer thread
48     * after the resultset was sent out.
49     * This makes sure that resultsets can not be interrupted by notifications.
50     * This also makes sure that the thread sending notification is not blocked
51     * by the LSCPServer thread.
52     */
53    fd_set LSCPServer::fdSet;
54    int LSCPServer::currentSocket = -1;
55    std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();
56    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    Mutex LSCPServer::RTNotifyMutex = Mutex();
63    
64    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      this->pSampler = pSampler;      this->pSampler = pSampler;
69        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        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
74        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        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
78        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
79        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
80        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
81        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
82        LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
83        LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
84        hSocket = -1;
85    }
86    
87    LSCPServer::~LSCPServer() {
88        if (hSocket >= 0) close(hSocket);
89    }
90    
91    /**
92     * Blocks the calling thread until the LSCP Server is initialized and
93     * accepting socket connections, if the server is already initialized then
94     * this method will return immediately.
95     * @param TimeoutSeconds     - optional: max. wait time in seconds
96     *                             (default: 0s)
97     * @param TimeoutNanoSeconds - optional: max wait time in nano seconds
98     *                             (default: 0ns)
99     * @returns  0 on success, a value less than 0 if timeout exceeded
100     */
101    int LSCPServer::WaitUntilInitialized(long TimeoutSeconds, long TimeoutNanoSeconds) {
102        return Initialized.WaitAndUnlockIf(false, TimeoutSeconds, TimeoutNanoSeconds);
103  }  }
104    
105  int LSCPServer::Main() {  int LSCPServer::Main() {
# Line 37  int LSCPServer::Main() { Line 110  int LSCPServer::Main() {
110          exit(EXIT_FAILURE);          exit(EXIT_FAILURE);
111      }      }
112    
     SocketAddress.sin_family      = AF_INET;  
     SocketAddress.sin_port        = htons(LSCP_PORT);  
     SocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);  
   
113      if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {      if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
114          std::cerr << "LSCPServer: Could not bind server socket." << std::endl;          std::cerr << "LSCPServer: Could not bind server socket, retrying for " << ToString(LSCP_SERVER_BIND_TIMEOUT) << " seconds...";
115          close(hSocket);          for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds
116          //return -1;              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
117          exit(EXIT_FAILURE);                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {
118                        std::cerr << "gave up!" << std::endl;
119                        close(hSocket);
120                        //return -1;
121                        exit(EXIT_FAILURE);
122                    }
123                    else sleep(1); // sleep 1s
124                }
125                else break; // success
126            }
127      }      }
128    
129      listen(hSocket, 1);      listen(hSocket, 1);
130      dmsg(1,("LSCPServer: Server running.\n")); // server running      Initialized.Set(true);
131    
132      // now wait for client connections and handle their requests      // now wait for client connections and handle their requests
133      sockaddr_in client;      sockaddr_in client;
134      int length = sizeof(client);      int length = sizeof(client);
135        FD_ZERO(&fdSet);
136        FD_SET(hSocket, &fdSet);
137        int maxSessions = hSocket;
138    
139        timeval timeout;
140    
141      while (true) {      while (true) {
142          hSession = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);          // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
143          if (hSession < 0) {          {
144              std::cerr << "LSCPServer: Client connection failed." << std::endl;              std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
145              close(hSocket);              std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
146              //return -1;              std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
147              exit(EXIT_FAILURE);              for (; itEngineChannel != itEnd; ++itEngineChannel) {
148          }                  if ((*itEngineChannel)->StatusChanged()) {
149                        SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->iSamplerChannelIndex));
150          dmsg(1,("LSCPServer: Client connection established.\n"));                  }
151          //send(hSession, "Welcome!\r\n", 10, 0);              }
152            }
153          // Parser invocation  
154          yyparse_param_t yyparse_param;          //Now let's deliver late notifies (if any)
155          yyparse_param.pServer = this;          NotifyBufferMutex.Lock();
156          yylex_init(&yyparse_param.pScanner);          for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
157          while (yyparse(&yyparse_param) == LSCP_SYNTAX_ERROR); // recall parser in case of syntax error  #ifdef MSG_NOSIGNAL
158          yylex_destroy(yyparse_param.pScanner);                  send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
159    #else
160                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
161    #endif
162            }
163            bufferedNotifies.clear();
164            NotifyBufferMutex.Unlock();
165    
166            fd_set selectSet = fdSet;
167            timeout.tv_sec  = 0;
168            timeout.tv_usec = 100000;
169    
170            int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
171    
172            if (retval == 0)
173                    continue; //Nothing try again
174            if (retval == -1) {
175                    std::cerr << "LSCPServer: Socket select error." << std::endl;
176                    close(hSocket);
177                    exit(EXIT_FAILURE);
178            }
179    
180          close(hSession);          //Accept new connections now (if any)
181          dmsg(1,("LSCPServer: Client connection terminated.\n"));          if (FD_ISSET(hSocket, &selectSet)) {
182                    int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
183                    if (socket < 0) {
184                            std::cerr << "LSCPServer: Client connection failed." << std::endl;
185                            exit(EXIT_FAILURE);
186                    }
187    
188                    if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
189                            std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
190                            exit(EXIT_FAILURE);
191                    }
192    
193                    // Parser initialization
194                    yyparse_param_t yyparse_param;
195                    yyparse_param.pServer  = this;
196                    yyparse_param.hSession = socket;
197    
198                    Sessions.push_back(yyparse_param);
199                    FD_SET(socket, &fdSet);
200                    if (socket > maxSessions)
201                            maxSessions = socket;
202                    dmsg(1,("LSCPServer: Client connection established on socket:%d.\n", socket));
203                    LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection established on socket", socket));
204                    continue; //Maybe this was the only selected socket, better select again
205            }
206    
207            //Something was selected and it was not the hSocket, so it must be some command(s) coming.
208            for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
209                    if (FD_ISSET((*iter).hSession, &selectSet)) {   //Was it this socket?
210                            if (GetLSCPCommand(iter)) {     //Have we read the entire command?
211                                    dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
212                                    int dummy; // just a temporary hack to fulfill the restart() function prototype
213                                    restart(NULL, dummy); // restart the 'scanner'
214                                    currentSocket = (*iter).hSession;  //a hack
215                                    dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
216                                    if ((*iter).bVerbose) { // if echo mode enabled
217                                        AnswerClient(bufferedCommands[currentSocket]);
218                                    }
219                                    int result = yyparse(&(*iter));
220                                    currentSocket = -1;     //continuation of a hack
221                                    dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
222                                    if (result == LSCP_QUIT) { //Was it a quit command by any chance?
223                                            CloseConnection(iter);
224                                    }
225                            }
226                            //socket may have been closed, iter may be invalid, get out of the loop for now.
227                            //we'll be back if there is data.
228                            break;
229                    }
230            }
231      }      }
232  }  }
233    
234    void LSCPServer::CloseConnection( std::vector<yyparse_param_t>::iterator iter ) {
235            int socket = (*iter).hSession;
236            dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));
237            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
238            Sessions.erase(iter);
239            FD_CLR(socket,  &fdSet);
240            SubscriptionMutex.Lock(); //Must unsubscribe this socket from all events (if any)
241            for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
242                    iter->second.remove(socket);
243            }
244            SubscriptionMutex.Unlock();
245            NotifyMutex.Lock();
246            bufferedCommands.erase(socket);
247            bufferedNotifies.erase(socket);
248            close(socket);
249            NotifyMutex.Unlock();
250    }
251    
252    int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {
253            int subs = 0;
254            SubscriptionMutex.Lock();
255            for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();
256                            iter != events.end(); iter++)
257            {
258                    subs += eventSubscriptions.count(*iter);
259            }
260            SubscriptionMutex.Unlock();
261            return subs;
262    }
263    
264    void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
265            SubscriptionMutex.Lock();
266            if (eventSubscriptions.count(event.GetType()) == 0) {
267                    SubscriptionMutex.Unlock();     //Nobody is subscribed to this event
268                    return;
269            }
270            std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();
271            std::list<int>::iterator end = eventSubscriptions[event.GetType()].end();
272            String notify = event.Produce();
273    
274            while (true) {
275                    if (NotifyMutex.Trylock()) {
276                            for(;iter != end; iter++)
277    #ifdef MSG_NOSIGNAL
278                                    send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
279    #else
280                                    send(*iter, notify.c_str(), notify.size(), 0);
281    #endif
282                            NotifyMutex.Unlock();
283                            break;
284                    } else {
285                            if (NotifyBufferMutex.Trylock()) {
286                                    for(;iter != end; iter++)
287                                            bufferedNotifies[*iter] += notify;
288                                    NotifyBufferMutex.Unlock();
289                                    break;
290                            }
291                    }
292            }
293            SubscriptionMutex.Unlock();
294    }
295    
296    extern int GetLSCPCommand( void *buf, int max_size ) {
297            String command = LSCPServer::bufferedCommands[LSCPServer::currentSocket];
298            if (command.size() == 0) {              //Parser wants input but we have nothing.
299                    strcpy((char*) buf, "\n");      //So give it an empty command
300                    return 1;                       //to keep it happy.
301            }
302    
303            if (max_size < command.size()) {
304                    std::cerr << "getLSCPCommand: Flex buffer too small, ignoring the command." << std::endl;
305                    return 0;       //This will never happen
306            }
307    
308            strcpy((char*) buf, command.c_str());
309            LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);
310            return command.size();
311    }
312    
313    /**
314     * Will be called to try to read the command from the socket
315     * If command is read, it will return true. Otherwise false is returned.
316     * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.
317     */
318    bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
319            int socket = (*iter).hSession;
320            char c;
321            int i = 0;
322            while (true) {
323                    int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now
324                    if (result == 0) { //socket was selected, so 0 here means client has closed the connection
325                            CloseConnection(iter);
326                            break;
327                    }
328                    if (result == 1) {
329                            if (c == '\r')
330                                    continue; //Ignore CR
331                            if (c == '\n') {
332                                    LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
333                                    bufferedCommands[socket] += "\r\n";
334                                    return true; //Complete command was read
335                            }
336                            bufferedCommands[socket] += c;
337                    }
338                    if (result == -1) {
339                            if (errno == EAGAIN) //Would block, try again later.
340                                    return false;
341                            switch(errno) {
342                                    case EBADF:
343                                            dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
344                                            break;
345                                    case ECONNREFUSED:
346                                            dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
347                                            break;
348                                    case ENOTCONN:
349                                            dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
350                                            break;
351                                    case ENOTSOCK:
352                                            dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
353                                            break;
354                                    case EAGAIN:
355                                            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"));
356                                            break;
357                                    case EINTR:
358                                            dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
359                                            break;
360                                    case EFAULT:
361                                            dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
362                                            break;
363                                    case EINVAL:
364                                            dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
365                                            break;
366                                    case ENOMEM:
367                                            dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
368                                            break;
369                                    default:
370                                            dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
371                                            break;
372                            }
373                            CloseConnection(iter);
374                            break;
375                    }
376            }
377            return false;
378    }
379    
380  /**  /**
381   * Will be called by the parser whenever it wants to send an answer to the   * Will be called by the parser whenever it wants to send an answer to the
382   * client / frontend.   * client / frontend.
# Line 86  int LSCPServer::Main() { Line 385  int LSCPServer::Main() {
385   */   */
386  void LSCPServer::AnswerClient(String ReturnMessage) {  void LSCPServer::AnswerClient(String ReturnMessage) {
387      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
388      send(hSession, ReturnMessage.c_str(), ReturnMessage.size(), 0);      if (currentSocket != -1) {
389                NotifyMutex.Lock();
390    #ifdef MSG_NOSIGNAL
391                send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
392    #else
393                send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
394    #endif
395                NotifyMutex.Unlock();
396        }
397    }
398    
399    /**
400     * Find a created audio output device index.
401     */
402    int LSCPServer::GetAudioOutputDeviceIndex ( AudioOutputDevice *pDevice )
403    {
404        // Search for the created device to get its index
405        std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
406        std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
407        for (; iter != devices.end(); iter++) {
408            if (iter->second == pDevice)
409                return iter->first;
410        }
411        // Not found.
412        return -1;
413    }
414    
415    /**
416     * Find a created midi input device index.
417     */
418    int LSCPServer::GetMidiInputDeviceIndex ( MidiInputDevice *pDevice )
419    {
420        // Search for the created device to get its index
421        std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
422        std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
423        for (; iter != devices.end(); iter++) {
424            if (iter->second == pDevice)
425                return iter->first;
426        }
427        // Not found.
428        return -1;
429    }
430    
431    String LSCPServer::CreateAudioOutputDevice(String Driver, std::map<String,String> Parameters) {
432        dmsg(2,("LSCPServer: CreateAudioOutputDevice(Driver=%s)\n", Driver.c_str()));
433        LSCPResultSet result;
434        try {
435            AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
436            // search for the created device to get its index
437            int index = GetAudioOutputDeviceIndex(pDevice);
438            if (index == -1) throw Exception("Internal error: could not find created audio output device.");
439            result = index; // success
440        }
441        catch (Exception e) {
442            result.Error(e);
443        }
444        return result.Produce();
445    }
446    
447    String LSCPServer::CreateMidiInputDevice(String Driver, std::map<String,String> Parameters) {
448        dmsg(2,("LSCPServer: CreateMidiInputDevice(Driver=%s)\n", Driver.c_str()));
449        LSCPResultSet result;
450        try {
451            MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
452            // search for the created device to get its index
453            int index = GetMidiInputDeviceIndex(pDevice);
454            if (index == -1) throw Exception("Internal error: could not find created midi input device.");
455            result = index; // success
456        }
457        catch (Exception e) {
458            result.Error(e);
459        }
460        return result.Produce();
461    }
462    
463    String LSCPServer::DestroyAudioOutputDevice(uint DeviceIndex) {
464        dmsg(2,("LSCPServer: DestroyAudioOutputDevice(DeviceIndex=%d)\n", DeviceIndex));
465        LSCPResultSet result;
466        try {
467            std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
468            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
469            AudioOutputDevice* pDevice = devices[DeviceIndex];
470            pSampler->DestroyAudioOutputDevice(pDevice);
471        }
472        catch (Exception e) {
473            result.Error(e);
474        }
475        return result.Produce();
476    }
477    
478    String LSCPServer::DestroyMidiInputDevice(uint DeviceIndex) {
479        dmsg(2,("LSCPServer: DestroyMidiInputDevice(DeviceIndex=%d)\n", DeviceIndex));
480        LSCPResultSet result;
481        try {
482            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
483            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
484            MidiInputDevice* pDevice = devices[DeviceIndex];
485            pSampler->DestroyMidiInputDevice(pDevice);
486        }
487        catch (Exception e) {
488            result.Error(e);
489        }
490        return result.Produce();
491  }  }
492    
493  /**  /**
494   * Will be called by the parser to load an instrument.   * Will be called by the parser to load an instrument.
495   */   */
496  String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel) {  String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel, bool bBackground) {
497      dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));      dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
498      LSCPResultSet result;      LSCPResultSet result;
499      try {      try {
500          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
501          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
502          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
503          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
504          pEngine->LoadInstrument(Filename.c_str(), uiInstrument);          if (!pSamplerChannel->GetAudioOutputDevice())
505                throw Exception("No audio output device connected to sampler channel");
506            if (bBackground) {
507                InstrumentManager::instrument_id_t id;
508                id.FileName = Filename;
509                id.Index    = uiInstrument;
510                InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
511            }
512            else {
513                // tell the engine channel which instrument to load
514                pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrument);
515                // actually start to load the instrument (blocks until completed)
516                pEngineChannel->LoadInstrument();
517            }
518      }      }
519      catch (LinuxSamplerException e) {      catch (Exception e) {
520           result.Error(e);           result.Error(e);
521      }      }
522      return result.Produce();      return result.Produce();
523  }  }
524    
525  /**  /**
526   * Will be called by the parser to load and deploy an engine.   * Will be called by the parser to assign a sampler engine type to a
527     * sampler channel.
528   */   */
529  String LSCPServer::LoadEngine(String EngineName, uint uiSamplerChannel) {  String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
530      dmsg(2,("LSCPServer: LoadEngine(EngineName=%s,SamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));      dmsg(2,("LSCPServer: SetEngineType(EngineName=%s,uiSamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
531      LSCPResultSet result;      LSCPResultSet result;
532      try {      try {
         Engine::type_t type;  
         if ((EngineName == "GigEngine") || (EngineName == "gig")) type = Engine::type_gig;  
         else throw LinuxSamplerException("Unknown engine type");  
533          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
534          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
535          pSamplerChannel->LoadEngine(type);          LockRTNotify();
536            pSamplerChannel->SetEngineType(EngineName);
537            if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
538            UnlockRTNotify();
539      }      }
540      catch (LinuxSamplerException e) {      catch (Exception e) {
541           result.Error(e);           result.Error(e);
542      }      }
543      return result.Produce();      return result.Produce();
# Line 139  String LSCPServer::GetChannels() { Line 554  String LSCPServer::GetChannels() {
554  }  }
555    
556  /**  /**
557     * Will be called by the parser to get the list of sampler channels.
558     */
559    String LSCPServer::ListChannels() {
560        dmsg(2,("LSCPServer: ListChannels()\n"));
561        String list;
562        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
563        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
564        for (; iter != channels.end(); iter++) {
565            if (list != "") list += ",";
566            list += ToString(iter->first);
567        }
568        LSCPResultSet result;
569        result.Add(list);
570        return result.Produce();
571    }
572    
573    /**
574   * Will be called by the parser to add a sampler channel.   * Will be called by the parser to add a sampler channel.
575   */   */
576  String LSCPServer::AddChannel() {  String LSCPServer::AddChannel() {
577      dmsg(2,("LSCPServer: AddChannel()\n"));      dmsg(2,("LSCPServer: AddChannel()\n"));
578        LockRTNotify();
579      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
580        UnlockRTNotify();
581      LSCPResultSet result(pSamplerChannel->Index());      LSCPResultSet result(pSamplerChannel->Index());
582      return result.Produce();      return result.Produce();
583  }  }
# Line 154  String LSCPServer::AddChannel() { Line 588  String LSCPServer::AddChannel() {
588  String LSCPServer::RemoveChannel(uint uiSamplerChannel) {  String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
589      dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
590      LSCPResultSet result;      LSCPResultSet result;
591        LockRTNotify();
592      pSampler->RemoveSamplerChannel(uiSamplerChannel);      pSampler->RemoveSamplerChannel(uiSamplerChannel);
593        UnlockRTNotify();
594      return result.Produce();      return result.Produce();
595  }  }
596    
597  /**  /**
598   * Will be called by the parser to get all available engines.   * Will be called by the parser to get the amount of all available engines.
599   */   */
600  String LSCPServer::GetAvailableEngines() {  String LSCPServer::GetAvailableEngines() {
601      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
602      LSCPResultSet result("GigEngine");      LSCPResultSet result;
603        try {
604            int n = EngineFactory::AvailableEngineTypes().size();
605            result.Add(n);
606        }
607        catch (Exception e) {
608            result.Error(e);
609        }
610      return result.Produce();      return result.Produce();
611  }  }
612    
613  /**  /**
614   * Will be called by the parser to get descriptions for a particular engine.   * Will be called by the parser to get a list of all available engines.
615     */
616    String LSCPServer::ListAvailableEngines() {
617        dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
618        LSCPResultSet result;
619        try {
620            String s = EngineFactory::AvailableEngineTypesAsString();
621            result.Add(s);
622        }
623        catch (Exception e) {
624            result.Error(e);
625        }
626        return result.Produce();
627    }
628    
629    /**
630     * Will be called by the parser to get descriptions for a particular
631     * sampler engine.
632   */   */
633  String LSCPServer::GetEngineInfo(String EngineName) {  String LSCPServer::GetEngineInfo(String EngineName) {
634      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
635      LSCPResultSet result;      LSCPResultSet result;
636        LockRTNotify();
637      try {      try {
638          if ((EngineName == "GigEngine") || (EngineName == "gig")) {          Engine* pEngine = EngineFactory::Create(EngineName);
639              Engine* pEngine = new LinuxSampler::gig::Engine;          result.Add("DESCRIPTION", pEngine->Description());
640              result.Add(pEngine->Description());          result.Add("VERSION",     pEngine->Version());
641              delete pEngine;          EngineFactory::Destroy(pEngine);
         }  
         else throw LinuxSamplerException("Unknown engine type");  
642      }      }
643      catch (LinuxSamplerException e) {      catch (Exception e) {
644           result.Error(e);           result.Error(e);
645      }      }
646        UnlockRTNotify();
647      return result.Produce();      return result.Produce();
648  }  }
649    
# Line 196  String LSCPServer::GetChannelInfo(uint u Line 656  String LSCPServer::GetChannelInfo(uint u
656      LSCPResultSet result;      LSCPResultSet result;
657      try {      try {
658          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
659          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
660          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
661            
662          //Defaults values          //Defaults values
663          String EngineName = "NONE";          String EngineName = "NONE";
664          float Volume = 0;          float Volume = 0.0f;
665          String InstrumentFileName = "NONE";          String InstrumentFileName = "NONE";
666          int InstrumentIndex = 0;          String InstrumentName = "NONE";
667                    int InstrumentIndex = -1;
668          if (pEngine) {          int InstrumentStatus = -1;
669              EngineName =  pEngine->EngineName();          int AudioOutputChannels = 0;
670              Volume = pEngine->Volume();          String AudioRouting;
671              int iIdx = pEngine->InstrumentIndex();          int Mute = 0;
672              if (iIdx != -1) {          bool Solo = false;
673                  InstrumentFileName = pEngine->InstrumentFileName();          String MidiInstrumentMap;
674                  InstrumentIndex = iIdx;  
675            if (pEngineChannel) {
676                EngineName          = pEngineChannel->EngineName();
677                AudioOutputChannels = pEngineChannel->Channels();
678                Volume              = pEngineChannel->Volume();
679                InstrumentStatus    = pEngineChannel->InstrumentStatus();
680                InstrumentIndex     = pEngineChannel->InstrumentIndex();
681                if (InstrumentIndex != -1) {
682                    InstrumentFileName = pEngineChannel->InstrumentFileName();
683                    InstrumentName     = pEngineChannel->InstrumentName();
684                }
685                for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
686                    if (AudioRouting != "") AudioRouting += ",";
687                    AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
688              }              }
689                Mute = pEngineChannel->GetMute();
690                Solo = pEngineChannel->GetSolo();
691                if (pEngineChannel->UsesNoMidiInstrumentMap())
692                    MidiInstrumentMap = "NONE";
693                else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
694                    MidiInstrumentMap = "DEFAULT";
695                else
696                    MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
697          }          }
698    
699          result.Add("ENGINE_NAME", EngineName);          result.Add("ENGINE_NAME", EngineName);
700          result.Add("VOLUME", Volume);          result.Add("VOLUME", Volume);
701    
702          //Some hardcoded stuff for now to make GUI look good          //Some not-so-hardcoded stuff to make GUI look good
703          result.Add("AUDIO_OUTPUT_DEVICE", "0");          result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
704          result.Add("AUDIO_OUTPUT_CHANNELS", "2");          result.Add("AUDIO_OUTPUT_CHANNELS", AudioOutputChannels);
705          result.Add("AUDIO_OUTPUT_ROUTING", "0,1");          result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
706    
707            result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
708            result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
709            if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
710            else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
711    
712          result.Add("INSTRUMENT_FILE", InstrumentFileName);          result.Add("INSTRUMENT_FILE", InstrumentFileName);
713          result.Add("INSTRUMENT_NR", InstrumentIndex);          result.Add("INSTRUMENT_NR", InstrumentIndex);
714                    result.Add("INSTRUMENT_NAME", InstrumentName);
715          //Some more hardcoded stuff for now to make GUI look good          result.Add("INSTRUMENT_STATUS", InstrumentStatus);
716          result.Add("MIDI_INPUT_DEVICE", "0");          result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
717          result.Add("MIDI_INPUT_PORT", "0");          result.Add("SOLO", Solo);
718          result.Add("MIDI_INPUT_CHANNEL", "1");          result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
719      }      }
720      catch (LinuxSamplerException e) {      catch (Exception e) {
721           result.Error(e);           result.Error(e);
722      }      }
723      return result.Produce();      return result.Produce();
# Line 246  String LSCPServer::GetVoiceCount(uint ui Line 732  String LSCPServer::GetVoiceCount(uint ui
732      LSCPResultSet result;      LSCPResultSet result;
733      try {      try {
734          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
735          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
736          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
737          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine loaded on sampler channel");
738          result.Add(pEngine->VoiceCount());          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
739            result.Add(pEngineChannel->GetEngine()->VoiceCount());
740      }      }
741      catch (LinuxSamplerException e) {      catch (Exception e) {
742           result.Error(e);           result.Error(e);
743      }      }
744      return result.Produce();      return result.Produce();
# Line 266  String LSCPServer::GetStreamCount(uint u Line 753  String LSCPServer::GetStreamCount(uint u
753      LSCPResultSet result;      LSCPResultSet result;
754      try {      try {
755          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
756          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
757          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
758          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
759          result.Add(pEngine->DiskStreamCount());          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
760            result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
761      }      }
762      catch (LinuxSamplerException e) {      catch (Exception e) {
763           result.Error(e);           result.Error(e);
764      }      }
765      return result.Produce();      return result.Produce();
# Line 286  String LSCPServer::GetBufferFill(fill_re Line 774  String LSCPServer::GetBufferFill(fill_re
774      LSCPResultSet result;      LSCPResultSet result;
775      try {      try {
776          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
777          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
778          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
779          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
780          if (!pEngine->DiskStreamSupported()) return "NA\r\n"; //FIXME: Update resultset class to support "NA"          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
781          switch (ResponseType) {          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
782              case fill_response_bytes:          else {
783                  result.Add(pEngine->DiskStreamBufferFillBytes());              switch (ResponseType) {
784                  break;                  case fill_response_bytes:
785              case fill_response_percentage:                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillBytes());
786                  result.Add(pEngine->DiskStreamBufferFillPercentage());                      break;
787                  break;                  case fill_response_percentage:
788              default:                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
789                  throw LinuxSamplerException("Unknown fill response type");                      break;
790          }                  default:
791                        throw Exception("Unknown fill response type");
792                }
793            }
794      }      }
795      catch (LinuxSamplerException e) {      catch (Exception e) {
796           result.Error(e);           result.Error(e);
797      }      }
798      return result.Produce();      return result.Produce();
799  }  }
800    
801  /**  String LSCPServer::GetAvailableAudioOutputDrivers() {
802   * Will be called by the parser to change the audio output type on a      dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
  * particular sampler channel.  
  */  
 String LSCPServer::SetAudioOutputType(AudioOutputDevice::type_t AudioOutputType, uint uiSamplerChannel) {  
     dmsg(2,("LSCPServer: SetAudioOutputType(AudioOutputType=%d, SamplerChannel=%d)\n", AudioOutputType, uiSamplerChannel));  
803      LSCPResultSet result;      LSCPResultSet result;
804      try {      try {
805          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          int n = AudioOutputDeviceFactory::AvailableDrivers().size();
806          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          result.Add(n);
         pSamplerChannel->SetAudioOutputDevice(AudioOutputType);  
807      }      }
808      catch (LinuxSamplerException e) {      catch (Exception e) {
809           result.Error(e);          result.Error(e);
810        }
811        return result.Produce();
812    }
813    
814    String LSCPServer::ListAvailableAudioOutputDrivers() {
815        dmsg(2,("LSCPServer: ListAvailableAudioOutputDrivers()\n"));
816        LSCPResultSet result;
817        try {
818            String s = AudioOutputDeviceFactory::AvailableDriversAsString();
819            result.Add(s);
820        }
821        catch (Exception e) {
822            result.Error(e);
823        }
824        return result.Produce();
825    }
826    
827    String LSCPServer::GetAvailableMidiInputDrivers() {
828        dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
829        LSCPResultSet result;
830        try {
831            int n = MidiInputDeviceFactory::AvailableDrivers().size();
832            result.Add(n);
833        }
834        catch (Exception e) {
835            result.Error(e);
836        }
837        return result.Produce();
838    }
839    
840    String LSCPServer::ListAvailableMidiInputDrivers() {
841        dmsg(2,("LSCPServer: ListAvailableMidiInputDrivers()\n"));
842        LSCPResultSet result;
843        try {
844            String s = MidiInputDeviceFactory::AvailableDriversAsString();
845            result.Add(s);
846        }
847        catch (Exception e) {
848            result.Error(e);
849        }
850        return result.Produce();
851    }
852    
853    String LSCPServer::GetMidiInputDriverInfo(String Driver) {
854        dmsg(2,("LSCPServer: GetMidiInputDriverInfo(Driver=%s)\n",Driver.c_str()));
855        LSCPResultSet result;
856        try {
857            result.Add("DESCRIPTION", MidiInputDeviceFactory::GetDriverDescription(Driver));
858            result.Add("VERSION",     MidiInputDeviceFactory::GetDriverVersion(Driver));
859    
860            std::map<String,DeviceCreationParameter*> parameters = MidiInputDeviceFactory::GetAvailableDriverParameters(Driver);
861            if (parameters.size()) { // if there are parameters defined for this driver
862                String s;
863                std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
864                for (;iter != parameters.end(); iter++) {
865                    if (s != "") s += ",";
866                    s += iter->first;
867                }
868                result.Add("PARAMETERS", s);
869            }
870        }
871        catch (Exception e) {
872            result.Error(e);
873        }
874        return result.Produce();
875    }
876    
877    String LSCPServer::GetAudioOutputDriverInfo(String Driver) {
878        dmsg(2,("LSCPServer: GetAudioOutputDriverInfo(Driver=%s)\n",Driver.c_str()));
879        LSCPResultSet result;
880        try {
881            result.Add("DESCRIPTION", AudioOutputDeviceFactory::GetDriverDescription(Driver));
882            result.Add("VERSION",     AudioOutputDeviceFactory::GetDriverVersion(Driver));
883    
884            std::map<String,DeviceCreationParameter*> parameters = AudioOutputDeviceFactory::GetAvailableDriverParameters(Driver);
885            if (parameters.size()) { // if there are parameters defined for this driver
886                String s;
887                std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
888                for (;iter != parameters.end(); iter++) {
889                    if (s != "") s += ",";
890                    s += iter->first;
891                }
892                result.Add("PARAMETERS", s);
893            }
894        }
895        catch (Exception e) {
896            result.Error(e);
897        }
898        return result.Produce();
899    }
900    
901    String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
902        dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
903        LSCPResultSet result;
904        try {
905            DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
906            result.Add("TYPE",         pParameter->Type());
907            result.Add("DESCRIPTION",  pParameter->Description());
908            result.Add("MANDATORY",    pParameter->Mandatory());
909            result.Add("FIX",          pParameter->Fix());
910            result.Add("MULTIPLICITY", pParameter->Multiplicity());
911            optional<String> oDepends       = pParameter->Depends();
912            optional<String> oDefault       = pParameter->Default(DependencyList);
913            optional<String> oRangeMin      = pParameter->RangeMin(DependencyList);
914            optional<String> oRangeMax      = pParameter->RangeMax(DependencyList);
915            optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
916            if (oDepends)       result.Add("DEPENDS",       *oDepends);
917            if (oDefault)       result.Add("DEFAULT",       *oDefault);
918            if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
919            if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
920            if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
921        }
922        catch (Exception e) {
923            result.Error(e);
924        }
925        return result.Produce();
926    }
927    
928    String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
929        dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
930        LSCPResultSet result;
931        try {
932            DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
933            result.Add("TYPE",         pParameter->Type());
934            result.Add("DESCRIPTION",  pParameter->Description());
935            result.Add("MANDATORY",    pParameter->Mandatory());
936            result.Add("FIX",          pParameter->Fix());
937            result.Add("MULTIPLICITY", pParameter->Multiplicity());
938            optional<String> oDepends       = pParameter->Depends();
939            optional<String> oDefault       = pParameter->Default(DependencyList);
940            optional<String> oRangeMin      = pParameter->RangeMin(DependencyList);
941            optional<String> oRangeMax      = pParameter->RangeMax(DependencyList);
942            optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
943            if (oDepends)       result.Add("DEPENDS",       *oDepends);
944            if (oDefault)       result.Add("DEFAULT",       *oDefault);
945            if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
946            if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
947            if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
948        }
949        catch (Exception e) {
950            result.Error(e);
951        }
952        return result.Produce();
953    }
954    
955    String LSCPServer::GetAudioOutputDeviceCount() {
956        dmsg(2,("LSCPServer: GetAudioOutputDeviceCount()\n"));
957        LSCPResultSet result;
958        try {
959            uint count = pSampler->AudioOutputDevices();
960            result.Add(count); // success
961        }
962        catch (Exception e) {
963            result.Error(e);
964        }
965        return result.Produce();
966    }
967    
968    String LSCPServer::GetMidiInputDeviceCount() {
969        dmsg(2,("LSCPServer: GetMidiInputDeviceCount()\n"));
970        LSCPResultSet result;
971        try {
972            uint count = pSampler->MidiInputDevices();
973            result.Add(count); // success
974        }
975        catch (Exception e) {
976            result.Error(e);
977        }
978        return result.Produce();
979    }
980    
981    String LSCPServer::GetAudioOutputDevices() {
982        dmsg(2,("LSCPServer: GetAudioOutputDevices()\n"));
983        LSCPResultSet result;
984        try {
985            String s;
986            std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
987            std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
988            for (; iter != devices.end(); iter++) {
989                if (s != "") s += ",";
990                s += ToString(iter->first);
991            }
992            result.Add(s);
993        }
994        catch (Exception e) {
995            result.Error(e);
996        }
997        return result.Produce();
998    }
999    
1000    String LSCPServer::GetMidiInputDevices() {
1001        dmsg(2,("LSCPServer: GetMidiInputDevices()\n"));
1002        LSCPResultSet result;
1003        try {
1004            String s;
1005            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1006            std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1007            for (; iter != devices.end(); iter++) {
1008                if (s != "") s += ",";
1009                s += ToString(iter->first);
1010            }
1011            result.Add(s);
1012        }
1013        catch (Exception e) {
1014            result.Error(e);
1015        }
1016        return result.Produce();
1017    }
1018    
1019    String LSCPServer::GetAudioOutputDeviceInfo(uint DeviceIndex) {
1020        dmsg(2,("LSCPServer: GetAudioOutputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1021        LSCPResultSet result;
1022        try {
1023            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1024            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1025            AudioOutputDevice* pDevice = devices[DeviceIndex];
1026            result.Add("DRIVER", pDevice->Driver());
1027            std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1028            std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1029            for (; iter != parameters.end(); iter++) {
1030                result.Add(iter->first, iter->second->Value());
1031            }
1032        }
1033        catch (Exception e) {
1034            result.Error(e);
1035        }
1036        return result.Produce();
1037    }
1038    
1039    String LSCPServer::GetMidiInputDeviceInfo(uint DeviceIndex) {
1040        dmsg(2,("LSCPServer: GetMidiInputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1041        LSCPResultSet result;
1042        try {
1043            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1044            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1045            MidiInputDevice* pDevice = devices[DeviceIndex];
1046            result.Add("DRIVER", pDevice->Driver());
1047            std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1048            std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1049            for (; iter != parameters.end(); iter++) {
1050                result.Add(iter->first, iter->second->Value());
1051            }
1052        }
1053        catch (Exception e) {
1054            result.Error(e);
1055        }
1056        return result.Produce();
1057    }
1058    String LSCPServer::GetMidiInputPortInfo(uint DeviceIndex, uint PortIndex) {
1059        dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
1060        LSCPResultSet result;
1061        try {
1062            // get MIDI input device
1063            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1064            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1065            MidiInputDevice* pDevice = devices[DeviceIndex];
1066    
1067            // get MIDI port
1068            MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1069            if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1070    
1071            // return the values of all MIDI port parameters
1072            std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1073            std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1074            for (; iter != parameters.end(); iter++) {
1075                result.Add(iter->first, iter->second->Value());
1076            }
1077        }
1078        catch (Exception e) {
1079            result.Error(e);
1080        }
1081        return result.Produce();
1082    }
1083    
1084    String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
1085        dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%d,ChannelId)\n",DeviceId,ChannelId));
1086        LSCPResultSet result;
1087        try {
1088            // get audio output device
1089            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1090            if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1091            AudioOutputDevice* pDevice = devices[DeviceId];
1092    
1093            // get audio channel
1094            AudioChannel* pChannel = pDevice->Channel(ChannelId);
1095            if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1096    
1097            // return the values of all audio channel parameters
1098            std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1099            std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1100            for (; iter != parameters.end(); iter++) {
1101                result.Add(iter->first, iter->second->Value());
1102            }
1103        }
1104        catch (Exception e) {
1105            result.Error(e);
1106        }
1107        return result.Produce();
1108    }
1109    
1110    String LSCPServer::GetMidiInputPortParameterInfo(uint DeviceId, uint PortId, String ParameterName) {
1111        dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
1112        LSCPResultSet result;
1113        try {
1114            // get MIDI input device
1115            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1116            if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1117            MidiInputDevice* pDevice = devices[DeviceId];
1118    
1119            // get midi port
1120            MidiInputPort* pPort = pDevice->GetPort(PortId);
1121            if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1122    
1123            // get desired port parameter
1124            std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1125            if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1126            DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1127    
1128            // return all fields of this audio channel parameter
1129            result.Add("TYPE",         pParameter->Type());
1130            result.Add("DESCRIPTION",  pParameter->Description());
1131            result.Add("FIX",          pParameter->Fix());
1132            result.Add("MULTIPLICITY", pParameter->Multiplicity());
1133            if (pParameter->RangeMin())      result.Add("RANGE_MIN",     *pParameter->RangeMin());
1134            if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1135            if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1136        }
1137        catch (Exception e) {
1138            result.Error(e);
1139        }
1140        return result.Produce();
1141    }
1142    
1143    String LSCPServer::GetAudioOutputChannelParameterInfo(uint DeviceId, uint ChannelId, String ParameterName) {
1144        dmsg(2,("LSCPServer: GetAudioOutputChannelParameterInfo(DeviceId=%d,ChannelId=%d,ParameterName=%s)\n",DeviceId,ChannelId,ParameterName.c_str()));
1145        LSCPResultSet result;
1146        try {
1147            // get audio output device
1148            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1149            if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1150            AudioOutputDevice* pDevice = devices[DeviceId];
1151    
1152            // get audio channel
1153            AudioChannel* pChannel = pDevice->Channel(ChannelId);
1154            if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1155    
1156            // get desired audio channel parameter
1157            std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1158            if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1159            DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1160    
1161            // return all fields of this audio channel parameter
1162            result.Add("TYPE",         pParameter->Type());
1163            result.Add("DESCRIPTION",  pParameter->Description());
1164            result.Add("FIX",          pParameter->Fix());
1165            result.Add("MULTIPLICITY", pParameter->Multiplicity());
1166            if (pParameter->RangeMin())      result.Add("RANGE_MIN",     *pParameter->RangeMin());
1167            if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1168            if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1169        }
1170        catch (Exception e) {
1171            result.Error(e);
1172        }
1173        return result.Produce();
1174    }
1175    
1176    String LSCPServer::SetAudioOutputChannelParameter(uint DeviceId, uint ChannelId, String ParamKey, String ParamVal) {
1177        dmsg(2,("LSCPServer: SetAudioOutputChannelParameter(DeviceId=%d,ChannelId=%d,ParamKey=%s,ParamVal=%s)\n",DeviceId,ChannelId,ParamKey.c_str(),ParamVal.c_str()));
1178        LSCPResultSet result;
1179        try {
1180            // get audio output device
1181            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1182            if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1183            AudioOutputDevice* pDevice = devices[DeviceId];
1184    
1185            // get audio channel
1186            AudioChannel* pChannel = pDevice->Channel(ChannelId);
1187            if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1188    
1189            // get desired audio channel parameter
1190            std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1191            if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1192            DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1193    
1194            // set new channel parameter value
1195            pParameter->SetValue(ParamVal);
1196            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1197        }
1198        catch (Exception e) {
1199            result.Error(e);
1200        }
1201        return result.Produce();
1202    }
1203    
1204    String LSCPServer::SetAudioOutputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1205        dmsg(2,("LSCPServer: SetAudioOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1206        LSCPResultSet result;
1207        try {
1208            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1209            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1210            AudioOutputDevice* pDevice = devices[DeviceIndex];
1211            std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1212            if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1213            parameters[ParamKey]->SetValue(ParamVal);
1214            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1215        }
1216        catch (Exception e) {
1217            result.Error(e);
1218        }
1219        return result.Produce();
1220    }
1221    
1222    String LSCPServer::SetMidiInputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1223        dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1224        LSCPResultSet result;
1225        try {
1226            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1227            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1228            MidiInputDevice* pDevice = devices[DeviceIndex];
1229            std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1230            if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1231            parameters[ParamKey]->SetValue(ParamVal);
1232            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1233        }
1234        catch (Exception e) {
1235            result.Error(e);
1236        }
1237        return result.Produce();
1238    }
1239    
1240    String LSCPServer::SetMidiInputPortParameter(uint DeviceIndex, uint PortIndex, String ParamKey, String ParamVal) {
1241        dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1242        LSCPResultSet result;
1243        try {
1244            // get MIDI input device
1245            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1246            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1247            MidiInputDevice* pDevice = devices[DeviceIndex];
1248    
1249            // get MIDI port
1250            MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1251            if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1252    
1253            // set port parameter value
1254            std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1255            if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1256            parameters[ParamKey]->SetValue(ParamVal);
1257            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1258        }
1259        catch (Exception e) {
1260            result.Error(e);
1261      }      }
1262      return result.Produce();      return result.Produce();
1263  }  }
# Line 329  String LSCPServer::SetAudioOutputType(Au Line 1266  String LSCPServer::SetAudioOutputType(Au
1266   * Will be called by the parser to change the audio output channel for   * Will be called by the parser to change the audio output channel for
1267   * playback on a particular sampler channel.   * playback on a particular sampler channel.
1268   */   */
1269  String LSCPServer::SetAudioOutputChannel(uint AudioOutputChannel, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1270      dmsg(2,("LSCPServer: SetAudioOutputChannel(AudioOutputChannel=%d, SamplerChannel=%d)\n", AudioOutputChannel, uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1271      return "ERR:0:Not implemented yet.\r\n"; //FIXME: Add support for this in resultset class?      LSCPResultSet result;
1272        try {
1273            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1274            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1275            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1276            if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1277            if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1278            pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1279        }
1280        catch (Exception e) {
1281             result.Error(e);
1282        }
1283        return result.Produce();
1284  }  }
1285    
1286  String LSCPServer::SetMIDIInputType(MidiInputDevice::type_t MidiInputType, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1287      dmsg(2,("LSCPServer: SetMIDIInputType(MidiInputType=%d, SamplerChannel=%d)\n", MidiInputType, uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1288      LSCPResultSet result;      LSCPResultSet result;
1289        LockRTNotify();
1290      try {      try {
1291          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1292          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1293          pSamplerChannel->SetMidiInputDevice(MidiInputType);          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1294            if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1295            AudioOutputDevice* pDevice = devices[AudioDeviceId];
1296            pSamplerChannel->SetAudioOutputDevice(pDevice);
1297      }      }
1298      catch (LinuxSamplerException e) {      catch (Exception e) {
1299           result.Error(e);           result.Error(e);
1300      }      }
1301        UnlockRTNotify();
1302      return result.Produce();      return result.Produce();
1303  }  }
1304    
1305  /**  String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1306   * Will be called by the parser to change the MIDI input port on which the      dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
  * engine of a particular sampler channel should listen to.  
  */  
 String LSCPServer::SetMIDIInputPort(String MIDIInputPort, uint uiSamplerChannel) {  
     dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIInputPort=%s, Samplerchannel=%d)\n", MIDIInputPort.c_str(), uiSamplerChannel));  
1307      LSCPResultSet result;      LSCPResultSet result;
1308        LockRTNotify();
1309      try {      try {
1310          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1311          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1312          if (!pSamplerChannel->GetMidiInputDevice()) throw LinuxSamplerException("No MIDI input device connected yet");          // Driver type name aliasing...
1313          pSamplerChannel->GetMidiInputDevice()->SetInputPort(MIDIInputPort.c_str());          if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1314            if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1315            // Check if there's one audio output device already created
1316            // for the intended audio driver type (AudioOutputDriver)...
1317            AudioOutputDevice *pDevice = NULL;
1318            std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1319            std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1320            for (; iter != devices.end(); iter++) {
1321                if ((iter->second)->Driver() == AudioOutputDriver) {
1322                    pDevice = iter->second;
1323                    break;
1324                }
1325            }
1326            // If it doesn't exist, create a new one with default parameters...
1327            if (pDevice == NULL) {
1328                std::map<String,String> params;
1329                pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1330            }
1331            // Must have a device...
1332            if (pDevice == NULL)
1333                throw Exception("Internal error: could not create audio output device.");
1334            // Set it as the current channel device...
1335            pSamplerChannel->SetAudioOutputDevice(pDevice);
1336      }      }
1337      catch (LinuxSamplerException e) {      catch (Exception e) {
1338             result.Error(e);
1339        }
1340        UnlockRTNotify();
1341        return result.Produce();
1342    }
1343    
1344    String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
1345        dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
1346        LSCPResultSet result;
1347        try {
1348            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1349            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1350            pSamplerChannel->SetMidiInputPort(MIDIPort);
1351        }
1352        catch (Exception e) {
1353             result.Error(e);
1354        }
1355        return result.Produce();
1356    }
1357    
1358    String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
1359        dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
1360        LSCPResultSet result;
1361        try {
1362            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1363            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1364            pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
1365        }
1366        catch (Exception e) {
1367             result.Error(e);
1368        }
1369        return result.Produce();
1370    }
1371    
1372    String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
1373        dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
1374        LSCPResultSet result;
1375        try {
1376            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1377            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1378            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1379            if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1380            MidiInputDevice* pDevice = devices[MIDIDeviceId];
1381            pSamplerChannel->SetMidiInputDevice(pDevice);
1382        }
1383        catch (Exception e) {
1384             result.Error(e);
1385        }
1386        return result.Produce();
1387    }
1388    
1389    String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
1390        dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
1391        LSCPResultSet result;
1392        try {
1393            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1394            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1395            // Driver type name aliasing...
1396            if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
1397            // Check if there's one MIDI input device already created
1398            // for the intended MIDI driver type (MidiInputDriver)...
1399            MidiInputDevice *pDevice = NULL;
1400            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1401            std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1402            for (; iter != devices.end(); iter++) {
1403                if ((iter->second)->Driver() == MidiInputDriver) {
1404                    pDevice = iter->second;
1405                    break;
1406                }
1407            }
1408            // If it doesn't exist, create a new one with default parameters...
1409            if (pDevice == NULL) {
1410                std::map<String,String> params;
1411                pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1412                // Make it with at least one initial port.
1413                std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1414                parameters["PORTS"]->SetValue("1");
1415            }
1416            // Must have a device...
1417            if (pDevice == NULL)
1418                throw Exception("Internal error: could not create MIDI input device.");
1419            // Set it as the current channel device...
1420            pSamplerChannel->SetMidiInputDevice(pDevice);
1421        }
1422        catch (Exception e) {
1423           result.Error(e);           result.Error(e);
1424      }      }
1425      return result.Produce();      return result.Produce();
1426  }  }
1427    
1428  /**  /**
1429   * Will be called by the parser to change the MIDI input channel on which the   * Will be called by the parser to change the MIDI input device, port and channel on which
1430   * engine of a particular sampler channel should listen to.   * engine of a particular sampler channel should listen to.
1431   */   */
1432  String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {  String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
1433      dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n", MIDIChannel, uiSamplerChannel));      dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
1434      LSCPResultSet result;      LSCPResultSet result;
1435      try {      try {
1436          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1437          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1438          if (!pSamplerChannel->GetMidiInputDevice()) throw LinuxSamplerException("No MIDI input device connected yet");          std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();
1439          MidiInputDevice::type_t oldtype = pSamplerChannel->GetMidiInputDevice()->Type();          if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1440          pSamplerChannel->SetMidiInputDevice(oldtype, (MidiInputDevice::midi_chan_t) MIDIChannel);          MidiInputDevice* pDevice = devices[MIDIDeviceId];
1441            pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
1442      }      }
1443      catch (LinuxSamplerException e) {      catch (Exception e) {
1444           result.Error(e);           result.Error(e);
1445      }      }
1446      return result.Produce();      return result.Produce();
# Line 391  String LSCPServer::SetMIDIInputChannel(u Line 1450  String LSCPServer::SetMIDIInputChannel(u
1450   * Will be called by the parser to change the global volume factor on a   * Will be called by the parser to change the global volume factor on a
1451   * particular sampler channel.   * particular sampler channel.
1452   */   */
1453  String LSCPServer::SetVolume(double Volume, uint uiSamplerChannel) {  String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
1454      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", Volume, uiSamplerChannel));      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
1455      LSCPResultSet result;      LSCPResultSet result;
1456      try {      try {
1457          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1458          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1459          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1460          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1461          pEngine->Volume(Volume);          pEngineChannel->Volume(dVolume);
1462      }      }
1463      catch (LinuxSamplerException e) {      catch (Exception e) {
1464           result.Error(e);           result.Error(e);
1465      }      }
1466      return result.Produce();      return result.Produce();
1467  }  }
1468    
1469  /**  /**
1470     * Will be called by the parser to mute/unmute particular sampler channel.
1471     */
1472    String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
1473        dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
1474        LSCPResultSet result;
1475        try {
1476            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1477            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1478    
1479            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1480            if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1481    
1482            if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
1483            else pEngineChannel->SetMute(1);
1484        } catch (Exception e) {
1485            result.Error(e);
1486        }
1487        return result.Produce();
1488    }
1489    
1490    /**
1491     * Will be called by the parser to solo particular sampler channel.
1492     */
1493    String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
1494        dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
1495        LSCPResultSet result;
1496        try {
1497            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1498            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1499    
1500            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1501            if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1502    
1503            bool oldSolo = pEngineChannel->GetSolo();
1504            bool hadSoloChannel = HasSoloChannel();
1505            
1506            pEngineChannel->SetSolo(bSolo);
1507            
1508            if(!oldSolo && bSolo) {
1509                if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
1510                if(!hadSoloChannel) MuteNonSoloChannels();
1511            }
1512            
1513            if(oldSolo && !bSolo) {
1514                if(!HasSoloChannel()) UnmuteChannels();
1515                else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
1516            }
1517        } catch (Exception e) {
1518            result.Error(e);
1519        }
1520        return result.Produce();
1521    }
1522    
1523    /**
1524     * Determines whether there is at least one solo channel in the channel list.
1525     *
1526     * @returns true if there is at least one solo channel in the channel list,
1527     * false otherwise.
1528     */
1529    bool LSCPServer::HasSoloChannel() {
1530        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1531        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1532        for (; iter != channels.end(); iter++) {
1533            EngineChannel* c = iter->second->GetEngineChannel();
1534            if(c && c->GetSolo()) return true;
1535        }
1536    
1537        return false;
1538    }
1539    
1540    /**
1541     * Mutes all unmuted non-solo channels. Notice that the channels are muted
1542     * with -1 which indicates that they are muted because of the presence
1543     * of a solo channel(s). Channels muted with -1 will be automatically unmuted
1544     * when there are no solo channels left.
1545     */
1546    void LSCPServer::MuteNonSoloChannels() {
1547        dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
1548        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1549        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1550        for (; iter != channels.end(); iter++) {
1551            EngineChannel* c = iter->second->GetEngineChannel();
1552            if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
1553        }
1554    }
1555    
1556    /**
1557     * Unmutes all channels that are muted because of the presence
1558     * of a solo channel(s).
1559     */
1560    void  LSCPServer::UnmuteChannels() {
1561        dmsg(2,("LSCPServer: UnmuteChannels()\n"));
1562        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1563        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1564        for (; iter != channels.end(); iter++) {
1565            EngineChannel* c = iter->second->GetEngineChannel();
1566            if(c && c->GetMute() == -1) c->SetMute(0);
1567        }
1568    }
1569    
1570    String LSCPServer::AddOrReplaceMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg, String EngineType, String InstrumentFile, uint InstrumentIndex, float Volume, MidiInstrumentMapper::mode_t LoadMode, String Name) {
1571        dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
1572    
1573        midi_prog_index_t idx;
1574        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1575        idx.midi_bank_lsb = MidiBank & 0x7f;
1576        idx.midi_prog     = MidiProg;
1577    
1578        MidiInstrumentMapper::entry_t entry;
1579        entry.EngineName      = EngineType;
1580        entry.InstrumentFile  = InstrumentFile;
1581        entry.InstrumentIndex = InstrumentIndex;
1582        entry.LoadMode        = LoadMode;
1583        entry.Volume          = Volume;
1584        entry.Name            = Name;
1585    
1586        LSCPResultSet result;
1587        try {
1588            // PERSISTENT mapping commands might bloock for a long time, so in
1589            // that case we add/replace the mapping in another thread
1590            bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT);
1591            MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
1592        } catch (Exception e) {
1593            result.Error(e);
1594        }
1595        return result.Produce();
1596    }
1597    
1598    String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
1599        dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
1600    
1601        midi_prog_index_t idx;
1602        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1603        idx.midi_bank_lsb = MidiBank & 0x7f;
1604        idx.midi_prog     = MidiProg;
1605    
1606        LSCPResultSet result;
1607        try {
1608            MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
1609        } catch (Exception e) {
1610            result.Error(e);
1611        }
1612        return result.Produce();
1613    }
1614    
1615    String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
1616        dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
1617        LSCPResultSet result;
1618        try {
1619            result.Add(MidiInstrumentMapper::Entries(MidiMapID).size());
1620        } catch (Exception e) {
1621            result.Error(e);
1622        }
1623        return result.Produce();
1624    }
1625    
1626    
1627    String LSCPServer::GetAllMidiInstrumentMappings() {
1628        dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
1629        LSCPResultSet result;
1630        std::vector<int> maps = MidiInstrumentMapper::Maps();
1631        int totalMappings = 0;
1632        for (int i = 0; i < maps.size(); i++) {
1633            try {
1634                totalMappings += MidiInstrumentMapper::Entries(maps[i]).size();
1635            } catch (Exception e) { /*NOOP*/ }
1636        }
1637        result.Add(totalMappings);
1638        return result.Produce();
1639    }
1640    
1641    String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
1642        dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
1643        LSCPResultSet result;
1644        try {
1645            midi_prog_index_t idx;
1646            idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1647            idx.midi_bank_lsb = MidiBank & 0x7f;
1648            idx.midi_prog     = MidiProg;
1649    
1650            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
1651            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.find(idx);
1652            if (iter == mappings.end()) result.Error("there is no map entry with that index");
1653            else { // found
1654                result.Add("NAME", iter->second.Name);
1655                result.Add("ENGINE_NAME", iter->second.EngineName);
1656                result.Add("INSTRUMENT_FILE", iter->second.InstrumentFile);
1657                result.Add("INSTRUMENT_NR", (int) iter->second.InstrumentIndex);
1658                String instrumentName;
1659                Engine* pEngine = EngineFactory::Create(iter->second.EngineName);
1660                if (pEngine) {
1661                    if (pEngine->GetInstrumentManager()) {
1662                        InstrumentManager::instrument_id_t instrID;
1663                        instrID.FileName = iter->second.InstrumentFile;
1664                        instrID.Index    = iter->second.InstrumentIndex;
1665                        instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
1666                    }
1667                    EngineFactory::Destroy(pEngine);
1668                }
1669                result.Add("INSTRUMENT_NAME", instrumentName);
1670                switch (iter->second.LoadMode) {
1671                    case MidiInstrumentMapper::ON_DEMAND:
1672                        result.Add("LOAD_MODE", "ON_DEMAND");
1673                        break;
1674                    case MidiInstrumentMapper::ON_DEMAND_HOLD:
1675                        result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
1676                        break;
1677                    case MidiInstrumentMapper::PERSISTENT:
1678                        result.Add("LOAD_MODE", "PERSISTENT");
1679                        break;
1680                    default:
1681                        throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
1682                }
1683                result.Add("VOLUME", iter->second.Volume);
1684            }
1685        } catch (Exception e) {
1686            result.Error(e);
1687        }
1688        return result.Produce();
1689    }
1690    
1691    String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
1692        dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
1693        LSCPResultSet result;
1694        try {
1695            String s;
1696            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
1697            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
1698            for (; iter != mappings.end(); iter++) {
1699                if (s.size()) s += ",";
1700                s += "{" + ToString(MidiMapID) + ","
1701                         + ToString((int(iter->first.midi_bank_msb) << 7) & int(iter->first.midi_bank_lsb)) + ","
1702                         + ToString(int(iter->first.midi_prog)) + "}";
1703            }
1704            result.Add(s);
1705        } catch (Exception e) {
1706            result.Error(e);
1707        }
1708        return result.Produce();
1709    }
1710    
1711    String LSCPServer::ListAllMidiInstrumentMappings() {
1712        dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
1713        LSCPResultSet result;
1714        try {
1715            std::vector<int> maps = MidiInstrumentMapper::Maps();
1716            String s;
1717            for (int i = 0; i < maps.size(); i++) {
1718                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
1719                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
1720                for (; iter != mappings.end(); iter++) {
1721                    if (s.size()) s += ",";
1722                    s += "{" + ToString(maps[i]) + ","
1723                             + ToString((int(iter->first.midi_bank_msb) << 7) & int(iter->first.midi_bank_lsb)) + ","
1724                             + ToString(int(iter->first.midi_prog)) + "}";
1725                }
1726            }
1727            result.Add(s);
1728        } catch (Exception e) {
1729            result.Error(e);
1730        }
1731        return result.Produce();
1732    }
1733    
1734    String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
1735        dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
1736        LSCPResultSet result;
1737        try {
1738            MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
1739        } catch (Exception e) {
1740            result.Error(e);
1741        }
1742        return result.Produce();
1743    }
1744    
1745    String LSCPServer::ClearAllMidiInstrumentMappings() {
1746        dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
1747        LSCPResultSet result;
1748        try {
1749            std::vector<int> maps = MidiInstrumentMapper::Maps();
1750            for (int i = 0; i < maps.size(); i++)
1751                MidiInstrumentMapper::RemoveAllEntries(maps[i]);
1752        } catch (Exception e) {
1753            result.Error(e);
1754        }
1755        return result.Produce();
1756    }
1757    
1758    String LSCPServer::AddMidiInstrumentMap(String MapName) {
1759        dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
1760        LSCPResultSet result;
1761        try {
1762            int MapID = MidiInstrumentMapper::AddMap(MapName);
1763            result = LSCPResultSet(MapID);
1764        } catch (Exception e) {
1765            result.Error(e);
1766        }
1767        return result.Produce();
1768    }
1769    
1770    String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
1771        dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
1772        LSCPResultSet result;
1773        try {
1774            MidiInstrumentMapper::RemoveMap(MidiMapID);
1775        } catch (Exception e) {
1776            result.Error(e);
1777        }
1778        return result.Produce();
1779    }
1780    
1781    String LSCPServer::RemoveAllMidiInstrumentMaps() {
1782        dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
1783        LSCPResultSet result;
1784        try {
1785            MidiInstrumentMapper::RemoveAllMaps();
1786        } catch (Exception e) {
1787            result.Error(e);
1788        }
1789        return result.Produce();
1790    }
1791    
1792    String LSCPServer::GetMidiInstrumentMaps() {
1793        dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
1794        LSCPResultSet result;
1795        try {
1796            result.Add(MidiInstrumentMapper::Maps().size());
1797        } catch (Exception e) {
1798            result.Error(e);
1799        }
1800        return result.Produce();
1801    }
1802    
1803    String LSCPServer::ListMidiInstrumentMaps() {
1804        dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
1805        LSCPResultSet result;
1806        try {
1807            std::vector<int> maps = MidiInstrumentMapper::Maps();
1808            String sList;
1809            for (int i = 0; i < maps.size(); i++) {
1810                if (sList != "") sList += ",";
1811                sList += ToString(maps[i]);
1812            }
1813            result.Add(sList);
1814        } catch (Exception e) {
1815            result.Error(e);
1816        }
1817        return result.Produce();
1818    }
1819    
1820    String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
1821        dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
1822        LSCPResultSet result;
1823        try {
1824            result.Add("NAME", MidiInstrumentMapper::MapName(MidiMapID));
1825        } catch (Exception e) {
1826            result.Error(e);
1827        }
1828        return result.Produce();
1829    }
1830    
1831    String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
1832        dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
1833        LSCPResultSet result;
1834        try {
1835            MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
1836        } catch (Exception e) {
1837            result.Error(e);
1838        }
1839        return result.Produce();
1840    }
1841    
1842    /**
1843     * Set the MIDI instrument map the given sampler channel shall use for
1844     * handling MIDI program change messages. There are the following two
1845     * special (negative) values:
1846     *
1847     *    - (-1) :  set to NONE (ignore program changes)
1848     *    - (-2) :  set to DEFAULT map
1849     */
1850    String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
1851        dmsg(2,("LSCPServer: SetChannelMap()\n"));
1852        LSCPResultSet result;
1853        try {
1854            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1855            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1856    
1857            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1858            if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1859    
1860            if      (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
1861            else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
1862            else                      pEngineChannel->SetMidiInstrumentMap(MidiMapID);
1863        } catch (Exception e) {
1864            result.Error(e);
1865        }
1866        return result.Produce();
1867    }
1868    
1869    String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
1870        dmsg(2,("LSCPServer: CreateFxSend()\n"));
1871        LSCPResultSet result;
1872        try {
1873            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1874            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1875    
1876            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1877            if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1878    
1879            FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
1880            if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
1881    
1882            result = LSCPResultSet(pFxSend->Id()); // success
1883        } catch (Exception e) {
1884            result.Error(e);
1885        }
1886        return result.Produce();
1887    }
1888    
1889    String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
1890        dmsg(2,("LSCPServer: DestroyFxSend()\n"));
1891        LSCPResultSet result;
1892        try {
1893            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1894            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1895    
1896            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1897            if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1898    
1899            FxSend* pFxSend = NULL;
1900            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
1901                if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
1902                    pFxSend = pEngineChannel->GetFxSend(i);
1903                    break;
1904                }
1905            }
1906            if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
1907            pEngineChannel->RemoveFxSend(pFxSend);
1908        } catch (Exception e) {
1909            result.Error(e);
1910        }
1911        return result.Produce();
1912    }
1913    
1914    String LSCPServer::GetFxSends(uint uiSamplerChannel) {
1915        dmsg(2,("LSCPServer: GetFxSends()\n"));
1916        LSCPResultSet result;
1917        try {
1918            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1919            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1920    
1921            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1922            if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1923    
1924            result.Add(pEngineChannel->GetFxSendCount());
1925        } catch (Exception e) {
1926            result.Error(e);
1927        }
1928        return result.Produce();
1929    }
1930    
1931    String LSCPServer::ListFxSends(uint uiSamplerChannel) {
1932        dmsg(2,("LSCPServer: ListFxSends()\n"));
1933        LSCPResultSet result;
1934        String list;
1935        try {
1936            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1937            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1938    
1939            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1940            if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1941    
1942            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
1943                FxSend* pFxSend = pEngineChannel->GetFxSend(i);
1944                if (list != "") list += ",";
1945                list += ToString(pFxSend->Id());
1946            }
1947            result.Add(list);
1948        } catch (Exception e) {
1949            result.Error(e);
1950        }
1951        return result.Produce();
1952    }
1953    
1954    String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
1955        dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
1956        LSCPResultSet result;
1957        try {
1958            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1959            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1960    
1961            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1962            if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1963    
1964            FxSend* pFxSend = NULL;
1965            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
1966                if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
1967                    pFxSend = pEngineChannel->GetFxSend(i);
1968                    break;
1969                }
1970            }
1971            if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
1972    
1973            // gather audio routing informations
1974            String AudioRouting;
1975            for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
1976                if (AudioRouting != "") AudioRouting += ",";
1977                AudioRouting += ToString(pFxSend->DestinationChannel(chan));
1978            }
1979    
1980            // success
1981            result.Add("NAME", pFxSend->Name());
1982            result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
1983        } catch (Exception e) {
1984            result.Error(e);
1985        }
1986        return result.Produce();
1987    }
1988    
1989    String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
1990        dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
1991        LSCPResultSet result;
1992        try {
1993            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1994            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1995    
1996            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1997            if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1998    
1999            FxSend* pFxSend = NULL;
2000            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2001                if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2002                    pFxSend = pEngineChannel->GetFxSend(i);
2003                    break;
2004                }
2005            }
2006            if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2007    
2008            pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2009        } catch (Exception e) {
2010            result.Error(e);
2011        }
2012        return result.Produce();
2013    }
2014    
2015    /**
2016   * Will be called by the parser to reset a particular sampler channel.   * Will be called by the parser to reset a particular sampler channel.
2017   */   */
2018  String LSCPServer::ResetChannel(uint uiSamplerChannel) {  String LSCPServer::ResetChannel(uint uiSamplerChannel) {
# Line 415  String LSCPServer::ResetChannel(uint uiS Line 2020  String LSCPServer::ResetChannel(uint uiS
2020      LSCPResultSet result;      LSCPResultSet result;
2021      try {      try {
2022          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2023          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2024          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2025          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
2026          pEngine->Reset();          pEngineChannel->Reset();
2027      }      }
2028      catch (LinuxSamplerException e) {      catch (Exception e) {
2029           result.Error(e);           result.Error(e);
2030      }      }
2031      return result.Produce();      return result.Produce();
2032  }  }
2033    
2034  /**  /**
2035     * Will be called by the parser to reset the whole sampler.
2036     */
2037    String LSCPServer::ResetSampler() {
2038        dmsg(2,("LSCPServer: ResetSampler()\n"));
2039        pSampler->Reset();
2040        LSCPResultSet result;
2041        return result.Produce();
2042    }
2043    
2044    /**
2045     * Will be called by the parser to return general informations about this
2046     * sampler.
2047     */
2048    String LSCPServer::GetServerInfo() {
2049        dmsg(2,("LSCPServer: GetServerInfo()\n"));
2050        LSCPResultSet result;
2051        result.Add("DESCRIPTION", "LinuxSampler - modular, streaming capable sampler");
2052        result.Add("VERSION", VERSION);
2053        result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
2054        return result.Produce();
2055    }
2056    
2057    /**
2058     * Will be called by the parser to return the current number of all active voices.
2059     */
2060    String LSCPServer::GetTotalVoiceCount() {
2061        dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
2062        LSCPResultSet result;
2063        result.Add(pSampler->GetVoiceCount());
2064        return result.Produce();
2065    }
2066    
2067    /**
2068     * Will be called by the parser to return the maximum number of voices.
2069     */
2070    String LSCPServer::GetTotalVoiceCountMax() {
2071        dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
2072        LSCPResultSet result;
2073        result.Add(EngineFactory::EngineInstances().size() * CONFIG_MAX_VOICES);
2074        return result.Produce();
2075    }
2076    
2077    String LSCPServer::GetGlobalVolume() {
2078        LSCPResultSet result;
2079        result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
2080        return result.Produce();
2081    }
2082    
2083    String LSCPServer::SetGlobalVolume(double dVolume) {
2084        LSCPResultSet result;
2085        try {
2086            if (dVolume < 0) throw Exception("Volume may not be negative");
2087            GLOBAL_VOLUME = dVolume; // see common/global.cpp
2088        } catch (Exception e) {
2089            result.Error(e);
2090        }
2091        return result.Produce();
2092    }
2093    
2094    /**
2095   * Will be called by the parser to subscribe a client (frontend) on the   * Will be called by the parser to subscribe a client (frontend) on the
2096   * server for receiving event messages.   * server for receiving event messages.
2097   */   */
2098  String LSCPServer::SubscribeNotification(uint UDPPort) {  String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
2099      dmsg(2,("LSCPServer: SubscribeNotification(UDPPort=%d)\n", UDPPort));      dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
2100      return "ERR:0:Not implemented yet.\r\n";      LSCPResultSet result;
2101        SubscriptionMutex.Lock();
2102        eventSubscriptions[type].push_back(currentSocket);
2103        SubscriptionMutex.Unlock();
2104        return result.Produce();
2105  }  }
2106    
2107  /**  /**
2108   * Will be called by the parser to unsubscribe a client on the server   * Will be called by the parser to unsubscribe a client on the server
2109   * for not receiving further event messages.   * for not receiving further event messages.
2110   */   */
2111  String LSCPServer::UnsubscribeNotification(String SessionID) {  String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
2112      dmsg(2,("LSCPServer: UnsubscribeNotification(SessionID=%s)\n", SessionID.c_str()));      dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
2113      return "ERR:0:Not implemented yet.\r\n";      LSCPResultSet result;
2114        SubscriptionMutex.Lock();
2115        eventSubscriptions[type].remove(currentSocket);
2116        SubscriptionMutex.Unlock();
2117        return result.Produce();
2118    }
2119    
2120    static int select_callback(void * lscpResultSet, int argc,
2121                            char **argv, char **azColName)
2122    {
2123        LSCPResultSet* resultSet = (LSCPResultSet*) lscpResultSet;
2124        resultSet->Add(argc, argv);
2125        return 0;
2126    }
2127    
2128    String LSCPServer::QueryDatabase(String query) {
2129        LSCPResultSet result;
2130    #if HAVE_SQLITE3
2131        char* zErrMsg = NULL;
2132        sqlite3 *db;
2133        String selectStr = "SELECT " + query;
2134    
2135        int rc = sqlite3_open("linuxsampler.db", &db);
2136        if (rc == SQLITE_OK)
2137        {
2138                rc = sqlite3_exec(db, selectStr.c_str(), select_callback, &result, &zErrMsg);
2139        }
2140        if ( rc != SQLITE_OK )
2141        {
2142                result.Error(String(zErrMsg), rc);
2143        }
2144        sqlite3_close(db);
2145    #else
2146        result.Error(String("SQLITE3 was not installed when linuxsampler was built. SELECT statement is not available."), 0);
2147    #endif
2148        return result.Produce();
2149    }
2150    
2151    /**
2152     * Will be called by the parser to enable or disable echo mode; if echo
2153     * mode is enabled, all commands from the client will (immediately) be
2154     * echoed back to the client.
2155     */
2156    String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
2157        dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
2158        LSCPResultSet result;
2159        try {
2160            if      (boolean_value == 0) pSession->bVerbose = false;
2161            else if (boolean_value == 1) pSession->bVerbose = true;
2162            else throw Exception("Not a boolean value, must either be 0 or 1");
2163        }
2164        catch (Exception e) {
2165             result.Error(e);
2166        }
2167        return result.Produce();
2168  }  }

Legend:
Removed from v.121  
changed lines
  Added in v.1005

  ViewVC Help
Powered by ViewVC