/[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 563 by schoenebeck, Sun May 22 20:43:32 2005 UTC revision 2198 by iliev, Sun Jul 3 18:06:51 2011 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 Christian Schoenebeck                              *   *   Copyright (C) 2005 - 2010 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This library 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  *
# Line 21  Line 21 
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
24    #include <algorithm>
25    #include <string>
26    
27    #include "../common/File.h"
28  #include "lscpserver.h"  #include "lscpserver.h"
29  #include "lscpresultset.h"  #include "lscpresultset.h"
30  #include "lscpevent.h"  #include "lscpevent.h"
 //#include "../common/global.h"  
31    
32    #if defined(WIN32)
33    #include <windows.h>
34    #else
35  #include <fcntl.h>  #include <fcntl.h>
36    #endif
37    
38  #if HAVE_SQLITE3  #if ! HAVE_SQLITE3
39  # include "sqlite3.h"  #define DOESNT_HAVE_SQLITE3 "No database support. SQLITE3 was not installed when linuxsampler was built."
40  #endif  #endif
41    
42  #include "../engines/EngineFactory.h"  #include "../engines/EngineFactory.h"
43    #include "../engines/EngineChannelFactory.h"
44  #include "../drivers/audio/AudioOutputDeviceFactory.h"  #include "../drivers/audio/AudioOutputDeviceFactory.h"
45  #include "../drivers/midi/MidiInputDeviceFactory.h"  #include "../drivers/midi/MidiInputDeviceFactory.h"
46    #include "../effects/EffectFactory.h"
47    
48    namespace LinuxSampler {
49    
50    /**
51     * Returns a copy of the given string where all special characters are
52     * replaced by LSCP escape sequences ("\xHH"). This function shall be used
53     * to escape LSCP response fields in case the respective response field is
54     * actually defined as using escape sequences in the LSCP specs.
55     *
56     * @e Caution: DO NOT use this function for escaping path based responses,
57     * use the Path class (src/common/Path.h) for this instead!
58     */
59    static String _escapeLscpResponse(String txt) {
60        for (int i = 0; i < txt.length(); i++) {
61            const char c = txt.c_str()[i];
62            if (
63                !(c >= '0' && c <= '9') &&
64                !(c >= 'a' && c <= 'z') &&
65                !(c >= 'A' && c <= 'Z') &&
66                !(c == ' ') && !(c == '!') && !(c == '#') && !(c == '$') &&
67                !(c == '%') && !(c == '&') && !(c == '(') && !(c == ')') &&
68                !(c == '*') && !(c == '+') && !(c == ',') && !(c == '-') &&
69                !(c == '.') && !(c == '/') && !(c == ':') && !(c == ';') &&
70                !(c == '<') && !(c == '=') && !(c == '>') && !(c == '?') &&
71                !(c == '@') && !(c == '[') && !(c == ']') &&
72                !(c == '^') && !(c == '_') && !(c == '`') && !(c == '{') &&
73                !(c == '|') && !(c == '}') && !(c == '~')
74            ) {
75                // convert the "special" character into a "\xHH" LSCP escape sequence
76                char buf[5];
77                snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
78                txt.replace(i, 1, buf);
79                i += 3;
80            }
81        }
82        return txt;
83    }
84    
85  /**  /**
86   * Below are a few static members of the LSCPServer class.   * Below are a few static members of the LSCPServer class.
# Line 52  Line 98 
98  fd_set LSCPServer::fdSet;  fd_set LSCPServer::fdSet;
99  int LSCPServer::currentSocket = -1;  int LSCPServer::currentSocket = -1;
100  std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();  std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();
101    std::vector<yyparse_param_t>::iterator itCurrentSession = std::vector<yyparse_param_t>::iterator();
102  std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();  std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();
103  std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();  std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();
104  std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();  std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();
# Line 60  Mutex LSCPServer::NotifyBufferMutex = Mu Line 107  Mutex LSCPServer::NotifyBufferMutex = Mu
107  Mutex LSCPServer::SubscriptionMutex = Mutex();  Mutex LSCPServer::SubscriptionMutex = Mutex();
108  Mutex LSCPServer::RTNotifyMutex = Mutex();  Mutex LSCPServer::RTNotifyMutex = Mutex();
109    
110  LSCPServer::LSCPServer(Sampler* pSampler) : Thread(true, false, 0, -4) {  LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4), eventHandler(this) {
111        SocketAddress.sin_family      = AF_INET;
112        SocketAddress.sin_addr.s_addr = addr;
113        SocketAddress.sin_port        = port;
114      this->pSampler = pSampler;      this->pSampler = pSampler;
115        LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT");
116        LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO");
117        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT");
118        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO");
119      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
120      LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
121      LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
122      LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");      LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
123      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
124        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_count, "FX_SEND_COUNT");
125        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_info, "FX_SEND_INFO");
126        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
127        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
128        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
129        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
130        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_count, "DB_INSTRUMENT_DIRECTORY_COUNT");
131        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_info, "DB_INSTRUMENT_DIRECTORY_INFO");
132        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_count, "DB_INSTRUMENT_COUNT");
133        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_info, "DB_INSTRUMENT_INFO");
134        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instrs_job_info, "DB_INSTRUMENTS_JOB_INFO");
135      LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");      LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
136        LSCPEvent::RegisterEvent(LSCPEvent::event_total_stream_count, "TOTAL_STREAM_COUNT");
137        LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
138        LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");
139        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_midi, "CHANNEL_MIDI");
140        LSCPEvent::RegisterEvent(LSCPEvent::event_device_midi, "DEVICE_MIDI");
141        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_count, "EFFECT_INSTANCE_COUNT");
142        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_info, "EFFECT_INSTANCE_INFO");
143        LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_count, "SEND_EFFECT_CHAIN_COUNT");
144        LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_info, "SEND_EFFECT_CHAIN_INFO");
145      hSocket = -1;      hSocket = -1;
146  }  }
147    
148  LSCPServer::~LSCPServer() {  LSCPServer::~LSCPServer() {
149        CloseAllConnections();
150        InstrumentManager::StopBackgroundThread();
151    #if defined(WIN32)
152        if (hSocket >= 0) closesocket(hSocket);
153    #else
154      if (hSocket >= 0) close(hSocket);      if (hSocket >= 0) close(hSocket);
155    #endif
156    }
157    
158    LSCPServer::EventHandler::EventHandler(LSCPServer* pParent) {
159        this->pParent = pParent;
160    }
161    
162    LSCPServer::EventHandler::~EventHandler() {
163        std::vector<midi_listener_entry> l = channelMidiListeners;
164        channelMidiListeners.clear();
165        for (int i = 0; i < l.size(); i++)
166            delete l[i].pMidiListener;
167    }
168    
169    void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {
170        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));
171    }
172    
173    void LSCPServer::EventHandler::ChannelAdded(SamplerChannel* pChannel) {
174        pChannel->AddEngineChangeListener(this);
175    }
176    
177    void LSCPServer::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) {
178        if (!pChannel->GetEngineChannel()) return;
179        EngineToBeChanged(pChannel->Index());
180    }
181    
182    void LSCPServer::EventHandler::EngineToBeChanged(int ChannelId) {
183        SamplerChannel* pSamplerChannel =
184            pParent->pSampler->GetSamplerChannel(ChannelId);
185        if (!pSamplerChannel) return;
186        EngineChannel* pEngineChannel =
187            pSamplerChannel->GetEngineChannel();
188        if (!pEngineChannel) return;
189        for (std::vector<midi_listener_entry>::iterator iter = channelMidiListeners.begin(); iter != channelMidiListeners.end(); ++iter) {
190            if ((*iter).pEngineChannel == pEngineChannel) {
191                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
192                pEngineChannel->Disconnect(pMidiListener);
193                channelMidiListeners.erase(iter);
194                delete pMidiListener;
195                return;
196            }
197        }
198    }
199    
200    void LSCPServer::EventHandler::EngineChanged(int ChannelId) {
201        SamplerChannel* pSamplerChannel =
202            pParent->pSampler->GetSamplerChannel(ChannelId);
203        if (!pSamplerChannel) return;
204        EngineChannel* pEngineChannel =
205            pSamplerChannel->GetEngineChannel();
206        if (!pEngineChannel) return;
207        VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
208        pEngineChannel->Connect(pMidiListener);
209        midi_listener_entry entry = {
210            pSamplerChannel, pEngineChannel, pMidiListener
211        };
212        channelMidiListeners.push_back(entry);
213    }
214    
215    void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {
216        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));
217    }
218    
219    void LSCPServer::EventHandler::MidiDeviceCountChanged(int NewCount) {
220        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));
221    }
222    
223    void LSCPServer::EventHandler::MidiDeviceToBeDestroyed(MidiInputDevice* pDevice) {
224        pDevice->RemoveMidiPortCountListener(this);
225        for (int i = 0; i < pDevice->PortCount(); ++i)
226            MidiPortToBeRemoved(pDevice->GetPort(i));
227    }
228    
229    void LSCPServer::EventHandler::MidiDeviceCreated(MidiInputDevice* pDevice) {
230        pDevice->AddMidiPortCountListener(this);
231        for (int i = 0; i < pDevice->PortCount(); ++i)
232            MidiPortAdded(pDevice->GetPort(i));
233    }
234    
235    void LSCPServer::EventHandler::MidiPortCountChanged(int NewCount) {
236        // yet unused
237    }
238    
239    void LSCPServer::EventHandler::MidiPortToBeRemoved(MidiInputPort* pPort) {
240        for (std::vector<device_midi_listener_entry>::iterator iter = deviceMidiListeners.begin(); iter != deviceMidiListeners.end(); ++iter) {
241            if ((*iter).pPort == pPort) {
242                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
243                pPort->Disconnect(pMidiListener);
244                deviceMidiListeners.erase(iter);
245                delete pMidiListener;
246                return;
247            }
248        }
249    }
250    
251    void LSCPServer::EventHandler::MidiPortAdded(MidiInputPort* pPort) {
252        // find out the device ID
253        std::map<uint, MidiInputDevice*> devices =
254            pParent->pSampler->GetMidiInputDevices();
255        for (
256            std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
257            iter != devices.end(); ++iter
258        ) {
259            if (iter->second == pPort->GetDevice()) { // found
260                VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
261                pPort->Connect(pMidiListener);
262                device_midi_listener_entry entry = {
263                    pPort, pMidiListener, iter->first
264                };
265                deviceMidiListeners.push_back(entry);
266                return;
267            }
268        }
269    }
270    
271    void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {
272        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));
273    }
274    
275    void LSCPServer::EventHandler::MidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
276        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_info, MapId, Bank, Program));
277    }
278    
279    void LSCPServer::EventHandler::MidiInstrumentMapCountChanged(int NewCount) {
280        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, NewCount));
281    }
282    
283    void LSCPServer::EventHandler::MidiInstrumentMapInfoChanged(int MapId) {
284        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_info, MapId));
285    }
286    
287    void LSCPServer::EventHandler::FxSendCountChanged(int ChannelId, int NewCount) {
288        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_count, ChannelId, NewCount));
289    }
290    
291    void LSCPServer::EventHandler::VoiceCountChanged(int ChannelId, int NewCount) {
292        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, ChannelId, NewCount));
293    }
294    
295    void LSCPServer::EventHandler::StreamCountChanged(int ChannelId, int NewCount) {
296        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, ChannelId, NewCount));
297    }
298    
299    void LSCPServer::EventHandler::BufferFillChanged(int ChannelId, String FillData) {
300        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, ChannelId, FillData));
301    }
302    
303    void LSCPServer::EventHandler::TotalVoiceCountChanged(int NewCount) {
304        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));
305    }
306    
307    void LSCPServer::EventHandler::TotalStreamCountChanged(int NewCount) {
308        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_stream_count, NewCount));
309    }
310    
311    #if HAVE_SQLITE3
312    void LSCPServer::DbInstrumentsEventHandler::DirectoryCountChanged(String Dir) {
313        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_count, InstrumentsDb::toEscapedPath(Dir)));
314    }
315    
316    void LSCPServer::DbInstrumentsEventHandler::DirectoryInfoChanged(String Dir) {
317        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, InstrumentsDb::toEscapedPath(Dir)));
318    }
319    
320    void LSCPServer::DbInstrumentsEventHandler::DirectoryNameChanged(String Dir, String NewName) {
321        Dir = "'" + InstrumentsDb::toEscapedPath(Dir) + "'";
322        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
323        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, "NAME", Dir, NewName));
324    }
325    
326    void LSCPServer::DbInstrumentsEventHandler::InstrumentCountChanged(String Dir) {
327        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_count, InstrumentsDb::toEscapedPath(Dir)));
328    }
329    
330    void LSCPServer::DbInstrumentsEventHandler::InstrumentInfoChanged(String Instr) {
331        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, InstrumentsDb::toEscapedPath(Instr)));
332    }
333    
334    void LSCPServer::DbInstrumentsEventHandler::InstrumentNameChanged(String Instr, String NewName) {
335        Instr = "'" + InstrumentsDb::toEscapedPath(Instr) + "'";
336        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
337        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, "NAME", Instr, NewName));
338    }
339    
340    void LSCPServer::DbInstrumentsEventHandler::JobStatusChanged(int JobId) {
341        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instrs_job_info, JobId));
342    }
343    #endif // HAVE_SQLITE3
344    
345    void LSCPServer::RemoveListeners() {
346        pSampler->RemoveChannelCountListener(&eventHandler);
347        pSampler->RemoveAudioDeviceCountListener(&eventHandler);
348        pSampler->RemoveMidiDeviceCountListener(&eventHandler);
349        pSampler->RemoveVoiceCountListener(&eventHandler);
350        pSampler->RemoveStreamCountListener(&eventHandler);
351        pSampler->RemoveBufferFillListener(&eventHandler);
352        pSampler->RemoveTotalStreamCountListener(&eventHandler);
353        pSampler->RemoveTotalVoiceCountListener(&eventHandler);
354        pSampler->RemoveFxSendCountListener(&eventHandler);
355        MidiInstrumentMapper::RemoveMidiInstrumentCountListener(&eventHandler);
356        MidiInstrumentMapper::RemoveMidiInstrumentInfoListener(&eventHandler);
357        MidiInstrumentMapper::RemoveMidiInstrumentMapCountListener(&eventHandler);
358        MidiInstrumentMapper::RemoveMidiInstrumentMapInfoListener(&eventHandler);
359    #if HAVE_SQLITE3
360        InstrumentsDb::GetInstrumentsDb()->RemoveInstrumentsDbListener(&dbInstrumentsEventHandler);
361    #endif
362  }  }
363    
364  /**  /**
# Line 90  int LSCPServer::WaitUntilInitialized(lon Line 376  int LSCPServer::WaitUntilInitialized(lon
376  }  }
377    
378  int LSCPServer::Main() {  int LSCPServer::Main() {
379            #if defined(WIN32)
380            WSADATA wsaData;
381            int iResult;
382            iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
383            if (iResult != 0) {
384                    std::cerr << "LSCPServer: WSAStartup failed: " << iResult << "\n";
385                    exit(EXIT_FAILURE);
386            }
387            #endif
388      hSocket = socket(AF_INET, SOCK_STREAM, 0);      hSocket = socket(AF_INET, SOCK_STREAM, 0);
389      if (hSocket < 0) {      if (hSocket < 0) {
390          std::cerr << "LSCPServer: Could not create server socket." << std::endl;          std::cerr << "LSCPServer: Could not create server socket." << std::endl;
# Line 97  int LSCPServer::Main() { Line 392  int LSCPServer::Main() {
392          exit(EXIT_FAILURE);          exit(EXIT_FAILURE);
393      }      }
394    
     SocketAddress.sin_family      = AF_INET;  
     SocketAddress.sin_port        = htons(LSCP_PORT);  
     SocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);  
   
395      if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {      if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
396          std::cerr << "LSCPServer: Could not bind server socket, retrying for " << ToString(LSCP_SERVER_BIND_TIMEOUT) << " seconds...";          std::cerr << "LSCPServer: Could not bind server socket, retrying for " << ToString(LSCP_SERVER_BIND_TIMEOUT) << " seconds...";
397          for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds          for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds
398              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
399                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {
400                      std::cerr << "gave up!" << std::endl;                      std::cerr << "gave up!" << std::endl;
401                        #if defined(WIN32)
402                        closesocket(hSocket);
403                        #else
404                      close(hSocket);                      close(hSocket);
405                        #endif
406                      //return -1;                      //return -1;
407                      exit(EXIT_FAILURE);                      exit(EXIT_FAILURE);
408                  }                  }
# Line 120  int LSCPServer::Main() { Line 415  int LSCPServer::Main() {
415      listen(hSocket, 1);      listen(hSocket, 1);
416      Initialized.Set(true);      Initialized.Set(true);
417    
418        // Registering event listeners
419        pSampler->AddChannelCountListener(&eventHandler);
420        pSampler->AddAudioDeviceCountListener(&eventHandler);
421        pSampler->AddMidiDeviceCountListener(&eventHandler);
422        pSampler->AddVoiceCountListener(&eventHandler);
423        pSampler->AddStreamCountListener(&eventHandler);
424        pSampler->AddBufferFillListener(&eventHandler);
425        pSampler->AddTotalStreamCountListener(&eventHandler);
426        pSampler->AddTotalVoiceCountListener(&eventHandler);
427        pSampler->AddFxSendCountListener(&eventHandler);
428        MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);
429        MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);
430        MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);
431        MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);
432    #if HAVE_SQLITE3
433        InstrumentsDb::GetInstrumentsDb()->AddInstrumentsDbListener(&dbInstrumentsEventHandler);
434    #endif
435      // now wait for client connections and handle their requests      // now wait for client connections and handle their requests
436      sockaddr_in client;      sockaddr_in client;
437      int length = sizeof(client);      int length = sizeof(client);
# Line 127  int LSCPServer::Main() { Line 439  int LSCPServer::Main() {
439      FD_SET(hSocket, &fdSet);      FD_SET(hSocket, &fdSet);
440      int maxSessions = hSocket;      int maxSessions = hSocket;
441    
442        timeval timeout;
443    
444      while (true) {      while (true) {
445          fd_set selectSet = fdSet;          #if CONFIG_PTHREAD_TESTCANCEL
446          int retval = select(maxSessions+1, &selectSet, NULL, NULL, NULL);                  TestCancel();
447          if (retval == 0)          #endif
448            // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
449            {
450                std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
451                std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
452                std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
453                for (; itEngineChannel != itEnd; ++itEngineChannel) {
454                    if ((*itEngineChannel)->StatusChanged()) {
455                        SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->GetSamplerChannel()->Index()));
456                    }
457    
458                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
459                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
460                        if(fxs != NULL && fxs->IsInfoChanged()) {
461                            int chn = (*itEngineChannel)->GetSamplerChannel()->Index();
462                            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));
463                            fxs->SetInfoChanged(false);
464                        }
465                    }
466                }
467            }
468    
469            // check if MIDI data arrived on some engine channel
470            for (int i = 0; i < eventHandler.channelMidiListeners.size(); ++i) {
471                const EventHandler::midi_listener_entry entry =
472                    eventHandler.channelMidiListeners[i];
473                VirtualMidiDevice* pMidiListener = entry.pMidiListener;
474                if (pMidiListener->NotesChanged()) {
475                    for (int iNote = 0; iNote < 128; iNote++) {
476                        if (pMidiListener->NoteChanged(iNote)) {
477                            const bool bActive = pMidiListener->NoteIsActive(iNote);
478                            LSCPServer::SendLSCPNotify(
479                                LSCPEvent(
480                                    LSCPEvent::event_channel_midi,
481                                    entry.pSamplerChannel->Index(),
482                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
483                                    iNote,
484                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
485                                            : pMidiListener->NoteOffVelocity(iNote)
486                                )
487                            );
488                        }
489                    }
490                }
491            }
492    
493            // check if MIDI data arrived on some MIDI device
494            for (int i = 0; i < eventHandler.deviceMidiListeners.size(); ++i) {
495                const EventHandler::device_midi_listener_entry entry =
496                    eventHandler.deviceMidiListeners[i];
497                VirtualMidiDevice* pMidiListener = entry.pMidiListener;
498                if (pMidiListener->NotesChanged()) {
499                    for (int iNote = 0; iNote < 128; iNote++) {
500                        if (pMidiListener->NoteChanged(iNote)) {
501                            const bool bActive = pMidiListener->NoteIsActive(iNote);
502                            LSCPServer::SendLSCPNotify(
503                                LSCPEvent(
504                                    LSCPEvent::event_device_midi,
505                                    entry.uiDeviceID,
506                                    entry.pPort->GetPortNumber(),
507                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
508                                    iNote,
509                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
510                                            : pMidiListener->NoteOffVelocity(iNote)
511                                )
512                            );
513                        }
514                    }
515                }
516            }
517    
518            //Now let's deliver late notifies (if any)
519            NotifyBufferMutex.Lock();
520            for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
521    #ifdef MSG_NOSIGNAL
522                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
523    #else
524                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
525    #endif
526            }
527            bufferedNotifies.clear();
528            NotifyBufferMutex.Unlock();
529    
530            fd_set selectSet = fdSet;
531            timeout.tv_sec  = 0;
532            timeout.tv_usec = 100000;
533    
534            int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
535    
536            if (retval == 0 || (retval == -1 && errno == EINTR))
537                  continue; //Nothing try again                  continue; //Nothing try again
538          if (retval == -1) {          if (retval == -1) {
539                  std::cerr << "LSCPServer: Socket select error." << std::endl;                  std::cerr << "LSCPServer: Socket select error." << std::endl;
540                    #if defined(WIN32)
541                    closesocket(hSocket);
542                    #else
543                  close(hSocket);                  close(hSocket);
544                    #endif
545                  exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
546          }          }
547    
# Line 146  int LSCPServer::Main() { Line 553  int LSCPServer::Main() {
553                          exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
554                  }                  }
555    
556                    #if defined(WIN32)
557                    u_long nonblock_io = 1;
558                    if( ioctlsocket(socket, FIONBIO, &nonblock_io) ) {
559                      std::cerr << "LSCPServer: ioctlsocket: set FIONBIO failed. Error " << WSAGetLastError() << std::endl;
560                      exit(EXIT_FAILURE);
561                    }
562            #else
563                    struct linger linger;
564                    linger.l_onoff = 1;
565                    linger.l_linger = 0;
566                    if(setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))) {
567                        std::cerr << "LSCPServer: Failed to set SO_LINGER\n";
568                    }
569    
570                  if (fcntl(socket, F_SETFL, O_NONBLOCK)) {                  if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
571                          std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;                          std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
572                          exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
573                  }                  }
574                    #endif
575    
576                  // Parser initialization                  // Parser initialization
577                  yyparse_param_t yyparse_param;                  yyparse_param_t yyparse_param;
# Line 173  int LSCPServer::Main() { Line 595  int LSCPServer::Main() {
595                                  int dummy; // just a temporary hack to fulfill the restart() function prototype                                  int dummy; // just a temporary hack to fulfill the restart() function prototype
596                                  restart(NULL, dummy); // restart the 'scanner'                                  restart(NULL, dummy); // restart the 'scanner'
597                                  currentSocket = (*iter).hSession;  //a hack                                  currentSocket = (*iter).hSession;  //a hack
598                                    itCurrentSession = iter; // another hack
599                                  dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));                                  dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
600                                  if ((*iter).bVerbose) { // if echo mode enabled                                  if ((*iter).bVerbose) { // if echo mode enabled
601                                      AnswerClient(bufferedCommands[currentSocket]);                                      AnswerClient(bufferedCommands[currentSocket]);
602                                  }                                  }
603                                  int result = yyparse(&(*iter));                                  int result = yyparse(&(*iter));
604                                  currentSocket = -1;     //continuation of a hack                                  currentSocket = -1;     //continuation of a hack
605                                    itCurrentSession = Sessions.end(); // hack as well
606                                  dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));                                  dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
607                                  if (result == LSCP_QUIT) { //Was it a quit command by any chance?                                  if (result == LSCP_QUIT) { //Was it a quit command by any chance?
608                                          CloseConnection(iter);                                          CloseConnection(iter);
# Line 189  int LSCPServer::Main() { Line 613  int LSCPServer::Main() {
613                          break;                          break;
614                  }                  }
615          }          }
   
         //Now let's deliver late notifies (if any)  
         NotifyBufferMutex.Lock();  
         for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {  
                 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);  
                 bufferedNotifies.erase(iterNotify);  
         }  
         NotifyBufferMutex.Unlock();  
616      }      }
617  }  }
618    
# Line 214  void LSCPServer::CloseConnection( std::v Line 630  void LSCPServer::CloseConnection( std::v
630          NotifyMutex.Lock();          NotifyMutex.Lock();
631          bufferedCommands.erase(socket);          bufferedCommands.erase(socket);
632          bufferedNotifies.erase(socket);          bufferedNotifies.erase(socket);
633            #if defined(WIN32)
634            closesocket(socket);
635            #else
636          close(socket);          close(socket);
637            #endif
638          NotifyMutex.Unlock();          NotifyMutex.Unlock();
639  }  }
640    
641    void LSCPServer::CloseAllConnections() {
642        std::vector<yyparse_param_t>::iterator iter = Sessions.begin();
643        while(iter != Sessions.end()) {
644            CloseConnection(iter);
645            iter = Sessions.begin();
646        }
647    }
648    
649    void LSCPServer::LockRTNotify() {
650        RTNotifyMutex.Lock();
651    }
652    
653    void LSCPServer::UnlockRTNotify() {
654        RTNotifyMutex.Unlock();
655    }
656    
657  int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {  int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {
658          int subs = 0;          int subs = 0;
659          SubscriptionMutex.Lock();          SubscriptionMutex.Lock();
# Line 243  void LSCPServer::SendLSCPNotify( LSCPEve Line 679  void LSCPServer::SendLSCPNotify( LSCPEve
679          while (true) {          while (true) {
680                  if (NotifyMutex.Trylock()) {                  if (NotifyMutex.Trylock()) {
681                          for(;iter != end; iter++)                          for(;iter != end; iter++)
682    #ifdef MSG_NOSIGNAL
683                                    send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
684    #else
685                                  send(*iter, notify.c_str(), notify.size(), 0);                                  send(*iter, notify.c_str(), notify.size(), 0);
686    #endif
687                          NotifyMutex.Unlock();                          NotifyMutex.Unlock();
688                          break;                          break;
689                  } else {                  } else {
# Line 275  extern int GetLSCPCommand( void *buf, in Line 715  extern int GetLSCPCommand( void *buf, in
715          return command.size();          return command.size();
716  }  }
717    
718    extern yyparse_param_t* GetCurrentYaccSession() {
719        return &(*itCurrentSession);
720    }
721    
722  /**  /**
723   * Will be called to try to read the command from the socket   * Will be called to try to read the command from the socket
724   * If command is read, it will return true. Otherwise false is returned.   * If command is read, it will return true. Otherwise false is returned.
# Line 285  bool LSCPServer::GetLSCPCommand( std::ve Line 729  bool LSCPServer::GetLSCPCommand( std::ve
729          char c;          char c;
730          int i = 0;          int i = 0;
731          while (true) {          while (true) {
732                    #if defined(WIN32)
733                    int result = recv(socket, (char *)&c, 1, 0); //Read one character at a time for now
734                    #else
735                  int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now                  int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now
736                    #endif
737                  if (result == 0) { //socket was selected, so 0 here means client has closed the connection                  if (result == 0) { //socket was selected, so 0 here means client has closed the connection
738                          CloseConnection(iter);                          CloseConnection(iter);
739                          break;                          break;
# Line 295  bool LSCPServer::GetLSCPCommand( std::ve Line 743  bool LSCPServer::GetLSCPCommand( std::ve
743                                  continue; //Ignore CR                                  continue; //Ignore CR
744                          if (c == '\n') {                          if (c == '\n') {
745                                  LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));                                  LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
746                                  bufferedCommands[socket] += "\n";                                  bufferedCommands[socket] += "\r\n";
747                                  return true; //Complete command was read                                  return true; //Complete command was read
748                          }                          }
749                          bufferedCommands[socket] += c;                          bufferedCommands[socket] += c;
750                  }                  }
751                    #if defined(WIN32)
752                    if (result == SOCKET_ERROR) {
753                        int wsa_lasterror = WSAGetLastError();
754                            if (wsa_lasterror == WSAEWOULDBLOCK) //Would block, try again later.
755                                    return false;
756                            dmsg(2,("LSCPScanner: Socket error after recv() Error %d.\n", wsa_lasterror));
757                            CloseConnection(iter);
758                            break;
759                    }
760                    #else
761                  if (result == -1) {                  if (result == -1) {
762                          if (errno == EAGAIN) //Would block, try again later.                          if (errno == EAGAIN) //Would block, try again later.
763                                  return false;                                  return false;
# Line 338  bool LSCPServer::GetLSCPCommand( std::ve Line 796  bool LSCPServer::GetLSCPCommand( std::ve
796                          CloseConnection(iter);                          CloseConnection(iter);
797                          break;                          break;
798                  }                  }
799                    #endif
800          }          }
801          return false;          return false;
802  }  }
# Line 352  void LSCPServer::AnswerClient(String Ret Line 811  void LSCPServer::AnswerClient(String Ret
811      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
812      if (currentSocket != -1) {      if (currentSocket != -1) {
813              NotifyMutex.Lock();              NotifyMutex.Lock();
814    #ifdef MSG_NOSIGNAL
815                send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
816    #else
817              send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);              send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
818    #endif
819              NotifyMutex.Unlock();              NotifyMutex.Unlock();
820      }      }
821  }  }
# Line 396  String LSCPServer::CreateAudioOutputDevi Line 859  String LSCPServer::CreateAudioOutputDevi
859          AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);          AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
860          // search for the created device to get its index          // search for the created device to get its index
861          int index = GetAudioOutputDeviceIndex(pDevice);          int index = GetAudioOutputDeviceIndex(pDevice);
862          if (index == -1) throw LinuxSamplerException("Internal error: could not find created audio output device.");          if (index == -1) throw Exception("Internal error: could not find created audio output device.");
863          result = index; // success          result = index; // success
864      }      }
865      catch (LinuxSamplerException e) {      catch (Exception e) {
866          result.Error(e);          result.Error(e);
867      }      }
868      return result.Produce();      return result.Produce();
# Line 412  String LSCPServer::CreateMidiInputDevice Line 875  String LSCPServer::CreateMidiInputDevice
875          MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);          MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
876          // search for the created device to get its index          // search for the created device to get its index
877          int index = GetMidiInputDeviceIndex(pDevice);          int index = GetMidiInputDeviceIndex(pDevice);
878          if (index == -1) throw LinuxSamplerException("Internal error: could not find created midi input device.");          if (index == -1) throw Exception("Internal error: could not find created midi input device.");
879          result = index; // success          result = index; // success
880      }      }
881      catch (LinuxSamplerException e) {      catch (Exception e) {
882          result.Error(e);          result.Error(e);
883      }      }
884      return result.Produce();      return result.Produce();
# Line 426  String LSCPServer::DestroyAudioOutputDev Line 889  String LSCPServer::DestroyAudioOutputDev
889      LSCPResultSet result;      LSCPResultSet result;
890      try {      try {
891          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
892          if (!devices.count(DeviceIndex)) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
893          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
894          pSampler->DestroyAudioOutputDevice(pDevice);          pSampler->DestroyAudioOutputDevice(pDevice);
895      }      }
896      catch (LinuxSamplerException e) {      catch (Exception e) {
897          result.Error(e);          result.Error(e);
898      }      }
899      return result.Produce();      return result.Produce();
# Line 441  String LSCPServer::DestroyMidiInputDevic Line 904  String LSCPServer::DestroyMidiInputDevic
904      LSCPResultSet result;      LSCPResultSet result;
905      try {      try {
906          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
907          if (!devices.count(DeviceIndex)) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
908          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
909          pSampler->DestroyMidiInputDevice(pDevice);          pSampler->DestroyMidiInputDevice(pDevice);
910      }      }
911      catch (LinuxSamplerException e) {      catch (Exception e) {
912          result.Error(e);          result.Error(e);
913      }      }
914      return result.Produce();      return result.Produce();
915  }  }
916    
917    EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
918        SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
919        if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
920    
921        EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
922        if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
923    
924        return pEngineChannel;
925    }
926    
927  /**  /**
928   * Will be called by the parser to load an instrument.   * Will be called by the parser to load an instrument.
929   */   */
# Line 459  String LSCPServer::LoadInstrument(String Line 932  String LSCPServer::LoadInstrument(String
932      LSCPResultSet result;      LSCPResultSet result;
933      try {      try {
934          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
935          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
936          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
937          if (!pEngineChannel) throw LinuxSamplerException("No engine type assigned to sampler channel yet");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
938          if (!pSamplerChannel->GetAudioOutputDevice())          if (!pSamplerChannel->GetAudioOutputDevice())
939              throw LinuxSamplerException("No audio output device connected to sampler channel");              throw Exception("No audio output device connected to sampler channel");
940          if (bBackground) {          if (bBackground) {
941              InstrumentLoader.StartNewLoad(Filename, uiInstrument, pEngineChannel);              InstrumentManager::instrument_id_t id;
942                id.FileName = Filename;
943                id.Index    = uiInstrument;
944                InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
945          }          }
946          else {          else {
947              // tell the engine channel which instrument to load              // tell the engine channel which instrument to load
# Line 474  String LSCPServer::LoadInstrument(String Line 950  String LSCPServer::LoadInstrument(String
950              pEngineChannel->LoadInstrument();              pEngineChannel->LoadInstrument();
951          }          }
952      }      }
953      catch (LinuxSamplerException e) {      catch (Exception e) {
954           result.Error(e);           result.Error(e);
955      }      }
956      return result.Produce();      return result.Produce();
# Line 485  String LSCPServer::LoadInstrument(String Line 961  String LSCPServer::LoadInstrument(String
961   * sampler channel.   * sampler channel.
962   */   */
963  String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {  String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
964      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));
965      LSCPResultSet result;      LSCPResultSet result;
966      try {      try {
967          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
968          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
969          LockRTNotify();          LockRTNotify();
970          pSamplerChannel->SetEngineType(EngineName);          pSamplerChannel->SetEngineType(EngineName);
971            if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
972          UnlockRTNotify();          UnlockRTNotify();
973      }      }
974      catch (LinuxSamplerException e) {      catch (Exception e) {
975           result.Error(e);           result.Error(e);
976      }      }
977      return result.Produce();      return result.Produce();
# Line 532  String LSCPServer::ListChannels() { Line 1009  String LSCPServer::ListChannels() {
1009   */   */
1010  String LSCPServer::AddChannel() {  String LSCPServer::AddChannel() {
1011      dmsg(2,("LSCPServer: AddChannel()\n"));      dmsg(2,("LSCPServer: AddChannel()\n"));
1012        LockRTNotify();
1013      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
1014        UnlockRTNotify();
1015      LSCPResultSet result(pSamplerChannel->Index());      LSCPResultSet result(pSamplerChannel->Index());
1016      return result.Produce();      return result.Produce();
1017  }  }
# Line 554  String LSCPServer::RemoveChannel(uint ui Line 1033  String LSCPServer::RemoveChannel(uint ui
1033   */   */
1034  String LSCPServer::GetAvailableEngines() {  String LSCPServer::GetAvailableEngines() {
1035      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
1036      LSCPResultSet result("1");      LSCPResultSet result;
1037        try {
1038            int n = EngineFactory::AvailableEngineTypes().size();
1039            result.Add(n);
1040        }
1041        catch (Exception e) {
1042            result.Error(e);
1043        }
1044      return result.Produce();      return result.Produce();
1045  }  }
1046    
# Line 563  String LSCPServer::GetAvailableEngines() Line 1049  String LSCPServer::GetAvailableEngines()
1049   */   */
1050  String LSCPServer::ListAvailableEngines() {  String LSCPServer::ListAvailableEngines() {
1051      dmsg(2,("LSCPServer: ListAvailableEngines()\n"));      dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
1052      LSCPResultSet result("\'GIG\'");      LSCPResultSet result;
1053        try {
1054            String s = EngineFactory::AvailableEngineTypesAsString();
1055            result.Add(s);
1056        }
1057        catch (Exception e) {
1058            result.Error(e);
1059        }
1060      return result.Produce();      return result.Produce();
1061  }  }
1062    
# Line 574  String LSCPServer::ListAvailableEngines( Line 1067  String LSCPServer::ListAvailableEngines(
1067  String LSCPServer::GetEngineInfo(String EngineName) {  String LSCPServer::GetEngineInfo(String EngineName) {
1068      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
1069      LSCPResultSet result;      LSCPResultSet result;
1070        LockRTNotify();
1071      try {      try {
1072          Engine* pEngine = EngineFactory::Create(EngineName);          Engine* pEngine = EngineFactory::Create(EngineName);
1073          result.Add("DESCRIPTION", pEngine->Description());          result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
1074          result.Add("VERSION",     pEngine->Version());          result.Add("VERSION",     pEngine->Version());
1075          delete pEngine;          EngineFactory::Destroy(pEngine);
1076      }      }
1077      catch (LinuxSamplerException e) {      catch (Exception e) {
1078           result.Error(e);           result.Error(e);
1079      }      }
1080        UnlockRTNotify();
1081      return result.Produce();      return result.Produce();
1082  }  }
1083    
# Line 595  String LSCPServer::GetChannelInfo(uint u Line 1090  String LSCPServer::GetChannelInfo(uint u
1090      LSCPResultSet result;      LSCPResultSet result;
1091      try {      try {
1092          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1093          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1094          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1095    
1096          //Defaults values          //Defaults values
# Line 607  String LSCPServer::GetChannelInfo(uint u Line 1102  String LSCPServer::GetChannelInfo(uint u
1102          int InstrumentStatus = -1;          int InstrumentStatus = -1;
1103          int AudioOutputChannels = 0;          int AudioOutputChannels = 0;
1104          String AudioRouting;          String AudioRouting;
1105            int Mute = 0;
1106            bool Solo = false;
1107            String MidiInstrumentMap = "NONE";
1108    
1109          if (pEngineChannel) {          if (pEngineChannel) {
1110              EngineName          = pEngineChannel->EngineName();              EngineName          = pEngineChannel->EngineName();
# Line 622  String LSCPServer::GetChannelInfo(uint u Line 1120  String LSCPServer::GetChannelInfo(uint u
1120                  if (AudioRouting != "") AudioRouting += ",";                  if (AudioRouting != "") AudioRouting += ",";
1121                  AudioRouting += ToString(pEngineChannel->OutputChannel(chan));                  AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
1122              }              }
1123                Mute = pEngineChannel->GetMute();
1124                Solo = pEngineChannel->GetSolo();
1125                if (pEngineChannel->UsesNoMidiInstrumentMap())
1126                    MidiInstrumentMap = "NONE";
1127                else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
1128                    MidiInstrumentMap = "DEFAULT";
1129                else
1130                    MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
1131          }          }
1132    
1133          result.Add("ENGINE_NAME", EngineName);          result.Add("ENGINE_NAME", EngineName);
# Line 634  String LSCPServer::GetChannelInfo(uint u Line 1140  String LSCPServer::GetChannelInfo(uint u
1140    
1141          result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));          result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
1142          result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());          result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
1143          if (pSamplerChannel->GetMidiInputChannel() == MidiInputPort::midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");          if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
1144          else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());          else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
1145    
1146            // convert the filename into the correct encoding as defined for LSCP
1147            // (especially in terms of special characters -> escape sequences)
1148            if (InstrumentFileName != "NONE" && InstrumentFileName != "") {
1149    #if WIN32
1150                InstrumentFileName = Path::fromWindows(InstrumentFileName).toLscp();
1151    #else
1152                // assuming POSIX
1153                InstrumentFileName = Path::fromPosix(InstrumentFileName).toLscp();
1154    #endif
1155            }
1156    
1157          result.Add("INSTRUMENT_FILE", InstrumentFileName);          result.Add("INSTRUMENT_FILE", InstrumentFileName);
1158          result.Add("INSTRUMENT_NR", InstrumentIndex);          result.Add("INSTRUMENT_NR", InstrumentIndex);
1159          result.Add("INSTRUMENT_NAME", InstrumentName);          result.Add("INSTRUMENT_NAME", _escapeLscpResponse(InstrumentName));
1160          result.Add("INSTRUMENT_STATUS", InstrumentStatus);          result.Add("INSTRUMENT_STATUS", InstrumentStatus);
1161            result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
1162            result.Add("SOLO", Solo);
1163            result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
1164      }      }
1165      catch (LinuxSamplerException e) {      catch (Exception e) {
1166           result.Error(e);           result.Error(e);
1167      }      }
1168      return result.Produce();      return result.Produce();
# Line 656  String LSCPServer::GetVoiceCount(uint ui Line 1176  String LSCPServer::GetVoiceCount(uint ui
1176      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
1177      LSCPResultSet result;      LSCPResultSet result;
1178      try {      try {
1179          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1180          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw LinuxSamplerException("No engine loaded on sampler channel");  
1181          result.Add(pEngineChannel->GetEngine()->VoiceCount());          result.Add(pEngineChannel->GetEngine()->VoiceCount());
1182      }      }
1183      catch (LinuxSamplerException e) {      catch (Exception e) {
1184           result.Error(e);           result.Error(e);
1185      }      }
1186      return result.Produce();      return result.Produce();
# Line 676  String LSCPServer::GetStreamCount(uint u Line 1194  String LSCPServer::GetStreamCount(uint u
1194      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
1195      LSCPResultSet result;      LSCPResultSet result;
1196      try {      try {
1197          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1198          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw LinuxSamplerException("No engine type assigned to sampler channel");  
1199          result.Add(pEngineChannel->GetEngine()->DiskStreamCount());          result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
1200      }      }
1201      catch (LinuxSamplerException e) {      catch (Exception e) {
1202           result.Error(e);           result.Error(e);
1203      }      }
1204      return result.Produce();      return result.Produce();
# Line 696  String LSCPServer::GetBufferFill(fill_re Line 1212  String LSCPServer::GetBufferFill(fill_re
1212      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
1213      LSCPResultSet result;      LSCPResultSet result;
1214      try {      try {
1215          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1216          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw LinuxSamplerException("No engine type assigned to sampler channel");  
1217          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
1218          else {          else {
1219              switch (ResponseType) {              switch (ResponseType) {
# Line 710  String LSCPServer::GetBufferFill(fill_re Line 1224  String LSCPServer::GetBufferFill(fill_re
1224                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
1225                      break;                      break;
1226                  default:                  default:
1227                      throw LinuxSamplerException("Unknown fill response type");                      throw Exception("Unknown fill response type");
1228              }              }
1229          }          }
1230      }      }
1231      catch (LinuxSamplerException e) {      catch (Exception e) {
1232           result.Error(e);           result.Error(e);
1233      }      }
1234      return result.Produce();      return result.Produce();
# Line 727  String LSCPServer::GetAvailableAudioOutp Line 1241  String LSCPServer::GetAvailableAudioOutp
1241          int n = AudioOutputDeviceFactory::AvailableDrivers().size();          int n = AudioOutputDeviceFactory::AvailableDrivers().size();
1242          result.Add(n);          result.Add(n);
1243      }      }
1244      catch (LinuxSamplerException e) {      catch (Exception e) {
1245          result.Error(e);          result.Error(e);
1246      }      }
1247      return result.Produce();      return result.Produce();
# Line 740  String LSCPServer::ListAvailableAudioOut Line 1254  String LSCPServer::ListAvailableAudioOut
1254          String s = AudioOutputDeviceFactory::AvailableDriversAsString();          String s = AudioOutputDeviceFactory::AvailableDriversAsString();
1255          result.Add(s);          result.Add(s);
1256      }      }
1257      catch (LinuxSamplerException e) {      catch (Exception e) {
1258          result.Error(e);          result.Error(e);
1259      }      }
1260      return result.Produce();      return result.Produce();
# Line 753  String LSCPServer::GetAvailableMidiInput Line 1267  String LSCPServer::GetAvailableMidiInput
1267          int n = MidiInputDeviceFactory::AvailableDrivers().size();          int n = MidiInputDeviceFactory::AvailableDrivers().size();
1268          result.Add(n);          result.Add(n);
1269      }      }
1270      catch (LinuxSamplerException e) {      catch (Exception e) {
1271          result.Error(e);          result.Error(e);
1272      }      }
1273      return result.Produce();      return result.Produce();
# Line 766  String LSCPServer::ListAvailableMidiInpu Line 1280  String LSCPServer::ListAvailableMidiInpu
1280          String s = MidiInputDeviceFactory::AvailableDriversAsString();          String s = MidiInputDeviceFactory::AvailableDriversAsString();
1281          result.Add(s);          result.Add(s);
1282      }      }
1283      catch (LinuxSamplerException e) {      catch (Exception e) {
1284          result.Error(e);          result.Error(e);
1285      }      }
1286      return result.Produce();      return result.Produce();
# Line 786  String LSCPServer::GetMidiInputDriverInf Line 1300  String LSCPServer::GetMidiInputDriverInf
1300              for (;iter != parameters.end(); iter++) {              for (;iter != parameters.end(); iter++) {
1301                  if (s != "") s += ",";                  if (s != "") s += ",";
1302                  s += iter->first;                  s += iter->first;
1303                    delete iter->second;
1304              }              }
1305              result.Add("PARAMETERS", s);              result.Add("PARAMETERS", s);
1306          }          }
1307      }      }
1308      catch (LinuxSamplerException e) {      catch (Exception e) {
1309          result.Error(e);          result.Error(e);
1310      }      }
1311      return result.Produce();      return result.Produce();
# Line 810  String LSCPServer::GetAudioOutputDriverI Line 1325  String LSCPServer::GetAudioOutputDriverI
1325              for (;iter != parameters.end(); iter++) {              for (;iter != parameters.end(); iter++) {
1326                  if (s != "") s += ",";                  if (s != "") s += ",";
1327                  s += iter->first;                  s += iter->first;
1328                    delete iter->second;
1329              }              }
1330              result.Add("PARAMETERS", s);              result.Add("PARAMETERS", s);
1331          }          }
1332      }      }
1333      catch (LinuxSamplerException e) {      catch (Exception e) {
1334          result.Error(e);          result.Error(e);
1335      }      }
1336      return result.Produce();      return result.Produce();
# Line 840  String LSCPServer::GetMidiInputDriverPar Line 1356  String LSCPServer::GetMidiInputDriverPar
1356          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1357          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1358          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1359            delete pParameter;
1360      }      }
1361      catch (LinuxSamplerException e) {      catch (Exception e) {
1362          result.Error(e);          result.Error(e);
1363      }      }
1364      return result.Produce();      return result.Produce();
# Line 867  String LSCPServer::GetAudioOutputDriverP Line 1384  String LSCPServer::GetAudioOutputDriverP
1384          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1385          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1386          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1387            delete pParameter;
1388      }      }
1389      catch (LinuxSamplerException e) {      catch (Exception e) {
1390          result.Error(e);          result.Error(e);
1391      }      }
1392      return result.Produce();      return result.Produce();
# Line 881  String LSCPServer::GetAudioOutputDeviceC Line 1399  String LSCPServer::GetAudioOutputDeviceC
1399          uint count = pSampler->AudioOutputDevices();          uint count = pSampler->AudioOutputDevices();
1400          result.Add(count); // success          result.Add(count); // success
1401      }      }
1402      catch (LinuxSamplerException e) {      catch (Exception e) {
1403          result.Error(e);          result.Error(e);
1404      }      }
1405      return result.Produce();      return result.Produce();
# Line 894  String LSCPServer::GetMidiInputDeviceCou Line 1412  String LSCPServer::GetMidiInputDeviceCou
1412          uint count = pSampler->MidiInputDevices();          uint count = pSampler->MidiInputDevices();
1413          result.Add(count); // success          result.Add(count); // success
1414      }      }
1415      catch (LinuxSamplerException e) {      catch (Exception e) {
1416          result.Error(e);          result.Error(e);
1417      }      }
1418      return result.Produce();      return result.Produce();
# Line 913  String LSCPServer::GetAudioOutputDevices Line 1431  String LSCPServer::GetAudioOutputDevices
1431          }          }
1432          result.Add(s);          result.Add(s);
1433      }      }
1434      catch (LinuxSamplerException e) {      catch (Exception e) {
1435          result.Error(e);          result.Error(e);
1436      }      }
1437      return result.Produce();      return result.Produce();
# Line 932  String LSCPServer::GetMidiInputDevices() Line 1450  String LSCPServer::GetMidiInputDevices()
1450          }          }
1451          result.Add(s);          result.Add(s);
1452      }      }
1453      catch (LinuxSamplerException e) {      catch (Exception e) {
1454          result.Error(e);          result.Error(e);
1455      }      }
1456      return result.Produce();      return result.Produce();
# Line 943  String LSCPServer::GetAudioOutputDeviceI Line 1461  String LSCPServer::GetAudioOutputDeviceI
1461      LSCPResultSet result;      LSCPResultSet result;
1462      try {      try {
1463          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1464          if (!devices.count(DeviceIndex)) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1465          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
1466          result.Add("DRIVER", pDevice->Driver());          result.Add("DRIVER", pDevice->Driver());
1467          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
# Line 952  String LSCPServer::GetAudioOutputDeviceI Line 1470  String LSCPServer::GetAudioOutputDeviceI
1470              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1471          }          }
1472      }      }
1473      catch (LinuxSamplerException e) {      catch (Exception e) {
1474          result.Error(e);          result.Error(e);
1475      }      }
1476      return result.Produce();      return result.Produce();
# Line 963  String LSCPServer::GetMidiInputDeviceInf Line 1481  String LSCPServer::GetMidiInputDeviceInf
1481      LSCPResultSet result;      LSCPResultSet result;
1482      try {      try {
1483          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1484          if (!devices.count(DeviceIndex)) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1485          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1486          result.Add("DRIVER", pDevice->Driver());          result.Add("DRIVER", pDevice->Driver());
1487          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
# Line 972  String LSCPServer::GetMidiInputDeviceInf Line 1490  String LSCPServer::GetMidiInputDeviceInf
1490              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1491          }          }
1492      }      }
1493      catch (LinuxSamplerException e) {      catch (Exception e) {
1494          result.Error(e);          result.Error(e);
1495      }      }
1496      return result.Produce();      return result.Produce();
# Line 983  String LSCPServer::GetMidiInputPortInfo( Line 1501  String LSCPServer::GetMidiInputPortInfo(
1501      try {      try {
1502          // get MIDI input device          // get MIDI input device
1503          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1504          if (!devices.count(DeviceIndex)) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1505          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1506    
1507          // get MIDI port          // get MIDI port
1508          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1509          if (!pMidiInputPort) throw LinuxSamplerException("There is no MIDI input port with index " + ToString(PortIndex) + ".");          if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1510    
1511          // return the values of all MIDI port parameters          // return the values of all MIDI port parameters
1512          std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
# Line 997  String LSCPServer::GetMidiInputPortInfo( Line 1515  String LSCPServer::GetMidiInputPortInfo(
1515              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1516          }          }
1517      }      }
1518      catch (LinuxSamplerException e) {      catch (Exception e) {
1519          result.Error(e);          result.Error(e);
1520      }      }
1521      return result.Produce();      return result.Produce();
# Line 1009  String LSCPServer::GetAudioOutputChannel Line 1527  String LSCPServer::GetAudioOutputChannel
1527      try {      try {
1528          // get audio output device          // get audio output device
1529          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1530          if (!devices.count(DeviceId)) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");          if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1531          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1532    
1533          // get audio channel          // get audio channel
1534          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1535          if (!pChannel) throw LinuxSamplerException("Audio output device does not have audio channel " + ToString(ChannelId) + ".");          if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1536    
1537          // return the values of all audio channel parameters          // return the values of all audio channel parameters
1538          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
# Line 1023  String LSCPServer::GetAudioOutputChannel Line 1541  String LSCPServer::GetAudioOutputChannel
1541              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1542          }          }
1543      }      }
1544      catch (LinuxSamplerException e) {      catch (Exception e) {
1545          result.Error(e);          result.Error(e);
1546      }      }
1547      return result.Produce();      return result.Produce();
# Line 1035  String LSCPServer::GetMidiInputPortParam Line 1553  String LSCPServer::GetMidiInputPortParam
1553      try {      try {
1554          // get MIDI input device          // get MIDI input device
1555          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1556          if (!devices.count(DeviceId)) throw LinuxSamplerException("There is no midi input device with index " + ToString(DeviceId) + ".");          if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1557          MidiInputDevice* pDevice = devices[DeviceId];          MidiInputDevice* pDevice = devices[DeviceId];
1558    
1559          // get midi port          // get midi port
1560          MidiInputPort* pPort = pDevice->GetPort(PortId);          MidiInputPort* pPort = pDevice->GetPort(PortId);
1561          if (!pPort) throw LinuxSamplerException("Midi input device does not have port " + ToString(PortId) + ".");          if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1562    
1563          // get desired port parameter          // get desired port parameter
1564          std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1565          if (!parameters.count(ParameterName)) throw LinuxSamplerException("Midi port does not provide a parameter '" + ParameterName + "'.");          if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1566          DeviceRuntimeParameter* pParameter = parameters[ParameterName];          DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1567    
1568          // return all fields of this audio channel parameter          // return all fields of this audio channel parameter
# Line 1056  String LSCPServer::GetMidiInputPortParam Line 1574  String LSCPServer::GetMidiInputPortParam
1574          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1575          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1576      }      }
1577      catch (LinuxSamplerException e) {      catch (Exception e) {
1578          result.Error(e);          result.Error(e);
1579      }      }
1580      return result.Produce();      return result.Produce();
# Line 1068  String LSCPServer::GetAudioOutputChannel Line 1586  String LSCPServer::GetAudioOutputChannel
1586      try {      try {
1587          // get audio output device          // get audio output device
1588          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1589          if (!devices.count(DeviceId)) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");          if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1590          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1591    
1592          // get audio channel          // get audio channel
1593          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1594          if (!pChannel) throw LinuxSamplerException("Audio output device does not have audio channel " + ToString(ChannelId) + ".");          if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1595    
1596          // get desired audio channel parameter          // get desired audio channel parameter
1597          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1598          if (!parameters.count(ParameterName)) throw LinuxSamplerException("Audio channel does not provide a parameter '" + ParameterName + "'.");          if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1599          DeviceRuntimeParameter* pParameter = parameters[ParameterName];          DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1600    
1601          // return all fields of this audio channel parameter          // return all fields of this audio channel parameter
# Line 1089  String LSCPServer::GetAudioOutputChannel Line 1607  String LSCPServer::GetAudioOutputChannel
1607          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1608          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1609      }      }
1610      catch (LinuxSamplerException e) {      catch (Exception e) {
1611          result.Error(e);          result.Error(e);
1612      }      }
1613      return result.Produce();      return result.Produce();
# Line 1101  String LSCPServer::SetAudioOutputChannel Line 1619  String LSCPServer::SetAudioOutputChannel
1619      try {      try {
1620          // get audio output device          // get audio output device
1621          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1622          if (!devices.count(DeviceId)) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");          if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1623          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1624    
1625          // get audio channel          // get audio channel
1626          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1627          if (!pChannel) throw LinuxSamplerException("Audio output device does not have audio channel " + ToString(ChannelId) + ".");          if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1628    
1629          // get desired audio channel parameter          // get desired audio channel parameter
1630          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1631          if (!parameters.count(ParamKey)) throw LinuxSamplerException("Audio channel does not provide a parameter '" + ParamKey + "'.");          if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1632          DeviceRuntimeParameter* pParameter = parameters[ParamKey];          DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1633    
1634          // set new channel parameter value          // set new channel parameter value
1635          pParameter->SetValue(ParamVal);          pParameter->SetValue(ParamVal);
1636            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1637      }      }
1638      catch (LinuxSamplerException e) {      catch (Exception e) {
1639          result.Error(e);          result.Error(e);
1640      }      }
1641      return result.Produce();      return result.Produce();
# Line 1127  String LSCPServer::SetAudioOutputDeviceP Line 1646  String LSCPServer::SetAudioOutputDeviceP
1646      LSCPResultSet result;      LSCPResultSet result;
1647      try {      try {
1648          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1649          if (!devices.count(DeviceIndex)) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1650          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
1651          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1652          if (!parameters.count(ParamKey)) throw LinuxSamplerException("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");          if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1653          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1654            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1655      }      }
1656      catch (LinuxSamplerException e) {      catch (Exception e) {
1657          result.Error(e);          result.Error(e);
1658      }      }
1659      return result.Produce();      return result.Produce();
# Line 1144  String LSCPServer::SetMidiInputDevicePar Line 1664  String LSCPServer::SetMidiInputDevicePar
1664      LSCPResultSet result;      LSCPResultSet result;
1665      try {      try {
1666          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1667          if (!devices.count(DeviceIndex)) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1668          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1669          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1670          if (!parameters.count(ParamKey)) throw LinuxSamplerException("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");          if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1671          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1672            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1673      }      }
1674      catch (LinuxSamplerException e) {      catch (Exception e) {
1675          result.Error(e);          result.Error(e);
1676      }      }
1677      return result.Produce();      return result.Produce();
# Line 1162  String LSCPServer::SetMidiInputPortParam Line 1683  String LSCPServer::SetMidiInputPortParam
1683      try {      try {
1684          // get MIDI input device          // get MIDI input device
1685          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1686          if (!devices.count(DeviceIndex)) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1687          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1688    
1689          // get MIDI port          // get MIDI port
1690          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1691          if (!pMidiInputPort) throw LinuxSamplerException("There is no MIDI input port with index " + ToString(PortIndex) + ".");          if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1692    
1693          // set port parameter value          // set port parameter value
1694          std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1695          if (!parameters.count(ParamKey)) throw LinuxSamplerException("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");          if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1696          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1697            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1698      }      }
1699      catch (LinuxSamplerException e) {      catch (Exception e) {
1700          result.Error(e);          result.Error(e);
1701      }      }
1702      return result.Produce();      return result.Produce();
# Line 1189  String LSCPServer::SetAudioOutputChannel Line 1711  String LSCPServer::SetAudioOutputChannel
1711      LSCPResultSet result;      LSCPResultSet result;
1712      try {      try {
1713          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1714          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1715          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1716          if (!pEngineChannel) throw LinuxSamplerException("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));          if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1717          if (!pSamplerChannel->GetAudioOutputDevice()) throw LinuxSamplerException("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));          if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1718          pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);          pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1719      }      }
1720      catch (LinuxSamplerException e) {      catch (Exception e) {
1721           result.Error(e);           result.Error(e);
1722      }      }
1723      return result.Produce();      return result.Produce();
# Line 1204  String LSCPServer::SetAudioOutputChannel Line 1726  String LSCPServer::SetAudioOutputChannel
1726  String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1727      dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1728      LSCPResultSet result;      LSCPResultSet result;
1729        LockRTNotify();
1730      try {      try {
1731          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1732          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1733          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1734          if (!devices.count(AudioDeviceId)) throw LinuxSamplerException("There is no audio output device with index " + ToString(AudioDeviceId));          if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1735          AudioOutputDevice* pDevice = devices[AudioDeviceId];          AudioOutputDevice* pDevice = devices[AudioDeviceId];
1736          pSamplerChannel->SetAudioOutputDevice(pDevice);          pSamplerChannel->SetAudioOutputDevice(pDevice);
1737      }      }
1738      catch (LinuxSamplerException e) {      catch (Exception e) {
1739           result.Error(e);           result.Error(e);
1740      }      }
1741        UnlockRTNotify();
1742      return result.Produce();      return result.Produce();
1743  }  }
1744    
1745  String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1746      dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1747      LSCPResultSet result;      LSCPResultSet result;
1748        LockRTNotify();
1749      try {      try {
1750          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1751          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1752          // Driver type name aliasing...          // Driver type name aliasing...
1753          if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";          if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1754          if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";          if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
# Line 1245  String LSCPServer::SetAudioOutputType(St Line 1770  String LSCPServer::SetAudioOutputType(St
1770          }          }
1771          // Must have a device...          // Must have a device...
1772          if (pDevice == NULL)          if (pDevice == NULL)
1773              throw LinuxSamplerException("Internal error: could not create audio output device.");              throw Exception("Internal error: could not create audio output device.");
1774          // Set it as the current channel device...          // Set it as the current channel device...
1775          pSamplerChannel->SetAudioOutputDevice(pDevice);          pSamplerChannel->SetAudioOutputDevice(pDevice);
1776      }      }
1777      catch (LinuxSamplerException e) {      catch (Exception e) {
1778           result.Error(e);           result.Error(e);
1779      }      }
1780        UnlockRTNotify();
1781      return result.Produce();      return result.Produce();
1782  }  }
1783    
# Line 1260  String LSCPServer::SetMIDIInputPort(uint Line 1786  String LSCPServer::SetMIDIInputPort(uint
1786      LSCPResultSet result;      LSCPResultSet result;
1787      try {      try {
1788          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1789          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1790          pSamplerChannel->SetMidiInputPort(MIDIPort);          pSamplerChannel->SetMidiInputPort(MIDIPort);
1791      }      }
1792      catch (LinuxSamplerException e) {      catch (Exception e) {
1793           result.Error(e);           result.Error(e);
1794      }      }
1795      return result.Produce();      return result.Produce();
# Line 1274  String LSCPServer::SetMIDIInputChannel(u Line 1800  String LSCPServer::SetMIDIInputChannel(u
1800      LSCPResultSet result;      LSCPResultSet result;
1801      try {      try {
1802          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1803          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1804          pSamplerChannel->SetMidiInputChannel((MidiInputPort::midi_chan_t) MIDIChannel);          pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
1805      }      }
1806      catch (LinuxSamplerException e) {      catch (Exception e) {
1807           result.Error(e);           result.Error(e);
1808      }      }
1809      return result.Produce();      return result.Produce();
# Line 1288  String LSCPServer::SetMIDIInputDevice(ui Line 1814  String LSCPServer::SetMIDIInputDevice(ui
1814      LSCPResultSet result;      LSCPResultSet result;
1815      try {      try {
1816          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1817          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1818          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1819          if (!devices.count(MIDIDeviceId)) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(MIDIDeviceId));          if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1820          MidiInputDevice* pDevice = devices[MIDIDeviceId];          MidiInputDevice* pDevice = devices[MIDIDeviceId];
1821          pSamplerChannel->SetMidiInputDevice(pDevice);          pSamplerChannel->SetMidiInputDevice(pDevice);
1822      }      }
1823      catch (LinuxSamplerException e) {      catch (Exception e) {
1824           result.Error(e);           result.Error(e);
1825      }      }
1826      return result.Produce();      return result.Produce();
# Line 1305  String LSCPServer::SetMIDIInputType(Stri Line 1831  String LSCPServer::SetMIDIInputType(Stri
1831      LSCPResultSet result;      LSCPResultSet result;
1832      try {      try {
1833          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1834          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1835          // Driver type name aliasing...          // Driver type name aliasing...
1836          if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";          if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
1837          // Check if there's one MIDI input device already created          // Check if there's one MIDI input device already created
# Line 1325  String LSCPServer::SetMIDIInputType(Stri Line 1851  String LSCPServer::SetMIDIInputType(Stri
1851              pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);              pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1852              // Make it with at least one initial port.              // Make it with at least one initial port.
1853              std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();              std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
             parameters["PORTS"]->SetValue("1");  
1854          }          }
1855          // Must have a device...          // Must have a device...
1856          if (pDevice == NULL)          if (pDevice == NULL)
1857              throw LinuxSamplerException("Internal error: could not create MIDI input device.");              throw Exception("Internal error: could not create MIDI input device.");
1858          // Set it as the current channel device...          // Set it as the current channel device...
1859          pSamplerChannel->SetMidiInputDevice(pDevice);          pSamplerChannel->SetMidiInputDevice(pDevice);
1860      }      }
1861      catch (LinuxSamplerException e) {      catch (Exception e) {
1862           result.Error(e);           result.Error(e);
1863      }      }
1864      return result.Produce();      return result.Produce();
# Line 1348  String LSCPServer::SetMIDIInput(uint MID Line 1873  String LSCPServer::SetMIDIInput(uint MID
1873      LSCPResultSet result;      LSCPResultSet result;
1874      try {      try {
1875          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1876          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1877          std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();
1878          if (!devices.count(MIDIDeviceId)) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(MIDIDeviceId));          if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1879          MidiInputDevice* pDevice = devices[MIDIDeviceId];          MidiInputDevice* pDevice = devices[MIDIDeviceId];
1880          pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (MidiInputPort::midi_chan_t) MIDIChannel);          pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
1881      }      }
1882      catch (LinuxSamplerException e) {      catch (Exception e) {
1883           result.Error(e);           result.Error(e);
1884      }      }
1885      return result.Produce();      return result.Produce();
# Line 1368  String LSCPServer::SetVolume(double dVol Line 1893  String LSCPServer::SetVolume(double dVol
1893      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
1894      LSCPResultSet result;      LSCPResultSet result;
1895      try {      try {
1896          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));  
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw LinuxSamplerException("No engine type assigned to sampler channel");  
1897          pEngineChannel->Volume(dVolume);          pEngineChannel->Volume(dVolume);
1898      }      }
1899      catch (LinuxSamplerException e) {      catch (Exception e) {
1900           result.Error(e);           result.Error(e);
1901      }      }
1902      return result.Produce();      return result.Produce();
1903  }  }
1904    
1905  /**  /**
1906     * Will be called by the parser to mute/unmute particular sampler channel.
1907     */
1908    String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
1909        dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
1910        LSCPResultSet result;
1911        try {
1912            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1913    
1914            if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
1915            else pEngineChannel->SetMute(1);
1916        } catch (Exception e) {
1917            result.Error(e);
1918        }
1919        return result.Produce();
1920    }
1921    
1922    /**
1923     * Will be called by the parser to solo particular sampler channel.
1924     */
1925    String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
1926        dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
1927        LSCPResultSet result;
1928        try {
1929            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1930    
1931            bool oldSolo = pEngineChannel->GetSolo();
1932            bool hadSoloChannel = HasSoloChannel();
1933    
1934            pEngineChannel->SetSolo(bSolo);
1935    
1936            if(!oldSolo && bSolo) {
1937                if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
1938                if(!hadSoloChannel) MuteNonSoloChannels();
1939            }
1940    
1941            if(oldSolo && !bSolo) {
1942                if(!HasSoloChannel()) UnmuteChannels();
1943                else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
1944            }
1945        } catch (Exception e) {
1946            result.Error(e);
1947        }
1948        return result.Produce();
1949    }
1950    
1951    /**
1952     * Determines whether there is at least one solo channel in the channel list.
1953     *
1954     * @returns true if there is at least one solo channel in the channel list,
1955     * false otherwise.
1956     */
1957    bool LSCPServer::HasSoloChannel() {
1958        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1959        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1960        for (; iter != channels.end(); iter++) {
1961            EngineChannel* c = iter->second->GetEngineChannel();
1962            if(c && c->GetSolo()) return true;
1963        }
1964    
1965        return false;
1966    }
1967    
1968    /**
1969     * Mutes all unmuted non-solo channels. Notice that the channels are muted
1970     * with -1 which indicates that they are muted because of the presence
1971     * of a solo channel(s). Channels muted with -1 will be automatically unmuted
1972     * when there are no solo channels left.
1973     */
1974    void LSCPServer::MuteNonSoloChannels() {
1975        dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
1976        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1977        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1978        for (; iter != channels.end(); iter++) {
1979            EngineChannel* c = iter->second->GetEngineChannel();
1980            if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
1981        }
1982    }
1983    
1984    /**
1985     * Unmutes all channels that are muted because of the presence
1986     * of a solo channel(s).
1987     */
1988    void  LSCPServer::UnmuteChannels() {
1989        dmsg(2,("LSCPServer: UnmuteChannels()\n"));
1990        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1991        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1992        for (; iter != channels.end(); iter++) {
1993            EngineChannel* c = iter->second->GetEngineChannel();
1994            if(c && c->GetMute() == -1) c->SetMute(0);
1995        }
1996    }
1997    
1998    String LSCPServer::AddOrReplaceMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg, String EngineType, String InstrumentFile, uint InstrumentIndex, float Volume, MidiInstrumentMapper::mode_t LoadMode, String Name, bool bModal) {
1999        dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
2000    
2001        midi_prog_index_t idx;
2002        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2003        idx.midi_bank_lsb = MidiBank & 0x7f;
2004        idx.midi_prog     = MidiProg;
2005    
2006        MidiInstrumentMapper::entry_t entry;
2007        entry.EngineName      = EngineType;
2008        entry.InstrumentFile  = InstrumentFile;
2009        entry.InstrumentIndex = InstrumentIndex;
2010        entry.LoadMode        = LoadMode;
2011        entry.Volume          = Volume;
2012        entry.Name            = Name;
2013    
2014        LSCPResultSet result;
2015        try {
2016            // PERSISTENT mapping commands might block for a long time, so in
2017            // that case we add/replace the mapping in another thread in case
2018            // the NON_MODAL argument was supplied, non persistent mappings
2019            // should return immediately, so we don't need to do that for them
2020            bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
2021            MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
2022        } catch (Exception e) {
2023            result.Error(e);
2024        }
2025        return result.Produce();
2026    }
2027    
2028    String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2029        dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
2030    
2031        midi_prog_index_t idx;
2032        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2033        idx.midi_bank_lsb = MidiBank & 0x7f;
2034        idx.midi_prog     = MidiProg;
2035    
2036        LSCPResultSet result;
2037        try {
2038            MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
2039        } catch (Exception e) {
2040            result.Error(e);
2041        }
2042        return result.Produce();
2043    }
2044    
2045    String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
2046        dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
2047        LSCPResultSet result;
2048        try {
2049            result.Add(MidiInstrumentMapper::GetInstrumentCount(MidiMapID));
2050        } catch (Exception e) {
2051            result.Error(e);
2052        }
2053        return result.Produce();
2054    }
2055    
2056    
2057    String LSCPServer::GetAllMidiInstrumentMappings() {
2058        dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
2059        LSCPResultSet result;
2060        try {
2061            result.Add(MidiInstrumentMapper::GetInstrumentCount());
2062        } catch (Exception e) {
2063            result.Error(e);
2064        }
2065        return result.Produce();
2066    }
2067    
2068    String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2069        dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
2070        LSCPResultSet result;
2071        try {
2072            MidiInstrumentMapper::entry_t entry = MidiInstrumentMapper::GetEntry(MidiMapID, MidiBank, MidiProg);
2073            // convert the filename into the correct encoding as defined for LSCP
2074            // (especially in terms of special characters -> escape sequences)
2075    #if WIN32
2076            const String instrumentFileName = Path::fromWindows(entry.InstrumentFile).toLscp();
2077    #else
2078            // assuming POSIX
2079            const String instrumentFileName = Path::fromPosix(entry.InstrumentFile).toLscp();
2080    #endif
2081    
2082            result.Add("NAME", _escapeLscpResponse(entry.Name));
2083            result.Add("ENGINE_NAME", entry.EngineName);
2084            result.Add("INSTRUMENT_FILE", instrumentFileName);
2085            result.Add("INSTRUMENT_NR", (int) entry.InstrumentIndex);
2086            String instrumentName;
2087            Engine* pEngine = EngineFactory::Create(entry.EngineName);
2088            if (pEngine) {
2089                if (pEngine->GetInstrumentManager()) {
2090                    InstrumentManager::instrument_id_t instrID;
2091                    instrID.FileName = entry.InstrumentFile;
2092                    instrID.Index    = entry.InstrumentIndex;
2093                    instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
2094                }
2095                EngineFactory::Destroy(pEngine);
2096            }
2097            result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2098            switch (entry.LoadMode) {
2099                case MidiInstrumentMapper::ON_DEMAND:
2100                    result.Add("LOAD_MODE", "ON_DEMAND");
2101                    break;
2102                case MidiInstrumentMapper::ON_DEMAND_HOLD:
2103                    result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2104                    break;
2105                case MidiInstrumentMapper::PERSISTENT:
2106                    result.Add("LOAD_MODE", "PERSISTENT");
2107                    break;
2108                default:
2109                    throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2110            }
2111            result.Add("VOLUME", entry.Volume);
2112        } catch (Exception e) {
2113            result.Error(e);
2114        }
2115        return result.Produce();
2116    }
2117    
2118    String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
2119        dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
2120        LSCPResultSet result;
2121        try {
2122            String s;
2123            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
2124            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2125            for (; iter != mappings.end(); iter++) {
2126                if (s.size()) s += ",";
2127                s += "{" + ToString(MidiMapID) + ","
2128                         + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2129                         + ToString(int(iter->first.midi_prog)) + "}";
2130            }
2131            result.Add(s);
2132        } catch (Exception e) {
2133            result.Error(e);
2134        }
2135        return result.Produce();
2136    }
2137    
2138    String LSCPServer::ListAllMidiInstrumentMappings() {
2139        dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
2140        LSCPResultSet result;
2141        try {
2142            std::vector<int> maps = MidiInstrumentMapper::Maps();
2143            String s;
2144            for (int i = 0; i < maps.size(); i++) {
2145                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
2146                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2147                for (; iter != mappings.end(); iter++) {
2148                    if (s.size()) s += ",";
2149                    s += "{" + ToString(maps[i]) + ","
2150                             + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2151                             + ToString(int(iter->first.midi_prog)) + "}";
2152                }
2153            }
2154            result.Add(s);
2155        } catch (Exception e) {
2156            result.Error(e);
2157        }
2158        return result.Produce();
2159    }
2160    
2161    String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
2162        dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
2163        LSCPResultSet result;
2164        try {
2165            MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
2166        } catch (Exception e) {
2167            result.Error(e);
2168        }
2169        return result.Produce();
2170    }
2171    
2172    String LSCPServer::ClearAllMidiInstrumentMappings() {
2173        dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
2174        LSCPResultSet result;
2175        try {
2176            std::vector<int> maps = MidiInstrumentMapper::Maps();
2177            for (int i = 0; i < maps.size(); i++)
2178                MidiInstrumentMapper::RemoveAllEntries(maps[i]);
2179        } catch (Exception e) {
2180            result.Error(e);
2181        }
2182        return result.Produce();
2183    }
2184    
2185    String LSCPServer::AddMidiInstrumentMap(String MapName) {
2186        dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
2187        LSCPResultSet result;
2188        try {
2189            int MapID = MidiInstrumentMapper::AddMap(MapName);
2190            result = LSCPResultSet(MapID);
2191        } catch (Exception e) {
2192            result.Error(e);
2193        }
2194        return result.Produce();
2195    }
2196    
2197    String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
2198        dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
2199        LSCPResultSet result;
2200        try {
2201            MidiInstrumentMapper::RemoveMap(MidiMapID);
2202        } catch (Exception e) {
2203            result.Error(e);
2204        }
2205        return result.Produce();
2206    }
2207    
2208    String LSCPServer::RemoveAllMidiInstrumentMaps() {
2209        dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
2210        LSCPResultSet result;
2211        try {
2212            MidiInstrumentMapper::RemoveAllMaps();
2213        } catch (Exception e) {
2214            result.Error(e);
2215        }
2216        return result.Produce();
2217    }
2218    
2219    String LSCPServer::GetMidiInstrumentMaps() {
2220        dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
2221        LSCPResultSet result;
2222        try {
2223            result.Add(MidiInstrumentMapper::Maps().size());
2224        } catch (Exception e) {
2225            result.Error(e);
2226        }
2227        return result.Produce();
2228    }
2229    
2230    String LSCPServer::ListMidiInstrumentMaps() {
2231        dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
2232        LSCPResultSet result;
2233        try {
2234            std::vector<int> maps = MidiInstrumentMapper::Maps();
2235            String sList;
2236            for (int i = 0; i < maps.size(); i++) {
2237                if (sList != "") sList += ",";
2238                sList += ToString(maps[i]);
2239            }
2240            result.Add(sList);
2241        } catch (Exception e) {
2242            result.Error(e);
2243        }
2244        return result.Produce();
2245    }
2246    
2247    String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
2248        dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2249        LSCPResultSet result;
2250        try {
2251            result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2252            result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2253        } catch (Exception e) {
2254            result.Error(e);
2255        }
2256        return result.Produce();
2257    }
2258    
2259    String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2260        dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2261        LSCPResultSet result;
2262        try {
2263            MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2264        } catch (Exception e) {
2265            result.Error(e);
2266        }
2267        return result.Produce();
2268    }
2269    
2270    /**
2271     * Set the MIDI instrument map the given sampler channel shall use for
2272     * handling MIDI program change messages. There are the following two
2273     * special (negative) values:
2274     *
2275     *    - (-1) :  set to NONE (ignore program changes)
2276     *    - (-2) :  set to DEFAULT map
2277     */
2278    String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2279        dmsg(2,("LSCPServer: SetChannelMap()\n"));
2280        LSCPResultSet result;
2281        try {
2282            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2283    
2284            if      (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2285            else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2286            else                      pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2287        } catch (Exception e) {
2288            result.Error(e);
2289        }
2290        return result.Produce();
2291    }
2292    
2293    String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2294        dmsg(2,("LSCPServer: CreateFxSend()\n"));
2295        LSCPResultSet result;
2296        try {
2297            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2298    
2299            FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2300            if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2301    
2302            result = LSCPResultSet(pFxSend->Id()); // success
2303        } catch (Exception e) {
2304            result.Error(e);
2305        }
2306        return result.Produce();
2307    }
2308    
2309    String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2310        dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2311        LSCPResultSet result;
2312        try {
2313            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2314    
2315            FxSend* pFxSend = NULL;
2316            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2317                if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2318                    pFxSend = pEngineChannel->GetFxSend(i);
2319                    break;
2320                }
2321            }
2322            if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2323            pEngineChannel->RemoveFxSend(pFxSend);
2324        } catch (Exception e) {
2325            result.Error(e);
2326        }
2327        return result.Produce();
2328    }
2329    
2330    String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2331        dmsg(2,("LSCPServer: GetFxSends()\n"));
2332        LSCPResultSet result;
2333        try {
2334            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2335    
2336            result.Add(pEngineChannel->GetFxSendCount());
2337        } catch (Exception e) {
2338            result.Error(e);
2339        }
2340        return result.Produce();
2341    }
2342    
2343    String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2344        dmsg(2,("LSCPServer: ListFxSends()\n"));
2345        LSCPResultSet result;
2346        String list;
2347        try {
2348            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2349    
2350            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2351                FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2352                if (list != "") list += ",";
2353                list += ToString(pFxSend->Id());
2354            }
2355            result.Add(list);
2356        } catch (Exception e) {
2357            result.Error(e);
2358        }
2359        return result.Produce();
2360    }
2361    
2362    FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2363        EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2364    
2365        FxSend* pFxSend = NULL;
2366        for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2367            if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2368                pFxSend = pEngineChannel->GetFxSend(i);
2369                break;
2370            }
2371        }
2372        if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2373        return pFxSend;
2374    }
2375    
2376    String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2377        dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2378        LSCPResultSet result;
2379        try {
2380            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2381            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2382    
2383            // gather audio routing informations
2384            String AudioRouting;
2385            for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2386                if (AudioRouting != "") AudioRouting += ",";
2387                AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2388            }
2389    
2390            const String sEffectRouting =
2391                (pFxSend->DestinationEffectChain() >= 0 && pFxSend->DestinationEffectChainPosition() >= 0)
2392                    ? ToString(pFxSend->DestinationEffectChain()) + "," + ToString(pFxSend->DestinationEffectChainPosition())
2393                    : "NONE";
2394    
2395            // success
2396            result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2397            result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2398            result.Add("LEVEL", ToString(pFxSend->Level()));
2399            result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2400            result.Add("EFFECT", sEffectRouting);
2401        } catch (Exception e) {
2402            result.Error(e);
2403        }
2404        return result.Produce();
2405    }
2406    
2407    String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2408        dmsg(2,("LSCPServer: SetFxSendName()\n"));
2409        LSCPResultSet result;
2410        try {
2411            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2412    
2413            pFxSend->SetName(Name);
2414            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2415        } catch (Exception e) {
2416            result.Error(e);
2417        }
2418        return result.Produce();
2419    }
2420    
2421    String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2422        dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2423        LSCPResultSet result;
2424        try {
2425            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2426    
2427            pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2428            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2429        } catch (Exception e) {
2430            result.Error(e);
2431        }
2432        return result.Produce();
2433    }
2434    
2435    String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2436        dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2437        LSCPResultSet result;
2438        try {
2439            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2440    
2441            pFxSend->SetMidiController(MidiController);
2442            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2443        } catch (Exception e) {
2444            result.Error(e);
2445        }
2446        return result.Produce();
2447    }
2448    
2449    String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2450        dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2451        LSCPResultSet result;
2452        try {
2453            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2454    
2455            pFxSend->SetLevel((float)dLevel);
2456            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2457        } catch (Exception e) {
2458            result.Error(e);
2459        }
2460        return result.Produce();
2461    }
2462    
2463    String LSCPServer::SetFxSendEffect(uint uiSamplerChannel, uint FxSendID, int iSendEffectChain, int iEffectChainPosition) {
2464        dmsg(2,("LSCPServer: SetFxSendEffect(%d,%d)\n", iSendEffectChain, iEffectChainPosition));
2465        LSCPResultSet result;
2466        try {
2467            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2468    
2469            pFxSend->SetDestinationEffect(iSendEffectChain, iEffectChainPosition);
2470            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2471        } catch (Exception e) {
2472            result.Error(e);
2473        }
2474        return result.Produce();
2475    }
2476    
2477    String LSCPServer::GetAvailableEffects() {
2478        dmsg(2,("LSCPServer: GetAvailableEffects()\n"));
2479        LSCPResultSet result;
2480        try {
2481            int n = EffectFactory::AvailableEffectsCount();
2482            result.Add(n);
2483        }
2484        catch (Exception e) {
2485            result.Error(e);
2486        }
2487        return result.Produce();
2488    }
2489    
2490    String LSCPServer::ListAvailableEffects() {
2491        dmsg(2,("LSCPServer: ListAvailableEffects()\n"));
2492        LSCPResultSet result;
2493        String list;
2494        try {
2495            //FIXME: for now we simply enumerate from 0 .. EffectFactory::AvailableEffectsCount() here, in future we should use unique IDs for effects during the whole sampler session. This issue comes into game when the user forces a reload of available effect plugins
2496            int n = EffectFactory::AvailableEffectsCount();
2497            for (int i = 0; i < n; i++) {
2498                if (i) list += ",";
2499                list += ToString(i);
2500            }
2501        }
2502        catch (Exception e) {
2503            result.Error(e);
2504        }
2505        result.Add(list);
2506        return result.Produce();
2507    }
2508    
2509    String LSCPServer::GetEffectInfo(int iEffectIndex) {
2510        dmsg(2,("LSCPServer: GetEffectInfo(%d)\n", iEffectIndex));
2511        LSCPResultSet result;
2512        try {
2513            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2514            if (!pEffectInfo)
2515                throw Exception("There is no effect with index " + ToString(iEffectIndex));
2516    
2517            // convert the filename into the correct encoding as defined for LSCP
2518            // (especially in terms of special characters -> escape sequences)
2519    #if WIN32
2520            const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2521    #else
2522            // assuming POSIX
2523            const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2524    #endif
2525    
2526            result.Add("SYSTEM", pEffectInfo->EffectSystem());
2527            result.Add("MODULE", dllFileName);
2528            result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2529            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2530        }
2531        catch (Exception e) {
2532            result.Error(e);
2533        }
2534        return result.Produce();    
2535    }
2536    
2537    String LSCPServer::GetEffectInstanceInfo(int iEffectInstance) {
2538        dmsg(2,("LSCPServer: GetEffectInstanceInfo(%d)\n", iEffectInstance));
2539        LSCPResultSet result;
2540        try {
2541            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2542            if (!pEffect)
2543                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2544    
2545            EffectInfo* pEffectInfo = pEffect->GetEffectInfo();
2546    
2547            // convert the filename into the correct encoding as defined for LSCP
2548            // (especially in terms of special characters -> escape sequences)
2549    #if WIN32
2550            const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2551    #else
2552            // assuming POSIX
2553            const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2554    #endif
2555    
2556            result.Add("SYSTEM", pEffectInfo->EffectSystem());
2557            result.Add("MODULE", dllFileName);
2558            result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2559            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2560            result.Add("INPUT_CONTROLS", ToString(pEffect->InputControlCount()));
2561        }
2562        catch (Exception e) {
2563            result.Error(e);
2564        }
2565        return result.Produce();
2566    }
2567    
2568    String LSCPServer::GetEffectInstanceInputControlInfo(int iEffectInstance, int iInputControlIndex) {
2569        dmsg(2,("LSCPServer: GetEffectInstanceInputControlInfo(%d,%d)\n", iEffectInstance, iInputControlIndex));
2570        LSCPResultSet result;
2571        try {
2572            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2573            if (!pEffect)
2574                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2575    
2576            EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2577            if (!pEffectControl)
2578                throw Exception(
2579                    "Effect instance " + ToString(iEffectInstance) +
2580                    " does not have an input control with index " +
2581                    ToString(iInputControlIndex)
2582                );
2583    
2584            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectControl->Description()));
2585            result.Add("VALUE", pEffectControl->Value());
2586            if (pEffectControl->MinValue())
2587                 result.Add("RANGE_MIN", *pEffectControl->MinValue());
2588            if (pEffectControl->MaxValue())
2589                 result.Add("RANGE_MAX", *pEffectControl->MaxValue());
2590            if (!pEffectControl->Possibilities().empty())
2591                 result.Add("POSSIBILITIES", pEffectControl->Possibilities());
2592            if (pEffectControl->DefaultValue())
2593                 result.Add("DEFAULT", *pEffectControl->DefaultValue());
2594        } catch (Exception e) {
2595            result.Error(e);
2596        }
2597        return result.Produce();
2598    }
2599    
2600    String LSCPServer::SetEffectInstanceInputControlValue(int iEffectInstance, int iInputControlIndex, double dValue) {
2601        dmsg(2,("LSCPServer: SetEffectInstanceInputControlValue(%d,%d,%f)\n", iEffectInstance, iInputControlIndex, dValue));
2602        LSCPResultSet result;
2603        try {
2604            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2605            if (!pEffect)
2606                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2607    
2608            EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2609            if (!pEffectControl)
2610                throw Exception(
2611                    "Effect instance " + ToString(iEffectInstance) +
2612                    " does not have an input control with index " +
2613                    ToString(iInputControlIndex)
2614                );
2615    
2616            pEffectControl->SetValue(dValue);
2617            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_info, iEffectInstance));
2618        } catch (Exception e) {
2619            result.Error(e);
2620        }
2621        return result.Produce();
2622    }
2623    
2624    String LSCPServer::CreateEffectInstance(int iEffectIndex) {
2625        dmsg(2,("LSCPServer: CreateEffectInstance(%d)\n", iEffectIndex));
2626        LSCPResultSet result;
2627        try {
2628            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2629            if (!pEffectInfo)
2630                throw Exception("There is no effect with index " + ToString(iEffectIndex));
2631            Effect* pEffect = EffectFactory::Create(pEffectInfo);
2632            result = pEffect->ID(); // success
2633            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2634        } catch (Exception e) {
2635            result.Error(e);
2636        }
2637        return result.Produce();
2638    }
2639    
2640    String LSCPServer::CreateEffectInstance(String effectSystem, String module, String effectName) {
2641        dmsg(2,("LSCPServer: CreateEffectInstance('%s','%s','%s')\n", effectSystem.c_str(), module.c_str(), effectName.c_str()));
2642        LSCPResultSet result;
2643        try {
2644            // to allow loading the same LSCP session file on different systems
2645            // successfully, probably with different effect plugin DLL paths or even
2646            // running completely different operating systems, we do the following
2647            // for finding the right effect:
2648            //
2649            // first try to search for an exact match of the effect plugin DLL
2650            // (a.k.a 'module'), to avoid picking the wrong DLL with the same
2651            // effect name ...
2652            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_MATCH_EXACTLY);
2653            // ... if no effect with exactly matchin DLL filename was found, then
2654            // try to lower the restrictions of matching the effect plugin DLL
2655            // filename and try again and again ...
2656            if (!pEffectInfo) {
2657                dmsg(2,("no exact module match, trying MODULE_IGNORE_PATH\n"));
2658                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH);
2659            }
2660            if (!pEffectInfo) {
2661                dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE\n"));
2662                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE);
2663            }
2664            if (!pEffectInfo) {
2665                dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE | MODULE_IGNORE_EXTENSION\n"));
2666                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE | EffectFactory::MODULE_IGNORE_EXTENSION);
2667            }
2668            // ... if there was still no effect found, then completely ignore the
2669            // DLL plugin filename argument and just search for the matching effect
2670            // system type and effect name
2671            if (!pEffectInfo) {
2672                dmsg(2,("no module match, trying MODULE_IGNORE_ALL\n"));
2673                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_ALL);
2674            }
2675            if (!pEffectInfo)
2676                throw Exception("There is no such effect '" + effectSystem + "' '" + module + "' '" + effectName + "'");
2677    
2678            Effect* pEffect = EffectFactory::Create(pEffectInfo);
2679            result = LSCPResultSet(pEffect->ID());
2680            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2681        } catch (Exception e) {
2682            result.Error(e);
2683        }
2684        return result.Produce();
2685    }
2686    
2687    String LSCPServer::DestroyEffectInstance(int iEffectInstance) {
2688        dmsg(2,("LSCPServer: DestroyEffectInstance(%d)\n", iEffectInstance));
2689        LSCPResultSet result;
2690        try {
2691            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2692            if (!pEffect)
2693                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2694            EffectFactory::Destroy(pEffect);
2695            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2696        } catch (Exception e) {
2697            result.Error(e);
2698        }
2699        return result.Produce();
2700    }
2701    
2702    String LSCPServer::GetEffectInstances() {
2703        dmsg(2,("LSCPServer: GetEffectInstances()\n"));
2704        LSCPResultSet result;
2705        try {
2706            int n = EffectFactory::EffectInstancesCount();
2707            result.Add(n);
2708        } catch (Exception e) {
2709            result.Error(e);
2710        }
2711        return result.Produce();
2712    }
2713    
2714    String LSCPServer::ListEffectInstances() {
2715        dmsg(2,("LSCPServer: ListEffectInstances()\n"));
2716        LSCPResultSet result;
2717        String list;
2718        try {
2719            int n = EffectFactory::EffectInstancesCount();
2720            for (int i = 0; i < n; i++) {
2721                Effect* pEffect = EffectFactory::GetEffectInstance(i);
2722                if (i) list += ",";
2723                list += ToString(pEffect->ID());
2724            }
2725        } catch (Exception e) {
2726            result.Error(e);
2727        }
2728        result.Add(list);
2729        return result.Produce();
2730    }
2731    
2732    String LSCPServer::GetSendEffectChains(int iAudioOutputDevice) {
2733        dmsg(2,("LSCPServer: GetSendEffectChains(%d)\n", iAudioOutputDevice));
2734        LSCPResultSet result;
2735        try {
2736            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2737            if (!devices.count(iAudioOutputDevice))
2738                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2739            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2740            int n = pDevice->SendEffectChainCount();
2741            result.Add(n);
2742        } catch (Exception e) {
2743            result.Error(e);
2744        }
2745        return result.Produce();
2746    }
2747    
2748    String LSCPServer::ListSendEffectChains(int iAudioOutputDevice) {
2749        dmsg(2,("LSCPServer: ListSendEffectChains(%d)\n", iAudioOutputDevice));
2750        LSCPResultSet result;
2751        String list;
2752        try {
2753            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2754            if (!devices.count(iAudioOutputDevice))
2755                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2756            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2757            int n = pDevice->SendEffectChainCount();
2758            for (int i = 0; i < n; i++) {
2759                EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2760                if (i) list += ",";
2761                list += ToString(pEffectChain->ID());
2762            }
2763        } catch (Exception e) {
2764            result.Error(e);
2765        }
2766        result.Add(list);
2767        return result.Produce();
2768    }
2769    
2770    String LSCPServer::AddSendEffectChain(int iAudioOutputDevice) {
2771        dmsg(2,("LSCPServer: AddSendEffectChain(%d)\n", iAudioOutputDevice));
2772        LSCPResultSet result;
2773        try {
2774            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2775            if (!devices.count(iAudioOutputDevice))
2776                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2777            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2778            EffectChain* pEffectChain = pDevice->AddSendEffectChain();
2779            result = pEffectChain->ID();
2780            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2781        } catch (Exception e) {
2782            result.Error(e);
2783        }
2784        return result.Produce();
2785    }
2786    
2787    String LSCPServer::RemoveSendEffectChain(int iAudioOutputDevice, int iSendEffectChain) {
2788        dmsg(2,("LSCPServer: RemoveSendEffectChain(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2789        LSCPResultSet result;
2790        try {
2791            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2792            if (!devices.count(iAudioOutputDevice))
2793                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2794    
2795            std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
2796            std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
2797            std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
2798            for (; itEngineChannel != itEnd; ++itEngineChannel) {
2799                AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
2800                if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
2801                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
2802                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
2803                        if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain) {
2804                            throw Exception("The effect chain is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
2805                        }
2806                    }
2807                }
2808            }
2809    
2810            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2811            for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
2812                EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2813                if (pEffectChain->ID() == iSendEffectChain) {
2814                    pDevice->RemoveSendEffectChain(i);
2815                    LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2816                    return result.Produce();
2817                }
2818            }
2819            throw Exception(
2820                "There is no send effect chain with ID " +
2821                ToString(iSendEffectChain) + " for audio output device " +
2822                ToString(iAudioOutputDevice) + "."
2823            );
2824        } catch (Exception e) {
2825            result.Error(e);
2826        }
2827        return result.Produce();
2828    }
2829    
2830    static EffectChain* _getSendEffectChain(Sampler* pSampler, int iAudioOutputDevice, int iSendEffectChain) throw (Exception) {
2831        std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2832        if (!devices.count(iAudioOutputDevice))
2833            throw Exception(
2834                "There is no audio output device with index " +
2835                ToString(iAudioOutputDevice) + "."
2836            );
2837        AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2838        EffectChain* pEffectChain = pDevice->SendEffectChainByID(iSendEffectChain);
2839        if(pEffectChain != NULL) return pEffectChain;
2840        throw Exception(
2841            "There is no send effect chain with ID " +
2842            ToString(iSendEffectChain) + " for audio output device " +
2843            ToString(iAudioOutputDevice) + "."
2844        );
2845    }
2846    
2847    String LSCPServer::GetSendEffectChainInfo(int iAudioOutputDevice, int iSendEffectChain) {
2848        dmsg(2,("LSCPServer: GetSendEffectChainInfo(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2849        LSCPResultSet result;
2850        try {
2851            EffectChain* pEffectChain =
2852                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2853            String sEffectSequence;
2854            for (int i = 0; i < pEffectChain->EffectCount(); i++) {
2855                if (i) sEffectSequence += ",";
2856                sEffectSequence += ToString(pEffectChain->GetEffect(i)->ID());
2857            }
2858            result.Add("EFFECT_COUNT", pEffectChain->EffectCount());
2859            result.Add("EFFECT_SEQUENCE", sEffectSequence);
2860        } catch (Exception e) {
2861            result.Error(e);
2862        }
2863        return result.Produce();
2864    }
2865    
2866    String LSCPServer::AppendSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectInstance) {
2867        dmsg(2,("LSCPServer: AppendSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectInstance));
2868        LSCPResultSet result;
2869        try {
2870            EffectChain* pEffectChain =
2871                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2872            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2873            if (!pEffect)
2874                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2875            pEffectChain->AppendEffect(pEffect);
2876            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2877        } catch (Exception e) {
2878            result.Error(e);
2879        }
2880        return result.Produce();
2881    }
2882    
2883    String LSCPServer::InsertSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition, int iEffectInstance) {
2884        dmsg(2,("LSCPServer: InsertSendEffectChainEffect(%d,%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition, iEffectInstance));
2885        LSCPResultSet result;
2886        try {
2887            EffectChain* pEffectChain =
2888                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2889            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2890            if (!pEffect)
2891                throw Exception("There is no effect instance with index " + ToString(iEffectInstance));
2892            pEffectChain->InsertEffect(pEffect, iEffectChainPosition);
2893            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2894        } catch (Exception e) {
2895            result.Error(e);
2896        }
2897        return result.Produce();
2898    }
2899    
2900    String LSCPServer::RemoveSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition) {
2901        dmsg(2,("LSCPServer: RemoveSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition));
2902        LSCPResultSet result;
2903        try {
2904            EffectChain* pEffectChain =
2905                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2906    
2907            std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
2908            std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
2909            std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
2910            for (; itEngineChannel != itEnd; ++itEngineChannel) {
2911                AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
2912                if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
2913                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
2914                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
2915                        if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain && fxs->DestinationEffectChainPosition() == iEffectChainPosition) {
2916                            throw Exception("The effect instance is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
2917                        }
2918                    }
2919                }
2920            }
2921    
2922            pEffectChain->RemoveEffect(iEffectChainPosition);
2923            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2924        } catch (Exception e) {
2925            result.Error(e);
2926        }
2927        return result.Produce();
2928    }
2929    
2930    String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
2931        dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
2932        LSCPResultSet result;
2933        try {
2934            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2935            if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
2936            Engine* pEngine = pEngineChannel->GetEngine();
2937            InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
2938            if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
2939            InstrumentManager::instrument_id_t instrumentID;
2940            instrumentID.FileName = pEngineChannel->InstrumentFileName();
2941            instrumentID.Index    = pEngineChannel->InstrumentIndex();
2942            pInstrumentManager->LaunchInstrumentEditor(instrumentID);
2943        } catch (Exception e) {
2944            result.Error(e);
2945        }
2946        return result.Produce();
2947    }
2948    
2949    String LSCPServer::SendChannelMidiData(String MidiMsg, uint uiSamplerChannel, uint Arg1, uint Arg2) {
2950        dmsg(2,("LSCPServer: SendChannelMidiData(MidiMsg=%s,uiSamplerChannel=%d,Arg1=%d,Arg2=%d)\n", MidiMsg.c_str(), uiSamplerChannel, Arg1, Arg2));
2951        LSCPResultSet result;
2952        try {
2953            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2954    
2955            if (Arg1 > 127 || Arg2 > 127) {
2956                throw Exception("Invalid MIDI message");
2957            }
2958    
2959            VirtualMidiDevice* pMidiDevice = NULL;
2960            std::vector<EventHandler::midi_listener_entry>::iterator iter = eventHandler.channelMidiListeners.begin();
2961            for (; iter != eventHandler.channelMidiListeners.end(); ++iter) {
2962                if ((*iter).pEngineChannel == pEngineChannel) {
2963                    pMidiDevice = (*iter).pMidiListener;
2964                    break;
2965                }
2966            }
2967            
2968            if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
2969    
2970            if (MidiMsg == "NOTE_ON") {
2971                pMidiDevice->SendNoteOnToDevice(Arg1, Arg2);
2972                bool b = pMidiDevice->SendNoteOnToSampler(Arg1, Arg2);
2973                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2974            } else if (MidiMsg == "NOTE_OFF") {
2975                pMidiDevice->SendNoteOffToDevice(Arg1, Arg2);
2976                bool b = pMidiDevice->SendNoteOffToSampler(Arg1, Arg2);
2977                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2978            } else if (MidiMsg == "CC") {
2979                pMidiDevice->SendCCToDevice(Arg1, Arg2);
2980                bool b = pMidiDevice->SendCCToSampler(Arg1, Arg2);
2981                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2982            } else {
2983                throw Exception("Unknown MIDI message type: " + MidiMsg);
2984            }
2985        } catch (Exception e) {
2986            result.Error(e);
2987        }
2988        return result.Produce();
2989    }
2990    
2991    /**
2992   * Will be called by the parser to reset a particular sampler channel.   * Will be called by the parser to reset a particular sampler channel.
2993   */   */
2994  String LSCPServer::ResetChannel(uint uiSamplerChannel) {  String LSCPServer::ResetChannel(uint uiSamplerChannel) {
2995      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
2996      LSCPResultSet result;      LSCPResultSet result;
2997      try {      try {
2998          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2999          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          pEngineChannel->Reset();
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw LinuxSamplerException("No engine type assigned to sampler channel");  
         pEngineChannel->GetEngine()->Reset();  
3000      }      }
3001      catch (LinuxSamplerException e) {      catch (Exception e) {
3002           result.Error(e);           result.Error(e);
3003      }      }
3004      return result.Produce();      return result.Produce();
# Line 1415  String LSCPServer::ResetSampler() { Line 3020  String LSCPServer::ResetSampler() {
3020   */   */
3021  String LSCPServer::GetServerInfo() {  String LSCPServer::GetServerInfo() {
3022      dmsg(2,("LSCPServer: GetServerInfo()\n"));      dmsg(2,("LSCPServer: GetServerInfo()\n"));
3023        const std::string description =
3024            _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
3025        LSCPResultSet result;
3026        result.Add("DESCRIPTION", description);
3027        result.Add("VERSION", VERSION);
3028        result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
3029    #if HAVE_SQLITE3
3030        result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
3031    #else
3032        result.Add("INSTRUMENTS_DB_SUPPORT", "no");
3033    #endif
3034    
3035        return result.Produce();
3036    }
3037    
3038    /**
3039     * Will be called by the parser to return the current number of all active streams.
3040     */
3041    String LSCPServer::GetTotalStreamCount() {
3042        dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
3043      LSCPResultSet result;      LSCPResultSet result;
3044      result.Add("DESCRIPTION", "LinuxSampler - modular, streaming capable sampler");      result.Add(pSampler->GetDiskStreamCount());
     result.Add("VERSION", VERSION);      
3045      return result.Produce();      return result.Produce();
3046  }  }
3047    
3048  /**  /**
3049     * Will be called by the parser to return the current number of all active voices.
3050     */
3051    String LSCPServer::GetTotalVoiceCount() {
3052        dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
3053        LSCPResultSet result;
3054        result.Add(pSampler->GetVoiceCount());
3055        return result.Produce();
3056    }
3057    
3058    /**
3059     * Will be called by the parser to return the maximum number of voices.
3060     */
3061    String LSCPServer::GetTotalVoiceCountMax() {
3062        dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3063        LSCPResultSet result;
3064        result.Add(EngineFactory::EngineInstances().size() * GLOBAL_MAX_VOICES);
3065        return result.Produce();
3066    }
3067    
3068    /**
3069     * Will be called by the parser to return the sampler global maximum
3070     * allowed number of voices.
3071     */
3072    String LSCPServer::GetGlobalMaxVoices() {
3073        dmsg(2,("LSCPServer: GetGlobalMaxVoices()\n"));
3074        LSCPResultSet result;
3075        result.Add(GLOBAL_MAX_VOICES);
3076        return result.Produce();
3077    }
3078    
3079    /**
3080     * Will be called by the parser to set the sampler global maximum number of
3081     * voices.
3082     */
3083    String LSCPServer::SetGlobalMaxVoices(int iVoices) {
3084        dmsg(2,("LSCPServer: SetGlobalMaxVoices(%d)\n", iVoices));
3085        LSCPResultSet result;
3086        try {
3087            if (iVoices < 1) throw Exception("Maximum voices may not be less than 1");
3088            GLOBAL_MAX_VOICES = iVoices; // see common/global_private.cpp
3089            const std::set<Engine*>& engines = EngineFactory::EngineInstances();
3090            if (engines.size() > 0) {
3091                std::set<Engine*>::iterator iter = engines.begin();
3092                std::set<Engine*>::iterator end  = engines.end();
3093                for (; iter != end; ++iter) {
3094                    (*iter)->SetMaxVoices(iVoices);
3095                }
3096            }
3097            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOICES", GLOBAL_MAX_VOICES));
3098        } catch (Exception e) {
3099            result.Error(e);
3100        }
3101        return result.Produce();
3102    }
3103    
3104    /**
3105     * Will be called by the parser to return the sampler global maximum
3106     * allowed number of disk streams.
3107     */
3108    String LSCPServer::GetGlobalMaxStreams() {
3109        dmsg(2,("LSCPServer: GetGlobalMaxStreams()\n"));
3110        LSCPResultSet result;
3111        result.Add(GLOBAL_MAX_STREAMS);
3112        return result.Produce();
3113    }
3114    
3115    /**
3116     * Will be called by the parser to set the sampler global maximum number of
3117     * disk streams.
3118     */
3119    String LSCPServer::SetGlobalMaxStreams(int iStreams) {
3120        dmsg(2,("LSCPServer: SetGlobalMaxStreams(%d)\n", iStreams));
3121        LSCPResultSet result;
3122        try {
3123            if (iStreams < 0) throw Exception("Maximum disk streams may not be negative");
3124            GLOBAL_MAX_STREAMS = iStreams; // see common/global_private.cpp
3125            const std::set<Engine*>& engines = EngineFactory::EngineInstances();
3126            if (engines.size() > 0) {
3127                std::set<Engine*>::iterator iter = engines.begin();
3128                std::set<Engine*>::iterator end  = engines.end();
3129                for (; iter != end; ++iter) {
3130                    (*iter)->SetMaxDiskStreams(iStreams);
3131                }
3132            }
3133            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "STREAMS", GLOBAL_MAX_STREAMS));
3134        } catch (Exception e) {
3135            result.Error(e);
3136        }
3137        return result.Produce();
3138    }
3139    
3140    String LSCPServer::GetGlobalVolume() {
3141        LSCPResultSet result;
3142        result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
3143        return result.Produce();
3144    }
3145    
3146    String LSCPServer::SetGlobalVolume(double dVolume) {
3147        LSCPResultSet result;
3148        try {
3149            if (dVolume < 0) throw Exception("Volume may not be negative");
3150            GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3151            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3152        } catch (Exception e) {
3153            result.Error(e);
3154        }
3155        return result.Produce();
3156    }
3157    
3158    String LSCPServer::GetFileInstruments(String Filename) {
3159        dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
3160        LSCPResultSet result;
3161        try {
3162            VerifyFile(Filename);
3163        } catch (Exception e) {
3164            result.Error(e);
3165            return result.Produce();
3166        }
3167        // try to find a sampler engine that can handle the file
3168        bool bFound = false;
3169        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3170        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3171            Engine* pEngine = NULL;
3172            try {
3173                pEngine = EngineFactory::Create(engineTypes[i]);
3174                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3175                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3176                if (pManager) {
3177                    std::vector<InstrumentManager::instrument_id_t> IDs =
3178                        pManager->GetInstrumentFileContent(Filename);
3179                    // return the amount of instruments in the file
3180                    result.Add(IDs.size());
3181                    // no more need to ask other engine types
3182                    bFound = true;
3183                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3184            } catch (Exception e) {
3185                // NOOP, as exception is thrown if engine doesn't support file
3186            }
3187            if (pEngine) EngineFactory::Destroy(pEngine);
3188        }
3189    
3190        if (!bFound) result.Error("Unknown file format");
3191        return result.Produce();
3192    }
3193    
3194    String LSCPServer::ListFileInstruments(String Filename) {
3195        dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
3196        LSCPResultSet result;
3197        try {
3198            VerifyFile(Filename);
3199        } catch (Exception e) {
3200            result.Error(e);
3201            return result.Produce();
3202        }
3203        // try to find a sampler engine that can handle the file
3204        bool bFound = false;
3205        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3206        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3207            Engine* pEngine = NULL;
3208            try {
3209                pEngine = EngineFactory::Create(engineTypes[i]);
3210                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3211                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3212                if (pManager) {
3213                    std::vector<InstrumentManager::instrument_id_t> IDs =
3214                        pManager->GetInstrumentFileContent(Filename);
3215                    // return a list of IDs of the instruments in the file
3216                    String s;
3217                    for (int j = 0; j < IDs.size(); j++) {
3218                        if (s.size()) s += ",";
3219                        s += ToString(IDs[j].Index);
3220                    }
3221                    result.Add(s);
3222                    // no more need to ask other engine types
3223                    bFound = true;
3224                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3225            } catch (Exception e) {
3226                // NOOP, as exception is thrown if engine doesn't support file
3227            }
3228            if (pEngine) EngineFactory::Destroy(pEngine);
3229        }
3230    
3231        if (!bFound) result.Error("Unknown file format");
3232        return result.Produce();
3233    }
3234    
3235    String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
3236        dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
3237        LSCPResultSet result;
3238        try {
3239            VerifyFile(Filename);
3240        } catch (Exception e) {
3241            result.Error(e);
3242            return result.Produce();
3243        }
3244        InstrumentManager::instrument_id_t id;
3245        id.FileName = Filename;
3246        id.Index    = InstrumentID;
3247        // try to find a sampler engine that can handle the file
3248        bool bFound = false;
3249        bool bFatalErr = false;
3250        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3251        for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
3252            Engine* pEngine = NULL;
3253            try {
3254                pEngine = EngineFactory::Create(engineTypes[i]);
3255                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3256                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3257                if (pManager) {
3258                    // check if the instrument index is valid
3259                    // FIXME: this won't work if an engine only supports parts of the instrument file
3260                    std::vector<InstrumentManager::instrument_id_t> IDs =
3261                        pManager->GetInstrumentFileContent(Filename);
3262                    if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
3263                        std::stringstream ss;
3264                        ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
3265                        bFatalErr = true;
3266                        throw Exception(ss.str());
3267                    }
3268                    // get the info of the requested instrument
3269                    InstrumentManager::instrument_info_t info =
3270                        pManager->GetInstrumentInfo(id);
3271                    // return detailed informations about the file
3272                    result.Add("NAME", info.InstrumentName);
3273                    result.Add("FORMAT_FAMILY", engineTypes[i]);
3274                    result.Add("FORMAT_VERSION", info.FormatVersion);
3275                    result.Add("PRODUCT", info.Product);
3276                    result.Add("ARTISTS", info.Artists);
3277    
3278                    std::stringstream ss;
3279                    bool b = false;
3280                    for (int i = 0; i < 128; i++) {
3281                        if (info.KeyBindings[i]) {
3282                            if (b) ss << ',';
3283                            ss << i; b = true;
3284                        }
3285                    }
3286                    result.Add("KEY_BINDINGS", ss.str());
3287    
3288                    b = false;
3289                    std::stringstream ss2;
3290                    for (int i = 0; i < 128; i++) {
3291                        if (info.KeySwitchBindings[i]) {
3292                            if (b) ss2 << ',';
3293                            ss2 << i; b = true;
3294                        }
3295                    }
3296                    result.Add("KEYSWITCH_BINDINGS", ss2.str());
3297                    // no more need to ask other engine types
3298                    bFound = true;
3299                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3300            } catch (Exception e) {
3301                // usually NOOP, as exception is thrown if engine doesn't support file
3302                if (bFatalErr) result.Error(e);
3303            }
3304            if (pEngine) EngineFactory::Destroy(pEngine);
3305        }
3306    
3307        if (!bFound && !bFatalErr) result.Error("Unknown file format");
3308        return result.Produce();
3309    }
3310    
3311    void LSCPServer::VerifyFile(String Filename) {
3312        #if WIN32
3313        WIN32_FIND_DATA win32FileAttributeData;
3314        BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
3315        if (!res) {
3316            std::stringstream ss;
3317            ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
3318            throw Exception(ss.str());
3319        }
3320        if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
3321            throw Exception("Directory is specified");
3322        }
3323        #else
3324        File f(Filename);
3325        if(!f.Exist()) throw Exception(f.GetErrorMsg());
3326        if (f.IsDirectory()) throw Exception("Directory is specified");
3327        #endif
3328    }
3329    
3330    /**
3331   * 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
3332   * server for receiving event messages.   * server for receiving event messages.
3333   */   */
# Line 1447  String LSCPServer::UnsubscribeNotificati Line 3353  String LSCPServer::UnsubscribeNotificati
3353      return result.Produce();      return result.Produce();
3354  }  }
3355    
3356  static int select_callback(void * lscpResultSet, int argc,  String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3357                          char **argv, char **azColName)      dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3358  {      LSCPResultSet result;
3359      LSCPResultSet* resultSet = (LSCPResultSet*) lscpResultSet;  #if HAVE_SQLITE3
3360      resultSet->Add(argc, argv);      try {
3361      return 0;          InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
3362        } catch (Exception e) {
3363             result.Error(e);
3364        }
3365    #else
3366        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3367    #endif
3368        return result.Produce();
3369    }
3370    
3371    String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3372        dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3373        LSCPResultSet result;
3374    #if HAVE_SQLITE3
3375        try {
3376            InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3377        } catch (Exception e) {
3378             result.Error(e);
3379        }
3380    #else
3381        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3382    #endif
3383        return result.Produce();
3384    }
3385    
3386    String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3387        dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3388        LSCPResultSet result;
3389    #if HAVE_SQLITE3
3390        try {
3391            result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
3392        } catch (Exception e) {
3393             result.Error(e);
3394        }
3395    #else
3396        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3397    #endif
3398        return result.Produce();
3399    }
3400    
3401    String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
3402        dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3403        LSCPResultSet result;
3404    #if HAVE_SQLITE3
3405        try {
3406            String list;
3407            StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
3408    
3409            for (int i = 0; i < dirs->size(); i++) {
3410                if (list != "") list += ",";
3411                list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
3412            }
3413    
3414            result.Add(list);
3415        } catch (Exception e) {
3416             result.Error(e);
3417        }
3418    #else
3419        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3420    #endif
3421        return result.Produce();
3422    }
3423    
3424    String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
3425        dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
3426        LSCPResultSet result;
3427    #if HAVE_SQLITE3
3428        try {
3429            DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
3430    
3431            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3432            result.Add("CREATED", info.Created);
3433            result.Add("MODIFIED", info.Modified);
3434        } catch (Exception e) {
3435             result.Error(e);
3436        }
3437    #else
3438        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3439    #endif
3440        return result.Produce();
3441    }
3442    
3443    String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
3444        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
3445        LSCPResultSet result;
3446    #if HAVE_SQLITE3
3447        try {
3448            InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
3449        } catch (Exception e) {
3450             result.Error(e);
3451        }
3452    #else
3453        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3454    #endif
3455        return result.Produce();
3456    }
3457    
3458    String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
3459        dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3460        LSCPResultSet result;
3461    #if HAVE_SQLITE3
3462        try {
3463            InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
3464        } catch (Exception e) {
3465             result.Error(e);
3466        }
3467    #else
3468        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3469    #endif
3470        return result.Produce();
3471    }
3472    
3473    String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
3474        dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3475        LSCPResultSet result;
3476    #if HAVE_SQLITE3
3477        try {
3478            InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
3479        } catch (Exception e) {
3480             result.Error(e);
3481        }
3482    #else
3483        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3484    #endif
3485        return result.Produce();
3486    }
3487    
3488    String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3489        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3490        LSCPResultSet result;
3491    #if HAVE_SQLITE3
3492        try {
3493            InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3494        } catch (Exception e) {
3495             result.Error(e);
3496        }
3497    #else
3498        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3499    #endif
3500        return result.Produce();
3501    }
3502    
3503    String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3504        dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
3505        LSCPResultSet result;
3506    #if HAVE_SQLITE3
3507        try {
3508            int id;
3509            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3510            id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
3511            if (bBackground) result = id;
3512        } catch (Exception e) {
3513             result.Error(e);
3514        }
3515    #else
3516        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3517    #endif
3518        return result.Produce();
3519    }
3520    
3521    String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground, bool insDir) {
3522        dmsg(2,("LSCPServer: AddDbInstruments(ScanMode=%s,DbDir=%s,FsDir=%s,bBackground=%d,insDir=%d)\n", ScanMode.c_str(), DbDir.c_str(), FsDir.c_str(), bBackground, insDir));
3523        LSCPResultSet result;
3524    #if HAVE_SQLITE3
3525        try {
3526            int id;
3527            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3528            if (ScanMode.compare("RECURSIVE") == 0) {
3529                id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground, insDir);
3530            } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
3531                id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground, insDir);
3532            } else if (ScanMode.compare("FLAT") == 0) {
3533                id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground, insDir);
3534            } else {
3535                throw Exception("Unknown scan mode: " + ScanMode);
3536            }
3537    
3538            if (bBackground) result = id;
3539        } catch (Exception e) {
3540             result.Error(e);
3541        }
3542    #else
3543        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3544    #endif
3545        return result.Produce();
3546    }
3547    
3548    String LSCPServer::RemoveDbInstrument(String Instr) {
3549        dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
3550        LSCPResultSet result;
3551    #if HAVE_SQLITE3
3552        try {
3553            InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
3554        } catch (Exception e) {
3555             result.Error(e);
3556        }
3557    #else
3558        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3559    #endif
3560        return result.Produce();
3561    }
3562    
3563    String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
3564        dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3565        LSCPResultSet result;
3566    #if HAVE_SQLITE3
3567        try {
3568            result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
3569        } catch (Exception e) {
3570             result.Error(e);
3571        }
3572    #else
3573        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3574    #endif
3575        return result.Produce();
3576    }
3577    
3578    String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
3579        dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3580        LSCPResultSet result;
3581    #if HAVE_SQLITE3
3582        try {
3583            String list;
3584            StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
3585    
3586            for (int i = 0; i < instrs->size(); i++) {
3587                if (list != "") list += ",";
3588                list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
3589            }
3590    
3591            result.Add(list);
3592        } catch (Exception e) {
3593             result.Error(e);
3594        }
3595    #else
3596        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3597    #endif
3598        return result.Produce();
3599    }
3600    
3601    String LSCPServer::GetDbInstrumentInfo(String Instr) {
3602        dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
3603        LSCPResultSet result;
3604    #if HAVE_SQLITE3
3605        try {
3606            DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
3607    
3608            result.Add("INSTRUMENT_FILE", info.InstrFile);
3609            result.Add("INSTRUMENT_NR", info.InstrNr);
3610            result.Add("FORMAT_FAMILY", info.FormatFamily);
3611            result.Add("FORMAT_VERSION", info.FormatVersion);
3612            result.Add("SIZE", (int)info.Size);
3613            result.Add("CREATED", info.Created);
3614            result.Add("MODIFIED", info.Modified);
3615            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3616            result.Add("IS_DRUM", info.IsDrum);
3617            result.Add("PRODUCT", _escapeLscpResponse(info.Product));
3618            result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
3619            result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
3620        } catch (Exception e) {
3621             result.Error(e);
3622        }
3623    #else
3624        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3625    #endif
3626        return result.Produce();
3627    }
3628    
3629    String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
3630        dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
3631        LSCPResultSet result;
3632    #if HAVE_SQLITE3
3633        try {
3634            ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
3635    
3636            result.Add("FILES_TOTAL", job.FilesTotal);
3637            result.Add("FILES_SCANNED", job.FilesScanned);
3638            result.Add("SCANNING", job.Scanning);
3639            result.Add("STATUS", job.Status);
3640        } catch (Exception e) {
3641             result.Error(e);
3642        }
3643    #else
3644        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3645    #endif
3646        return result.Produce();
3647  }  }
3648    
3649  String LSCPServer::QueryDatabase(String query) {  String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
3650        dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
3651      LSCPResultSet result;      LSCPResultSet result;
3652  #if HAVE_SQLITE3  #if HAVE_SQLITE3
3653      char* zErrMsg = NULL;      try {
3654      sqlite3 *db;          InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
3655      String selectStr = "SELECT " + query;      } catch (Exception e) {
3656             result.Error(e);
3657        }
3658    #else
3659        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3660    #endif
3661        return result.Produce();
3662    }
3663    
3664      int rc = sqlite3_open("linuxsampler.db", &db);  String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
3665      if (rc == SQLITE_OK)      dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3666      {      LSCPResultSet result;
3667              rc = sqlite3_exec(db, selectStr.c_str(), select_callback, &result, &zErrMsg);  #if HAVE_SQLITE3
3668        try {
3669            InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
3670        } catch (Exception e) {
3671             result.Error(e);
3672      }      }
3673      if ( rc != SQLITE_OK )  #else
3674      {      result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3675              result.Error(String(zErrMsg), rc);  #endif
3676        return result.Produce();
3677    }
3678    
3679    String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3680        dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3681        LSCPResultSet result;
3682    #if HAVE_SQLITE3
3683        try {
3684            InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3685        } catch (Exception e) {
3686             result.Error(e);
3687        }
3688    #else
3689        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3690    #endif
3691        return result.Produce();
3692    }
3693    
3694    String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3695        dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3696        LSCPResultSet result;
3697    #if HAVE_SQLITE3
3698        try {
3699            InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3700        } catch (Exception e) {
3701             result.Error(e);
3702      }      }
     sqlite3_close(db);  
3703  #else  #else
3704      result.Error(String("SQLITE3 was not installed when linuxsampler was built. SELECT statement is not available."), 0);      result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3705  #endif  #endif
3706      return result.Produce();      return result.Produce();
3707  }  }
3708    
3709    String LSCPServer::SetDbInstrumentFilePath(String OldPath, String NewPath) {
3710        dmsg(2,("LSCPServer: SetDbInstrumentFilePath(OldPath=%s,NewPath=%s)\n", OldPath.c_str(), NewPath.c_str()));
3711        LSCPResultSet result;
3712    #if HAVE_SQLITE3
3713        try {
3714            InstrumentsDb::GetInstrumentsDb()->SetInstrumentFilePath(OldPath, NewPath);
3715        } catch (Exception e) {
3716             result.Error(e);
3717        }
3718    #else
3719        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3720    #endif
3721        return result.Produce();
3722    }
3723    
3724    String LSCPServer::FindLostDbInstrumentFiles() {
3725        dmsg(2,("LSCPServer: FindLostDbInstrumentFiles()\n"));
3726        LSCPResultSet result;
3727    #if HAVE_SQLITE3
3728        try {
3729            String list;
3730            StringListPtr pLostFiles = InstrumentsDb::GetInstrumentsDb()->FindLostInstrumentFiles();
3731    
3732            for (int i = 0; i < pLostFiles->size(); i++) {
3733                if (list != "") list += ",";
3734                list += "'" + pLostFiles->at(i) + "'";
3735            }
3736    
3737            result.Add(list);
3738        } catch (Exception e) {
3739             result.Error(e);
3740        }
3741    #else
3742        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3743    #endif
3744        return result.Produce();
3745    }
3746    
3747    String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3748        dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3749        LSCPResultSet result;
3750    #if HAVE_SQLITE3
3751        try {
3752            SearchQuery Query;
3753            std::map<String,String>::iterator iter;
3754            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3755                if (iter->first.compare("NAME") == 0) {
3756                    Query.Name = iter->second;
3757                } else if (iter->first.compare("CREATED") == 0) {
3758                    Query.SetCreated(iter->second);
3759                } else if (iter->first.compare("MODIFIED") == 0) {
3760                    Query.SetModified(iter->second);
3761                } else if (iter->first.compare("DESCRIPTION") == 0) {
3762                    Query.Description = iter->second;
3763                } else {
3764                    throw Exception("Unknown search criteria: " + iter->first);
3765                }
3766            }
3767    
3768            String list;
3769            StringListPtr pDirectories =
3770                InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3771    
3772            for (int i = 0; i < pDirectories->size(); i++) {
3773                if (list != "") list += ",";
3774                list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3775            }
3776    
3777            result.Add(list);
3778        } catch (Exception e) {
3779             result.Error(e);
3780        }
3781    #else
3782        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3783    #endif
3784        return result.Produce();
3785    }
3786    
3787    String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
3788        dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
3789        LSCPResultSet result;
3790    #if HAVE_SQLITE3
3791        try {
3792            SearchQuery Query;
3793            std::map<String,String>::iterator iter;
3794            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3795                if (iter->first.compare("NAME") == 0) {
3796                    Query.Name = iter->second;
3797                } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
3798                    Query.SetFormatFamilies(iter->second);
3799                } else if (iter->first.compare("SIZE") == 0) {
3800                    Query.SetSize(iter->second);
3801                } else if (iter->first.compare("CREATED") == 0) {
3802                    Query.SetCreated(iter->second);
3803                } else if (iter->first.compare("MODIFIED") == 0) {
3804                    Query.SetModified(iter->second);
3805                } else if (iter->first.compare("DESCRIPTION") == 0) {
3806                    Query.Description = iter->second;
3807                } else if (iter->first.compare("IS_DRUM") == 0) {
3808                    if (!strcasecmp(iter->second.c_str(), "true")) {
3809                        Query.InstrType = SearchQuery::DRUM;
3810                    } else {
3811                        Query.InstrType = SearchQuery::CHROMATIC;
3812                    }
3813                } else if (iter->first.compare("PRODUCT") == 0) {
3814                     Query.Product = iter->second;
3815                } else if (iter->first.compare("ARTISTS") == 0) {
3816                     Query.Artists = iter->second;
3817                } else if (iter->first.compare("KEYWORDS") == 0) {
3818                     Query.Keywords = iter->second;
3819                } else {
3820                    throw Exception("Unknown search criteria: " + iter->first);
3821                }
3822            }
3823    
3824            String list;
3825            StringListPtr pInstruments =
3826                InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
3827    
3828            for (int i = 0; i < pInstruments->size(); i++) {
3829                if (list != "") list += ",";
3830                list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
3831            }
3832    
3833            result.Add(list);
3834        } catch (Exception e) {
3835             result.Error(e);
3836        }
3837    #else
3838        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3839    #endif
3840        return result.Produce();
3841    }
3842    
3843    String LSCPServer::FormatInstrumentsDb() {
3844        dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
3845        LSCPResultSet result;
3846    #if HAVE_SQLITE3
3847        try {
3848            InstrumentsDb::GetInstrumentsDb()->Format();
3849        } catch (Exception e) {
3850             result.Error(e);
3851        }
3852    #else
3853        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3854    #endif
3855        return result.Produce();
3856    }
3857    
3858    
3859  /**  /**
3860   * Will be called by the parser to enable or disable echo mode; if echo   * Will be called by the parser to enable or disable echo mode; if echo
3861   * mode is enabled, all commands from the client will (immediately) be   * mode is enabled, all commands from the client will (immediately) be
# Line 1489  String LSCPServer::SetEcho(yyparse_param Line 3867  String LSCPServer::SetEcho(yyparse_param
3867      try {      try {
3868          if      (boolean_value == 0) pSession->bVerbose = false;          if      (boolean_value == 0) pSession->bVerbose = false;
3869          else if (boolean_value == 1) pSession->bVerbose = true;          else if (boolean_value == 1) pSession->bVerbose = true;
3870          else throw LinuxSamplerException("Not a boolean value, must either be 0 or 1");          else throw Exception("Not a boolean value, must either be 0 or 1");
3871      }      }
3872      catch (LinuxSamplerException e) {      catch (Exception e) {
3873           result.Error(e);           result.Error(e);
3874      }      }
3875      return result.Produce();      return result.Produce();
3876  }  }
3877    
3878    }

Legend:
Removed from v.563  
changed lines
  Added in v.2198

  ViewVC Help
Powered by ViewVC