/[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 793 by iliev, Wed Oct 26 09:34:38 2005 UTC revision 3055 by schoenebeck, Thu Dec 15 13:01:58 2016 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 - 2016 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    typedef unsigned short in_port_t;
35    typedef unsigned long in_addr_t;
36    #else
37  #include <fcntl.h>  #include <fcntl.h>
38    #endif
39    
40  #if HAVE_SQLITE3  #if ! HAVE_SQLITE3
41  # include "sqlite3.h"  #define DOESNT_HAVE_SQLITE3 "No database support. SQLITE3 was not installed when linuxsampler was built."
42  #endif  #endif
43    
44  #include "../engines/EngineFactory.h"  #include "../engines/EngineFactory.h"
45  #include "../engines/EngineChannelFactory.h"  #include "../engines/EngineChannelFactory.h"
46  #include "../drivers/audio/AudioOutputDeviceFactory.h"  #include "../drivers/audio/AudioOutputDeviceFactory.h"
47  #include "../drivers/midi/MidiInputDeviceFactory.h"  #include "../drivers/midi/MidiInputDeviceFactory.h"
48    #include "../effects/EffectFactory.h"
49    
50    namespace LinuxSampler {
51    
52    String lscpParserProcessShellInteraction(String& line, yyparse_param_t* param, bool possibilities);
53    
54    /**
55     * Returns a copy of the given string where all special characters are
56     * replaced by LSCP escape sequences ("\xHH"). This function shall be used
57     * to escape LSCP response fields in case the respective response field is
58     * actually defined as using escape sequences in the LSCP specs.
59     *
60     * @e Caution: DO NOT use this function for escaping path based responses,
61     * use the Path class (src/common/Path.h) for this instead!
62     */
63    static String _escapeLscpResponse(String txt) {
64        for (int i = 0; i < txt.length(); i++) {
65            const char c = txt.c_str()[i];
66            if (
67                !(c >= '0' && c <= '9') &&
68                !(c >= 'a' && c <= 'z') &&
69                !(c >= 'A' && c <= 'Z') &&
70                !(c == ' ') && !(c == '!') && !(c == '#') && !(c == '$') &&
71                !(c == '%') && !(c == '&') && !(c == '(') && !(c == ')') &&
72                !(c == '*') && !(c == '+') && !(c == ',') && !(c == '-') &&
73                !(c == '.') && !(c == '/') && !(c == ':') && !(c == ';') &&
74                !(c == '<') && !(c == '=') && !(c == '>') && !(c == '?') &&
75                !(c == '@') && !(c == '[') && !(c == ']') &&
76                !(c == '^') && !(c == '_') && !(c == '`') && !(c == '{') &&
77                !(c == '|') && !(c == '}') && !(c == '~')
78            ) {
79                // convert the "special" character into a "\xHH" LSCP escape sequence
80                char buf[5];
81                snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
82                txt.replace(i, 1, buf);
83                i += 3;
84            }
85        }
86        return txt;
87    }
88    
89  /**  /**
90   * Below are a few static members of the LSCPServer class.   * Below are a few static members of the LSCPServer class.
# Line 52  Line 101 
101   */   */
102  fd_set LSCPServer::fdSet;  fd_set LSCPServer::fdSet;
103  int LSCPServer::currentSocket = -1;  int LSCPServer::currentSocket = -1;
104  std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();  std::vector<yyparse_param_t> LSCPServer::Sessions;
105  std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();  std::vector<yyparse_param_t>::iterator itCurrentSession;
106  std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();  std::map<int,String> LSCPServer::bufferedNotifies;
107  std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();  std::map<int,String> LSCPServer::bufferedCommands;
108  Mutex LSCPServer::NotifyMutex = Mutex();  std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions;
109  Mutex LSCPServer::NotifyBufferMutex = Mutex();  Mutex LSCPServer::NotifyMutex;
110  Mutex LSCPServer::SubscriptionMutex = Mutex();  Mutex LSCPServer::NotifyBufferMutex;
111  Mutex LSCPServer::RTNotifyMutex = Mutex();  Mutex LSCPServer::SubscriptionMutex;
112    Mutex LSCPServer::RTNotifyMutex;
113    
114  LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4) {  LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4), eventHandler(this) {
115      SocketAddress.sin_family      = AF_INET;      SocketAddress.sin_family      = AF_INET;
116      SocketAddress.sin_addr.s_addr = addr;      SocketAddress.sin_addr.s_addr = (in_addr_t)addr;
117      SocketAddress.sin_port        = port;      SocketAddress.sin_port        = (in_port_t)port;
118      this->pSampler = pSampler;      this->pSampler = pSampler;
119        LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT");
120        LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO");
121        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT");
122        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO");
123      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
124      LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
125      LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
126      LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");      LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
127      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
128        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_count, "FX_SEND_COUNT");
129        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_info, "FX_SEND_INFO");
130        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
131        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
132        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
133        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
134        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_count, "DB_INSTRUMENT_DIRECTORY_COUNT");
135        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_info, "DB_INSTRUMENT_DIRECTORY_INFO");
136        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_count, "DB_INSTRUMENT_COUNT");
137        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_info, "DB_INSTRUMENT_INFO");
138        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instrs_job_info, "DB_INSTRUMENTS_JOB_INFO");
139      LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");      LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
140        LSCPEvent::RegisterEvent(LSCPEvent::event_total_stream_count, "TOTAL_STREAM_COUNT");
141      LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
142        LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");
143        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_midi, "CHANNEL_MIDI");
144        LSCPEvent::RegisterEvent(LSCPEvent::event_device_midi, "DEVICE_MIDI");
145        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_count, "EFFECT_INSTANCE_COUNT");
146        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_info, "EFFECT_INSTANCE_INFO");
147        LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_count, "SEND_EFFECT_CHAIN_COUNT");
148        LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_info, "SEND_EFFECT_CHAIN_INFO");
149      hSocket = -1;      hSocket = -1;
150  }  }
151    
152  LSCPServer::~LSCPServer() {  LSCPServer::~LSCPServer() {
153        CloseAllConnections();
154        InstrumentManager::StopBackgroundThread();
155    #if defined(WIN32)
156        if (hSocket >= 0) closesocket(hSocket);
157    #else
158      if (hSocket >= 0) close(hSocket);      if (hSocket >= 0) close(hSocket);
159    #endif
160    }
161    
162    LSCPServer::EventHandler::EventHandler(LSCPServer* pParent) {
163        this->pParent = pParent;
164    }
165    
166    LSCPServer::EventHandler::~EventHandler() {
167        std::vector<midi_listener_entry> l = channelMidiListeners;
168        channelMidiListeners.clear();
169        for (int i = 0; i < l.size(); i++)
170            delete l[i].pMidiListener;
171    }
172    
173    void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {
174        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));
175    }
176    
177    void LSCPServer::EventHandler::ChannelAdded(SamplerChannel* pChannel) {
178        pChannel->AddEngineChangeListener(this);
179    }
180    
181    void LSCPServer::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) {
182        if (!pChannel->GetEngineChannel()) return;
183        EngineToBeChanged(pChannel->Index());
184    }
185    
186    void LSCPServer::EventHandler::EngineToBeChanged(int ChannelId) {
187        SamplerChannel* pSamplerChannel =
188            pParent->pSampler->GetSamplerChannel(ChannelId);
189        if (!pSamplerChannel) return;
190        EngineChannel* pEngineChannel =
191            pSamplerChannel->GetEngineChannel();
192        if (!pEngineChannel) return;
193        for (std::vector<midi_listener_entry>::iterator iter = channelMidiListeners.begin(); iter != channelMidiListeners.end(); ++iter) {
194            if ((*iter).pEngineChannel == pEngineChannel) {
195                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
196                pEngineChannel->Disconnect(pMidiListener);
197                channelMidiListeners.erase(iter);
198                delete pMidiListener;
199                return;
200            }
201        }
202    }
203    
204    void LSCPServer::EventHandler::EngineChanged(int ChannelId) {
205        SamplerChannel* pSamplerChannel =
206            pParent->pSampler->GetSamplerChannel(ChannelId);
207        if (!pSamplerChannel) return;
208        EngineChannel* pEngineChannel =
209            pSamplerChannel->GetEngineChannel();
210        if (!pEngineChannel) return;
211        VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
212        pEngineChannel->Connect(pMidiListener);
213        midi_listener_entry entry = {
214            pSamplerChannel, pEngineChannel, pMidiListener
215        };
216        channelMidiListeners.push_back(entry);
217    }
218    
219    void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {
220        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));
221    }
222    
223    void LSCPServer::EventHandler::MidiDeviceCountChanged(int NewCount) {
224        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));
225    }
226    
227    void LSCPServer::EventHandler::MidiDeviceToBeDestroyed(MidiInputDevice* pDevice) {
228        pDevice->RemoveMidiPortCountListener(this);
229        for (int i = 0; i < pDevice->PortCount(); ++i)
230            MidiPortToBeRemoved(pDevice->GetPort(i));
231    }
232    
233    void LSCPServer::EventHandler::MidiDeviceCreated(MidiInputDevice* pDevice) {
234        pDevice->AddMidiPortCountListener(this);
235        for (int i = 0; i < pDevice->PortCount(); ++i)
236            MidiPortAdded(pDevice->GetPort(i));
237    }
238    
239    void LSCPServer::EventHandler::MidiPortCountChanged(int NewCount) {
240        // yet unused
241    }
242    
243    void LSCPServer::EventHandler::MidiPortToBeRemoved(MidiInputPort* pPort) {
244        for (std::vector<device_midi_listener_entry>::iterator iter = deviceMidiListeners.begin(); iter != deviceMidiListeners.end(); ++iter) {
245            if ((*iter).pPort == pPort) {
246                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
247                pPort->Disconnect(pMidiListener);
248                deviceMidiListeners.erase(iter);
249                delete pMidiListener;
250                return;
251            }
252        }
253    }
254    
255    void LSCPServer::EventHandler::MidiPortAdded(MidiInputPort* pPort) {
256        // find out the device ID
257        std::map<uint, MidiInputDevice*> devices =
258            pParent->pSampler->GetMidiInputDevices();
259        for (
260            std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
261            iter != devices.end(); ++iter
262        ) {
263            if (iter->second == pPort->GetDevice()) { // found
264                VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
265                pPort->Connect(pMidiListener);
266                device_midi_listener_entry entry = {
267                    pPort, pMidiListener, iter->first
268                };
269                deviceMidiListeners.push_back(entry);
270                return;
271            }
272        }
273    }
274    
275    void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {
276        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));
277    }
278    
279    void LSCPServer::EventHandler::MidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
280        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_info, MapId, Bank, Program));
281    }
282    
283    void LSCPServer::EventHandler::MidiInstrumentMapCountChanged(int NewCount) {
284        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, NewCount));
285    }
286    
287    void LSCPServer::EventHandler::MidiInstrumentMapInfoChanged(int MapId) {
288        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_info, MapId));
289    }
290    
291    void LSCPServer::EventHandler::FxSendCountChanged(int ChannelId, int NewCount) {
292        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_count, ChannelId, NewCount));
293    }
294    
295    void LSCPServer::EventHandler::VoiceCountChanged(int ChannelId, int NewCount) {
296        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, ChannelId, NewCount));
297    }
298    
299    void LSCPServer::EventHandler::StreamCountChanged(int ChannelId, int NewCount) {
300        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, ChannelId, NewCount));
301    }
302    
303    void LSCPServer::EventHandler::BufferFillChanged(int ChannelId, String FillData) {
304        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, ChannelId, FillData));
305    }
306    
307    void LSCPServer::EventHandler::TotalVoiceCountChanged(int NewCount) {
308        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));
309    }
310    
311    void LSCPServer::EventHandler::TotalStreamCountChanged(int NewCount) {
312        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_stream_count, NewCount));
313    }
314    
315    #if HAVE_SQLITE3
316    void LSCPServer::DbInstrumentsEventHandler::DirectoryCountChanged(String Dir) {
317        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_count, InstrumentsDb::toEscapedPath(Dir)));
318    }
319    
320    void LSCPServer::DbInstrumentsEventHandler::DirectoryInfoChanged(String Dir) {
321        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, InstrumentsDb::toEscapedPath(Dir)));
322    }
323    
324    void LSCPServer::DbInstrumentsEventHandler::DirectoryNameChanged(String Dir, String NewName) {
325        Dir = "'" + InstrumentsDb::toEscapedPath(Dir) + "'";
326        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
327        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, "NAME", Dir, NewName));
328    }
329    
330    void LSCPServer::DbInstrumentsEventHandler::InstrumentCountChanged(String Dir) {
331        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_count, InstrumentsDb::toEscapedPath(Dir)));
332    }
333    
334    void LSCPServer::DbInstrumentsEventHandler::InstrumentInfoChanged(String Instr) {
335        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, InstrumentsDb::toEscapedPath(Instr)));
336    }
337    
338    void LSCPServer::DbInstrumentsEventHandler::InstrumentNameChanged(String Instr, String NewName) {
339        Instr = "'" + InstrumentsDb::toEscapedPath(Instr) + "'";
340        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
341        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, "NAME", Instr, NewName));
342    }
343    
344    void LSCPServer::DbInstrumentsEventHandler::JobStatusChanged(int JobId) {
345        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instrs_job_info, JobId));
346    }
347    #endif // HAVE_SQLITE3
348    
349    void LSCPServer::RemoveListeners() {
350        pSampler->RemoveChannelCountListener(&eventHandler);
351        pSampler->RemoveAudioDeviceCountListener(&eventHandler);
352        pSampler->RemoveMidiDeviceCountListener(&eventHandler);
353        pSampler->RemoveVoiceCountListener(&eventHandler);
354        pSampler->RemoveStreamCountListener(&eventHandler);
355        pSampler->RemoveBufferFillListener(&eventHandler);
356        pSampler->RemoveTotalStreamCountListener(&eventHandler);
357        pSampler->RemoveTotalVoiceCountListener(&eventHandler);
358        pSampler->RemoveFxSendCountListener(&eventHandler);
359        MidiInstrumentMapper::RemoveMidiInstrumentCountListener(&eventHandler);
360        MidiInstrumentMapper::RemoveMidiInstrumentInfoListener(&eventHandler);
361        MidiInstrumentMapper::RemoveMidiInstrumentMapCountListener(&eventHandler);
362        MidiInstrumentMapper::RemoveMidiInstrumentMapInfoListener(&eventHandler);
363    #if HAVE_SQLITE3
364        InstrumentsDb::GetInstrumentsDb()->RemoveInstrumentsDbListener(&dbInstrumentsEventHandler);
365    #endif
366  }  }
367    
368  /**  /**
# Line 95  int LSCPServer::WaitUntilInitialized(lon Line 380  int LSCPServer::WaitUntilInitialized(lon
380  }  }
381    
382  int LSCPServer::Main() {  int LSCPServer::Main() {
383            #if defined(WIN32)
384            WSADATA wsaData;
385            int iResult;
386            iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
387            if (iResult != 0) {
388                    std::cerr << "LSCPServer: WSAStartup failed: " << iResult << "\n";
389                    exit(EXIT_FAILURE);
390            }
391            #endif
392      hSocket = socket(AF_INET, SOCK_STREAM, 0);      hSocket = socket(AF_INET, SOCK_STREAM, 0);
393      if (hSocket < 0) {      if (hSocket < 0) {
394          std::cerr << "LSCPServer: Could not create server socket." << std::endl;          std::cerr << "LSCPServer: Could not create server socket." << std::endl;
# Line 108  int LSCPServer::Main() { Line 402  int LSCPServer::Main() {
402              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
403                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {
404                      std::cerr << "gave up!" << std::endl;                      std::cerr << "gave up!" << std::endl;
405                        #if defined(WIN32)
406                        closesocket(hSocket);
407                        #else
408                      close(hSocket);                      close(hSocket);
409                        #endif
410                      //return -1;                      //return -1;
411                      exit(EXIT_FAILURE);                      exit(EXIT_FAILURE);
412                  }                  }
# Line 121  int LSCPServer::Main() { Line 419  int LSCPServer::Main() {
419      listen(hSocket, 1);      listen(hSocket, 1);
420      Initialized.Set(true);      Initialized.Set(true);
421    
422        // Registering event listeners
423        pSampler->AddChannelCountListener(&eventHandler);
424        pSampler->AddAudioDeviceCountListener(&eventHandler);
425        pSampler->AddMidiDeviceCountListener(&eventHandler);
426        pSampler->AddVoiceCountListener(&eventHandler);
427        pSampler->AddStreamCountListener(&eventHandler);
428        pSampler->AddBufferFillListener(&eventHandler);
429        pSampler->AddTotalStreamCountListener(&eventHandler);
430        pSampler->AddTotalVoiceCountListener(&eventHandler);
431        pSampler->AddFxSendCountListener(&eventHandler);
432        MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);
433        MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);
434        MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);
435        MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);
436    #if HAVE_SQLITE3
437        InstrumentsDb::GetInstrumentsDb()->AddInstrumentsDbListener(&dbInstrumentsEventHandler);
438    #endif
439      // now wait for client connections and handle their requests      // now wait for client connections and handle their requests
440      sockaddr_in client;      sockaddr_in client;
441      int length = sizeof(client);      int length = sizeof(client);
# Line 131  int LSCPServer::Main() { Line 446  int LSCPServer::Main() {
446      timeval timeout;      timeval timeout;
447    
448      while (true) {      while (true) {
449            #if CONFIG_PTHREAD_TESTCANCEL
450                    TestCancel();
451            #endif
452          // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers          // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
453          {          {
454                LockGuard lock(EngineChannelFactory::EngineChannelsMutex);
455              std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();              std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
456              std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();              std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
457              std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();              std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
458              for (; itEngineChannel != itEnd; ++itEngineChannel) {              for (; itEngineChannel != itEnd; ++itEngineChannel) {
459                  if ((*itEngineChannel)->StatusChanged()) {                  if ((*itEngineChannel)->StatusChanged()) {
460                      SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->iSamplerChannelIndex));                      SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->GetSamplerChannel()->Index()));
461                    }
462    
463                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
464                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
465                        if(fxs != NULL && fxs->IsInfoChanged()) {
466                            int chn = (*itEngineChannel)->GetSamplerChannel()->Index();
467                            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));
468                            fxs->SetInfoChanged(false);
469                        }
470                  }                  }
471              }              }
472          }          }
473    
474          //Now let's deliver late notifies (if any)          // check if MIDI data arrived on some engine channel
475          NotifyBufferMutex.Lock();          for (int i = 0; i < eventHandler.channelMidiListeners.size(); ++i) {
476          for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {              const EventHandler::midi_listener_entry entry =
477                  send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);                  eventHandler.channelMidiListeners[i];
478                  bufferedNotifies.erase(iterNotify);              VirtualMidiDevice* pMidiListener = entry.pMidiListener;
479          }              if (pMidiListener->NotesChanged()) {
480          NotifyBufferMutex.Unlock();                  for (int iNote = 0; iNote < 128; iNote++) {
481                        if (pMidiListener->NoteChanged(iNote)) {
482                            const bool bActive = pMidiListener->NoteIsActive(iNote);
483                            LSCPServer::SendLSCPNotify(
484                                LSCPEvent(
485                                    LSCPEvent::event_channel_midi,
486                                    entry.pSamplerChannel->Index(),
487                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
488                                    iNote,
489                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
490                                            : pMidiListener->NoteOffVelocity(iNote)
491                                )
492                            );
493                        }
494                    }
495                }
496            }
497    
498            // check if MIDI data arrived on some MIDI device
499            for (int i = 0; i < eventHandler.deviceMidiListeners.size(); ++i) {
500                const EventHandler::device_midi_listener_entry entry =
501                    eventHandler.deviceMidiListeners[i];
502                VirtualMidiDevice* pMidiListener = entry.pMidiListener;
503                if (pMidiListener->NotesChanged()) {
504                    for (int iNote = 0; iNote < 128; iNote++) {
505                        if (pMidiListener->NoteChanged(iNote)) {
506                            const bool bActive = pMidiListener->NoteIsActive(iNote);
507                            LSCPServer::SendLSCPNotify(
508                                LSCPEvent(
509                                    LSCPEvent::event_device_midi,
510                                    entry.uiDeviceID,
511                                    entry.pPort->GetPortNumber(),
512                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
513                                    iNote,
514                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
515                                            : pMidiListener->NoteOffVelocity(iNote)
516                                )
517                            );
518                        }
519                    }
520                }
521            }
522    
523            //Now let's deliver late notifies (if any)
524            {
525                LockGuard lock(NotifyBufferMutex);
526                for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
527    #ifdef MSG_NOSIGNAL
528                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
529    #else
530                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
531    #endif
532                }
533                bufferedNotifies.clear();
534            }
535    
536          fd_set selectSet = fdSet;          fd_set selectSet = fdSet;
537          timeout.tv_sec  = 0;          timeout.tv_sec  = 0;
# Line 157  int LSCPServer::Main() { Line 539  int LSCPServer::Main() {
539    
540          int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);          int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
541    
542          if (retval == 0)          if (retval == 0 || (retval == -1 && errno == EINTR))
543                  continue; //Nothing try again                  continue; //Nothing try again
544          if (retval == -1) {          if (retval == -1) {
545                  std::cerr << "LSCPServer: Socket select error." << std::endl;                  std::cerr << "LSCPServer: Socket select error." << std::endl;
546                    #if defined(WIN32)
547                    closesocket(hSocket);
548                    #else
549                  close(hSocket);                  close(hSocket);
550                    #endif
551                  exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
552          }          }
553    
# Line 173  int LSCPServer::Main() { Line 559  int LSCPServer::Main() {
559                          exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
560                  }                  }
561    
562                    #if defined(WIN32)
563                    u_long nonblock_io = 1;
564                    if( ioctlsocket(socket, FIONBIO, &nonblock_io) ) {
565                      std::cerr << "LSCPServer: ioctlsocket: set FIONBIO failed. Error " << WSAGetLastError() << std::endl;
566                      exit(EXIT_FAILURE);
567                    }
568            #else
569                    struct linger linger;
570                    linger.l_onoff = 1;
571                    linger.l_linger = 0;
572                    if(setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))) {
573                        std::cerr << "LSCPServer: Failed to set SO_LINGER\n";
574                    }
575    
576                  if (fcntl(socket, F_SETFL, O_NONBLOCK)) {                  if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
577                          std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;                          std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
578                          exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
579                  }                  }
580                    #endif
581    
582                  // Parser initialization                  // Parser initialization
583                  yyparse_param_t yyparse_param;                  yyparse_param_t yyparse_param;
# Line 195  int LSCPServer::Main() { Line 596  int LSCPServer::Main() {
596          //Something was selected and it was not the hSocket, so it must be some command(s) coming.          //Something was selected and it was not the hSocket, so it must be some command(s) coming.
597          for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {          for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
598                  if (FD_ISSET((*iter).hSession, &selectSet)) {   //Was it this socket?                  if (FD_ISSET((*iter).hSession, &selectSet)) {   //Was it this socket?
599                            currentSocket = (*iter).hSession;  //a hack
600                          if (GetLSCPCommand(iter)) {     //Have we read the entire command?                          if (GetLSCPCommand(iter)) {     //Have we read the entire command?
601                                  dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));                                  dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
602                                  int dummy; // just a temporary hack to fulfill the restart() function prototype                                  int dummy; // just a temporary hack to fulfill the restart() function prototype
603                                  restart(NULL, dummy); // restart the 'scanner'                                  restart(NULL, dummy); // restart the 'scanner'
604                                  currentSocket = (*iter).hSession;  //a hack                                  itCurrentSession = iter; // another hack
605                                  dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));                                  dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
606                                  if ((*iter).bVerbose) { // if echo mode enabled                                  if ((*iter).bVerbose) { // if echo mode enabled
607                                      AnswerClient(bufferedCommands[currentSocket]);                                      AnswerClient(bufferedCommands[currentSocket]);
608                                  }                                  }
609                                  int result = yyparse(&(*iter));                                  int result = yyparse(&(*iter));
610                                  currentSocket = -1;     //continuation of a hack                                  currentSocket = -1;     //continuation of a hack
611                                    itCurrentSession = Sessions.end(); // hack as well
612                                  dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));                                  dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
613                                  if (result == LSCP_QUIT) { //Was it a quit command by any chance?                                  if (result == LSCP_QUIT) { //Was it a quit command by any chance?
614                                          CloseConnection(iter);                                          CloseConnection(iter);
615                                  }                                  }
616                          }                          }
617                            currentSocket = -1;     //continuation of a hack
618                          //socket may have been closed, iter may be invalid, get out of the loop for now.                          //socket may have been closed, iter may be invalid, get out of the loop for now.
619                          //we'll be back if there is data.                          //we'll be back if there is data.
620                          break;                          break;
# Line 225  void LSCPServer::CloseConnection( std::v Line 629  void LSCPServer::CloseConnection( std::v
629          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
630          Sessions.erase(iter);          Sessions.erase(iter);
631          FD_CLR(socket,  &fdSet);          FD_CLR(socket,  &fdSet);
632          SubscriptionMutex.Lock(); //Must unsubscribe this socket from all events (if any)          {
633          for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {              LockGuard lock(SubscriptionMutex);
634                  iter->second.remove(socket);              // Must unsubscribe this socket from all events (if any)
635          }              for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
636          SubscriptionMutex.Unlock();                  iter->second.remove(socket);
637          NotifyMutex.Lock();              }
638            }
639            LockGuard lock(NotifyMutex);
640          bufferedCommands.erase(socket);          bufferedCommands.erase(socket);
641          bufferedNotifies.erase(socket);          bufferedNotifies.erase(socket);
642            #if defined(WIN32)
643            closesocket(socket);
644            #else
645          close(socket);          close(socket);
646          NotifyMutex.Unlock();          #endif
647    }
648    
649    void LSCPServer::CloseAllConnections() {
650        std::vector<yyparse_param_t>::iterator iter = Sessions.begin();
651        while(iter != Sessions.end()) {
652            CloseConnection(iter);
653            iter = Sessions.begin();
654        }
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();          LockGuard lock(SubscriptionMutex);
660          for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();          for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();
661                          iter != events.end(); iter++)                          iter != events.end(); iter++)
662          {          {
663                  subs += eventSubscriptions.count(*iter);                  subs += eventSubscriptions.count(*iter);
664          }          }
         SubscriptionMutex.Unlock();  
665          return subs;          return subs;
666  }  }
667    
668  void LSCPServer::SendLSCPNotify( LSCPEvent event ) {  void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
669          SubscriptionMutex.Lock();          LockGuard lock(SubscriptionMutex);
670          if (eventSubscriptions.count(event.GetType()) == 0) {          if (eventSubscriptions.count(event.GetType()) == 0) {
671                  SubscriptionMutex.Unlock();     //Nobody is subscribed to this event                  // Nobody is subscribed to this event
672                  return;                  return;
673          }          }
674          std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();          std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();
# Line 262  void LSCPServer::SendLSCPNotify( LSCPEve Line 678  void LSCPServer::SendLSCPNotify( LSCPEve
678          while (true) {          while (true) {
679                  if (NotifyMutex.Trylock()) {                  if (NotifyMutex.Trylock()) {
680                          for(;iter != end; iter++)                          for(;iter != end; iter++)
681    #ifdef MSG_NOSIGNAL
682                                  send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);                                  send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
683    #else
684                                    send(*iter, notify.c_str(), notify.size(), 0);
685    #endif
686                          NotifyMutex.Unlock();                          NotifyMutex.Unlock();
687                          break;                          break;
688                  } else {                  } else {
# Line 274  void LSCPServer::SendLSCPNotify( LSCPEve Line 694  void LSCPServer::SendLSCPNotify( LSCPEve
694                          }                          }
695                  }                  }
696          }          }
         SubscriptionMutex.Unlock();  
697  }  }
698    
699  extern int GetLSCPCommand( void *buf, int max_size ) {  extern int GetLSCPCommand( void *buf, int max_size ) {
# Line 291  extern int GetLSCPCommand( void *buf, in Line 710  extern int GetLSCPCommand( void *buf, in
710    
711          strcpy((char*) buf, command.c_str());          strcpy((char*) buf, command.c_str());
712          LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);          LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);
713          return command.size();          return (int) command.size();
714    }
715    
716    extern yyparse_param_t* GetCurrentYaccSession() {
717        return &(*itCurrentSession);
718    }
719    
720    /**
721     * Generate the relevant LSCP documentation reference section if necessary.
722     * The documentation section for the currently active command on the LSCP
723     * shell's command line will be encoded in a special format, specifically for
724     * the LSCP shell application.
725     *
726     * @param line - current LSCP command line
727     * @param param - reentrant Bison parser parameters
728     *
729     * @return encoded reference string or empty string if nothing shall be sent
730     *         to LSCP shell (client) at this point
731     */
732    String LSCPServer::generateLSCPDocReply(const String& line, yyparse_param_t* param) {
733        String result;
734        lscp_ref_entry_t* ref = lscp_reference_for_command(line.c_str());
735        // Pointer comparison works here, since the function above always
736        // returns the same constant pointer for the respective LSCP
737        // command ... Only send the LSCP reference section to the client if
738        // another LSCP reference section became relevant now:
739        if (ref != param->pLSCPDocRef) {
740            param->pLSCPDocRef = ref;
741            if (ref) { // send a new LSCP doc section to client ...
742                result += "SHD:" + ToString(LSCP_SHD_MATCH) + ":" + String(ref->name) + "\n";
743                result += String(ref->section) + "\n";
744                result += "."; // dot line marks the end of the text for client
745            } else { // inform client that no LSCP doc section matches right now ...
746                result = "SHD:" + ToString(LSCP_SHD_NO_MATCH);
747            }
748        }
749        dmsg(4,("LSCP doc reply -> '%s'\n", result.c_str()));
750        return result;
751  }  }
752    
753  /**  /**
# Line 301  extern int GetLSCPCommand( void *buf, in Line 757  extern int GetLSCPCommand( void *buf, in
757   */   */
758  bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {  bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
759          int socket = (*iter).hSession;          int socket = (*iter).hSession;
760            int result;
761          char c;          char c;
762          int i = 0;          std::vector<char> input;
763    
764            // first get as many character as possible and add it to the 'input' buffer
765          while (true) {          while (true) {
766                  int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now                  #if defined(WIN32)
767                  if (result == 0) { //socket was selected, so 0 here means client has closed the connection                  result = (int)recv(socket, (char*)&c, 1, 0); //Read one character at a time for now
768                          CloseConnection(iter);                  #else
769                          break;                  result = (int)recv(socket, (void*)&c, 1, 0); //Read one character at a time for now
770                    #endif
771                    if (result == 1) input.push_back(c);
772                    else break; // end of input or some error
773                    if (c == '\n') break; // process line by line
774            }
775    
776            // process input buffer
777            for (int i = 0; i < input.size(); ++i) {
778                    c = input[i];
779                    if (c == '\r') continue; //Ignore CR
780                    if (c == '\n') {
781                            // only if the other side is the LSCP shell application:
782                            // check the current (incomplete) command line for syntax errors,
783                            // possible completions and report everything back to the shell
784                            if ((*iter).bShellInteract || (*iter).bShellAutoCorrect) {
785                                    String s = lscpParserProcessShellInteraction(bufferedCommands[socket], &(*iter), false);
786                                    if (!s.empty() && (*iter).bShellInteract) AnswerClient(s + "\n");
787                            }
788                            // if other side is LSCP shell application, send the relevant LSCP
789                            // documentation section of the current command line (if necessary)
790                            if ((*iter).bShellSendLSCPDoc && (*iter).bShellInteract) {
791                                    String s = generateLSCPDocReply(bufferedCommands[socket], &(*iter));
792                                    if (!s.empty()) AnswerClient(s + "\n");
793                            }
794                            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
795                            bufferedCommands[socket] += "\r\n";
796                            return true; //Complete command was read
797                    } else if (c == 2) { // custom ASCII code usage for moving cursor left (LSCP shell)
798                            if (iter->iCursorOffset + bufferedCommands[socket].size() > 0)
799                                    iter->iCursorOffset--;
800                    } else if (c == 3) { // custom ASCII code usage for moving cursor right (LSCP shell)
801                            if (iter->iCursorOffset < 0) iter->iCursorOffset++;
802                    } else {
803                            ssize_t cursorPos = bufferedCommands[socket].size() + iter->iCursorOffset;
804                            // backspace character - should only happen with shell
805                            if (c == '\b') {
806                                    if (!bufferedCommands[socket].empty() && cursorPos > 0)
807                                            bufferedCommands[socket].erase(cursorPos - 1, 1);
808                            } else { // append (or insert) new character (at current cursor position) ...
809                                    if (cursorPos >= 0)
810                                            bufferedCommands[socket].insert(cursorPos, String(1,c)); // insert
811                                    else
812                                            bufferedCommands[socket] += c; // append
813                            }
814                  }                  }
815                  if (result == 1) {                  // Only if the other side (client) is the LSCP shell application:
816                          if (c == '\r')                  // The following block takes care about automatic correction, auto
817                                  continue; //Ignore CR                  // completion (and suggestions), LSCP reference documentation, etc.
818                          if (c == '\n') {                  // The "if" statement here is for optimization reasons, so that the
819                                  LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));                  // heavy LSCP grammar evaluation algorithm is only executed once for an
820                                  bufferedCommands[socket] += "\n";                  // entire command line received.
821                                  return true; //Complete command was read                  if (i == input.size() - 1) {
822                            // check the current (incomplete) command line for syntax errors,
823                            // possible completions and report everything back to the shell
824                            if ((*iter).bShellInteract || (*iter).bShellAutoCorrect) {
825                                    String s = lscpParserProcessShellInteraction(bufferedCommands[socket], &(*iter), true);
826                                    if (!s.empty() && (*iter).bShellInteract && i == input.size() - 1)
827                                            AnswerClient(s + "\n");
828                            }
829                            // if other side is LSCP shell application, send the relevant LSCP
830                            // documentation section of the current command line (if necessary)
831                            if ((*iter).bShellSendLSCPDoc && (*iter).bShellInteract) {
832                                    String s = generateLSCPDocReply(bufferedCommands[socket], &(*iter));
833                                    if (!s.empty()) AnswerClient(s + "\n");
834                          }                          }
                         bufferedCommands[socket] += c;  
835                  }                  }
836                  if (result == -1) {          }
837                          if (errno == EAGAIN) //Would block, try again later.  
838            // handle network errors ...
839            if (result == 0) { //socket was selected, so 0 here means client has closed the connection
840                    CloseConnection(iter);
841                    return false;
842            }
843            #if defined(WIN32)
844            if (result == SOCKET_ERROR) {
845                    int wsa_lasterror = WSAGetLastError();
846                    if (wsa_lasterror == WSAEWOULDBLOCK) //Would block, try again later.
847                            return false;
848                    dmsg(2,("LSCPScanner: Socket error after recv() Error %d.\n", wsa_lasterror));
849                    CloseConnection(iter);
850                    return false;
851            }
852            #else
853            if (result == -1) {
854                    if (errno == EAGAIN) //Would block, try again later.
855                            return false;
856                    switch(errno) {
857                            case EBADF:
858                                    dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
859                                    return false;
860                            case ECONNREFUSED:
861                                    dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
862                                    return false;
863                            case ENOTCONN:
864                                    dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
865                                    return false;
866                            case ENOTSOCK:
867                                    dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
868                                    return false;
869                            case EAGAIN:
870                                    dmsg(2,("LSCPScanner: The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.\n"));
871                                    return false;
872                            case EINTR:
873                                    dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
874                                    return false;
875                            case EFAULT:
876                                    dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
877                                    return false;
878                            case EINVAL:
879                                    dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
880                                    return false;
881                            case ENOMEM:
882                                    dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
883                                    return false;
884                            default:
885                                    dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
886                                  return false;                                  return false;
                         switch(errno) {  
                                 case EBADF:  
                                         dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));  
                                         break;  
                                 case ECONNREFUSED:  
                                         dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));  
                                         break;  
                                 case ENOTCONN:  
                                         dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));  
                                         break;  
                                 case ENOTSOCK:  
                                         dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));  
                                         break;  
                                 case EAGAIN:  
                                         dmsg(2,("LSCPScanner: The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.\n"));  
                                         break;  
                                 case EINTR:  
                                         dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));  
                                         break;  
                                 case EFAULT:  
                                         dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));  
                                         break;  
                                 case EINVAL:  
                                         dmsg(2,("LSCPScanner: Invalid argument passed.\n"));  
                                         break;  
                                 case ENOMEM:  
                                         dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));  
                                         break;  
                                 default:  
                                         dmsg(2,("LSCPScanner: Unknown recv() error.\n"));  
                                         break;  
                         }  
                         CloseConnection(iter);  
                         break;  
887                  }                  }
888                    CloseConnection(iter);
889                    return false;
890          }          }
891            #endif
892    
893          return false;          return false;
894  }  }
895    
# Line 368  bool LSCPServer::GetLSCPCommand( std::ve Line 900  bool LSCPServer::GetLSCPCommand( std::ve
900   * @param ReturnMessage - message that will be send to the client   * @param ReturnMessage - message that will be send to the client
901   */   */
902  void LSCPServer::AnswerClient(String ReturnMessage) {  void LSCPServer::AnswerClient(String ReturnMessage) {
903      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage='%s')", ReturnMessage.c_str()));
904      if (currentSocket != -1) {      if (currentSocket != -1) {
905              NotifyMutex.Lock();              LockGuard lock(NotifyMutex);
906    
907            // just if other side is LSCP shell: in case respose is a multi-line
908            // one, then inform client about it before sending the actual mult-line
909            // response
910            if (GetCurrentYaccSession()->bShellInteract) {
911                // check if this is a multi-line response
912                int n = 0;
913                for (int i = 0; i < ReturnMessage.size(); ++i)
914                    if (ReturnMessage[i] == '\n') ++n;
915                if (n >= 2) {
916                    dmsg(2,("LSCP Shell <- expect mult-line response\n"));
917                    String s = LSCP_SHK_EXPECT_MULTI_LINE "\r\n";
918    #ifdef MSG_NOSIGNAL
919                    send(currentSocket, s.c_str(), s.size(), MSG_NOSIGNAL);
920    #else
921                    send(currentSocket, s.c_str(), s.size(), 0);
922    #endif                
923                }
924            }
925    
926    #ifdef MSG_NOSIGNAL
927              send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);              send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
928              NotifyMutex.Unlock();  #else
929                send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
930    #endif
931      }      }
932  }  }
933    
# Line 415  String LSCPServer::CreateAudioOutputDevi Line 970  String LSCPServer::CreateAudioOutputDevi
970          AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);          AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
971          // search for the created device to get its index          // search for the created device to get its index
972          int index = GetAudioOutputDeviceIndex(pDevice);          int index = GetAudioOutputDeviceIndex(pDevice);
973          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.");
974          result = index; // success          result = index; // success
975      }      }
976      catch (LinuxSamplerException e) {      catch (Exception e) {
977          result.Error(e);          result.Error(e);
978      }      }
979      return result.Produce();      return result.Produce();
# Line 431  String LSCPServer::CreateMidiInputDevice Line 986  String LSCPServer::CreateMidiInputDevice
986          MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);          MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
987          // search for the created device to get its index          // search for the created device to get its index
988          int index = GetMidiInputDeviceIndex(pDevice);          int index = GetMidiInputDeviceIndex(pDevice);
989          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.");
990          result = index; // success          result = index; // success
991      }      }
992      catch (LinuxSamplerException e) {      catch (Exception e) {
993          result.Error(e);          result.Error(e);
994      }      }
995      return result.Produce();      return result.Produce();
# Line 445  String LSCPServer::DestroyAudioOutputDev Line 1000  String LSCPServer::DestroyAudioOutputDev
1000      LSCPResultSet result;      LSCPResultSet result;
1001      try {      try {
1002          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1003          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) + ".");
1004          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
1005          pSampler->DestroyAudioOutputDevice(pDevice);          pSampler->DestroyAudioOutputDevice(pDevice);
1006      }      }
1007      catch (LinuxSamplerException e) {      catch (Exception e) {
1008          result.Error(e);          result.Error(e);
1009      }      }
1010      return result.Produce();      return result.Produce();
# Line 460  String LSCPServer::DestroyMidiInputDevic Line 1015  String LSCPServer::DestroyMidiInputDevic
1015      LSCPResultSet result;      LSCPResultSet result;
1016      try {      try {
1017          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1018          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) + ".");
1019          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1020          pSampler->DestroyMidiInputDevice(pDevice);          pSampler->DestroyMidiInputDevice(pDevice);
1021      }      }
1022      catch (LinuxSamplerException e) {      catch (Exception e) {
1023          result.Error(e);          result.Error(e);
1024      }      }
1025      return result.Produce();      return result.Produce();
1026  }  }
1027    
1028    EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
1029        SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1030        if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1031    
1032        EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1033        if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1034    
1035        return pEngineChannel;
1036    }
1037    
1038  /**  /**
1039   * Will be called by the parser to load an instrument.   * Will be called by the parser to load an instrument.
1040   */   */
# Line 478  String LSCPServer::LoadInstrument(String Line 1043  String LSCPServer::LoadInstrument(String
1043      LSCPResultSet result;      LSCPResultSet result;
1044      try {      try {
1045          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1046          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1047          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1048          if (!pEngineChannel) throw LinuxSamplerException("No engine type assigned to sampler channel yet");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
1049          if (!pSamplerChannel->GetAudioOutputDevice())          if (!pSamplerChannel->GetAudioOutputDevice())
1050              throw LinuxSamplerException("No audio output device connected to sampler channel");              throw Exception("No audio output device connected to sampler channel");
1051          if (bBackground) {          if (bBackground) {
1052              InstrumentLoader.StartNewLoad(Filename, uiInstrument, pEngineChannel);              InstrumentManager::instrument_id_t id;
1053                id.FileName = Filename;
1054                id.Index    = uiInstrument;
1055                InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
1056          }          }
1057          else {          else {
1058              // tell the engine channel which instrument to load              // tell the engine channel which instrument to load
# Line 493  String LSCPServer::LoadInstrument(String Line 1061  String LSCPServer::LoadInstrument(String
1061              pEngineChannel->LoadInstrument();              pEngineChannel->LoadInstrument();
1062          }          }
1063      }      }
1064      catch (LinuxSamplerException e) {      catch (Exception e) {
1065           result.Error(e);           result.Error(e);
1066      }      }
1067      return result.Produce();      return result.Produce();
# Line 508  String LSCPServer::SetEngineType(String Line 1076  String LSCPServer::SetEngineType(String
1076      LSCPResultSet result;      LSCPResultSet result;
1077      try {      try {
1078          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1079          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1080          LockRTNotify();          LockGuard lock(RTNotifyMutex);
1081          pSamplerChannel->SetEngineType(EngineName);          pSamplerChannel->SetEngineType(EngineName);
1082          if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);          if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
         UnlockRTNotify();  
1083      }      }
1084      catch (LinuxSamplerException e) {      catch (Exception e) {
1085           result.Error(e);           result.Error(e);
1086      }      }
1087      return result.Produce();      return result.Produce();
# Line 552  String LSCPServer::ListChannels() { Line 1119  String LSCPServer::ListChannels() {
1119   */   */
1120  String LSCPServer::AddChannel() {  String LSCPServer::AddChannel() {
1121      dmsg(2,("LSCPServer: AddChannel()\n"));      dmsg(2,("LSCPServer: AddChannel()\n"));
1122      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();      SamplerChannel* pSamplerChannel;
1123        {
1124            LockGuard lock(RTNotifyMutex);
1125            pSamplerChannel = pSampler->AddSamplerChannel();
1126        }
1127      LSCPResultSet result(pSamplerChannel->Index());      LSCPResultSet result(pSamplerChannel->Index());
1128      return result.Produce();      return result.Produce();
1129  }  }
# Line 563  String LSCPServer::AddChannel() { Line 1134  String LSCPServer::AddChannel() {
1134  String LSCPServer::RemoveChannel(uint uiSamplerChannel) {  String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
1135      dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
1136      LSCPResultSet result;      LSCPResultSet result;
1137      LockRTNotify();      {
1138      pSampler->RemoveSamplerChannel(uiSamplerChannel);          LockGuard lock(RTNotifyMutex);
1139      UnlockRTNotify();          pSampler->RemoveSamplerChannel(uiSamplerChannel);
1140        }
1141      return result.Produce();      return result.Produce();
1142  }  }
1143    
# Line 574  String LSCPServer::RemoveChannel(uint ui Line 1146  String LSCPServer::RemoveChannel(uint ui
1146   */   */
1147  String LSCPServer::GetAvailableEngines() {  String LSCPServer::GetAvailableEngines() {
1148      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
1149      LSCPResultSet result("1");      LSCPResultSet result;
1150        try {
1151            int n = (int)EngineFactory::AvailableEngineTypes().size();
1152            result.Add(n);
1153        }
1154        catch (Exception e) {
1155            result.Error(e);
1156        }
1157      return result.Produce();      return result.Produce();
1158  }  }
1159    
# Line 583  String LSCPServer::GetAvailableEngines() Line 1162  String LSCPServer::GetAvailableEngines()
1162   */   */
1163  String LSCPServer::ListAvailableEngines() {  String LSCPServer::ListAvailableEngines() {
1164      dmsg(2,("LSCPServer: ListAvailableEngines()\n"));      dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
1165      LSCPResultSet result("\'GIG\'");      LSCPResultSet result;
1166        try {
1167            String s = EngineFactory::AvailableEngineTypesAsString();
1168            result.Add(s);
1169        }
1170        catch (Exception e) {
1171            result.Error(e);
1172        }
1173      return result.Produce();      return result.Produce();
1174  }  }
1175    
# Line 594  String LSCPServer::ListAvailableEngines( Line 1180  String LSCPServer::ListAvailableEngines(
1180  String LSCPServer::GetEngineInfo(String EngineName) {  String LSCPServer::GetEngineInfo(String EngineName) {
1181      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
1182      LSCPResultSet result;      LSCPResultSet result;
1183      try {      {
1184          Engine* pEngine = EngineFactory::Create(EngineName);          LockGuard lock(RTNotifyMutex);
1185          result.Add("DESCRIPTION", pEngine->Description());          try {
1186          result.Add("VERSION",     pEngine->Version());              Engine* pEngine = EngineFactory::Create(EngineName);
1187          EngineFactory::Destroy(pEngine);              result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
1188      }              result.Add("VERSION",     pEngine->Version());
1189      catch (LinuxSamplerException e) {              EngineFactory::Destroy(pEngine);
1190           result.Error(e);          }
1191            catch (Exception e) {
1192                result.Error(e);
1193            }
1194      }      }
1195      return result.Produce();      return result.Produce();
1196  }  }
# Line 615  String LSCPServer::GetChannelInfo(uint u Line 1204  String LSCPServer::GetChannelInfo(uint u
1204      LSCPResultSet result;      LSCPResultSet result;
1205      try {      try {
1206          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1207          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1208          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1209    
1210          //Defaults values          //Defaults values
# Line 629  String LSCPServer::GetChannelInfo(uint u Line 1218  String LSCPServer::GetChannelInfo(uint u
1218          String AudioRouting;          String AudioRouting;
1219          int Mute = 0;          int Mute = 0;
1220          bool Solo = false;          bool Solo = false;
1221            String MidiInstrumentMap = "NONE";
1222    
1223          if (pEngineChannel) {          if (pEngineChannel) {
1224              EngineName          = pEngineChannel->EngineName();              EngineName          = pEngineChannel->EngineName();
# Line 646  String LSCPServer::GetChannelInfo(uint u Line 1236  String LSCPServer::GetChannelInfo(uint u
1236              }              }
1237              Mute = pEngineChannel->GetMute();              Mute = pEngineChannel->GetMute();
1238              Solo = pEngineChannel->GetSolo();              Solo = pEngineChannel->GetSolo();
1239                if (pEngineChannel->UsesNoMidiInstrumentMap())
1240                    MidiInstrumentMap = "NONE";
1241                else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
1242                    MidiInstrumentMap = "DEFAULT";
1243                else
1244                    MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
1245          }          }
1246    
1247          result.Add("ENGINE_NAME", EngineName);          result.Add("ENGINE_NAME", EngineName);
# Line 661  String LSCPServer::GetChannelInfo(uint u Line 1257  String LSCPServer::GetChannelInfo(uint u
1257          if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");          if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
1258          else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());          else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
1259    
1260            // convert the filename into the correct encoding as defined for LSCP
1261            // (especially in terms of special characters -> escape sequences)
1262            if (InstrumentFileName != "NONE" && InstrumentFileName != "") {
1263    #if WIN32
1264                InstrumentFileName = Path::fromWindows(InstrumentFileName).toLscp();
1265    #else
1266                // assuming POSIX
1267                InstrumentFileName = Path::fromPosix(InstrumentFileName).toLscp();
1268    #endif
1269            }
1270    
1271          result.Add("INSTRUMENT_FILE", InstrumentFileName);          result.Add("INSTRUMENT_FILE", InstrumentFileName);
1272          result.Add("INSTRUMENT_NR", InstrumentIndex);          result.Add("INSTRUMENT_NR", InstrumentIndex);
1273          result.Add("INSTRUMENT_NAME", InstrumentName);          result.Add("INSTRUMENT_NAME", _escapeLscpResponse(InstrumentName));
1274          result.Add("INSTRUMENT_STATUS", InstrumentStatus);          result.Add("INSTRUMENT_STATUS", InstrumentStatus);
1275          result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));          result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
1276          result.Add("SOLO", Solo);          result.Add("SOLO", Solo);
1277            result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
1278      }      }
1279      catch (LinuxSamplerException e) {      catch (Exception e) {
1280           result.Error(e);           result.Error(e);
1281      }      }
1282      return result.Produce();      return result.Produce();
# Line 682  String LSCPServer::GetVoiceCount(uint ui Line 1290  String LSCPServer::GetVoiceCount(uint ui
1290      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
1291      LSCPResultSet result;      LSCPResultSet result;
1292      try {      try {
1293          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1294          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");  
         if (!pEngineChannel->GetEngine()) throw LinuxSamplerException("No audio output device connected to sampler channel");  
1295          result.Add(pEngineChannel->GetEngine()->VoiceCount());          result.Add(pEngineChannel->GetEngine()->VoiceCount());
1296      }      }
1297      catch (LinuxSamplerException e) {      catch (Exception e) {
1298           result.Error(e);           result.Error(e);
1299      }      }
1300      return result.Produce();      return result.Produce();
# Line 703  String LSCPServer::GetStreamCount(uint u Line 1308  String LSCPServer::GetStreamCount(uint u
1308      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
1309      LSCPResultSet result;      LSCPResultSet result;
1310      try {      try {
1311          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1312          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");  
         if (!pEngineChannel->GetEngine()) throw LinuxSamplerException("No audio output device connected to sampler channel");  
1313          result.Add(pEngineChannel->GetEngine()->DiskStreamCount());          result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
1314      }      }
1315      catch (LinuxSamplerException e) {      catch (Exception e) {
1316           result.Error(e);           result.Error(e);
1317      }      }
1318      return result.Produce();      return result.Produce();
# Line 724  String LSCPServer::GetBufferFill(fill_re Line 1326  String LSCPServer::GetBufferFill(fill_re
1326      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
1327      LSCPResultSet result;      LSCPResultSet result;
1328      try {      try {
1329          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1330          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");  
         if (!pEngineChannel->GetEngine()) throw LinuxSamplerException("No audio output device connected to sampler channel");  
1331          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
1332          else {          else {
1333              switch (ResponseType) {              switch (ResponseType) {
# Line 739  String LSCPServer::GetBufferFill(fill_re Line 1338  String LSCPServer::GetBufferFill(fill_re
1338                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
1339                      break;                      break;
1340                  default:                  default:
1341                      throw LinuxSamplerException("Unknown fill response type");                      throw Exception("Unknown fill response type");
1342              }              }
1343          }          }
1344      }      }
1345      catch (LinuxSamplerException e) {      catch (Exception e) {
1346           result.Error(e);           result.Error(e);
1347      }      }
1348      return result.Produce();      return result.Produce();
# Line 753  String LSCPServer::GetAvailableAudioOutp Line 1352  String LSCPServer::GetAvailableAudioOutp
1352      dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));      dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
1353      LSCPResultSet result;      LSCPResultSet result;
1354      try {      try {
1355          int n = AudioOutputDeviceFactory::AvailableDrivers().size();          int n = (int) AudioOutputDeviceFactory::AvailableDrivers().size();
1356          result.Add(n);          result.Add(n);
1357      }      }
1358      catch (LinuxSamplerException e) {      catch (Exception e) {
1359          result.Error(e);          result.Error(e);
1360      }      }
1361      return result.Produce();      return result.Produce();
# Line 769  String LSCPServer::ListAvailableAudioOut Line 1368  String LSCPServer::ListAvailableAudioOut
1368          String s = AudioOutputDeviceFactory::AvailableDriversAsString();          String s = AudioOutputDeviceFactory::AvailableDriversAsString();
1369          result.Add(s);          result.Add(s);
1370      }      }
1371      catch (LinuxSamplerException e) {      catch (Exception e) {
1372          result.Error(e);          result.Error(e);
1373      }      }
1374      return result.Produce();      return result.Produce();
# Line 779  String LSCPServer::GetAvailableMidiInput Line 1378  String LSCPServer::GetAvailableMidiInput
1378      dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));      dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
1379      LSCPResultSet result;      LSCPResultSet result;
1380      try {      try {
1381          int n = MidiInputDeviceFactory::AvailableDrivers().size();          int n = (int)MidiInputDeviceFactory::AvailableDrivers().size();
1382          result.Add(n);          result.Add(n);
1383      }      }
1384      catch (LinuxSamplerException e) {      catch (Exception e) {
1385          result.Error(e);          result.Error(e);
1386      }      }
1387      return result.Produce();      return result.Produce();
# Line 795  String LSCPServer::ListAvailableMidiInpu Line 1394  String LSCPServer::ListAvailableMidiInpu
1394          String s = MidiInputDeviceFactory::AvailableDriversAsString();          String s = MidiInputDeviceFactory::AvailableDriversAsString();
1395          result.Add(s);          result.Add(s);
1396      }      }
1397      catch (LinuxSamplerException e) {      catch (Exception e) {
1398          result.Error(e);          result.Error(e);
1399      }      }
1400      return result.Produce();      return result.Produce();
# Line 815  String LSCPServer::GetMidiInputDriverInf Line 1414  String LSCPServer::GetMidiInputDriverInf
1414              for (;iter != parameters.end(); iter++) {              for (;iter != parameters.end(); iter++) {
1415                  if (s != "") s += ",";                  if (s != "") s += ",";
1416                  s += iter->first;                  s += iter->first;
1417                    delete iter->second;
1418              }              }
1419              result.Add("PARAMETERS", s);              result.Add("PARAMETERS", s);
1420          }          }
1421      }      }
1422      catch (LinuxSamplerException e) {      catch (Exception e) {
1423          result.Error(e);          result.Error(e);
1424      }      }
1425      return result.Produce();      return result.Produce();
# Line 839  String LSCPServer::GetAudioOutputDriverI Line 1439  String LSCPServer::GetAudioOutputDriverI
1439              for (;iter != parameters.end(); iter++) {              for (;iter != parameters.end(); iter++) {
1440                  if (s != "") s += ",";                  if (s != "") s += ",";
1441                  s += iter->first;                  s += iter->first;
1442                    delete iter->second;
1443              }              }
1444              result.Add("PARAMETERS", s);              result.Add("PARAMETERS", s);
1445          }          }
1446      }      }
1447      catch (LinuxSamplerException e) {      catch (Exception e) {
1448          result.Error(e);          result.Error(e);
1449      }      }
1450      return result.Produce();      return result.Produce();
1451  }  }
1452    
1453  String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {  String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1454      dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));      dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),int(DependencyList.size())));
1455      LSCPResultSet result;      LSCPResultSet result;
1456      try {      try {
1457          DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);          DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
# Line 869  String LSCPServer::GetMidiInputDriverPar Line 1470  String LSCPServer::GetMidiInputDriverPar
1470          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1471          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1472          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1473            delete pParameter;
1474      }      }
1475      catch (LinuxSamplerException e) {      catch (Exception e) {
1476          result.Error(e);          result.Error(e);
1477      }      }
1478      return result.Produce();      return result.Produce();
1479  }  }
1480    
1481  String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {  String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1482      dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));      dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),int(DependencyList.size())));
1483      LSCPResultSet result;      LSCPResultSet result;
1484      try {      try {
1485          DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);          DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
# Line 896  String LSCPServer::GetAudioOutputDriverP Line 1498  String LSCPServer::GetAudioOutputDriverP
1498          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1499          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1500          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1501            delete pParameter;
1502      }      }
1503      catch (LinuxSamplerException e) {      catch (Exception e) {
1504          result.Error(e);          result.Error(e);
1505      }      }
1506      return result.Produce();      return result.Produce();
# Line 910  String LSCPServer::GetAudioOutputDeviceC Line 1513  String LSCPServer::GetAudioOutputDeviceC
1513          uint count = pSampler->AudioOutputDevices();          uint count = pSampler->AudioOutputDevices();
1514          result.Add(count); // success          result.Add(count); // success
1515      }      }
1516      catch (LinuxSamplerException e) {      catch (Exception e) {
1517          result.Error(e);          result.Error(e);
1518      }      }
1519      return result.Produce();      return result.Produce();
# Line 923  String LSCPServer::GetMidiInputDeviceCou Line 1526  String LSCPServer::GetMidiInputDeviceCou
1526          uint count = pSampler->MidiInputDevices();          uint count = pSampler->MidiInputDevices();
1527          result.Add(count); // success          result.Add(count); // success
1528      }      }
1529      catch (LinuxSamplerException e) {      catch (Exception e) {
1530          result.Error(e);          result.Error(e);
1531      }      }
1532      return result.Produce();      return result.Produce();
# Line 942  String LSCPServer::GetAudioOutputDevices Line 1545  String LSCPServer::GetAudioOutputDevices
1545          }          }
1546          result.Add(s);          result.Add(s);
1547      }      }
1548      catch (LinuxSamplerException e) {      catch (Exception e) {
1549          result.Error(e);          result.Error(e);
1550      }      }
1551      return result.Produce();      return result.Produce();
# Line 961  String LSCPServer::GetMidiInputDevices() Line 1564  String LSCPServer::GetMidiInputDevices()
1564          }          }
1565          result.Add(s);          result.Add(s);
1566      }      }
1567      catch (LinuxSamplerException e) {      catch (Exception e) {
1568          result.Error(e);          result.Error(e);
1569      }      }
1570      return result.Produce();      return result.Produce();
# Line 972  String LSCPServer::GetAudioOutputDeviceI Line 1575  String LSCPServer::GetAudioOutputDeviceI
1575      LSCPResultSet result;      LSCPResultSet result;
1576      try {      try {
1577          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1578          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) + ".");
1579          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
1580          result.Add("DRIVER", pDevice->Driver());          result.Add("DRIVER", pDevice->Driver());
1581          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
# Line 981  String LSCPServer::GetAudioOutputDeviceI Line 1584  String LSCPServer::GetAudioOutputDeviceI
1584              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1585          }          }
1586      }      }
1587      catch (LinuxSamplerException e) {      catch (Exception e) {
1588          result.Error(e);          result.Error(e);
1589      }      }
1590      return result.Produce();      return result.Produce();
# Line 992  String LSCPServer::GetMidiInputDeviceInf Line 1595  String LSCPServer::GetMidiInputDeviceInf
1595      LSCPResultSet result;      LSCPResultSet result;
1596      try {      try {
1597          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1598          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) + ".");
1599          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1600          result.Add("DRIVER", pDevice->Driver());          result.Add("DRIVER", pDevice->Driver());
1601          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
# Line 1001  String LSCPServer::GetMidiInputDeviceInf Line 1604  String LSCPServer::GetMidiInputDeviceInf
1604              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1605          }          }
1606      }      }
1607      catch (LinuxSamplerException e) {      catch (Exception e) {
1608          result.Error(e);          result.Error(e);
1609      }      }
1610      return result.Produce();      return result.Produce();
# Line 1012  String LSCPServer::GetMidiInputPortInfo( Line 1615  String LSCPServer::GetMidiInputPortInfo(
1615      try {      try {
1616          // get MIDI input device          // get MIDI input device
1617          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1618          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) + ".");
1619          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1620    
1621          // get MIDI port          // get MIDI port
1622          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1623          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) + ".");
1624    
1625          // return the values of all MIDI port parameters          // return the values of all MIDI port parameters
1626          std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
# Line 1026  String LSCPServer::GetMidiInputPortInfo( Line 1629  String LSCPServer::GetMidiInputPortInfo(
1629              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1630          }          }
1631      }      }
1632      catch (LinuxSamplerException e) {      catch (Exception e) {
1633          result.Error(e);          result.Error(e);
1634      }      }
1635      return result.Produce();      return result.Produce();
1636  }  }
1637    
1638  String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {  String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
1639      dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%d,ChannelId)\n",DeviceId,ChannelId));      dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%u,ChannelId=%u)\n",DeviceId,ChannelId));
1640      LSCPResultSet result;      LSCPResultSet result;
1641      try {      try {
1642          // get audio output device          // get audio output device
1643          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1644          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) + ".");
1645          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1646    
1647          // get audio channel          // get audio channel
1648          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1649          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) + ".");
1650    
1651          // return the values of all audio channel parameters          // return the values of all audio channel parameters
1652          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
# Line 1052  String LSCPServer::GetAudioOutputChannel Line 1655  String LSCPServer::GetAudioOutputChannel
1655              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1656          }          }
1657      }      }
1658      catch (LinuxSamplerException e) {      catch (Exception e) {
1659          result.Error(e);          result.Error(e);
1660      }      }
1661      return result.Produce();      return result.Produce();
# Line 1064  String LSCPServer::GetMidiInputPortParam Line 1667  String LSCPServer::GetMidiInputPortParam
1667      try {      try {
1668          // get MIDI input device          // get MIDI input device
1669          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1670          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) + ".");
1671          MidiInputDevice* pDevice = devices[DeviceId];          MidiInputDevice* pDevice = devices[DeviceId];
1672    
1673          // get midi port          // get midi port
1674          MidiInputPort* pPort = pDevice->GetPort(PortId);          MidiInputPort* pPort = pDevice->GetPort(PortId);
1675          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) + ".");
1676    
1677          // get desired port parameter          // get desired port parameter
1678          std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1679          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 + "'.");
1680          DeviceRuntimeParameter* pParameter = parameters[ParameterName];          DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1681    
1682          // return all fields of this audio channel parameter          // return all fields of this audio channel parameter
# Line 1085  String LSCPServer::GetMidiInputPortParam Line 1688  String LSCPServer::GetMidiInputPortParam
1688          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1689          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1690      }      }
1691      catch (LinuxSamplerException e) {      catch (Exception e) {
1692          result.Error(e);          result.Error(e);
1693      }      }
1694      return result.Produce();      return result.Produce();
# Line 1097  String LSCPServer::GetAudioOutputChannel Line 1700  String LSCPServer::GetAudioOutputChannel
1700      try {      try {
1701          // get audio output device          // get audio output device
1702          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1703          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) + ".");
1704          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1705    
1706          // get audio channel          // get audio channel
1707          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1708          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) + ".");
1709    
1710          // get desired audio channel parameter          // get desired audio channel parameter
1711          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1712          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 + "'.");
1713          DeviceRuntimeParameter* pParameter = parameters[ParameterName];          DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1714    
1715          // return all fields of this audio channel parameter          // return all fields of this audio channel parameter
# Line 1118  String LSCPServer::GetAudioOutputChannel Line 1721  String LSCPServer::GetAudioOutputChannel
1721          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1722          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1723      }      }
1724      catch (LinuxSamplerException e) {      catch (Exception e) {
1725          result.Error(e);          result.Error(e);
1726      }      }
1727      return result.Produce();      return result.Produce();
# Line 1130  String LSCPServer::SetAudioOutputChannel Line 1733  String LSCPServer::SetAudioOutputChannel
1733      try {      try {
1734          // get audio output device          // get audio output device
1735          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1736          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) + ".");
1737          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1738    
1739          // get audio channel          // get audio channel
1740          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1741          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) + ".");
1742    
1743          // get desired audio channel parameter          // get desired audio channel parameter
1744          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1745          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 + "'.");
1746          DeviceRuntimeParameter* pParameter = parameters[ParamKey];          DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1747    
1748          // set new channel parameter value          // set new channel parameter value
1749          pParameter->SetValue(ParamVal);          pParameter->SetValue(ParamVal);
1750            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1751      }      }
1752      catch (LinuxSamplerException e) {      catch (Exception e) {
1753          result.Error(e);          result.Error(e);
1754      }      }
1755      return result.Produce();      return result.Produce();
# Line 1156  String LSCPServer::SetAudioOutputDeviceP Line 1760  String LSCPServer::SetAudioOutputDeviceP
1760      LSCPResultSet result;      LSCPResultSet result;
1761      try {      try {
1762          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1763          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) + ".");
1764          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
1765          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1766          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 + "'");
1767          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1768            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1769      }      }
1770      catch (LinuxSamplerException e) {      catch (Exception e) {
1771          result.Error(e);          result.Error(e);
1772      }      }
1773      return result.Produce();      return result.Produce();
# Line 1173  String LSCPServer::SetMidiInputDevicePar Line 1778  String LSCPServer::SetMidiInputDevicePar
1778      LSCPResultSet result;      LSCPResultSet result;
1779      try {      try {
1780          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1781          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) + ".");
1782          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1783          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1784          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 + "'");
1785          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1786            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1787      }      }
1788      catch (LinuxSamplerException e) {      catch (Exception e) {
1789          result.Error(e);          result.Error(e);
1790      }      }
1791      return result.Produce();      return result.Produce();
# Line 1191  String LSCPServer::SetMidiInputPortParam Line 1797  String LSCPServer::SetMidiInputPortParam
1797      try {      try {
1798          // get MIDI input device          // get MIDI input device
1799          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1800          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) + ".");
1801          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1802    
1803          // get MIDI port          // get MIDI port
1804          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1805          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) + ".");
1806    
1807          // set port parameter value          // set port parameter value
1808          std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1809          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 + "'");
1810          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1811            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1812      }      }
1813      catch (LinuxSamplerException e) {      catch (Exception e) {
1814          result.Error(e);          result.Error(e);
1815      }      }
1816      return result.Produce();      return result.Produce();
# Line 1218  String LSCPServer::SetAudioOutputChannel Line 1825  String LSCPServer::SetAudioOutputChannel
1825      LSCPResultSet result;      LSCPResultSet result;
1826      try {      try {
1827          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1828          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1829          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1830          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));
1831          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));
1832          pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);          pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1833      }      }
1834      catch (LinuxSamplerException e) {      catch (Exception e) {
1835           result.Error(e);           result.Error(e);
1836      }      }
1837      return result.Produce();      return result.Produce();
# Line 1233  String LSCPServer::SetAudioOutputChannel Line 1840  String LSCPServer::SetAudioOutputChannel
1840  String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1841      dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1842      LSCPResultSet result;      LSCPResultSet result;
1843      try {      {
1844          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          LockGuard lock(RTNotifyMutex);
1845          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          try {
1846          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();              SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1847          if (!devices.count(AudioDeviceId)) throw LinuxSamplerException("There is no audio output device with index " + ToString(AudioDeviceId));              if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1848          AudioOutputDevice* pDevice = devices[AudioDeviceId];              std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1849          pSamplerChannel->SetAudioOutputDevice(pDevice);              if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1850      }              AudioOutputDevice* pDevice = devices[AudioDeviceId];
1851      catch (LinuxSamplerException e) {              pSamplerChannel->SetAudioOutputDevice(pDevice);
1852           result.Error(e);          }
1853            catch (Exception e) {
1854                result.Error(e);
1855            }
1856      }      }
1857      return result.Produce();      return result.Produce();
1858  }  }
# Line 1250  String LSCPServer::SetAudioOutputDevice( Line 1860  String LSCPServer::SetAudioOutputDevice(
1860  String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1861      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));
1862      LSCPResultSet result;      LSCPResultSet result;
1863      try {      {
1864          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          LockGuard lock(RTNotifyMutex);
1865          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          try {
1866          // Driver type name aliasing...              SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1867          if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";              if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1868          if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";              // Driver type name aliasing...
1869          // Check if there's one audio output device already created              if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1870          // for the intended audio driver type (AudioOutputDriver)...              if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1871          AudioOutputDevice *pDevice = NULL;              // Check if there's one audio output device already created
1872          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();              // for the intended audio driver type (AudioOutputDriver)...
1873          std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();              AudioOutputDevice *pDevice = NULL;
1874          for (; iter != devices.end(); iter++) {              std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1875              if ((iter->second)->Driver() == AudioOutputDriver) {              std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1876                  pDevice = iter->second;              for (; iter != devices.end(); iter++) {
1877                  break;                  if ((iter->second)->Driver() == AudioOutputDriver) {
1878                        pDevice = iter->second;
1879                        break;
1880                    }
1881              }              }
1882                // If it doesn't exist, create a new one with default parameters...
1883                if (pDevice == NULL) {
1884                    std::map<String,String> params;
1885                    pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1886                }
1887                // Must have a device...
1888                if (pDevice == NULL)
1889                    throw Exception("Internal error: could not create audio output device.");
1890                // Set it as the current channel device...
1891                pSamplerChannel->SetAudioOutputDevice(pDevice);
1892          }          }
1893          // If it doesn't exist, create a new one with default parameters...          catch (Exception e) {
1894          if (pDevice == NULL) {              result.Error(e);
             std::map<String,String> params;  
             pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);  
1895          }          }
         // Must have a device...  
         if (pDevice == NULL)  
             throw LinuxSamplerException("Internal error: could not create audio output device.");  
         // Set it as the current channel device...  
         pSamplerChannel->SetAudioOutputDevice(pDevice);  
1896      }      }
1897      catch (LinuxSamplerException e) {      return result.Produce();
1898           result.Error(e);  }
1899    
1900    String LSCPServer::AddChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId, uint MIDIPort) {
1901        dmsg(2,("LSCPServer: AddChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d, MIDIPort=%d)\n",uiSamplerChannel,MIDIDeviceId,MIDIPort));
1902        LSCPResultSet result;
1903        try {
1904            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1905            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1906    
1907            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1908            if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1909            MidiInputDevice* pDevice = devices[MIDIDeviceId];
1910    
1911            MidiInputPort* pPort = pDevice->GetPort(MIDIPort);
1912            if (!pPort) throw Exception("There is no MIDI input port with index " + ToString(MIDIPort) + " on MIDI input device with index " + ToString(MIDIDeviceId));
1913    
1914            pSamplerChannel->Connect(pPort);
1915        } catch (Exception e) {
1916            result.Error(e);
1917        }
1918        return result.Produce();
1919    }
1920    
1921    String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel) {
1922        dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d)\n",uiSamplerChannel));
1923        LSCPResultSet result;
1924        try {
1925            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1926            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1927            pSamplerChannel->DisconnectAllMidiInputPorts();
1928        } catch (Exception e) {
1929            result.Error(e);
1930        }
1931        return result.Produce();
1932    }
1933    
1934    String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId) {
1935        dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d)\n",uiSamplerChannel,MIDIDeviceId));
1936        LSCPResultSet result;
1937        try {
1938            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1939            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1940    
1941            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1942            if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1943            MidiInputDevice* pDevice = devices[MIDIDeviceId];
1944            
1945            std::vector<MidiInputPort*> vPorts = pSamplerChannel->GetMidiInputPorts();
1946            for (int i = 0; i < vPorts.size(); ++i)
1947                if (vPorts[i]->GetDevice() == pDevice)
1948                    pSamplerChannel->Disconnect(vPorts[i]);
1949    
1950        } catch (Exception e) {
1951            result.Error(e);
1952        }
1953        return result.Produce();
1954    }
1955    
1956    String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId, uint MIDIPort) {
1957        dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d, MIDIPort=%d)\n",uiSamplerChannel,MIDIDeviceId,MIDIPort));
1958        LSCPResultSet result;
1959        try {
1960            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1961            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1962    
1963            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1964            if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1965            MidiInputDevice* pDevice = devices[MIDIDeviceId];
1966    
1967            MidiInputPort* pPort = pDevice->GetPort(MIDIPort);
1968            if (!pPort) throw Exception("There is no MIDI input port with index " + ToString(MIDIPort) + " on MIDI input device with index " + ToString(MIDIDeviceId));
1969    
1970            pSamplerChannel->Disconnect(pPort);
1971        } catch (Exception e) {
1972            result.Error(e);
1973        }
1974        return result.Produce();
1975    }
1976    
1977    String LSCPServer::ListChannelMidiInputs(uint uiSamplerChannel) {
1978        dmsg(2,("LSCPServer: ListChannelMidiInputs(uiSamplerChannel=%d)\n",uiSamplerChannel));
1979        LSCPResultSet result;
1980        try {
1981            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1982            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1983            std::vector<MidiInputPort*> vPorts = pSamplerChannel->GetMidiInputPorts();
1984    
1985            String s;
1986            for (int i = 0; i < vPorts.size(); ++i) {
1987                const int iDeviceID = vPorts[i]->GetDevice()->MidiInputDeviceID();
1988                const int iPortNr   = vPorts[i]->GetPortNumber();
1989                if (s.size()) s += ",";
1990                s += "{" + ToString(iDeviceID) + ","
1991                         + ToString(iPortNr) + "}";
1992            }
1993            result.Add(s);
1994        } catch (Exception e) {
1995            result.Error(e);
1996      }      }
1997      return result.Produce();      return result.Produce();
1998  }  }
# Line 1289  String LSCPServer::SetMIDIInputPort(uint Line 2002  String LSCPServer::SetMIDIInputPort(uint
2002      LSCPResultSet result;      LSCPResultSet result;
2003      try {      try {
2004          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2005          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2006          pSamplerChannel->SetMidiInputPort(MIDIPort);          pSamplerChannel->SetMidiInputPort(MIDIPort);
2007      }      }
2008      catch (LinuxSamplerException e) {      catch (Exception e) {
2009           result.Error(e);           result.Error(e);
2010      }      }
2011      return result.Produce();      return result.Produce();
# Line 1303  String LSCPServer::SetMIDIInputChannel(u Line 2016  String LSCPServer::SetMIDIInputChannel(u
2016      LSCPResultSet result;      LSCPResultSet result;
2017      try {      try {
2018          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2019          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2020          pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);          pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
2021      }      }
2022      catch (LinuxSamplerException e) {      catch (Exception e) {
2023           result.Error(e);           result.Error(e);
2024      }      }
2025      return result.Produce();      return result.Produce();
# Line 1317  String LSCPServer::SetMIDIInputDevice(ui Line 2030  String LSCPServer::SetMIDIInputDevice(ui
2030      LSCPResultSet result;      LSCPResultSet result;
2031      try {      try {
2032          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2033          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2034          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
2035          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));
2036          MidiInputDevice* pDevice = devices[MIDIDeviceId];          MidiInputDevice* pDevice = devices[MIDIDeviceId];
2037          pSamplerChannel->SetMidiInputDevice(pDevice);          pSamplerChannel->SetMidiInputDevice(pDevice);
2038      }      }
2039      catch (LinuxSamplerException e) {      catch (Exception e) {
2040           result.Error(e);           result.Error(e);
2041      }      }
2042      return result.Produce();      return result.Produce();
# Line 1334  String LSCPServer::SetMIDIInputType(Stri Line 2047  String LSCPServer::SetMIDIInputType(Stri
2047      LSCPResultSet result;      LSCPResultSet result;
2048      try {      try {
2049          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2050          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2051          // Driver type name aliasing...          // Driver type name aliasing...
2052          if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";          if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
2053          // Check if there's one MIDI input device already created          // Check if there's one MIDI input device already created
# Line 1354  String LSCPServer::SetMIDIInputType(Stri Line 2067  String LSCPServer::SetMIDIInputType(Stri
2067              pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);              pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
2068              // Make it with at least one initial port.              // Make it with at least one initial port.
2069              std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();              std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
             parameters["PORTS"]->SetValue("1");  
2070          }          }
2071          // Must have a device...          // Must have a device...
2072          if (pDevice == NULL)          if (pDevice == NULL)
2073              throw LinuxSamplerException("Internal error: could not create MIDI input device.");              throw Exception("Internal error: could not create MIDI input device.");
2074          // Set it as the current channel device...          // Set it as the current channel device...
2075          pSamplerChannel->SetMidiInputDevice(pDevice);          pSamplerChannel->SetMidiInputDevice(pDevice);
2076      }      }
2077      catch (LinuxSamplerException e) {      catch (Exception e) {
2078           result.Error(e);           result.Error(e);
2079      }      }
2080      return result.Produce();      return result.Produce();
# Line 1377  String LSCPServer::SetMIDIInput(uint MID Line 2089  String LSCPServer::SetMIDIInput(uint MID
2089      LSCPResultSet result;      LSCPResultSet result;
2090      try {      try {
2091          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2092          if (!pSamplerChannel) throw LinuxSamplerException("Invalid sampler channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2093          std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();
2094          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));
2095          MidiInputDevice* pDevice = devices[MIDIDeviceId];          MidiInputDevice* pDevice = devices[MIDIDeviceId];
2096          pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);          pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
2097      }      }
2098      catch (LinuxSamplerException e) {      catch (Exception e) {
2099           result.Error(e);           result.Error(e);
2100      }      }
2101      return result.Produce();      return result.Produce();
# Line 1397  String LSCPServer::SetVolume(double dVol Line 2109  String LSCPServer::SetVolume(double dVol
2109      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
2110      LSCPResultSet result;      LSCPResultSet result;
2111      try {      try {
2112          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");  
2113          pEngineChannel->Volume(dVolume);          pEngineChannel->Volume(dVolume);
2114      }      }
2115      catch (LinuxSamplerException e) {      catch (Exception e) {
2116           result.Error(e);           result.Error(e);
2117      }      }
2118      return result.Produce();      return result.Produce();
# Line 1416  String LSCPServer::SetChannelMute(bool b Line 2125  String LSCPServer::SetChannelMute(bool b
2125      dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));      dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
2126      LSCPResultSet result;      LSCPResultSet result;
2127      try {      try {
2128          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");  
2129    
2130          if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);          if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
2131          else pEngineChannel->SetMute(1);          else pEngineChannel->SetMute(1);
2132      } catch (LinuxSamplerException e) {      } catch (Exception e) {
2133          result.Error(e);          result.Error(e);
2134      }      }
2135      return result.Produce();      return result.Produce();
# Line 1437  String LSCPServer::SetChannelSolo(bool b Line 2142  String LSCPServer::SetChannelSolo(bool b
2142      dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));      dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
2143      LSCPResultSet result;      LSCPResultSet result;
2144      try {      try {
2145          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");  
2146    
2147          bool oldSolo = pEngineChannel->GetSolo();          bool oldSolo = pEngineChannel->GetSolo();
2148          bool hadSoloChannel = HasSoloChannel();          bool hadSoloChannel = HasSoloChannel();
2149            
2150          pEngineChannel->SetSolo(bSolo);          pEngineChannel->SetSolo(bSolo);
2151            
2152          if(!oldSolo && bSolo) {          if(!oldSolo && bSolo) {
2153              if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);              if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
2154              if(!hadSoloChannel) MuteNonSoloChannels();              if(!hadSoloChannel) MuteNonSoloChannels();
2155          }          }
2156            
2157          if(oldSolo && !bSolo) {          if(oldSolo && !bSolo) {
2158              if(!HasSoloChannel()) UnmuteChannels();              if(!HasSoloChannel()) UnmuteChannels();
2159              else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);              else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
2160          }          }
2161      } catch (LinuxSamplerException e) {      } catch (Exception e) {
2162          result.Error(e);          result.Error(e);
2163      }      }
2164      return result.Produce();      return result.Produce();
# Line 1510  void  LSCPServer::UnmuteChannels() { Line 2211  void  LSCPServer::UnmuteChannels() {
2211      }      }
2212  }  }
2213    
2214    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) {
2215        dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
2216    
2217        midi_prog_index_t idx;
2218        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2219        idx.midi_bank_lsb = MidiBank & 0x7f;
2220        idx.midi_prog     = MidiProg;
2221    
2222        MidiInstrumentMapper::entry_t entry;
2223        entry.EngineName      = EngineType;
2224        entry.InstrumentFile  = InstrumentFile;
2225        entry.InstrumentIndex = InstrumentIndex;
2226        entry.LoadMode        = LoadMode;
2227        entry.Volume          = Volume;
2228        entry.Name            = Name;
2229    
2230        LSCPResultSet result;
2231        try {
2232            // PERSISTENT mapping commands might block for a long time, so in
2233            // that case we add/replace the mapping in another thread in case
2234            // the NON_MODAL argument was supplied, non persistent mappings
2235            // should return immediately, so we don't need to do that for them
2236            bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
2237            MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
2238        } catch (Exception e) {
2239            result.Error(e);
2240        }
2241        return result.Produce();
2242    }
2243    
2244    String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2245        dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
2246    
2247        midi_prog_index_t idx;
2248        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2249        idx.midi_bank_lsb = MidiBank & 0x7f;
2250        idx.midi_prog     = MidiProg;
2251    
2252        LSCPResultSet result;
2253        try {
2254            MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
2255        } catch (Exception e) {
2256            result.Error(e);
2257        }
2258        return result.Produce();
2259    }
2260    
2261    String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
2262        dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
2263        LSCPResultSet result;
2264        try {
2265            result.Add(MidiInstrumentMapper::GetInstrumentCount(MidiMapID));
2266        } catch (Exception e) {
2267            result.Error(e);
2268        }
2269        return result.Produce();
2270    }
2271    
2272    
2273    String LSCPServer::GetAllMidiInstrumentMappings() {
2274        dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
2275        LSCPResultSet result;
2276        try {
2277            result.Add(MidiInstrumentMapper::GetInstrumentCount());
2278        } catch (Exception e) {
2279            result.Error(e);
2280        }
2281        return result.Produce();
2282    }
2283    
2284    String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2285        dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
2286        LSCPResultSet result;
2287        try {
2288            MidiInstrumentMapper::entry_t entry = MidiInstrumentMapper::GetEntry(MidiMapID, MidiBank, MidiProg);
2289            // convert the filename into the correct encoding as defined for LSCP
2290            // (especially in terms of special characters -> escape sequences)
2291    #if WIN32
2292            const String instrumentFileName = Path::fromWindows(entry.InstrumentFile).toLscp();
2293    #else
2294            // assuming POSIX
2295            const String instrumentFileName = Path::fromPosix(entry.InstrumentFile).toLscp();
2296    #endif
2297    
2298            result.Add("NAME", _escapeLscpResponse(entry.Name));
2299            result.Add("ENGINE_NAME", entry.EngineName);
2300            result.Add("INSTRUMENT_FILE", instrumentFileName);
2301            result.Add("INSTRUMENT_NR", (int) entry.InstrumentIndex);
2302            String instrumentName;
2303            Engine* pEngine = EngineFactory::Create(entry.EngineName);
2304            if (pEngine) {
2305                if (pEngine->GetInstrumentManager()) {
2306                    InstrumentManager::instrument_id_t instrID;
2307                    instrID.FileName = entry.InstrumentFile;
2308                    instrID.Index    = entry.InstrumentIndex;
2309                    instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
2310                }
2311                EngineFactory::Destroy(pEngine);
2312            }
2313            result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2314            switch (entry.LoadMode) {
2315                case MidiInstrumentMapper::ON_DEMAND:
2316                    result.Add("LOAD_MODE", "ON_DEMAND");
2317                    break;
2318                case MidiInstrumentMapper::ON_DEMAND_HOLD:
2319                    result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2320                    break;
2321                case MidiInstrumentMapper::PERSISTENT:
2322                    result.Add("LOAD_MODE", "PERSISTENT");
2323                    break;
2324                default:
2325                    throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2326            }
2327            result.Add("VOLUME", entry.Volume);
2328        } catch (Exception e) {
2329            result.Error(e);
2330        }
2331        return result.Produce();
2332    }
2333    
2334    String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
2335        dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
2336        LSCPResultSet result;
2337        try {
2338            String s;
2339            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
2340            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2341            for (; iter != mappings.end(); iter++) {
2342                if (s.size()) s += ",";
2343                s += "{" + ToString(MidiMapID) + ","
2344                         + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2345                         + ToString(int(iter->first.midi_prog)) + "}";
2346            }
2347            result.Add(s);
2348        } catch (Exception e) {
2349            result.Error(e);
2350        }
2351        return result.Produce();
2352    }
2353    
2354    String LSCPServer::ListAllMidiInstrumentMappings() {
2355        dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
2356        LSCPResultSet result;
2357        try {
2358            std::vector<int> maps = MidiInstrumentMapper::Maps();
2359            String s;
2360            for (int i = 0; i < maps.size(); i++) {
2361                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
2362                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2363                for (; iter != mappings.end(); iter++) {
2364                    if (s.size()) s += ",";
2365                    s += "{" + ToString(maps[i]) + ","
2366                             + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2367                             + ToString(int(iter->first.midi_prog)) + "}";
2368                }
2369            }
2370            result.Add(s);
2371        } catch (Exception e) {
2372            result.Error(e);
2373        }
2374        return result.Produce();
2375    }
2376    
2377    String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
2378        dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
2379        LSCPResultSet result;
2380        try {
2381            MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
2382        } catch (Exception e) {
2383            result.Error(e);
2384        }
2385        return result.Produce();
2386    }
2387    
2388    String LSCPServer::ClearAllMidiInstrumentMappings() {
2389        dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
2390        LSCPResultSet result;
2391        try {
2392            std::vector<int> maps = MidiInstrumentMapper::Maps();
2393            for (int i = 0; i < maps.size(); i++)
2394                MidiInstrumentMapper::RemoveAllEntries(maps[i]);
2395        } catch (Exception e) {
2396            result.Error(e);
2397        }
2398        return result.Produce();
2399    }
2400    
2401    String LSCPServer::AddMidiInstrumentMap(String MapName) {
2402        dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
2403        LSCPResultSet result;
2404        try {
2405            int MapID = MidiInstrumentMapper::AddMap(MapName);
2406            result = LSCPResultSet(MapID);
2407        } catch (Exception e) {
2408            result.Error(e);
2409        }
2410        return result.Produce();
2411    }
2412    
2413    String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
2414        dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
2415        LSCPResultSet result;
2416        try {
2417            MidiInstrumentMapper::RemoveMap(MidiMapID);
2418        } catch (Exception e) {
2419            result.Error(e);
2420        }
2421        return result.Produce();
2422    }
2423    
2424    String LSCPServer::RemoveAllMidiInstrumentMaps() {
2425        dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
2426        LSCPResultSet result;
2427        try {
2428            MidiInstrumentMapper::RemoveAllMaps();
2429        } catch (Exception e) {
2430            result.Error(e);
2431        }
2432        return result.Produce();
2433    }
2434    
2435    String LSCPServer::GetMidiInstrumentMaps() {
2436        dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
2437        LSCPResultSet result;
2438        try {
2439            result.Add(int(MidiInstrumentMapper::Maps().size()));
2440        } catch (Exception e) {
2441            result.Error(e);
2442        }
2443        return result.Produce();
2444    }
2445    
2446    String LSCPServer::ListMidiInstrumentMaps() {
2447        dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
2448        LSCPResultSet result;
2449        try {
2450            std::vector<int> maps = MidiInstrumentMapper::Maps();
2451            String sList;
2452            for (int i = 0; i < maps.size(); i++) {
2453                if (sList != "") sList += ",";
2454                sList += ToString(maps[i]);
2455            }
2456            result.Add(sList);
2457        } catch (Exception e) {
2458            result.Error(e);
2459        }
2460        return result.Produce();
2461    }
2462    
2463    String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
2464        dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2465        LSCPResultSet result;
2466        try {
2467            result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2468            result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2469        } catch (Exception e) {
2470            result.Error(e);
2471        }
2472        return result.Produce();
2473    }
2474    
2475    String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2476        dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2477        LSCPResultSet result;
2478        try {
2479            MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2480        } catch (Exception e) {
2481            result.Error(e);
2482        }
2483        return result.Produce();
2484    }
2485    
2486    /**
2487     * Set the MIDI instrument map the given sampler channel shall use for
2488     * handling MIDI program change messages. There are the following two
2489     * special (negative) values:
2490     *
2491     *    - (-1) :  set to NONE (ignore program changes)
2492     *    - (-2) :  set to DEFAULT map
2493     */
2494    String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2495        dmsg(2,("LSCPServer: SetChannelMap()\n"));
2496        LSCPResultSet result;
2497        try {
2498            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2499    
2500            if      (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2501            else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2502            else                      pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2503        } catch (Exception e) {
2504            result.Error(e);
2505        }
2506        return result.Produce();
2507    }
2508    
2509    String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2510        dmsg(2,("LSCPServer: CreateFxSend()\n"));
2511        LSCPResultSet result;
2512        try {
2513            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2514    
2515            FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2516            if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2517    
2518            result = LSCPResultSet(pFxSend->Id()); // success
2519        } catch (Exception e) {
2520            result.Error(e);
2521        }
2522        return result.Produce();
2523    }
2524    
2525    String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2526        dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2527        LSCPResultSet result;
2528        try {
2529            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2530    
2531            FxSend* pFxSend = NULL;
2532            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2533                if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2534                    pFxSend = pEngineChannel->GetFxSend(i);
2535                    break;
2536                }
2537            }
2538            if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2539            pEngineChannel->RemoveFxSend(pFxSend);
2540        } catch (Exception e) {
2541            result.Error(e);
2542        }
2543        return result.Produce();
2544    }
2545    
2546    String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2547        dmsg(2,("LSCPServer: GetFxSends()\n"));
2548        LSCPResultSet result;
2549        try {
2550            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2551    
2552            result.Add(pEngineChannel->GetFxSendCount());
2553        } catch (Exception e) {
2554            result.Error(e);
2555        }
2556        return result.Produce();
2557    }
2558    
2559    String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2560        dmsg(2,("LSCPServer: ListFxSends()\n"));
2561        LSCPResultSet result;
2562        String list;
2563        try {
2564            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2565    
2566            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2567                FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2568                if (list != "") list += ",";
2569                list += ToString(pFxSend->Id());
2570            }
2571            result.Add(list);
2572        } catch (Exception e) {
2573            result.Error(e);
2574        }
2575        return result.Produce();
2576    }
2577    
2578    FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2579        EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2580    
2581        FxSend* pFxSend = NULL;
2582        for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2583            if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2584                pFxSend = pEngineChannel->GetFxSend(i);
2585                break;
2586            }
2587        }
2588        if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2589        return pFxSend;
2590    }
2591    
2592    String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2593        dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2594        LSCPResultSet result;
2595        try {
2596            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2597            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2598    
2599            // gather audio routing informations
2600            String AudioRouting;
2601            for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2602                if (AudioRouting != "") AudioRouting += ",";
2603                AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2604            }
2605    
2606            const String sEffectRouting =
2607                (pFxSend->DestinationEffectChain() >= 0 && pFxSend->DestinationEffectChainPosition() >= 0)
2608                    ? ToString(pFxSend->DestinationEffectChain()) + "," + ToString(pFxSend->DestinationEffectChainPosition())
2609                    : "NONE";
2610    
2611            // success
2612            result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2613            result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2614            result.Add("LEVEL", ToString(pFxSend->Level()));
2615            result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2616            result.Add("EFFECT", sEffectRouting);
2617        } catch (Exception e) {
2618            result.Error(e);
2619        }
2620        return result.Produce();
2621    }
2622    
2623    String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2624        dmsg(2,("LSCPServer: SetFxSendName()\n"));
2625        LSCPResultSet result;
2626        try {
2627            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2628    
2629            pFxSend->SetName(Name);
2630            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2631        } catch (Exception e) {
2632            result.Error(e);
2633        }
2634        return result.Produce();
2635    }
2636    
2637    String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2638        dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2639        LSCPResultSet result;
2640        try {
2641            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2642    
2643            pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2644            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2645        } catch (Exception e) {
2646            result.Error(e);
2647        }
2648        return result.Produce();
2649    }
2650    
2651    String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2652        dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2653        LSCPResultSet result;
2654        try {
2655            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2656    
2657            pFxSend->SetMidiController(MidiController);
2658            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2659        } catch (Exception e) {
2660            result.Error(e);
2661        }
2662        return result.Produce();
2663    }
2664    
2665    String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2666        dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2667        LSCPResultSet result;
2668        try {
2669            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2670    
2671            pFxSend->SetLevel((float)dLevel);
2672            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2673        } catch (Exception e) {
2674            result.Error(e);
2675        }
2676        return result.Produce();
2677    }
2678    
2679    String LSCPServer::SetFxSendEffect(uint uiSamplerChannel, uint FxSendID, int iSendEffectChain, int iEffectChainPosition) {
2680        dmsg(2,("LSCPServer: SetFxSendEffect(%d,%d)\n", iSendEffectChain, iEffectChainPosition));
2681        LSCPResultSet result;
2682        try {
2683            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2684    
2685            pFxSend->SetDestinationEffect(iSendEffectChain, iEffectChainPosition);
2686            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2687        } catch (Exception e) {
2688            result.Error(e);
2689        }
2690        return result.Produce();
2691    }
2692    
2693    String LSCPServer::GetAvailableEffects() {
2694        dmsg(2,("LSCPServer: GetAvailableEffects()\n"));
2695        LSCPResultSet result;
2696        try {
2697            int n = EffectFactory::AvailableEffectsCount();
2698            result.Add(n);
2699        }
2700        catch (Exception e) {
2701            result.Error(e);
2702        }
2703        return result.Produce();
2704    }
2705    
2706    String LSCPServer::ListAvailableEffects() {
2707        dmsg(2,("LSCPServer: ListAvailableEffects()\n"));
2708        LSCPResultSet result;
2709        String list;
2710        try {
2711            //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
2712            int n = EffectFactory::AvailableEffectsCount();
2713            for (int i = 0; i < n; i++) {
2714                if (i) list += ",";
2715                list += ToString(i);
2716            }
2717        }
2718        catch (Exception e) {
2719            result.Error(e);
2720        }
2721        result.Add(list);
2722        return result.Produce();
2723    }
2724    
2725    String LSCPServer::GetEffectInfo(int iEffectIndex) {
2726        dmsg(2,("LSCPServer: GetEffectInfo(%d)\n", iEffectIndex));
2727        LSCPResultSet result;
2728        try {
2729            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2730            if (!pEffectInfo)
2731                throw Exception("There is no effect with index " + ToString(iEffectIndex));
2732    
2733            // convert the filename into the correct encoding as defined for LSCP
2734            // (especially in terms of special characters -> escape sequences)
2735    #if WIN32
2736            const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2737    #else
2738            // assuming POSIX
2739            const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2740    #endif
2741    
2742            result.Add("SYSTEM", pEffectInfo->EffectSystem());
2743            result.Add("MODULE", dllFileName);
2744            result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2745            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2746        }
2747        catch (Exception e) {
2748            result.Error(e);
2749        }
2750        return result.Produce();    
2751    }
2752    
2753    String LSCPServer::GetEffectInstanceInfo(int iEffectInstance) {
2754        dmsg(2,("LSCPServer: GetEffectInstanceInfo(%d)\n", iEffectInstance));
2755        LSCPResultSet result;
2756        try {
2757            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2758            if (!pEffect)
2759                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2760    
2761            EffectInfo* pEffectInfo = pEffect->GetEffectInfo();
2762    
2763            // convert the filename into the correct encoding as defined for LSCP
2764            // (especially in terms of special characters -> escape sequences)
2765    #if WIN32
2766            const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2767    #else
2768            // assuming POSIX
2769            const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2770    #endif
2771    
2772            result.Add("SYSTEM", pEffectInfo->EffectSystem());
2773            result.Add("MODULE", dllFileName);
2774            result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2775            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2776            result.Add("INPUT_CONTROLS", ToString(pEffect->InputControlCount()));
2777        }
2778        catch (Exception e) {
2779            result.Error(e);
2780        }
2781        return result.Produce();
2782    }
2783    
2784    String LSCPServer::GetEffectInstanceInputControlInfo(int iEffectInstance, int iInputControlIndex) {
2785        dmsg(2,("LSCPServer: GetEffectInstanceInputControlInfo(%d,%d)\n", iEffectInstance, iInputControlIndex));
2786        LSCPResultSet result;
2787        try {
2788            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2789            if (!pEffect)
2790                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2791    
2792            EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2793            if (!pEffectControl)
2794                throw Exception(
2795                    "Effect instance " + ToString(iEffectInstance) +
2796                    " does not have an input control with index " +
2797                    ToString(iInputControlIndex)
2798                );
2799    
2800            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectControl->Description()));
2801            result.Add("VALUE", pEffectControl->Value());
2802            if (pEffectControl->MinValue())
2803                 result.Add("RANGE_MIN", *pEffectControl->MinValue());
2804            if (pEffectControl->MaxValue())
2805                 result.Add("RANGE_MAX", *pEffectControl->MaxValue());
2806            if (!pEffectControl->Possibilities().empty())
2807                 result.Add("POSSIBILITIES", pEffectControl->Possibilities());
2808            if (pEffectControl->DefaultValue())
2809                 result.Add("DEFAULT", *pEffectControl->DefaultValue());
2810        } catch (Exception e) {
2811            result.Error(e);
2812        }
2813        return result.Produce();
2814    }
2815    
2816    String LSCPServer::SetEffectInstanceInputControlValue(int iEffectInstance, int iInputControlIndex, double dValue) {
2817        dmsg(2,("LSCPServer: SetEffectInstanceInputControlValue(%d,%d,%f)\n", iEffectInstance, iInputControlIndex, dValue));
2818        LSCPResultSet result;
2819        try {
2820            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2821            if (!pEffect)
2822                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2823    
2824            EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2825            if (!pEffectControl)
2826                throw Exception(
2827                    "Effect instance " + ToString(iEffectInstance) +
2828                    " does not have an input control with index " +
2829                    ToString(iInputControlIndex)
2830                );
2831    
2832            pEffectControl->SetValue(dValue);
2833            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_info, iEffectInstance));
2834        } catch (Exception e) {
2835            result.Error(e);
2836        }
2837        return result.Produce();
2838    }
2839    
2840    String LSCPServer::CreateEffectInstance(int iEffectIndex) {
2841        dmsg(2,("LSCPServer: CreateEffectInstance(%d)\n", iEffectIndex));
2842        LSCPResultSet result;
2843        try {
2844            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2845            if (!pEffectInfo)
2846                throw Exception("There is no effect with index " + ToString(iEffectIndex));
2847            Effect* pEffect = EffectFactory::Create(pEffectInfo);
2848            result = pEffect->ID(); // success
2849            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2850        } catch (Exception e) {
2851            result.Error(e);
2852        }
2853        return result.Produce();
2854    }
2855    
2856    String LSCPServer::CreateEffectInstance(String effectSystem, String module, String effectName) {
2857        dmsg(2,("LSCPServer: CreateEffectInstance('%s','%s','%s')\n", effectSystem.c_str(), module.c_str(), effectName.c_str()));
2858        LSCPResultSet result;
2859        try {
2860            // to allow loading the same LSCP session file on different systems
2861            // successfully, probably with different effect plugin DLL paths or even
2862            // running completely different operating systems, we do the following
2863            // for finding the right effect:
2864            //
2865            // first try to search for an exact match of the effect plugin DLL
2866            // (a.k.a 'module'), to avoid picking the wrong DLL with the same
2867            // effect name ...
2868            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_MATCH_EXACTLY);
2869            // ... if no effect with exactly matchin DLL filename was found, then
2870            // try to lower the restrictions of matching the effect plugin DLL
2871            // filename and try again and again ...
2872            if (!pEffectInfo) {
2873                dmsg(2,("no exact module match, trying MODULE_IGNORE_PATH\n"));
2874                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH);
2875            }
2876            if (!pEffectInfo) {
2877                dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE\n"));
2878                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE);
2879            }
2880            if (!pEffectInfo) {
2881                dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE | MODULE_IGNORE_EXTENSION\n"));
2882                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE | EffectFactory::MODULE_IGNORE_EXTENSION);
2883            }
2884            // ... if there was still no effect found, then completely ignore the
2885            // DLL plugin filename argument and just search for the matching effect
2886            // system type and effect name
2887            if (!pEffectInfo) {
2888                dmsg(2,("no module match, trying MODULE_IGNORE_ALL\n"));
2889                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_ALL);
2890            }
2891            if (!pEffectInfo)
2892                throw Exception("There is no such effect '" + effectSystem + "' '" + module + "' '" + effectName + "'");
2893    
2894            Effect* pEffect = EffectFactory::Create(pEffectInfo);
2895            result = LSCPResultSet(pEffect->ID());
2896            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2897        } catch (Exception e) {
2898            result.Error(e);
2899        }
2900        return result.Produce();
2901    }
2902    
2903    String LSCPServer::DestroyEffectInstance(int iEffectInstance) {
2904        dmsg(2,("LSCPServer: DestroyEffectInstance(%d)\n", iEffectInstance));
2905        LSCPResultSet result;
2906        try {
2907            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2908            if (!pEffect)
2909                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2910            EffectFactory::Destroy(pEffect);
2911            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2912        } catch (Exception e) {
2913            result.Error(e);
2914        }
2915        return result.Produce();
2916    }
2917    
2918    String LSCPServer::GetEffectInstances() {
2919        dmsg(2,("LSCPServer: GetEffectInstances()\n"));
2920        LSCPResultSet result;
2921        try {
2922            int n = EffectFactory::EffectInstancesCount();
2923            result.Add(n);
2924        } catch (Exception e) {
2925            result.Error(e);
2926        }
2927        return result.Produce();
2928    }
2929    
2930    String LSCPServer::ListEffectInstances() {
2931        dmsg(2,("LSCPServer: ListEffectInstances()\n"));
2932        LSCPResultSet result;
2933        String list;
2934        try {
2935            int n = EffectFactory::EffectInstancesCount();
2936            for (int i = 0; i < n; i++) {
2937                Effect* pEffect = EffectFactory::GetEffectInstance(i);
2938                if (i) list += ",";
2939                list += ToString(pEffect->ID());
2940            }
2941        } catch (Exception e) {
2942            result.Error(e);
2943        }
2944        result.Add(list);
2945        return result.Produce();
2946    }
2947    
2948    String LSCPServer::GetSendEffectChains(int iAudioOutputDevice) {
2949        dmsg(2,("LSCPServer: GetSendEffectChains(%d)\n", iAudioOutputDevice));
2950        LSCPResultSet result;
2951        try {
2952            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2953            if (!devices.count(iAudioOutputDevice))
2954                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2955            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2956            int n = pDevice->SendEffectChainCount();
2957            result.Add(n);
2958        } catch (Exception e) {
2959            result.Error(e);
2960        }
2961        return result.Produce();
2962    }
2963    
2964    String LSCPServer::ListSendEffectChains(int iAudioOutputDevice) {
2965        dmsg(2,("LSCPServer: ListSendEffectChains(%d)\n", iAudioOutputDevice));
2966        LSCPResultSet result;
2967        String list;
2968        try {
2969            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2970            if (!devices.count(iAudioOutputDevice))
2971                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2972            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2973            int n = pDevice->SendEffectChainCount();
2974            for (int i = 0; i < n; i++) {
2975                EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2976                if (i) list += ",";
2977                list += ToString(pEffectChain->ID());
2978            }
2979        } catch (Exception e) {
2980            result.Error(e);
2981        }
2982        result.Add(list);
2983        return result.Produce();
2984    }
2985    
2986    String LSCPServer::AddSendEffectChain(int iAudioOutputDevice) {
2987        dmsg(2,("LSCPServer: AddSendEffectChain(%d)\n", iAudioOutputDevice));
2988        LSCPResultSet result;
2989        try {
2990            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2991            if (!devices.count(iAudioOutputDevice))
2992                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2993            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2994            EffectChain* pEffectChain = pDevice->AddSendEffectChain();
2995            result = pEffectChain->ID();
2996            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2997        } catch (Exception e) {
2998            result.Error(e);
2999        }
3000        return result.Produce();
3001    }
3002    
3003    String LSCPServer::RemoveSendEffectChain(int iAudioOutputDevice, int iSendEffectChain) {
3004        dmsg(2,("LSCPServer: RemoveSendEffectChain(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
3005        LSCPResultSet result;
3006        try {
3007            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
3008            if (!devices.count(iAudioOutputDevice))
3009                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
3010    
3011            std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
3012            std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
3013            std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
3014            for (; itEngineChannel != itEnd; ++itEngineChannel) {
3015                AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
3016                if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
3017                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
3018                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
3019                        if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain) {
3020                            throw Exception("The effect chain is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
3021                        }
3022                    }
3023                }
3024            }
3025    
3026            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
3027            for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
3028                EffectChain* pEffectChain = pDevice->SendEffectChain(i);
3029                if (pEffectChain->ID() == iSendEffectChain) {
3030                    pDevice->RemoveSendEffectChain(i);
3031                    LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
3032                    return result.Produce();
3033                }
3034            }
3035            throw Exception(
3036                "There is no send effect chain with ID " +
3037                ToString(iSendEffectChain) + " for audio output device " +
3038                ToString(iAudioOutputDevice) + "."
3039            );
3040        } catch (Exception e) {
3041            result.Error(e);
3042        }
3043        return result.Produce();
3044    }
3045    
3046    static EffectChain* _getSendEffectChain(Sampler* pSampler, int iAudioOutputDevice, int iSendEffectChain) throw (Exception) {
3047        std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
3048        if (!devices.count(iAudioOutputDevice))
3049            throw Exception(
3050                "There is no audio output device with index " +
3051                ToString(iAudioOutputDevice) + "."
3052            );
3053        AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
3054        EffectChain* pEffectChain = pDevice->SendEffectChainByID(iSendEffectChain);
3055        if(pEffectChain != NULL) return pEffectChain;
3056        throw Exception(
3057            "There is no send effect chain with ID " +
3058            ToString(iSendEffectChain) + " for audio output device " +
3059            ToString(iAudioOutputDevice) + "."
3060        );
3061    }
3062    
3063    String LSCPServer::GetSendEffectChainInfo(int iAudioOutputDevice, int iSendEffectChain) {
3064        dmsg(2,("LSCPServer: GetSendEffectChainInfo(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
3065        LSCPResultSet result;
3066        try {
3067            EffectChain* pEffectChain =
3068                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3069            String sEffectSequence;
3070            for (int i = 0; i < pEffectChain->EffectCount(); i++) {
3071                if (i) sEffectSequence += ",";
3072                sEffectSequence += ToString(pEffectChain->GetEffect(i)->ID());
3073            }
3074            result.Add("EFFECT_COUNT", pEffectChain->EffectCount());
3075            result.Add("EFFECT_SEQUENCE", sEffectSequence);
3076        } catch (Exception e) {
3077            result.Error(e);
3078        }
3079        return result.Produce();
3080    }
3081    
3082    String LSCPServer::AppendSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectInstance) {
3083        dmsg(2,("LSCPServer: AppendSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectInstance));
3084        LSCPResultSet result;
3085        try {
3086            EffectChain* pEffectChain =
3087                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3088            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
3089            if (!pEffect)
3090                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
3091            pEffectChain->AppendEffect(pEffect);
3092            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3093        } catch (Exception e) {
3094            result.Error(e);
3095        }
3096        return result.Produce();
3097    }
3098    
3099    String LSCPServer::InsertSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition, int iEffectInstance) {
3100        dmsg(2,("LSCPServer: InsertSendEffectChainEffect(%d,%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition, iEffectInstance));
3101        LSCPResultSet result;
3102        try {
3103            EffectChain* pEffectChain =
3104                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3105            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
3106            if (!pEffect)
3107                throw Exception("There is no effect instance with index " + ToString(iEffectInstance));
3108            pEffectChain->InsertEffect(pEffect, iEffectChainPosition);
3109            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3110        } catch (Exception e) {
3111            result.Error(e);
3112        }
3113        return result.Produce();
3114    }
3115    
3116    String LSCPServer::RemoveSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition) {
3117        dmsg(2,("LSCPServer: RemoveSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition));
3118        LSCPResultSet result;
3119        try {
3120            EffectChain* pEffectChain =
3121                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3122    
3123            std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
3124            std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
3125            std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
3126            for (; itEngineChannel != itEnd; ++itEngineChannel) {
3127                AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
3128                if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
3129                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
3130                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
3131                        if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain && fxs->DestinationEffectChainPosition() == iEffectChainPosition) {
3132                            throw Exception("The effect instance is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
3133                        }
3134                    }
3135                }
3136            }
3137    
3138            pEffectChain->RemoveEffect(iEffectChainPosition);
3139            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3140        } catch (Exception e) {
3141            result.Error(e);
3142        }
3143        return result.Produce();
3144    }
3145    
3146    String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
3147        dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
3148        LSCPResultSet result;
3149        try {
3150            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3151            if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
3152            Engine* pEngine = pEngineChannel->GetEngine();
3153            InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
3154            if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
3155            InstrumentManager::instrument_id_t instrumentID;
3156            instrumentID.FileName = pEngineChannel->InstrumentFileName();
3157            instrumentID.Index    = pEngineChannel->InstrumentIndex();
3158            pInstrumentManager->LaunchInstrumentEditor(pEngineChannel, instrumentID);
3159        } catch (Exception e) {
3160            result.Error(e);
3161        }
3162        return result.Produce();
3163    }
3164    
3165    String LSCPServer::SendChannelMidiData(String MidiMsg, uint uiSamplerChannel, uint Arg1, uint Arg2) {
3166        dmsg(2,("LSCPServer: SendChannelMidiData(MidiMsg=%s,uiSamplerChannel=%d,Arg1=%d,Arg2=%d)\n", MidiMsg.c_str(), uiSamplerChannel, Arg1, Arg2));
3167        LSCPResultSet result;
3168        try {
3169            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3170    
3171            if (Arg1 > 127 || Arg2 > 127) {
3172                throw Exception("Invalid MIDI message");
3173            }
3174    
3175            VirtualMidiDevice* pMidiDevice = NULL;
3176            std::vector<EventHandler::midi_listener_entry>::iterator iter = eventHandler.channelMidiListeners.begin();
3177            for (; iter != eventHandler.channelMidiListeners.end(); ++iter) {
3178                if ((*iter).pEngineChannel == pEngineChannel) {
3179                    pMidiDevice = (*iter).pMidiListener;
3180                    break;
3181                }
3182            }
3183            
3184            if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
3185    
3186            if (MidiMsg == "NOTE_ON") {
3187                pMidiDevice->SendNoteOnToDevice(Arg1, Arg2);
3188                bool b = pMidiDevice->SendNoteOnToSampler(Arg1, Arg2);
3189                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3190            } else if (MidiMsg == "NOTE_OFF") {
3191                pMidiDevice->SendNoteOffToDevice(Arg1, Arg2);
3192                bool b = pMidiDevice->SendNoteOffToSampler(Arg1, Arg2);
3193                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3194            } else if (MidiMsg == "CC") {
3195                pMidiDevice->SendCCToDevice(Arg1, Arg2);
3196                bool b = pMidiDevice->SendCCToSampler(Arg1, Arg2);
3197                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3198            } else {
3199                throw Exception("Unknown MIDI message type: " + MidiMsg);
3200            }
3201        } catch (Exception e) {
3202            result.Error(e);
3203        }
3204        return result.Produce();
3205    }
3206    
3207  /**  /**
3208   * Will be called by the parser to reset a particular sampler channel.   * Will be called by the parser to reset a particular sampler channel.
3209   */   */
# Line 1517  String LSCPServer::ResetChannel(uint uiS Line 3211  String LSCPServer::ResetChannel(uint uiS
3211      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
3212      LSCPResultSet result;      LSCPResultSet result;
3213      try {      try {
3214          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");  
3215          pEngineChannel->Reset();          pEngineChannel->Reset();
3216      }      }
3217      catch (LinuxSamplerException e) {      catch (Exception e) {
3218           result.Error(e);           result.Error(e);
3219      }      }
3220      return result.Produce();      return result.Produce();
# Line 1545  String LSCPServer::ResetSampler() { Line 3236  String LSCPServer::ResetSampler() {
3236   */   */
3237  String LSCPServer::GetServerInfo() {  String LSCPServer::GetServerInfo() {
3238      dmsg(2,("LSCPServer: GetServerInfo()\n"));      dmsg(2,("LSCPServer: GetServerInfo()\n"));
3239        const std::string description =
3240            _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
3241      LSCPResultSet result;      LSCPResultSet result;
3242      result.Add("DESCRIPTION", "LinuxSampler - modular, streaming capable sampler");      result.Add("DESCRIPTION", description);
3243      result.Add("VERSION", VERSION);      result.Add("VERSION", VERSION);
3244      result.Add("PROTOCOL_VERSION", "1.0");      result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
3245    #if HAVE_SQLITE3
3246        result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
3247    #else
3248        result.Add("INSTRUMENTS_DB_SUPPORT", "no");
3249    #endif
3250    
3251        return result.Produce();
3252    }
3253    
3254    /**
3255     * Will be called by the parser to return the current number of all active streams.
3256     */
3257    String LSCPServer::GetTotalStreamCount() {
3258        dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
3259        LSCPResultSet result;
3260        result.Add(pSampler->GetDiskStreamCount());
3261      return result.Produce();      return result.Produce();
3262  }  }
3263    
# Line 1568  String LSCPServer::GetTotalVoiceCount() Line 3277  String LSCPServer::GetTotalVoiceCount()
3277  String LSCPServer::GetTotalVoiceCountMax() {  String LSCPServer::GetTotalVoiceCountMax() {
3278      dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));      dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3279      LSCPResultSet result;      LSCPResultSet result;
3280      result.Add(EngineFactory::EngineInstances().size() * CONFIG_MAX_VOICES);      result.Add(int(EngineFactory::EngineInstances().size() * pSampler->GetGlobalMaxVoices()));
3281        return result.Produce();
3282    }
3283    
3284    /**
3285     * Will be called by the parser to return the sampler global maximum
3286     * allowed number of voices.
3287     */
3288    String LSCPServer::GetGlobalMaxVoices() {
3289        dmsg(2,("LSCPServer: GetGlobalMaxVoices()\n"));
3290        LSCPResultSet result;
3291        result.Add(pSampler->GetGlobalMaxVoices());
3292        return result.Produce();
3293    }
3294    
3295    /**
3296     * Will be called by the parser to set the sampler global maximum number of
3297     * voices.
3298     */
3299    String LSCPServer::SetGlobalMaxVoices(int iVoices) {
3300        dmsg(2,("LSCPServer: SetGlobalMaxVoices(%d)\n", iVoices));
3301        LSCPResultSet result;
3302        try {
3303            pSampler->SetGlobalMaxVoices(iVoices);
3304            LSCPServer::SendLSCPNotify(
3305                LSCPEvent(LSCPEvent::event_global_info, "VOICES", pSampler->GetGlobalMaxVoices())
3306            );
3307        } catch (Exception e) {
3308            result.Error(e);
3309        }
3310        return result.Produce();
3311    }
3312    
3313    /**
3314     * Will be called by the parser to return the sampler global maximum
3315     * allowed number of disk streams.
3316     */
3317    String LSCPServer::GetGlobalMaxStreams() {
3318        dmsg(2,("LSCPServer: GetGlobalMaxStreams()\n"));
3319        LSCPResultSet result;
3320        result.Add(pSampler->GetGlobalMaxStreams());
3321        return result.Produce();
3322    }
3323    
3324    /**
3325     * Will be called by the parser to set the sampler global maximum number of
3326     * disk streams.
3327     */
3328    String LSCPServer::SetGlobalMaxStreams(int iStreams) {
3329        dmsg(2,("LSCPServer: SetGlobalMaxStreams(%d)\n", iStreams));
3330        LSCPResultSet result;
3331        try {
3332            pSampler->SetGlobalMaxStreams(iStreams);
3333            LSCPServer::SendLSCPNotify(
3334                LSCPEvent(LSCPEvent::event_global_info, "STREAMS", pSampler->GetGlobalMaxStreams())
3335            );
3336        } catch (Exception e) {
3337            result.Error(e);
3338        }
3339        return result.Produce();
3340    }
3341    
3342    String LSCPServer::GetGlobalVolume() {
3343        LSCPResultSet result;
3344        result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
3345        return result.Produce();
3346    }
3347    
3348    String LSCPServer::SetGlobalVolume(double dVolume) {
3349        LSCPResultSet result;
3350        try {
3351            if (dVolume < 0) throw Exception("Volume may not be negative");
3352            GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3353            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3354        } catch (Exception e) {
3355            result.Error(e);
3356        }
3357        return result.Produce();
3358    }
3359    
3360    String LSCPServer::GetFileInstruments(String Filename) {
3361        dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
3362        LSCPResultSet result;
3363        try {
3364            VerifyFile(Filename);
3365        } catch (Exception e) {
3366            result.Error(e);
3367            return result.Produce();
3368        }
3369        // try to find a sampler engine that can handle the file
3370        bool bFound = false;
3371        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3372        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3373            Engine* pEngine = NULL;
3374            try {
3375                pEngine = EngineFactory::Create(engineTypes[i]);
3376                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3377                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3378                if (pManager) {
3379                    std::vector<InstrumentManager::instrument_id_t> IDs =
3380                        pManager->GetInstrumentFileContent(Filename);
3381                    // return the amount of instruments in the file
3382                    result.Add((int)IDs.size());
3383                    // no more need to ask other engine types
3384                    bFound = true;
3385                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3386            } catch (Exception e) {
3387                // NOOP, as exception is thrown if engine doesn't support file
3388            }
3389            if (pEngine) EngineFactory::Destroy(pEngine);
3390        }
3391    
3392        if (!bFound) result.Error("Unknown file format");
3393        return result.Produce();
3394    }
3395    
3396    String LSCPServer::ListFileInstruments(String Filename) {
3397        dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
3398        LSCPResultSet result;
3399        try {
3400            VerifyFile(Filename);
3401        } catch (Exception e) {
3402            result.Error(e);
3403            return result.Produce();
3404        }
3405        // try to find a sampler engine that can handle the file
3406        bool bFound = false;
3407        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3408        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3409            Engine* pEngine = NULL;
3410            try {
3411                pEngine = EngineFactory::Create(engineTypes[i]);
3412                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3413                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3414                if (pManager) {
3415                    std::vector<InstrumentManager::instrument_id_t> IDs =
3416                        pManager->GetInstrumentFileContent(Filename);
3417                    // return a list of IDs of the instruments in the file
3418                    String s;
3419                    for (int j = 0; j < IDs.size(); j++) {
3420                        if (s.size()) s += ",";
3421                        s += ToString(IDs[j].Index);
3422                    }
3423                    result.Add(s);
3424                    // no more need to ask other engine types
3425                    bFound = true;
3426                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3427            } catch (Exception e) {
3428                // NOOP, as exception is thrown if engine doesn't support file
3429            }
3430            if (pEngine) EngineFactory::Destroy(pEngine);
3431        }
3432    
3433        if (!bFound) result.Error("Unknown file format");
3434        return result.Produce();
3435    }
3436    
3437    String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
3438        dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
3439        LSCPResultSet result;
3440        try {
3441            VerifyFile(Filename);
3442        } catch (Exception e) {
3443            result.Error(e);
3444            return result.Produce();
3445        }
3446        InstrumentManager::instrument_id_t id;
3447        id.FileName = Filename;
3448        id.Index    = InstrumentID;
3449        // try to find a sampler engine that can handle the file
3450        bool bFound = false;
3451        bool bFatalErr = false;
3452        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3453        for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
3454            Engine* pEngine = NULL;
3455            try {
3456                pEngine = EngineFactory::Create(engineTypes[i]);
3457                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3458                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3459                if (pManager) {
3460                    // check if the instrument index is valid
3461                    // FIXME: this won't work if an engine only supports parts of the instrument file
3462                    std::vector<InstrumentManager::instrument_id_t> IDs =
3463                        pManager->GetInstrumentFileContent(Filename);
3464                    if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
3465                        std::stringstream ss;
3466                        ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
3467                        bFatalErr = true;
3468                        throw Exception(ss.str());
3469                    }
3470                    // get the info of the requested instrument
3471                    InstrumentManager::instrument_info_t info =
3472                        pManager->GetInstrumentInfo(id);
3473                    // return detailed informations about the file
3474                    result.Add("NAME", info.InstrumentName);
3475                    result.Add("FORMAT_FAMILY", engineTypes[i]);
3476                    result.Add("FORMAT_VERSION", info.FormatVersion);
3477                    result.Add("PRODUCT", info.Product);
3478                    result.Add("ARTISTS", info.Artists);
3479    
3480                    std::stringstream ss;
3481                    bool b = false;
3482                    for (int i = 0; i < 128; i++) {
3483                        if (info.KeyBindings[i]) {
3484                            if (b) ss << ',';
3485                            ss << i; b = true;
3486                        }
3487                    }
3488                    result.Add("KEY_BINDINGS", ss.str());
3489    
3490                    b = false;
3491                    std::stringstream ss2;
3492                    for (int i = 0; i < 128; i++) {
3493                        if (info.KeySwitchBindings[i]) {
3494                            if (b) ss2 << ',';
3495                            ss2 << i; b = true;
3496                        }
3497                    }
3498                    result.Add("KEYSWITCH_BINDINGS", ss2.str());
3499                    // no more need to ask other engine types
3500                    bFound = true;
3501                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3502            } catch (Exception e) {
3503                // usually NOOP, as exception is thrown if engine doesn't support file
3504                if (bFatalErr) result.Error(e);
3505            }
3506            if (pEngine) EngineFactory::Destroy(pEngine);
3507        }
3508    
3509        if (!bFound && !bFatalErr) result.Error("Unknown file format");
3510      return result.Produce();      return result.Produce();
3511  }  }
3512    
3513    void LSCPServer::VerifyFile(String Filename) {
3514        #if WIN32
3515        WIN32_FIND_DATA win32FileAttributeData;
3516        BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
3517        if (!res) {
3518            std::stringstream ss;
3519            ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
3520            throw Exception(ss.str());
3521        }
3522        if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
3523            throw Exception("Directory is specified");
3524        }
3525        #else
3526        File f(Filename);
3527        if(!f.Exist()) throw Exception(f.GetErrorMsg());
3528        if (f.IsDirectory()) throw Exception("Directory is specified");
3529        #endif
3530    }
3531    
3532  /**  /**
3533   * 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
3534   * server for receiving event messages.   * server for receiving event messages.
# Line 1579  String LSCPServer::GetTotalVoiceCountMax Line 3536  String LSCPServer::GetTotalVoiceCountMax
3536  String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {  String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
3537      dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));      dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3538      LSCPResultSet result;      LSCPResultSet result;
3539      SubscriptionMutex.Lock();      {
3540      eventSubscriptions[type].push_back(currentSocket);          LockGuard lock(SubscriptionMutex);
3541      SubscriptionMutex.Unlock();          eventSubscriptions[type].push_back(currentSocket);
3542        }
3543      return result.Produce();      return result.Produce();
3544  }  }
3545    
# Line 1592  String LSCPServer::SubscribeNotification Line 3550  String LSCPServer::SubscribeNotification
3550  String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {  String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
3551      dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));      dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3552      LSCPResultSet result;      LSCPResultSet result;
3553      SubscriptionMutex.Lock();      {
3554      eventSubscriptions[type].remove(currentSocket);          LockGuard lock(SubscriptionMutex);
3555      SubscriptionMutex.Unlock();          eventSubscriptions[type].remove(currentSocket);
3556        }
3557      return result.Produce();      return result.Produce();
3558  }  }
3559    
3560  static int select_callback(void * lscpResultSet, int argc,  String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3561                          char **argv, char **azColName)      dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3562  {      LSCPResultSet result;
3563      LSCPResultSet* resultSet = (LSCPResultSet*) lscpResultSet;  #if HAVE_SQLITE3
3564      resultSet->Add(argc, argv);      try {
3565      return 0;          InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
3566        } catch (Exception e) {
3567             result.Error(e);
3568        }
3569    #else
3570        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3571    #endif
3572        return result.Produce();
3573  }  }
3574    
3575  String LSCPServer::QueryDatabase(String query) {  String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3576        dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3577      LSCPResultSet result;      LSCPResultSet result;
3578  #if HAVE_SQLITE3  #if HAVE_SQLITE3
3579      char* zErrMsg = NULL;      try {
3580      sqlite3 *db;          InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3581      String selectStr = "SELECT " + query;      } catch (Exception e) {
3582             result.Error(e);
3583        }
3584    #else
3585        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3586    #endif
3587        return result.Produce();
3588    }
3589    
3590      int rc = sqlite3_open("linuxsampler.db", &db);  String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3591      if (rc == SQLITE_OK)      dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3592      {      LSCPResultSet result;
3593              rc = sqlite3_exec(db, selectStr.c_str(), select_callback, &result, &zErrMsg);  #if HAVE_SQLITE3
3594        try {
3595            result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
3596        } catch (Exception e) {
3597             result.Error(e);
3598      }      }
3599      if ( rc != SQLITE_OK )  #else
3600      {      result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3601              result.Error(String(zErrMsg), rc);  #endif
3602        return result.Produce();
3603    }
3604    
3605    String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
3606        dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3607        LSCPResultSet result;
3608    #if HAVE_SQLITE3
3609        try {
3610            String list;
3611            StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
3612    
3613            for (int i = 0; i < dirs->size(); i++) {
3614                if (list != "") list += ",";
3615                list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
3616            }
3617    
3618            result.Add(list);
3619        } catch (Exception e) {
3620             result.Error(e);
3621        }
3622    #else
3623        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3624    #endif
3625        return result.Produce();
3626    }
3627    
3628    String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
3629        dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
3630        LSCPResultSet result;
3631    #if HAVE_SQLITE3
3632        try {
3633            DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
3634    
3635            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3636            result.Add("CREATED", info.Created);
3637            result.Add("MODIFIED", info.Modified);
3638        } catch (Exception e) {
3639             result.Error(e);
3640        }
3641    #else
3642        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3643    #endif
3644        return result.Produce();
3645    }
3646    
3647    String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
3648        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
3649        LSCPResultSet result;
3650    #if HAVE_SQLITE3
3651        try {
3652            InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
3653        } catch (Exception e) {
3654             result.Error(e);
3655        }
3656    #else
3657        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3658    #endif
3659        return result.Produce();
3660    }
3661    
3662    String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
3663        dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3664        LSCPResultSet result;
3665    #if HAVE_SQLITE3
3666        try {
3667            InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
3668        } catch (Exception e) {
3669             result.Error(e);
3670        }
3671    #else
3672        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3673    #endif
3674        return result.Produce();
3675    }
3676    
3677    String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
3678        dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3679        LSCPResultSet result;
3680    #if HAVE_SQLITE3
3681        try {
3682            InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
3683        } catch (Exception e) {
3684             result.Error(e);
3685        }
3686    #else
3687        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3688    #endif
3689        return result.Produce();
3690    }
3691    
3692    String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3693        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3694        LSCPResultSet result;
3695    #if HAVE_SQLITE3
3696        try {
3697            InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3698        } catch (Exception e) {
3699             result.Error(e);
3700        }
3701    #else
3702        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3703    #endif
3704        return result.Produce();
3705    }
3706    
3707    String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3708        dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
3709        LSCPResultSet result;
3710    #if HAVE_SQLITE3
3711        try {
3712            int id;
3713            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3714            id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
3715            if (bBackground) result = id;
3716        } catch (Exception e) {
3717             result.Error(e);
3718        }
3719    #else
3720        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3721    #endif
3722        return result.Produce();
3723    }
3724    
3725    String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground, bool insDir) {
3726        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));
3727        LSCPResultSet result;
3728    #if HAVE_SQLITE3
3729        try {
3730            int id;
3731            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3732            if (ScanMode.compare("RECURSIVE") == 0) {
3733                id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground, insDir);
3734            } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
3735                id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground, insDir);
3736            } else if (ScanMode.compare("FLAT") == 0) {
3737                id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground, insDir);
3738            } else {
3739                throw Exception("Unknown scan mode: " + ScanMode);
3740            }
3741    
3742            if (bBackground) result = id;
3743        } catch (Exception e) {
3744             result.Error(e);
3745        }
3746    #else
3747        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3748    #endif
3749        return result.Produce();
3750    }
3751    
3752    String LSCPServer::RemoveDbInstrument(String Instr) {
3753        dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
3754        LSCPResultSet result;
3755    #if HAVE_SQLITE3
3756        try {
3757            InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
3758        } catch (Exception e) {
3759             result.Error(e);
3760        }
3761    #else
3762        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3763    #endif
3764        return result.Produce();
3765    }
3766    
3767    String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
3768        dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3769        LSCPResultSet result;
3770    #if HAVE_SQLITE3
3771        try {
3772            result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
3773        } catch (Exception e) {
3774             result.Error(e);
3775        }
3776    #else
3777        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3778    #endif
3779        return result.Produce();
3780    }
3781    
3782    String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
3783        dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3784        LSCPResultSet result;
3785    #if HAVE_SQLITE3
3786        try {
3787            String list;
3788            StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
3789    
3790            for (int i = 0; i < instrs->size(); i++) {
3791                if (list != "") list += ",";
3792                list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
3793            }
3794    
3795            result.Add(list);
3796        } catch (Exception e) {
3797             result.Error(e);
3798        }
3799    #else
3800        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3801    #endif
3802        return result.Produce();
3803    }
3804    
3805    String LSCPServer::GetDbInstrumentInfo(String Instr) {
3806        dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
3807        LSCPResultSet result;
3808    #if HAVE_SQLITE3
3809        try {
3810            DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
3811    
3812            result.Add("INSTRUMENT_FILE", info.InstrFile);
3813            result.Add("INSTRUMENT_NR", info.InstrNr);
3814            result.Add("FORMAT_FAMILY", info.FormatFamily);
3815            result.Add("FORMAT_VERSION", info.FormatVersion);
3816            result.Add("SIZE", (int)info.Size);
3817            result.Add("CREATED", info.Created);
3818            result.Add("MODIFIED", info.Modified);
3819            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3820            result.Add("IS_DRUM", info.IsDrum);
3821            result.Add("PRODUCT", _escapeLscpResponse(info.Product));
3822            result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
3823            result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
3824        } catch (Exception e) {
3825             result.Error(e);
3826        }
3827    #else
3828        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3829    #endif
3830        return result.Produce();
3831    }
3832    
3833    String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
3834        dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
3835        LSCPResultSet result;
3836    #if HAVE_SQLITE3
3837        try {
3838            ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
3839    
3840            result.Add("FILES_TOTAL", job.FilesTotal);
3841            result.Add("FILES_SCANNED", job.FilesScanned);
3842            result.Add("SCANNING", job.Scanning);
3843            result.Add("STATUS", job.Status);
3844        } catch (Exception e) {
3845             result.Error(e);
3846        }
3847    #else
3848        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3849    #endif
3850        return result.Produce();
3851    }
3852    
3853    String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
3854        dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
3855        LSCPResultSet result;
3856    #if HAVE_SQLITE3
3857        try {
3858            InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
3859        } catch (Exception e) {
3860             result.Error(e);
3861        }
3862    #else
3863        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3864    #endif
3865        return result.Produce();
3866    }
3867    
3868    String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
3869        dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3870        LSCPResultSet result;
3871    #if HAVE_SQLITE3
3872        try {
3873            InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
3874        } catch (Exception e) {
3875             result.Error(e);
3876        }
3877    #else
3878        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3879    #endif
3880        return result.Produce();
3881    }
3882    
3883    String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3884        dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3885        LSCPResultSet result;
3886    #if HAVE_SQLITE3
3887        try {
3888            InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3889        } catch (Exception e) {
3890             result.Error(e);
3891        }
3892    #else
3893        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3894    #endif
3895        return result.Produce();
3896    }
3897    
3898    String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3899        dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3900        LSCPResultSet result;
3901    #if HAVE_SQLITE3
3902        try {
3903            InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3904        } catch (Exception e) {
3905             result.Error(e);
3906        }
3907    #else
3908        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3909    #endif
3910        return result.Produce();
3911    }
3912    
3913    String LSCPServer::SetDbInstrumentFilePath(String OldPath, String NewPath) {
3914        dmsg(2,("LSCPServer: SetDbInstrumentFilePath(OldPath=%s,NewPath=%s)\n", OldPath.c_str(), NewPath.c_str()));
3915        LSCPResultSet result;
3916    #if HAVE_SQLITE3
3917        try {
3918            InstrumentsDb::GetInstrumentsDb()->SetInstrumentFilePath(OldPath, NewPath);
3919        } catch (Exception e) {
3920             result.Error(e);
3921        }
3922    #else
3923        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3924    #endif
3925        return result.Produce();
3926    }
3927    
3928    String LSCPServer::FindLostDbInstrumentFiles() {
3929        dmsg(2,("LSCPServer: FindLostDbInstrumentFiles()\n"));
3930        LSCPResultSet result;
3931    #if HAVE_SQLITE3
3932        try {
3933            String list;
3934            StringListPtr pLostFiles = InstrumentsDb::GetInstrumentsDb()->FindLostInstrumentFiles();
3935    
3936            for (int i = 0; i < pLostFiles->size(); i++) {
3937                if (list != "") list += ",";
3938                list += "'" + pLostFiles->at(i) + "'";
3939            }
3940    
3941            result.Add(list);
3942        } catch (Exception e) {
3943             result.Error(e);
3944        }
3945    #else
3946        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3947    #endif
3948        return result.Produce();
3949    }
3950    
3951    String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3952        dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3953        LSCPResultSet result;
3954    #if HAVE_SQLITE3
3955        try {
3956            SearchQuery Query;
3957            std::map<String,String>::iterator iter;
3958            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3959                if (iter->first.compare("NAME") == 0) {
3960                    Query.Name = iter->second;
3961                } else if (iter->first.compare("CREATED") == 0) {
3962                    Query.SetCreated(iter->second);
3963                } else if (iter->first.compare("MODIFIED") == 0) {
3964                    Query.SetModified(iter->second);
3965                } else if (iter->first.compare("DESCRIPTION") == 0) {
3966                    Query.Description = iter->second;
3967                } else {
3968                    throw Exception("Unknown search criteria: " + iter->first);
3969                }
3970            }
3971    
3972            String list;
3973            StringListPtr pDirectories =
3974                InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3975    
3976            for (int i = 0; i < pDirectories->size(); i++) {
3977                if (list != "") list += ",";
3978                list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3979            }
3980    
3981            result.Add(list);
3982        } catch (Exception e) {
3983             result.Error(e);
3984        }
3985    #else
3986        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3987    #endif
3988        return result.Produce();
3989    }
3990    
3991    String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
3992        dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
3993        LSCPResultSet result;
3994    #if HAVE_SQLITE3
3995        try {
3996            SearchQuery Query;
3997            std::map<String,String>::iterator iter;
3998            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3999                if (iter->first.compare("NAME") == 0) {
4000                    Query.Name = iter->second;
4001                } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
4002                    Query.SetFormatFamilies(iter->second);
4003                } else if (iter->first.compare("SIZE") == 0) {
4004                    Query.SetSize(iter->second);
4005                } else if (iter->first.compare("CREATED") == 0) {
4006                    Query.SetCreated(iter->second);
4007                } else if (iter->first.compare("MODIFIED") == 0) {
4008                    Query.SetModified(iter->second);
4009                } else if (iter->first.compare("DESCRIPTION") == 0) {
4010                    Query.Description = iter->second;
4011                } else if (iter->first.compare("IS_DRUM") == 0) {
4012                    if (!strcasecmp(iter->second.c_str(), "true")) {
4013                        Query.InstrType = SearchQuery::DRUM;
4014                    } else {
4015                        Query.InstrType = SearchQuery::CHROMATIC;
4016                    }
4017                } else if (iter->first.compare("PRODUCT") == 0) {
4018                     Query.Product = iter->second;
4019                } else if (iter->first.compare("ARTISTS") == 0) {
4020                     Query.Artists = iter->second;
4021                } else if (iter->first.compare("KEYWORDS") == 0) {
4022                     Query.Keywords = iter->second;
4023                } else {
4024                    throw Exception("Unknown search criteria: " + iter->first);
4025                }
4026            }
4027    
4028            String list;
4029            StringListPtr pInstruments =
4030                InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
4031    
4032            for (int i = 0; i < pInstruments->size(); i++) {
4033                if (list != "") list += ",";
4034                list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
4035            }
4036    
4037            result.Add(list);
4038        } catch (Exception e) {
4039             result.Error(e);
4040        }
4041    #else
4042        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
4043    #endif
4044        return result.Produce();
4045    }
4046    
4047    String LSCPServer::FormatInstrumentsDb() {
4048        dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
4049        LSCPResultSet result;
4050    #if HAVE_SQLITE3
4051        try {
4052            InstrumentsDb::GetInstrumentsDb()->Format();
4053        } catch (Exception e) {
4054             result.Error(e);
4055      }      }
     sqlite3_close(db);  
4056  #else  #else
4057      result.Error(String("SQLITE3 was not installed when linuxsampler was built. SELECT statement is not available."), 0);      result.Error(String(DOESNT_HAVE_SQLITE3), 0);
4058  #endif  #endif
4059      return result.Produce();      return result.Produce();
4060  }  }
4061    
4062    
4063  /**  /**
4064   * 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
4065   * mode is enabled, all commands from the client will (immediately) be   * mode is enabled, all commands from the client will (immediately) be
# Line 1640  String LSCPServer::SetEcho(yyparse_param Line 4071  String LSCPServer::SetEcho(yyparse_param
4071      try {      try {
4072          if      (boolean_value == 0) pSession->bVerbose = false;          if      (boolean_value == 0) pSession->bVerbose = false;
4073          else if (boolean_value == 1) pSession->bVerbose = true;          else if (boolean_value == 1) pSession->bVerbose = true;
4074          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");
4075      }      }
4076      catch (LinuxSamplerException e) {      catch (Exception e) {
4077           result.Error(e);           result.Error(e);
4078      }      }
4079      return result.Produce();      return result.Produce();
4080  }  }
4081    
4082    String LSCPServer::SetShellInteract(yyparse_param_t* pSession, double boolean_value) {
4083        dmsg(2,("LSCPServer: SetShellInteract(val=%f)\n", boolean_value));
4084        LSCPResultSet result;
4085        try {
4086            if      (boolean_value == 0) pSession->bShellInteract = false;
4087            else if (boolean_value == 1) pSession->bShellInteract = true;
4088            else throw Exception("Not a boolean value, must either be 0 or 1");
4089        } catch (Exception e) {
4090            result.Error(e);
4091        }
4092        return result.Produce();
4093    }
4094    
4095    String LSCPServer::SetShellAutoCorrect(yyparse_param_t* pSession, double boolean_value) {
4096        dmsg(2,("LSCPServer: SetShellAutoCorrect(val=%f)\n", boolean_value));
4097        LSCPResultSet result;
4098        try {
4099            if      (boolean_value == 0) pSession->bShellAutoCorrect = false;
4100            else if (boolean_value == 1) pSession->bShellAutoCorrect = true;
4101            else throw Exception("Not a boolean value, must either be 0 or 1");
4102        } catch (Exception e) {
4103            result.Error(e);
4104        }
4105        return result.Produce();
4106    }
4107    
4108    String LSCPServer::SetShellDoc(yyparse_param_t* pSession, double boolean_value) {
4109        dmsg(2,("LSCPServer: SetShellDoc(val=%f)\n", boolean_value));
4110        LSCPResultSet result;
4111        try {
4112            if      (boolean_value == 0) pSession->bShellSendLSCPDoc = false;
4113            else if (boolean_value == 1) pSession->bShellSendLSCPDoc = true;
4114            else throw Exception("Not a boolean value, must either be 0 or 1");
4115        } catch (Exception e) {
4116            result.Error(e);
4117        }
4118        return result.Produce();
4119    }
4120    
4121    }

Legend:
Removed from v.793  
changed lines
  Added in v.3055

  ViewVC Help
Powered by ViewVC