/[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 1133 by iliev, Mon Mar 26 08:27:06 2007 UTC revision 2198 by iliev, Sun Jul 3 18:06:51 2011 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005 - 2007 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2010 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This library is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 21  Line 21 
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
24    #include <algorithm>
25    #include <string>
26    
27    #include "../common/File.h"
28  #include "lscpserver.h"  #include "lscpserver.h"
29  #include "lscpresultset.h"  #include "lscpresultset.h"
30  #include "lscpevent.h"  #include "lscpevent.h"
 #include "../common/global.h"  
31    
32    #if defined(WIN32)
33    #include <windows.h>
34    #else
35  #include <fcntl.h>  #include <fcntl.h>
36    #endif
37    
38  #if HAVE_SQLITE3  #if ! HAVE_SQLITE3
39  # include "sqlite3.h"  #define DOESNT_HAVE_SQLITE3 "No database support. SQLITE3 was not installed when linuxsampler was built."
40  #endif  #endif
41    
42  #include "../engines/EngineFactory.h"  #include "../engines/EngineFactory.h"
43  #include "../engines/EngineChannelFactory.h"  #include "../engines/EngineChannelFactory.h"
44  #include "../drivers/audio/AudioOutputDeviceFactory.h"  #include "../drivers/audio/AudioOutputDeviceFactory.h"
45  #include "../drivers/midi/MidiInputDeviceFactory.h"  #include "../drivers/midi/MidiInputDeviceFactory.h"
46    #include "../effects/EffectFactory.h"
47    
48    namespace LinuxSampler {
49    
50    /**
51     * Returns a copy of the given string where all special characters are
52     * replaced by LSCP escape sequences ("\xHH"). This function shall be used
53     * to escape LSCP response fields in case the respective response field is
54     * actually defined as using escape sequences in the LSCP specs.
55     *
56     * @e Caution: DO NOT use this function for escaping path based responses,
57     * use the Path class (src/common/Path.h) for this instead!
58     */
59    static String _escapeLscpResponse(String txt) {
60        for (int i = 0; i < txt.length(); i++) {
61            const char c = txt.c_str()[i];
62            if (
63                !(c >= '0' && c <= '9') &&
64                !(c >= 'a' && c <= 'z') &&
65                !(c >= 'A' && c <= 'Z') &&
66                !(c == ' ') && !(c == '!') && !(c == '#') && !(c == '$') &&
67                !(c == '%') && !(c == '&') && !(c == '(') && !(c == ')') &&
68                !(c == '*') && !(c == '+') && !(c == ',') && !(c == '-') &&
69                !(c == '.') && !(c == '/') && !(c == ':') && !(c == ';') &&
70                !(c == '<') && !(c == '=') && !(c == '>') && !(c == '?') &&
71                !(c == '@') && !(c == '[') && !(c == ']') &&
72                !(c == '^') && !(c == '_') && !(c == '`') && !(c == '{') &&
73                !(c == '|') && !(c == '}') && !(c == '~')
74            ) {
75                // convert the "special" character into a "\xHH" LSCP escape sequence
76                char buf[5];
77                snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
78                txt.replace(i, 1, buf);
79                i += 3;
80            }
81        }
82        return txt;
83    }
84    
85  /**  /**
86   * Below are a few static members of the LSCPServer class.   * Below are a few static members of the LSCPServer class.
# Line 53  Line 98 
98  fd_set LSCPServer::fdSet;  fd_set LSCPServer::fdSet;
99  int LSCPServer::currentSocket = -1;  int LSCPServer::currentSocket = -1;
100  std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();  std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();
101    std::vector<yyparse_param_t>::iterator itCurrentSession = std::vector<yyparse_param_t>::iterator();
102  std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();  std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();
103  std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();  std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();
104  std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();  std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();
# Line 61  Mutex LSCPServer::NotifyBufferMutex = Mu Line 107  Mutex LSCPServer::NotifyBufferMutex = Mu
107  Mutex LSCPServer::SubscriptionMutex = Mutex();  Mutex LSCPServer::SubscriptionMutex = Mutex();
108  Mutex LSCPServer::RTNotifyMutex = Mutex();  Mutex LSCPServer::RTNotifyMutex = Mutex();
109    
110  LSCPServer::LSCPServer(Sampler* pSampler, 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) {
111      SocketAddress.sin_family      = AF_INET;      SocketAddress.sin_family      = AF_INET;
112      SocketAddress.sin_addr.s_addr = addr;      SocketAddress.sin_addr.s_addr = addr;
113      SocketAddress.sin_port        = port;      SocketAddress.sin_port        = port;
# Line 81  LSCPServer::LSCPServer(Sampler* pSampler Line 127  LSCPServer::LSCPServer(Sampler* pSampler
127      LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");      LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
128      LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
129      LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");      LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
130        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_count, "DB_INSTRUMENT_DIRECTORY_COUNT");
131        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_info, "DB_INSTRUMENT_DIRECTORY_INFO");
132        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_count, "DB_INSTRUMENT_COUNT");
133        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_info, "DB_INSTRUMENT_INFO");
134        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instrs_job_info, "DB_INSTRUMENTS_JOB_INFO");
135      LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");      LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
136        LSCPEvent::RegisterEvent(LSCPEvent::event_total_stream_count, "TOTAL_STREAM_COUNT");
137      LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
138      LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");      LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");
139        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_midi, "CHANNEL_MIDI");
140        LSCPEvent::RegisterEvent(LSCPEvent::event_device_midi, "DEVICE_MIDI");
141        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_count, "EFFECT_INSTANCE_COUNT");
142        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_info, "EFFECT_INSTANCE_INFO");
143        LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_count, "SEND_EFFECT_CHAIN_COUNT");
144        LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_info, "SEND_EFFECT_CHAIN_INFO");
145      hSocket = -1;      hSocket = -1;
146  }  }
147    
148  LSCPServer::~LSCPServer() {  LSCPServer::~LSCPServer() {
149        CloseAllConnections();
150        InstrumentManager::StopBackgroundThread();
151    #if defined(WIN32)
152        if (hSocket >= 0) closesocket(hSocket);
153    #else
154      if (hSocket >= 0) close(hSocket);      if (hSocket >= 0) close(hSocket);
155    #endif
156    }
157    
158    LSCPServer::EventHandler::EventHandler(LSCPServer* pParent) {
159        this->pParent = pParent;
160    }
161    
162    LSCPServer::EventHandler::~EventHandler() {
163        std::vector<midi_listener_entry> l = channelMidiListeners;
164        channelMidiListeners.clear();
165        for (int i = 0; i < l.size(); i++)
166            delete l[i].pMidiListener;
167  }  }
168    
169  void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {  void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {
170      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));
171  }  }
172    
173    void LSCPServer::EventHandler::ChannelAdded(SamplerChannel* pChannel) {
174        pChannel->AddEngineChangeListener(this);
175    }
176    
177    void LSCPServer::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) {
178        if (!pChannel->GetEngineChannel()) return;
179        EngineToBeChanged(pChannel->Index());
180    }
181    
182    void LSCPServer::EventHandler::EngineToBeChanged(int ChannelId) {
183        SamplerChannel* pSamplerChannel =
184            pParent->pSampler->GetSamplerChannel(ChannelId);
185        if (!pSamplerChannel) return;
186        EngineChannel* pEngineChannel =
187            pSamplerChannel->GetEngineChannel();
188        if (!pEngineChannel) return;
189        for (std::vector<midi_listener_entry>::iterator iter = channelMidiListeners.begin(); iter != channelMidiListeners.end(); ++iter) {
190            if ((*iter).pEngineChannel == pEngineChannel) {
191                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
192                pEngineChannel->Disconnect(pMidiListener);
193                channelMidiListeners.erase(iter);
194                delete pMidiListener;
195                return;
196            }
197        }
198    }
199    
200    void LSCPServer::EventHandler::EngineChanged(int ChannelId) {
201        SamplerChannel* pSamplerChannel =
202            pParent->pSampler->GetSamplerChannel(ChannelId);
203        if (!pSamplerChannel) return;
204        EngineChannel* pEngineChannel =
205            pSamplerChannel->GetEngineChannel();
206        if (!pEngineChannel) return;
207        VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
208        pEngineChannel->Connect(pMidiListener);
209        midi_listener_entry entry = {
210            pSamplerChannel, pEngineChannel, pMidiListener
211        };
212        channelMidiListeners.push_back(entry);
213    }
214    
215  void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {  void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {
216      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));
217  }  }
# Line 103  void LSCPServer::EventHandler::MidiDevic Line 220  void LSCPServer::EventHandler::MidiDevic
220      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));
221  }  }
222    
223    void LSCPServer::EventHandler::MidiDeviceToBeDestroyed(MidiInputDevice* pDevice) {
224        pDevice->RemoveMidiPortCountListener(this);
225        for (int i = 0; i < pDevice->PortCount(); ++i)
226            MidiPortToBeRemoved(pDevice->GetPort(i));
227    }
228    
229    void LSCPServer::EventHandler::MidiDeviceCreated(MidiInputDevice* pDevice) {
230        pDevice->AddMidiPortCountListener(this);
231        for (int i = 0; i < pDevice->PortCount(); ++i)
232            MidiPortAdded(pDevice->GetPort(i));
233    }
234    
235    void LSCPServer::EventHandler::MidiPortCountChanged(int NewCount) {
236        // yet unused
237    }
238    
239    void LSCPServer::EventHandler::MidiPortToBeRemoved(MidiInputPort* pPort) {
240        for (std::vector<device_midi_listener_entry>::iterator iter = deviceMidiListeners.begin(); iter != deviceMidiListeners.end(); ++iter) {
241            if ((*iter).pPort == pPort) {
242                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
243                pPort->Disconnect(pMidiListener);
244                deviceMidiListeners.erase(iter);
245                delete pMidiListener;
246                return;
247            }
248        }
249    }
250    
251    void LSCPServer::EventHandler::MidiPortAdded(MidiInputPort* pPort) {
252        // find out the device ID
253        std::map<uint, MidiInputDevice*> devices =
254            pParent->pSampler->GetMidiInputDevices();
255        for (
256            std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
257            iter != devices.end(); ++iter
258        ) {
259            if (iter->second == pPort->GetDevice()) { // found
260                VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
261                pPort->Connect(pMidiListener);
262                device_midi_listener_entry entry = {
263                    pPort, pMidiListener, iter->first
264                };
265                deviceMidiListeners.push_back(entry);
266                return;
267            }
268        }
269    }
270    
271  void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {  void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {
272      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));
273  }  }
# Line 139  void LSCPServer::EventHandler::TotalVoic Line 304  void LSCPServer::EventHandler::TotalVoic
304      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));      LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));
305  }  }
306    
307    void LSCPServer::EventHandler::TotalStreamCountChanged(int NewCount) {
308        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_stream_count, NewCount));
309    }
310    
311    #if HAVE_SQLITE3
312    void LSCPServer::DbInstrumentsEventHandler::DirectoryCountChanged(String Dir) {
313        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_count, InstrumentsDb::toEscapedPath(Dir)));
314    }
315    
316    void LSCPServer::DbInstrumentsEventHandler::DirectoryInfoChanged(String Dir) {
317        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, InstrumentsDb::toEscapedPath(Dir)));
318    }
319    
320    void LSCPServer::DbInstrumentsEventHandler::DirectoryNameChanged(String Dir, String NewName) {
321        Dir = "'" + InstrumentsDb::toEscapedPath(Dir) + "'";
322        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
323        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, "NAME", Dir, NewName));
324    }
325    
326    void LSCPServer::DbInstrumentsEventHandler::InstrumentCountChanged(String Dir) {
327        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_count, InstrumentsDb::toEscapedPath(Dir)));
328    }
329    
330    void LSCPServer::DbInstrumentsEventHandler::InstrumentInfoChanged(String Instr) {
331        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, InstrumentsDb::toEscapedPath(Instr)));
332    }
333    
334    void LSCPServer::DbInstrumentsEventHandler::InstrumentNameChanged(String Instr, String NewName) {
335        Instr = "'" + InstrumentsDb::toEscapedPath(Instr) + "'";
336        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
337        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, "NAME", Instr, NewName));
338    }
339    
340    void LSCPServer::DbInstrumentsEventHandler::JobStatusChanged(int JobId) {
341        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instrs_job_info, JobId));
342    }
343    #endif // HAVE_SQLITE3
344    
345    void LSCPServer::RemoveListeners() {
346        pSampler->RemoveChannelCountListener(&eventHandler);
347        pSampler->RemoveAudioDeviceCountListener(&eventHandler);
348        pSampler->RemoveMidiDeviceCountListener(&eventHandler);
349        pSampler->RemoveVoiceCountListener(&eventHandler);
350        pSampler->RemoveStreamCountListener(&eventHandler);
351        pSampler->RemoveBufferFillListener(&eventHandler);
352        pSampler->RemoveTotalStreamCountListener(&eventHandler);
353        pSampler->RemoveTotalVoiceCountListener(&eventHandler);
354        pSampler->RemoveFxSendCountListener(&eventHandler);
355        MidiInstrumentMapper::RemoveMidiInstrumentCountListener(&eventHandler);
356        MidiInstrumentMapper::RemoveMidiInstrumentInfoListener(&eventHandler);
357        MidiInstrumentMapper::RemoveMidiInstrumentMapCountListener(&eventHandler);
358        MidiInstrumentMapper::RemoveMidiInstrumentMapInfoListener(&eventHandler);
359    #if HAVE_SQLITE3
360        InstrumentsDb::GetInstrumentsDb()->RemoveInstrumentsDbListener(&dbInstrumentsEventHandler);
361    #endif
362    }
363    
364  /**  /**
365   * Blocks the calling thread until the LSCP Server is initialized and   * Blocks the calling thread until the LSCP Server is initialized and
# Line 155  int LSCPServer::WaitUntilInitialized(lon Line 376  int LSCPServer::WaitUntilInitialized(lon
376  }  }
377    
378  int LSCPServer::Main() {  int LSCPServer::Main() {
379            #if defined(WIN32)
380            WSADATA wsaData;
381            int iResult;
382            iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
383            if (iResult != 0) {
384                    std::cerr << "LSCPServer: WSAStartup failed: " << iResult << "\n";
385                    exit(EXIT_FAILURE);
386            }
387            #endif
388      hSocket = socket(AF_INET, SOCK_STREAM, 0);      hSocket = socket(AF_INET, SOCK_STREAM, 0);
389      if (hSocket < 0) {      if (hSocket < 0) {
390          std::cerr << "LSCPServer: Could not create server socket." << std::endl;          std::cerr << "LSCPServer: Could not create server socket." << std::endl;
# Line 168  int LSCPServer::Main() { Line 398  int LSCPServer::Main() {
398              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
399                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {
400                      std::cerr << "gave up!" << std::endl;                      std::cerr << "gave up!" << std::endl;
401                        #if defined(WIN32)
402                        closesocket(hSocket);
403                        #else
404                      close(hSocket);                      close(hSocket);
405                        #endif
406                      //return -1;                      //return -1;
407                      exit(EXIT_FAILURE);                      exit(EXIT_FAILURE);
408                  }                  }
# Line 180  int LSCPServer::Main() { Line 414  int LSCPServer::Main() {
414    
415      listen(hSocket, 1);      listen(hSocket, 1);
416      Initialized.Set(true);      Initialized.Set(true);
417        
418      // Registering event listeners      // Registering event listeners
419      pSampler->AddChannelCountListener(&eventHandler);      pSampler->AddChannelCountListener(&eventHandler);
420      pSampler->AddAudioDeviceCountListener(&eventHandler);      pSampler->AddAudioDeviceCountListener(&eventHandler);
# Line 188  int LSCPServer::Main() { Line 422  int LSCPServer::Main() {
422      pSampler->AddVoiceCountListener(&eventHandler);      pSampler->AddVoiceCountListener(&eventHandler);
423      pSampler->AddStreamCountListener(&eventHandler);      pSampler->AddStreamCountListener(&eventHandler);
424      pSampler->AddBufferFillListener(&eventHandler);      pSampler->AddBufferFillListener(&eventHandler);
425        pSampler->AddTotalStreamCountListener(&eventHandler);
426      pSampler->AddTotalVoiceCountListener(&eventHandler);      pSampler->AddTotalVoiceCountListener(&eventHandler);
427      pSampler->AddFxSendCountListener(&eventHandler);      pSampler->AddFxSendCountListener(&eventHandler);
428      MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);      MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);
429      MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);      MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);
430      MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);      MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);
431      MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);      MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);
432    #if HAVE_SQLITE3
433        InstrumentsDb::GetInstrumentsDb()->AddInstrumentsDbListener(&dbInstrumentsEventHandler);
434    #endif
435      // now wait for client connections and handle their requests      // now wait for client connections and handle their requests
436      sockaddr_in client;      sockaddr_in client;
437      int length = sizeof(client);      int length = sizeof(client);
# Line 205  int LSCPServer::Main() { Line 442  int LSCPServer::Main() {
442      timeval timeout;      timeval timeout;
443    
444      while (true) {      while (true) {
445            #if CONFIG_PTHREAD_TESTCANCEL
446                    TestCancel();
447            #endif
448          // 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
449          {          {
450              std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();              std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
# Line 212  int LSCPServer::Main() { Line 452  int LSCPServer::Main() {
452              std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();              std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
453              for (; itEngineChannel != itEnd; ++itEngineChannel) {              for (; itEngineChannel != itEnd; ++itEngineChannel) {
454                  if ((*itEngineChannel)->StatusChanged()) {                  if ((*itEngineChannel)->StatusChanged()) {
455                      SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->iSamplerChannelIndex));                      SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->GetSamplerChannel()->Index()));
456                  }                  }
457    
458                  for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {                  for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
459                      FxSend* fxs = (*itEngineChannel)->GetFxSend(i);                      FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
460                      if(fxs != NULL && fxs->IsInfoChanged()) {                      if(fxs != NULL && fxs->IsInfoChanged()) {
461                          int chn = (*itEngineChannel)->iSamplerChannelIndex;                          int chn = (*itEngineChannel)->GetSamplerChannel()->Index();
462                          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));                          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));
463                          fxs->SetInfoChanged(false);                          fxs->SetInfoChanged(false);
464                      }                      }
# Line 226  int LSCPServer::Main() { Line 466  int LSCPServer::Main() {
466              }              }
467          }          }
468    
469            // check if MIDI data arrived on some engine channel
470            for (int i = 0; i < eventHandler.channelMidiListeners.size(); ++i) {
471                const EventHandler::midi_listener_entry entry =
472                    eventHandler.channelMidiListeners[i];
473                VirtualMidiDevice* pMidiListener = entry.pMidiListener;
474                if (pMidiListener->NotesChanged()) {
475                    for (int iNote = 0; iNote < 128; iNote++) {
476                        if (pMidiListener->NoteChanged(iNote)) {
477                            const bool bActive = pMidiListener->NoteIsActive(iNote);
478                            LSCPServer::SendLSCPNotify(
479                                LSCPEvent(
480                                    LSCPEvent::event_channel_midi,
481                                    entry.pSamplerChannel->Index(),
482                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
483                                    iNote,
484                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
485                                            : pMidiListener->NoteOffVelocity(iNote)
486                                )
487                            );
488                        }
489                    }
490                }
491            }
492    
493            // check if MIDI data arrived on some MIDI device
494            for (int i = 0; i < eventHandler.deviceMidiListeners.size(); ++i) {
495                const EventHandler::device_midi_listener_entry entry =
496                    eventHandler.deviceMidiListeners[i];
497                VirtualMidiDevice* pMidiListener = entry.pMidiListener;
498                if (pMidiListener->NotesChanged()) {
499                    for (int iNote = 0; iNote < 128; iNote++) {
500                        if (pMidiListener->NoteChanged(iNote)) {
501                            const bool bActive = pMidiListener->NoteIsActive(iNote);
502                            LSCPServer::SendLSCPNotify(
503                                LSCPEvent(
504                                    LSCPEvent::event_device_midi,
505                                    entry.uiDeviceID,
506                                    entry.pPort->GetPortNumber(),
507                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
508                                    iNote,
509                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
510                                            : pMidiListener->NoteOffVelocity(iNote)
511                                )
512                            );
513                        }
514                    }
515                }
516            }
517    
518          //Now let's deliver late notifies (if any)          //Now let's deliver late notifies (if any)
519          NotifyBufferMutex.Lock();          NotifyBufferMutex.Lock();
520          for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {          for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
# Line 244  int LSCPServer::Main() { Line 533  int LSCPServer::Main() {
533    
534          int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);          int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
535    
536          if (retval == 0)          if (retval == 0 || (retval == -1 && errno == EINTR))
537                  continue; //Nothing try again                  continue; //Nothing try again
538          if (retval == -1) {          if (retval == -1) {
539                  std::cerr << "LSCPServer: Socket select error." << std::endl;                  std::cerr << "LSCPServer: Socket select error." << std::endl;
540                    #if defined(WIN32)
541                    closesocket(hSocket);
542                    #else
543                  close(hSocket);                  close(hSocket);
544                    #endif
545                  exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
546          }          }
547    
# Line 260  int LSCPServer::Main() { Line 553  int LSCPServer::Main() {
553                          exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
554                  }                  }
555    
556                    #if defined(WIN32)
557                    u_long nonblock_io = 1;
558                    if( ioctlsocket(socket, FIONBIO, &nonblock_io) ) {
559                      std::cerr << "LSCPServer: ioctlsocket: set FIONBIO failed. Error " << WSAGetLastError() << std::endl;
560                      exit(EXIT_FAILURE);
561                    }
562            #else
563                    struct linger linger;
564                    linger.l_onoff = 1;
565                    linger.l_linger = 0;
566                    if(setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))) {
567                        std::cerr << "LSCPServer: Failed to set SO_LINGER\n";
568                    }
569    
570                  if (fcntl(socket, F_SETFL, O_NONBLOCK)) {                  if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
571                          std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;                          std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
572                          exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
573                  }                  }
574                    #endif
575    
576                  // Parser initialization                  // Parser initialization
577                  yyparse_param_t yyparse_param;                  yyparse_param_t yyparse_param;
# Line 287  int LSCPServer::Main() { Line 595  int LSCPServer::Main() {
595                                  int dummy; // just a temporary hack to fulfill the restart() function prototype                                  int dummy; // just a temporary hack to fulfill the restart() function prototype
596                                  restart(NULL, dummy); // restart the 'scanner'                                  restart(NULL, dummy); // restart the 'scanner'
597                                  currentSocket = (*iter).hSession;  //a hack                                  currentSocket = (*iter).hSession;  //a hack
598                                    itCurrentSession = iter; // another hack
599                                  dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));                                  dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
600                                  if ((*iter).bVerbose) { // if echo mode enabled                                  if ((*iter).bVerbose) { // if echo mode enabled
601                                      AnswerClient(bufferedCommands[currentSocket]);                                      AnswerClient(bufferedCommands[currentSocket]);
602                                  }                                  }
603                                  int result = yyparse(&(*iter));                                  int result = yyparse(&(*iter));
604                                  currentSocket = -1;     //continuation of a hack                                  currentSocket = -1;     //continuation of a hack
605                                    itCurrentSession = Sessions.end(); // hack as well
606                                  dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));                                  dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
607                                  if (result == LSCP_QUIT) { //Was it a quit command by any chance?                                  if (result == LSCP_QUIT) { //Was it a quit command by any chance?
608                                          CloseConnection(iter);                                          CloseConnection(iter);
# Line 320  void LSCPServer::CloseConnection( std::v Line 630  void LSCPServer::CloseConnection( std::v
630          NotifyMutex.Lock();          NotifyMutex.Lock();
631          bufferedCommands.erase(socket);          bufferedCommands.erase(socket);
632          bufferedNotifies.erase(socket);          bufferedNotifies.erase(socket);
633            #if defined(WIN32)
634            closesocket(socket);
635            #else
636          close(socket);          close(socket);
637            #endif
638          NotifyMutex.Unlock();          NotifyMutex.Unlock();
639  }  }
640    
641    void LSCPServer::CloseAllConnections() {
642        std::vector<yyparse_param_t>::iterator iter = Sessions.begin();
643        while(iter != Sessions.end()) {
644            CloseConnection(iter);
645            iter = Sessions.begin();
646        }
647    }
648    
649    void LSCPServer::LockRTNotify() {
650        RTNotifyMutex.Lock();
651    }
652    
653    void LSCPServer::UnlockRTNotify() {
654        RTNotifyMutex.Unlock();
655    }
656    
657  int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {  int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {
658          int subs = 0;          int subs = 0;
659          SubscriptionMutex.Lock();          SubscriptionMutex.Lock();
# Line 385  extern int GetLSCPCommand( void *buf, in Line 715  extern int GetLSCPCommand( void *buf, in
715          return command.size();          return command.size();
716  }  }
717    
718    extern yyparse_param_t* GetCurrentYaccSession() {
719        return &(*itCurrentSession);
720    }
721    
722  /**  /**
723   * Will be called to try to read the command from the socket   * Will be called to try to read the command from the socket
724   * If command is read, it will return true. Otherwise false is returned.   * If command is read, it will return true. Otherwise false is returned.
# Line 395  bool LSCPServer::GetLSCPCommand( std::ve Line 729  bool LSCPServer::GetLSCPCommand( std::ve
729          char c;          char c;
730          int i = 0;          int i = 0;
731          while (true) {          while (true) {
732                    #if defined(WIN32)
733                    int result = recv(socket, (char *)&c, 1, 0); //Read one character at a time for now
734                    #else
735                  int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now                  int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now
736                    #endif
737                  if (result == 0) { //socket was selected, so 0 here means client has closed the connection                  if (result == 0) { //socket was selected, so 0 here means client has closed the connection
738                          CloseConnection(iter);                          CloseConnection(iter);
739                          break;                          break;
# Line 410  bool LSCPServer::GetLSCPCommand( std::ve Line 748  bool LSCPServer::GetLSCPCommand( std::ve
748                          }                          }
749                          bufferedCommands[socket] += c;                          bufferedCommands[socket] += c;
750                  }                  }
751                    #if defined(WIN32)
752                    if (result == SOCKET_ERROR) {
753                        int wsa_lasterror = WSAGetLastError();
754                            if (wsa_lasterror == WSAEWOULDBLOCK) //Would block, try again later.
755                                    return false;
756                            dmsg(2,("LSCPScanner: Socket error after recv() Error %d.\n", wsa_lasterror));
757                            CloseConnection(iter);
758                            break;
759                    }
760                    #else
761                  if (result == -1) {                  if (result == -1) {
762                          if (errno == EAGAIN) //Would block, try again later.                          if (errno == EAGAIN) //Would block, try again later.
763                                  return false;                                  return false;
# Line 448  bool LSCPServer::GetLSCPCommand( std::ve Line 796  bool LSCPServer::GetLSCPCommand( std::ve
796                          CloseConnection(iter);                          CloseConnection(iter);
797                          break;                          break;
798                  }                  }
799                    #endif
800          }          }
801          return false;          return false;
802  }  }
# Line 565  String LSCPServer::DestroyMidiInputDevic Line 914  String LSCPServer::DestroyMidiInputDevic
914      return result.Produce();      return result.Produce();
915  }  }
916    
917    EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
918        SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
919        if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
920    
921        EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
922        if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
923    
924        return pEngineChannel;
925    }
926    
927  /**  /**
928   * Will be called by the parser to load an instrument.   * Will be called by the parser to load an instrument.
929   */   */
# Line 711  String LSCPServer::GetEngineInfo(String Line 1070  String LSCPServer::GetEngineInfo(String
1070      LockRTNotify();      LockRTNotify();
1071      try {      try {
1072          Engine* pEngine = EngineFactory::Create(EngineName);          Engine* pEngine = EngineFactory::Create(EngineName);
1073          result.Add("DESCRIPTION", pEngine->Description());          result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
1074          result.Add("VERSION",     pEngine->Version());          result.Add("VERSION",     pEngine->Version());
1075          EngineFactory::Destroy(pEngine);          EngineFactory::Destroy(pEngine);
1076      }      }
# Line 784  String LSCPServer::GetChannelInfo(uint u Line 1143  String LSCPServer::GetChannelInfo(uint u
1143          if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");          if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
1144          else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());          else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
1145    
1146            // convert the filename into the correct encoding as defined for LSCP
1147            // (especially in terms of special characters -> escape sequences)
1148            if (InstrumentFileName != "NONE" && InstrumentFileName != "") {
1149    #if WIN32
1150                InstrumentFileName = Path::fromWindows(InstrumentFileName).toLscp();
1151    #else
1152                // assuming POSIX
1153                InstrumentFileName = Path::fromPosix(InstrumentFileName).toLscp();
1154    #endif
1155            }
1156    
1157          result.Add("INSTRUMENT_FILE", InstrumentFileName);          result.Add("INSTRUMENT_FILE", InstrumentFileName);
1158          result.Add("INSTRUMENT_NR", InstrumentIndex);          result.Add("INSTRUMENT_NR", InstrumentIndex);
1159          result.Add("INSTRUMENT_NAME", InstrumentName);          result.Add("INSTRUMENT_NAME", _escapeLscpResponse(InstrumentName));
1160          result.Add("INSTRUMENT_STATUS", InstrumentStatus);          result.Add("INSTRUMENT_STATUS", InstrumentStatus);
1161          result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));          result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
1162          result.Add("SOLO", Solo);          result.Add("SOLO", Solo);
# Line 806  String LSCPServer::GetVoiceCount(uint ui Line 1176  String LSCPServer::GetVoiceCount(uint ui
1176      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
1177      LSCPResultSet result;      LSCPResultSet result;
1178      try {      try {
1179          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("No engine loaded on sampler channel");  
1180          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1181          result.Add(pEngineChannel->GetEngine()->VoiceCount());          result.Add(pEngineChannel->GetEngine()->VoiceCount());
1182      }      }
# Line 827  String LSCPServer::GetStreamCount(uint u Line 1194  String LSCPServer::GetStreamCount(uint u
1194      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
1195      LSCPResultSet result;      LSCPResultSet result;
1196      try {      try {
1197          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");  
1198          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1199          result.Add(pEngineChannel->GetEngine()->DiskStreamCount());          result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
1200      }      }
# Line 848  String LSCPServer::GetBufferFill(fill_re Line 1212  String LSCPServer::GetBufferFill(fill_re
1212      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
1213      LSCPResultSet result;      LSCPResultSet result;
1214      try {      try {
1215          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");  
1216          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1217          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
1218          else {          else {
# Line 939  String LSCPServer::GetMidiInputDriverInf Line 1300  String LSCPServer::GetMidiInputDriverInf
1300              for (;iter != parameters.end(); iter++) {              for (;iter != parameters.end(); iter++) {
1301                  if (s != "") s += ",";                  if (s != "") s += ",";
1302                  s += iter->first;                  s += iter->first;
1303                    delete iter->second;
1304              }              }
1305              result.Add("PARAMETERS", s);              result.Add("PARAMETERS", s);
1306          }          }
# Line 963  String LSCPServer::GetAudioOutputDriverI Line 1325  String LSCPServer::GetAudioOutputDriverI
1325              for (;iter != parameters.end(); iter++) {              for (;iter != parameters.end(); iter++) {
1326                  if (s != "") s += ",";                  if (s != "") s += ",";
1327                  s += iter->first;                  s += iter->first;
1328                    delete iter->second;
1329              }              }
1330              result.Add("PARAMETERS", s);              result.Add("PARAMETERS", s);
1331          }          }
# Line 993  String LSCPServer::GetMidiInputDriverPar Line 1356  String LSCPServer::GetMidiInputDriverPar
1356          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1357          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1358          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1359            delete pParameter;
1360      }      }
1361      catch (Exception e) {      catch (Exception e) {
1362          result.Error(e);          result.Error(e);
# Line 1020  String LSCPServer::GetAudioOutputDriverP Line 1384  String LSCPServer::GetAudioOutputDriverP
1384          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);          if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1385          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);          if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1386          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);          if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1387            delete pParameter;
1388      }      }
1389      catch (Exception e) {      catch (Exception e) {
1390          result.Error(e);          result.Error(e);
# Line 1486  String LSCPServer::SetMIDIInputType(Stri Line 1851  String LSCPServer::SetMIDIInputType(Stri
1851              pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);              pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1852              // Make it with at least one initial port.              // Make it with at least one initial port.
1853              std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();              std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
             parameters["PORTS"]->SetValue("1");  
1854          }          }
1855          // Must have a device...          // Must have a device...
1856          if (pDevice == NULL)          if (pDevice == NULL)
# Line 1529  String LSCPServer::SetVolume(double dVol Line 1893  String LSCPServer::SetVolume(double dVol
1893      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
1894      LSCPResultSet result;      LSCPResultSet result;
1895      try {      try {
1896          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");  
1897          pEngineChannel->Volume(dVolume);          pEngineChannel->Volume(dVolume);
1898      }      }
1899      catch (Exception e) {      catch (Exception e) {
# Line 1548  String LSCPServer::SetChannelMute(bool b Line 1909  String LSCPServer::SetChannelMute(bool b
1909      dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));      dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
1910      LSCPResultSet result;      LSCPResultSet result;
1911      try {      try {
1912          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");  
1913    
1914          if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);          if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
1915          else pEngineChannel->SetMute(1);          else pEngineChannel->SetMute(1);
# Line 1569  String LSCPServer::SetChannelSolo(bool b Line 1926  String LSCPServer::SetChannelSolo(bool b
1926      dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));      dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
1927      LSCPResultSet result;      LSCPResultSet result;
1928      try {      try {
1929          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");  
1930    
1931          bool oldSolo = pEngineChannel->GetSolo();          bool oldSolo = pEngineChannel->GetSolo();
1932          bool hadSoloChannel = HasSoloChannel();          bool hadSoloChannel = HasSoloChannel();
# Line 1693  String LSCPServer::GetMidiInstrumentMapp Line 2046  String LSCPServer::GetMidiInstrumentMapp
2046      dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));      dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
2047      LSCPResultSet result;      LSCPResultSet result;
2048      try {      try {
2049          result.Add(MidiInstrumentMapper::Entries(MidiMapID).size());          result.Add(MidiInstrumentMapper::GetInstrumentCount(MidiMapID));
2050      } catch (Exception e) {      } catch (Exception e) {
2051          result.Error(e);          result.Error(e);
2052      }      }
# Line 1704  String LSCPServer::GetMidiInstrumentMapp Line 2057  String LSCPServer::GetMidiInstrumentMapp
2057  String LSCPServer::GetAllMidiInstrumentMappings() {  String LSCPServer::GetAllMidiInstrumentMappings() {
2058      dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));      dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
2059      LSCPResultSet result;      LSCPResultSet result;
2060      std::vector<int> maps = MidiInstrumentMapper::Maps();      try {
2061      int totalMappings = 0;          result.Add(MidiInstrumentMapper::GetInstrumentCount());
2062      for (int i = 0; i < maps.size(); i++) {      } catch (Exception e) {
2063          try {          result.Error(e);
             totalMappings += MidiInstrumentMapper::Entries(maps[i]).size();  
         } catch (Exception e) { /*NOOP*/ }  
2064      }      }
     result.Add(totalMappings);  
2065      return result.Produce();      return result.Produce();
2066  }  }
2067    
# Line 1719  String LSCPServer::GetMidiInstrumentMapp Line 2069  String LSCPServer::GetMidiInstrumentMapp
2069      dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));      dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
2070      LSCPResultSet result;      LSCPResultSet result;
2071      try {      try {
2072          midi_prog_index_t idx;          MidiInstrumentMapper::entry_t entry = MidiInstrumentMapper::GetEntry(MidiMapID, MidiBank, MidiProg);
2073          idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;          // convert the filename into the correct encoding as defined for LSCP
2074          idx.midi_bank_lsb = MidiBank & 0x7f;          // (especially in terms of special characters -> escape sequences)
2075          idx.midi_prog     = MidiProg;  #if WIN32
2076            const String instrumentFileName = Path::fromWindows(entry.InstrumentFile).toLscp();
2077    #else
2078            // assuming POSIX
2079            const String instrumentFileName = Path::fromPosix(entry.InstrumentFile).toLscp();
2080    #endif
2081    
2082          std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);          result.Add("NAME", _escapeLscpResponse(entry.Name));
2083          std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.find(idx);          result.Add("ENGINE_NAME", entry.EngineName);
2084          if (iter == mappings.end()) result.Error("there is no map entry with that index");          result.Add("INSTRUMENT_FILE", instrumentFileName);
2085          else { // found          result.Add("INSTRUMENT_NR", (int) entry.InstrumentIndex);
2086              result.Add("NAME", iter->second.Name);          String instrumentName;
2087              result.Add("ENGINE_NAME", iter->second.EngineName);          Engine* pEngine = EngineFactory::Create(entry.EngineName);
2088              result.Add("INSTRUMENT_FILE", iter->second.InstrumentFile);          if (pEngine) {
2089              result.Add("INSTRUMENT_NR", (int) iter->second.InstrumentIndex);              if (pEngine->GetInstrumentManager()) {
2090              String instrumentName;                  InstrumentManager::instrument_id_t instrID;
2091              Engine* pEngine = EngineFactory::Create(iter->second.EngineName);                  instrID.FileName = entry.InstrumentFile;
2092              if (pEngine) {                  instrID.Index    = entry.InstrumentIndex;
2093                  if (pEngine->GetInstrumentManager()) {                  instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
                     InstrumentManager::instrument_id_t instrID;  
                     instrID.FileName = iter->second.InstrumentFile;  
                     instrID.Index    = iter->second.InstrumentIndex;  
                     instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);  
                 }  
                 EngineFactory::Destroy(pEngine);  
2094              }              }
2095              result.Add("INSTRUMENT_NAME", instrumentName);              EngineFactory::Destroy(pEngine);
2096              switch (iter->second.LoadMode) {          }
2097                  case MidiInstrumentMapper::ON_DEMAND:          result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2098                      result.Add("LOAD_MODE", "ON_DEMAND");          switch (entry.LoadMode) {
2099                      break;              case MidiInstrumentMapper::ON_DEMAND:
2100                  case MidiInstrumentMapper::ON_DEMAND_HOLD:                  result.Add("LOAD_MODE", "ON_DEMAND");
2101                      result.Add("LOAD_MODE", "ON_DEMAND_HOLD");                  break;
2102                      break;              case MidiInstrumentMapper::ON_DEMAND_HOLD:
2103                  case MidiInstrumentMapper::PERSISTENT:                  result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2104                      result.Add("LOAD_MODE", "PERSISTENT");                  break;
2105                      break;              case MidiInstrumentMapper::PERSISTENT:
2106                  default:                  result.Add("LOAD_MODE", "PERSISTENT");
2107                      throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");                  break;
2108              }              default:
2109              result.Add("VOLUME", iter->second.Volume);                  throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2110          }          }
2111            result.Add("VOLUME", entry.Volume);
2112      } catch (Exception e) {      } catch (Exception e) {
2113          result.Error(e);          result.Error(e);
2114      }      }
# Line 1898  String LSCPServer::GetMidiInstrumentMap( Line 2248  String LSCPServer::GetMidiInstrumentMap(
2248      dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));      dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2249      LSCPResultSet result;      LSCPResultSet result;
2250      try {      try {
2251          result.Add("NAME", MidiInstrumentMapper::MapName(MidiMapID));          result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2252            result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2253      } catch (Exception e) {      } catch (Exception e) {
2254          result.Error(e);          result.Error(e);
2255      }      }
# Line 1928  String LSCPServer::SetChannelMap(uint ui Line 2279  String LSCPServer::SetChannelMap(uint ui
2279      dmsg(2,("LSCPServer: SetChannelMap()\n"));      dmsg(2,("LSCPServer: SetChannelMap()\n"));
2280      LSCPResultSet result;      LSCPResultSet result;
2281      try {      try {
2282          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");  
2283    
2284          if      (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();          if      (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2285          else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();          else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
# Line 1947  String LSCPServer::CreateFxSend(uint uiS Line 2294  String LSCPServer::CreateFxSend(uint uiS
2294      dmsg(2,("LSCPServer: CreateFxSend()\n"));      dmsg(2,("LSCPServer: CreateFxSend()\n"));
2295      LSCPResultSet result;      LSCPResultSet result;
2296      try {      try {
2297          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");  
2298    
2299          FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);          FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2300          if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");          if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
# Line 1967  String LSCPServer::DestroyFxSend(uint ui Line 2310  String LSCPServer::DestroyFxSend(uint ui
2310      dmsg(2,("LSCPServer: DestroyFxSend()\n"));      dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2311      LSCPResultSet result;      LSCPResultSet result;
2312      try {      try {
2313          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");  
2314    
2315          FxSend* pFxSend = NULL;          FxSend* pFxSend = NULL;
2316          for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {          for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
# Line 1992  String LSCPServer::GetFxSends(uint uiSam Line 2331  String LSCPServer::GetFxSends(uint uiSam
2331      dmsg(2,("LSCPServer: GetFxSends()\n"));      dmsg(2,("LSCPServer: GetFxSends()\n"));
2332      LSCPResultSet result;      LSCPResultSet result;
2333      try {      try {
2334          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");  
2335    
2336          result.Add(pEngineChannel->GetFxSendCount());          result.Add(pEngineChannel->GetFxSendCount());
2337      } catch (Exception e) {      } catch (Exception e) {
# Line 2010  String LSCPServer::ListFxSends(uint uiSa Line 2345  String LSCPServer::ListFxSends(uint uiSa
2345      LSCPResultSet result;      LSCPResultSet result;
2346      String list;      String list;
2347      try {      try {
2348          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");  
2349    
2350          for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {          for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2351              FxSend* pFxSend = pEngineChannel->GetFxSend(i);              FxSend* pFxSend = pEngineChannel->GetFxSend(i);
# Line 2028  String LSCPServer::ListFxSends(uint uiSa Line 2359  String LSCPServer::ListFxSends(uint uiSa
2359      return result.Produce();      return result.Produce();
2360  }  }
2361    
2362    FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2363        EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2364    
2365        FxSend* pFxSend = NULL;
2366        for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2367            if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2368                pFxSend = pEngineChannel->GetFxSend(i);
2369                break;
2370            }
2371        }
2372        if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2373        return pFxSend;
2374    }
2375    
2376  String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {  String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2377      dmsg(2,("LSCPServer: GetFxSendInfo()\n"));      dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2378      LSCPResultSet result;      LSCPResultSet result;
2379      try {      try {
2380          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2381          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));          FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");  
   
         FxSend* pFxSend = NULL;  
         for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {  
             if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {  
                 pFxSend = pEngineChannel->GetFxSend(i);  
                 break;  
             }  
         }  
         if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");  
2382    
2383          // gather audio routing informations          // gather audio routing informations
2384          String AudioRouting;          String AudioRouting;
# Line 2054  String LSCPServer::GetFxSendInfo(uint ui Line 2387  String LSCPServer::GetFxSendInfo(uint ui
2387              AudioRouting += ToString(pFxSend->DestinationChannel(chan));              AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2388          }          }
2389    
2390            const String sEffectRouting =
2391                (pFxSend->DestinationEffectChain() >= 0 && pFxSend->DestinationEffectChainPosition() >= 0)
2392                    ? ToString(pFxSend->DestinationEffectChain()) + "," + ToString(pFxSend->DestinationEffectChainPosition())
2393                    : "NONE";
2394    
2395          // success          // success
2396          result.Add("NAME", pFxSend->Name());          result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2397          result.Add("MIDI_CONTROLLER", pFxSend->MidiController());          result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2398          result.Add("LEVEL", ToString(pFxSend->Level()));          result.Add("LEVEL", ToString(pFxSend->Level()));
2399          result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);          result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2400            result.Add("EFFECT", sEffectRouting);
2401      } catch (Exception e) {      } catch (Exception e) {
2402          result.Error(e);          result.Error(e);
2403      }      }
2404      return result.Produce();      return result.Produce();
2405  }  }
2406    
2407  String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {  String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2408      dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));      dmsg(2,("LSCPServer: SetFxSendName()\n"));
2409      LSCPResultSet result;      LSCPResultSet result;
2410      try {      try {
2411          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
2412    
2413          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();          pFxSend->SetName(Name);
2414          if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2415        } catch (Exception e) {
2416            result.Error(e);
2417        }
2418        return result.Produce();
2419    }
2420    
2421          FxSend* pFxSend = NULL;  String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2422          for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {      dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2423              if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {      LSCPResultSet result;
2424                  pFxSend = pEngineChannel->GetFxSend(i);      try {
2425                  break;          FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
             }  
         }  
         if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");  
2426    
2427          pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);          pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2428          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
# Line 2096  String LSCPServer::SetFxSendMidiControll Line 2436  String LSCPServer::SetFxSendMidiControll
2436      dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));      dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2437      LSCPResultSet result;      LSCPResultSet result;
2438      try {      try {
2439          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
   
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");  
   
         FxSend* pFxSend = NULL;  
         for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {  
             if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {  
                 pFxSend = pEngineChannel->GetFxSend(i);  
                 break;  
             }  
         }  
         if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");  
2440    
2441          pFxSend->SetMidiController(MidiController);          pFxSend->SetMidiController(MidiController);
2442          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
# Line 2123  String LSCPServer::SetFxSendLevel(uint u Line 2450  String LSCPServer::SetFxSendLevel(uint u
2450      dmsg(2,("LSCPServer: SetFxSendLevel()\n"));      dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2451      LSCPResultSet result;      LSCPResultSet result;
2452      try {      try {
2453          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
2454    
2455          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();          pFxSend->SetLevel((float)dLevel);
2456          if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2457        } catch (Exception e) {
2458            result.Error(e);
2459        }
2460        return result.Produce();
2461    }
2462    
2463          FxSend* pFxSend = NULL;  String LSCPServer::SetFxSendEffect(uint uiSamplerChannel, uint FxSendID, int iSendEffectChain, int iEffectChainPosition) {
2464          for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {      dmsg(2,("LSCPServer: SetFxSendEffect(%d,%d)\n", iSendEffectChain, iEffectChainPosition));
2465              if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {      LSCPResultSet result;
2466                  pFxSend = pEngineChannel->GetFxSend(i);      try {
2467            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2468    
2469            pFxSend->SetDestinationEffect(iSendEffectChain, iEffectChainPosition);
2470            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2471        } catch (Exception e) {
2472            result.Error(e);
2473        }
2474        return result.Produce();
2475    }
2476    
2477    String LSCPServer::GetAvailableEffects() {
2478        dmsg(2,("LSCPServer: GetAvailableEffects()\n"));
2479        LSCPResultSet result;
2480        try {
2481            int n = EffectFactory::AvailableEffectsCount();
2482            result.Add(n);
2483        }
2484        catch (Exception e) {
2485            result.Error(e);
2486        }
2487        return result.Produce();
2488    }
2489    
2490    String LSCPServer::ListAvailableEffects() {
2491        dmsg(2,("LSCPServer: ListAvailableEffects()\n"));
2492        LSCPResultSet result;
2493        String list;
2494        try {
2495            //FIXME: for now we simply enumerate from 0 .. EffectFactory::AvailableEffectsCount() here, in future we should use unique IDs for effects during the whole sampler session. This issue comes into game when the user forces a reload of available effect plugins
2496            int n = EffectFactory::AvailableEffectsCount();
2497            for (int i = 0; i < n; i++) {
2498                if (i) list += ",";
2499                list += ToString(i);
2500            }
2501        }
2502        catch (Exception e) {
2503            result.Error(e);
2504        }
2505        result.Add(list);
2506        return result.Produce();
2507    }
2508    
2509    String LSCPServer::GetEffectInfo(int iEffectIndex) {
2510        dmsg(2,("LSCPServer: GetEffectInfo(%d)\n", iEffectIndex));
2511        LSCPResultSet result;
2512        try {
2513            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2514            if (!pEffectInfo)
2515                throw Exception("There is no effect with index " + ToString(iEffectIndex));
2516    
2517            // convert the filename into the correct encoding as defined for LSCP
2518            // (especially in terms of special characters -> escape sequences)
2519    #if WIN32
2520            const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2521    #else
2522            // assuming POSIX
2523            const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2524    #endif
2525    
2526            result.Add("SYSTEM", pEffectInfo->EffectSystem());
2527            result.Add("MODULE", dllFileName);
2528            result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2529            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2530        }
2531        catch (Exception e) {
2532            result.Error(e);
2533        }
2534        return result.Produce();    
2535    }
2536    
2537    String LSCPServer::GetEffectInstanceInfo(int iEffectInstance) {
2538        dmsg(2,("LSCPServer: GetEffectInstanceInfo(%d)\n", iEffectInstance));
2539        LSCPResultSet result;
2540        try {
2541            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2542            if (!pEffect)
2543                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2544    
2545            EffectInfo* pEffectInfo = pEffect->GetEffectInfo();
2546    
2547            // convert the filename into the correct encoding as defined for LSCP
2548            // (especially in terms of special characters -> escape sequences)
2549    #if WIN32
2550            const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2551    #else
2552            // assuming POSIX
2553            const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2554    #endif
2555    
2556            result.Add("SYSTEM", pEffectInfo->EffectSystem());
2557            result.Add("MODULE", dllFileName);
2558            result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2559            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2560            result.Add("INPUT_CONTROLS", ToString(pEffect->InputControlCount()));
2561        }
2562        catch (Exception e) {
2563            result.Error(e);
2564        }
2565        return result.Produce();
2566    }
2567    
2568    String LSCPServer::GetEffectInstanceInputControlInfo(int iEffectInstance, int iInputControlIndex) {
2569        dmsg(2,("LSCPServer: GetEffectInstanceInputControlInfo(%d,%d)\n", iEffectInstance, iInputControlIndex));
2570        LSCPResultSet result;
2571        try {
2572            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2573            if (!pEffect)
2574                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2575    
2576            EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2577            if (!pEffectControl)
2578                throw Exception(
2579                    "Effect instance " + ToString(iEffectInstance) +
2580                    " does not have an input control with index " +
2581                    ToString(iInputControlIndex)
2582                );
2583    
2584            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectControl->Description()));
2585            result.Add("VALUE", pEffectControl->Value());
2586            if (pEffectControl->MinValue())
2587                 result.Add("RANGE_MIN", *pEffectControl->MinValue());
2588            if (pEffectControl->MaxValue())
2589                 result.Add("RANGE_MAX", *pEffectControl->MaxValue());
2590            if (!pEffectControl->Possibilities().empty())
2591                 result.Add("POSSIBILITIES", pEffectControl->Possibilities());
2592            if (pEffectControl->DefaultValue())
2593                 result.Add("DEFAULT", *pEffectControl->DefaultValue());
2594        } catch (Exception e) {
2595            result.Error(e);
2596        }
2597        return result.Produce();
2598    }
2599    
2600    String LSCPServer::SetEffectInstanceInputControlValue(int iEffectInstance, int iInputControlIndex, double dValue) {
2601        dmsg(2,("LSCPServer: SetEffectInstanceInputControlValue(%d,%d,%f)\n", iEffectInstance, iInputControlIndex, dValue));
2602        LSCPResultSet result;
2603        try {
2604            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2605            if (!pEffect)
2606                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2607    
2608            EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2609            if (!pEffectControl)
2610                throw Exception(
2611                    "Effect instance " + ToString(iEffectInstance) +
2612                    " does not have an input control with index " +
2613                    ToString(iInputControlIndex)
2614                );
2615    
2616            pEffectControl->SetValue(dValue);
2617            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_info, iEffectInstance));
2618        } catch (Exception e) {
2619            result.Error(e);
2620        }
2621        return result.Produce();
2622    }
2623    
2624    String LSCPServer::CreateEffectInstance(int iEffectIndex) {
2625        dmsg(2,("LSCPServer: CreateEffectInstance(%d)\n", iEffectIndex));
2626        LSCPResultSet result;
2627        try {
2628            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2629            if (!pEffectInfo)
2630                throw Exception("There is no effect with index " + ToString(iEffectIndex));
2631            Effect* pEffect = EffectFactory::Create(pEffectInfo);
2632            result = pEffect->ID(); // success
2633            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2634        } catch (Exception e) {
2635            result.Error(e);
2636        }
2637        return result.Produce();
2638    }
2639    
2640    String LSCPServer::CreateEffectInstance(String effectSystem, String module, String effectName) {
2641        dmsg(2,("LSCPServer: CreateEffectInstance('%s','%s','%s')\n", effectSystem.c_str(), module.c_str(), effectName.c_str()));
2642        LSCPResultSet result;
2643        try {
2644            // to allow loading the same LSCP session file on different systems
2645            // successfully, probably with different effect plugin DLL paths or even
2646            // running completely different operating systems, we do the following
2647            // for finding the right effect:
2648            //
2649            // first try to search for an exact match of the effect plugin DLL
2650            // (a.k.a 'module'), to avoid picking the wrong DLL with the same
2651            // effect name ...
2652            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_MATCH_EXACTLY);
2653            // ... if no effect with exactly matchin DLL filename was found, then
2654            // try to lower the restrictions of matching the effect plugin DLL
2655            // filename and try again and again ...
2656            if (!pEffectInfo) {
2657                dmsg(2,("no exact module match, trying MODULE_IGNORE_PATH\n"));
2658                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH);
2659            }
2660            if (!pEffectInfo) {
2661                dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE\n"));
2662                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE);
2663            }
2664            if (!pEffectInfo) {
2665                dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE | MODULE_IGNORE_EXTENSION\n"));
2666                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE | EffectFactory::MODULE_IGNORE_EXTENSION);
2667            }
2668            // ... if there was still no effect found, then completely ignore the
2669            // DLL plugin filename argument and just search for the matching effect
2670            // system type and effect name
2671            if (!pEffectInfo) {
2672                dmsg(2,("no module match, trying MODULE_IGNORE_ALL\n"));
2673                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_ALL);
2674            }
2675            if (!pEffectInfo)
2676                throw Exception("There is no such effect '" + effectSystem + "' '" + module + "' '" + effectName + "'");
2677    
2678            Effect* pEffect = EffectFactory::Create(pEffectInfo);
2679            result = LSCPResultSet(pEffect->ID());
2680            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2681        } catch (Exception e) {
2682            result.Error(e);
2683        }
2684        return result.Produce();
2685    }
2686    
2687    String LSCPServer::DestroyEffectInstance(int iEffectInstance) {
2688        dmsg(2,("LSCPServer: DestroyEffectInstance(%d)\n", iEffectInstance));
2689        LSCPResultSet result;
2690        try {
2691            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2692            if (!pEffect)
2693                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2694            EffectFactory::Destroy(pEffect);
2695            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2696        } catch (Exception e) {
2697            result.Error(e);
2698        }
2699        return result.Produce();
2700    }
2701    
2702    String LSCPServer::GetEffectInstances() {
2703        dmsg(2,("LSCPServer: GetEffectInstances()\n"));
2704        LSCPResultSet result;
2705        try {
2706            int n = EffectFactory::EffectInstancesCount();
2707            result.Add(n);
2708        } catch (Exception e) {
2709            result.Error(e);
2710        }
2711        return result.Produce();
2712    }
2713    
2714    String LSCPServer::ListEffectInstances() {
2715        dmsg(2,("LSCPServer: ListEffectInstances()\n"));
2716        LSCPResultSet result;
2717        String list;
2718        try {
2719            int n = EffectFactory::EffectInstancesCount();
2720            for (int i = 0; i < n; i++) {
2721                Effect* pEffect = EffectFactory::GetEffectInstance(i);
2722                if (i) list += ",";
2723                list += ToString(pEffect->ID());
2724            }
2725        } catch (Exception e) {
2726            result.Error(e);
2727        }
2728        result.Add(list);
2729        return result.Produce();
2730    }
2731    
2732    String LSCPServer::GetSendEffectChains(int iAudioOutputDevice) {
2733        dmsg(2,("LSCPServer: GetSendEffectChains(%d)\n", iAudioOutputDevice));
2734        LSCPResultSet result;
2735        try {
2736            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2737            if (!devices.count(iAudioOutputDevice))
2738                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2739            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2740            int n = pDevice->SendEffectChainCount();
2741            result.Add(n);
2742        } catch (Exception e) {
2743            result.Error(e);
2744        }
2745        return result.Produce();
2746    }
2747    
2748    String LSCPServer::ListSendEffectChains(int iAudioOutputDevice) {
2749        dmsg(2,("LSCPServer: ListSendEffectChains(%d)\n", iAudioOutputDevice));
2750        LSCPResultSet result;
2751        String list;
2752        try {
2753            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2754            if (!devices.count(iAudioOutputDevice))
2755                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2756            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2757            int n = pDevice->SendEffectChainCount();
2758            for (int i = 0; i < n; i++) {
2759                EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2760                if (i) list += ",";
2761                list += ToString(pEffectChain->ID());
2762            }
2763        } catch (Exception e) {
2764            result.Error(e);
2765        }
2766        result.Add(list);
2767        return result.Produce();
2768    }
2769    
2770    String LSCPServer::AddSendEffectChain(int iAudioOutputDevice) {
2771        dmsg(2,("LSCPServer: AddSendEffectChain(%d)\n", iAudioOutputDevice));
2772        LSCPResultSet result;
2773        try {
2774            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2775            if (!devices.count(iAudioOutputDevice))
2776                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2777            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2778            EffectChain* pEffectChain = pDevice->AddSendEffectChain();
2779            result = pEffectChain->ID();
2780            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2781        } catch (Exception e) {
2782            result.Error(e);
2783        }
2784        return result.Produce();
2785    }
2786    
2787    String LSCPServer::RemoveSendEffectChain(int iAudioOutputDevice, int iSendEffectChain) {
2788        dmsg(2,("LSCPServer: RemoveSendEffectChain(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2789        LSCPResultSet result;
2790        try {
2791            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2792            if (!devices.count(iAudioOutputDevice))
2793                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2794    
2795            std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
2796            std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
2797            std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
2798            for (; itEngineChannel != itEnd; ++itEngineChannel) {
2799                AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
2800                if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
2801                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
2802                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
2803                        if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain) {
2804                            throw Exception("The effect chain is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
2805                        }
2806                    }
2807                }
2808            }
2809    
2810            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2811            for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
2812                EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2813                if (pEffectChain->ID() == iSendEffectChain) {
2814                    pDevice->RemoveSendEffectChain(i);
2815                    LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2816                    return result.Produce();
2817                }
2818            }
2819            throw Exception(
2820                "There is no send effect chain with ID " +
2821                ToString(iSendEffectChain) + " for audio output device " +
2822                ToString(iAudioOutputDevice) + "."
2823            );
2824        } catch (Exception e) {
2825            result.Error(e);
2826        }
2827        return result.Produce();
2828    }
2829    
2830    static EffectChain* _getSendEffectChain(Sampler* pSampler, int iAudioOutputDevice, int iSendEffectChain) throw (Exception) {
2831        std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2832        if (!devices.count(iAudioOutputDevice))
2833            throw Exception(
2834                "There is no audio output device with index " +
2835                ToString(iAudioOutputDevice) + "."
2836            );
2837        AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2838        EffectChain* pEffectChain = pDevice->SendEffectChainByID(iSendEffectChain);
2839        if(pEffectChain != NULL) return pEffectChain;
2840        throw Exception(
2841            "There is no send effect chain with ID " +
2842            ToString(iSendEffectChain) + " for audio output device " +
2843            ToString(iAudioOutputDevice) + "."
2844        );
2845    }
2846    
2847    String LSCPServer::GetSendEffectChainInfo(int iAudioOutputDevice, int iSendEffectChain) {
2848        dmsg(2,("LSCPServer: GetSendEffectChainInfo(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2849        LSCPResultSet result;
2850        try {
2851            EffectChain* pEffectChain =
2852                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2853            String sEffectSequence;
2854            for (int i = 0; i < pEffectChain->EffectCount(); i++) {
2855                if (i) sEffectSequence += ",";
2856                sEffectSequence += ToString(pEffectChain->GetEffect(i)->ID());
2857            }
2858            result.Add("EFFECT_COUNT", pEffectChain->EffectCount());
2859            result.Add("EFFECT_SEQUENCE", sEffectSequence);
2860        } catch (Exception e) {
2861            result.Error(e);
2862        }
2863        return result.Produce();
2864    }
2865    
2866    String LSCPServer::AppendSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectInstance) {
2867        dmsg(2,("LSCPServer: AppendSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectInstance));
2868        LSCPResultSet result;
2869        try {
2870            EffectChain* pEffectChain =
2871                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2872            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2873            if (!pEffect)
2874                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2875            pEffectChain->AppendEffect(pEffect);
2876            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2877        } catch (Exception e) {
2878            result.Error(e);
2879        }
2880        return result.Produce();
2881    }
2882    
2883    String LSCPServer::InsertSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition, int iEffectInstance) {
2884        dmsg(2,("LSCPServer: InsertSendEffectChainEffect(%d,%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition, iEffectInstance));
2885        LSCPResultSet result;
2886        try {
2887            EffectChain* pEffectChain =
2888                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2889            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2890            if (!pEffect)
2891                throw Exception("There is no effect instance with index " + ToString(iEffectInstance));
2892            pEffectChain->InsertEffect(pEffect, iEffectChainPosition);
2893            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2894        } catch (Exception e) {
2895            result.Error(e);
2896        }
2897        return result.Produce();
2898    }
2899    
2900    String LSCPServer::RemoveSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition) {
2901        dmsg(2,("LSCPServer: RemoveSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition));
2902        LSCPResultSet result;
2903        try {
2904            EffectChain* pEffectChain =
2905                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2906    
2907            std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
2908            std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
2909            std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
2910            for (; itEngineChannel != itEnd; ++itEngineChannel) {
2911                AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
2912                if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
2913                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
2914                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
2915                        if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain && fxs->DestinationEffectChainPosition() == iEffectChainPosition) {
2916                            throw Exception("The effect instance is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
2917                        }
2918                    }
2919                }
2920            }
2921    
2922            pEffectChain->RemoveEffect(iEffectChainPosition);
2923            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2924        } catch (Exception e) {
2925            result.Error(e);
2926        }
2927        return result.Produce();
2928    }
2929    
2930    String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
2931        dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
2932        LSCPResultSet result;
2933        try {
2934            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2935            if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
2936            Engine* pEngine = pEngineChannel->GetEngine();
2937            InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
2938            if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
2939            InstrumentManager::instrument_id_t instrumentID;
2940            instrumentID.FileName = pEngineChannel->InstrumentFileName();
2941            instrumentID.Index    = pEngineChannel->InstrumentIndex();
2942            pInstrumentManager->LaunchInstrumentEditor(instrumentID);
2943        } catch (Exception e) {
2944            result.Error(e);
2945        }
2946        return result.Produce();
2947    }
2948    
2949    String LSCPServer::SendChannelMidiData(String MidiMsg, uint uiSamplerChannel, uint Arg1, uint Arg2) {
2950        dmsg(2,("LSCPServer: SendChannelMidiData(MidiMsg=%s,uiSamplerChannel=%d,Arg1=%d,Arg2=%d)\n", MidiMsg.c_str(), uiSamplerChannel, Arg1, Arg2));
2951        LSCPResultSet result;
2952        try {
2953            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2954    
2955            if (Arg1 > 127 || Arg2 > 127) {
2956                throw Exception("Invalid MIDI message");
2957            }
2958    
2959            VirtualMidiDevice* pMidiDevice = NULL;
2960            std::vector<EventHandler::midi_listener_entry>::iterator iter = eventHandler.channelMidiListeners.begin();
2961            for (; iter != eventHandler.channelMidiListeners.end(); ++iter) {
2962                if ((*iter).pEngineChannel == pEngineChannel) {
2963                    pMidiDevice = (*iter).pMidiListener;
2964                  break;                  break;
2965              }              }
2966          }          }
2967          if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");          
2968            if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
2969    
2970          pFxSend->SetLevel((float)dLevel);          if (MidiMsg == "NOTE_ON") {
2971          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));              pMidiDevice->SendNoteOnToDevice(Arg1, Arg2);
2972                bool b = pMidiDevice->SendNoteOnToSampler(Arg1, Arg2);
2973                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2974            } else if (MidiMsg == "NOTE_OFF") {
2975                pMidiDevice->SendNoteOffToDevice(Arg1, Arg2);
2976                bool b = pMidiDevice->SendNoteOffToSampler(Arg1, Arg2);
2977                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2978            } else if (MidiMsg == "CC") {
2979                pMidiDevice->SendCCToDevice(Arg1, Arg2);
2980                bool b = pMidiDevice->SendCCToSampler(Arg1, Arg2);
2981                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2982            } else {
2983                throw Exception("Unknown MIDI message type: " + MidiMsg);
2984            }
2985      } catch (Exception e) {      } catch (Exception e) {
2986          result.Error(e);          result.Error(e);
2987      }      }
# Line 2153  String LSCPServer::ResetChannel(uint uiS Line 2995  String LSCPServer::ResetChannel(uint uiS
2995      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
2996      LSCPResultSet result;      LSCPResultSet result;
2997      try {      try {
2998          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
         if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));  
         EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();  
         if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");  
2999          pEngineChannel->Reset();          pEngineChannel->Reset();
3000      }      }
3001      catch (Exception e) {      catch (Exception e) {
# Line 2181  String LSCPServer::ResetSampler() { Line 3020  String LSCPServer::ResetSampler() {
3020   */   */
3021  String LSCPServer::GetServerInfo() {  String LSCPServer::GetServerInfo() {
3022      dmsg(2,("LSCPServer: GetServerInfo()\n"));      dmsg(2,("LSCPServer: GetServerInfo()\n"));
3023        const std::string description =
3024            _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
3025      LSCPResultSet result;      LSCPResultSet result;
3026      result.Add("DESCRIPTION", "LinuxSampler - modular, streaming capable sampler");      result.Add("DESCRIPTION", description);
3027      result.Add("VERSION", VERSION);      result.Add("VERSION", VERSION);
3028      result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));      result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
3029    #if HAVE_SQLITE3
3030        result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
3031    #else
3032        result.Add("INSTRUMENTS_DB_SUPPORT", "no");
3033    #endif
3034    
3035        return result.Produce();
3036    }
3037    
3038    /**
3039     * Will be called by the parser to return the current number of all active streams.
3040     */
3041    String LSCPServer::GetTotalStreamCount() {
3042        dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
3043        LSCPResultSet result;
3044        result.Add(pSampler->GetDiskStreamCount());
3045      return result.Produce();      return result.Produce();
3046  }  }
3047    
# Line 2204  String LSCPServer::GetTotalVoiceCount() Line 3061  String LSCPServer::GetTotalVoiceCount()
3061  String LSCPServer::GetTotalVoiceCountMax() {  String LSCPServer::GetTotalVoiceCountMax() {
3062      dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));      dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3063      LSCPResultSet result;      LSCPResultSet result;
3064      result.Add(EngineFactory::EngineInstances().size() * CONFIG_MAX_VOICES);      result.Add(EngineFactory::EngineInstances().size() * GLOBAL_MAX_VOICES);
3065        return result.Produce();
3066    }
3067    
3068    /**
3069     * Will be called by the parser to return the sampler global maximum
3070     * allowed number of voices.
3071     */
3072    String LSCPServer::GetGlobalMaxVoices() {
3073        dmsg(2,("LSCPServer: GetGlobalMaxVoices()\n"));
3074        LSCPResultSet result;
3075        result.Add(GLOBAL_MAX_VOICES);
3076        return result.Produce();
3077    }
3078    
3079    /**
3080     * Will be called by the parser to set the sampler global maximum number of
3081     * voices.
3082     */
3083    String LSCPServer::SetGlobalMaxVoices(int iVoices) {
3084        dmsg(2,("LSCPServer: SetGlobalMaxVoices(%d)\n", iVoices));
3085        LSCPResultSet result;
3086        try {
3087            if (iVoices < 1) throw Exception("Maximum voices may not be less than 1");
3088            GLOBAL_MAX_VOICES = iVoices; // see common/global_private.cpp
3089            const std::set<Engine*>& engines = EngineFactory::EngineInstances();
3090            if (engines.size() > 0) {
3091                std::set<Engine*>::iterator iter = engines.begin();
3092                std::set<Engine*>::iterator end  = engines.end();
3093                for (; iter != end; ++iter) {
3094                    (*iter)->SetMaxVoices(iVoices);
3095                }
3096            }
3097            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOICES", GLOBAL_MAX_VOICES));
3098        } catch (Exception e) {
3099            result.Error(e);
3100        }
3101        return result.Produce();
3102    }
3103    
3104    /**
3105     * Will be called by the parser to return the sampler global maximum
3106     * allowed number of disk streams.
3107     */
3108    String LSCPServer::GetGlobalMaxStreams() {
3109        dmsg(2,("LSCPServer: GetGlobalMaxStreams()\n"));
3110        LSCPResultSet result;
3111        result.Add(GLOBAL_MAX_STREAMS);
3112        return result.Produce();
3113    }
3114    
3115    /**
3116     * Will be called by the parser to set the sampler global maximum number of
3117     * disk streams.
3118     */
3119    String LSCPServer::SetGlobalMaxStreams(int iStreams) {
3120        dmsg(2,("LSCPServer: SetGlobalMaxStreams(%d)\n", iStreams));
3121        LSCPResultSet result;
3122        try {
3123            if (iStreams < 0) throw Exception("Maximum disk streams may not be negative");
3124            GLOBAL_MAX_STREAMS = iStreams; // see common/global_private.cpp
3125            const std::set<Engine*>& engines = EngineFactory::EngineInstances();
3126            if (engines.size() > 0) {
3127                std::set<Engine*>::iterator iter = engines.begin();
3128                std::set<Engine*>::iterator end  = engines.end();
3129                for (; iter != end; ++iter) {
3130                    (*iter)->SetMaxDiskStreams(iStreams);
3131                }
3132            }
3133            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "STREAMS", GLOBAL_MAX_STREAMS));
3134        } catch (Exception e) {
3135            result.Error(e);
3136        }
3137      return result.Produce();      return result.Produce();
3138  }  }
3139    
# Line 2218  String LSCPServer::SetGlobalVolume(doubl Line 3147  String LSCPServer::SetGlobalVolume(doubl
3147      LSCPResultSet result;      LSCPResultSet result;
3148      try {      try {
3149          if (dVolume < 0) throw Exception("Volume may not be negative");          if (dVolume < 0) throw Exception("Volume may not be negative");
3150          GLOBAL_VOLUME = dVolume; // see common/global.cpp          GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3151          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3152      } catch (Exception e) {      } catch (Exception e) {
3153          result.Error(e);          result.Error(e);
# Line 2226  String LSCPServer::SetGlobalVolume(doubl Line 3155  String LSCPServer::SetGlobalVolume(doubl
3155      return result.Produce();      return result.Produce();
3156  }  }
3157    
3158    String LSCPServer::GetFileInstruments(String Filename) {
3159        dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
3160        LSCPResultSet result;
3161        try {
3162            VerifyFile(Filename);
3163        } catch (Exception e) {
3164            result.Error(e);
3165            return result.Produce();
3166        }
3167        // try to find a sampler engine that can handle the file
3168        bool bFound = false;
3169        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3170        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3171            Engine* pEngine = NULL;
3172            try {
3173                pEngine = EngineFactory::Create(engineTypes[i]);
3174                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3175                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3176                if (pManager) {
3177                    std::vector<InstrumentManager::instrument_id_t> IDs =
3178                        pManager->GetInstrumentFileContent(Filename);
3179                    // return the amount of instruments in the file
3180                    result.Add(IDs.size());
3181                    // no more need to ask other engine types
3182                    bFound = true;
3183                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3184            } catch (Exception e) {
3185                // NOOP, as exception is thrown if engine doesn't support file
3186            }
3187            if (pEngine) EngineFactory::Destroy(pEngine);
3188        }
3189    
3190        if (!bFound) result.Error("Unknown file format");
3191        return result.Produce();
3192    }
3193    
3194    String LSCPServer::ListFileInstruments(String Filename) {
3195        dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
3196        LSCPResultSet result;
3197        try {
3198            VerifyFile(Filename);
3199        } catch (Exception e) {
3200            result.Error(e);
3201            return result.Produce();
3202        }
3203        // try to find a sampler engine that can handle the file
3204        bool bFound = false;
3205        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3206        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3207            Engine* pEngine = NULL;
3208            try {
3209                pEngine = EngineFactory::Create(engineTypes[i]);
3210                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3211                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3212                if (pManager) {
3213                    std::vector<InstrumentManager::instrument_id_t> IDs =
3214                        pManager->GetInstrumentFileContent(Filename);
3215                    // return a list of IDs of the instruments in the file
3216                    String s;
3217                    for (int j = 0; j < IDs.size(); j++) {
3218                        if (s.size()) s += ",";
3219                        s += ToString(IDs[j].Index);
3220                    }
3221                    result.Add(s);
3222                    // no more need to ask other engine types
3223                    bFound = true;
3224                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3225            } catch (Exception e) {
3226                // NOOP, as exception is thrown if engine doesn't support file
3227            }
3228            if (pEngine) EngineFactory::Destroy(pEngine);
3229        }
3230    
3231        if (!bFound) result.Error("Unknown file format");
3232        return result.Produce();
3233    }
3234    
3235    String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
3236        dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
3237        LSCPResultSet result;
3238        try {
3239            VerifyFile(Filename);
3240        } catch (Exception e) {
3241            result.Error(e);
3242            return result.Produce();
3243        }
3244        InstrumentManager::instrument_id_t id;
3245        id.FileName = Filename;
3246        id.Index    = InstrumentID;
3247        // try to find a sampler engine that can handle the file
3248        bool bFound = false;
3249        bool bFatalErr = false;
3250        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3251        for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
3252            Engine* pEngine = NULL;
3253            try {
3254                pEngine = EngineFactory::Create(engineTypes[i]);
3255                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3256                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3257                if (pManager) {
3258                    // check if the instrument index is valid
3259                    // FIXME: this won't work if an engine only supports parts of the instrument file
3260                    std::vector<InstrumentManager::instrument_id_t> IDs =
3261                        pManager->GetInstrumentFileContent(Filename);
3262                    if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
3263                        std::stringstream ss;
3264                        ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
3265                        bFatalErr = true;
3266                        throw Exception(ss.str());
3267                    }
3268                    // get the info of the requested instrument
3269                    InstrumentManager::instrument_info_t info =
3270                        pManager->GetInstrumentInfo(id);
3271                    // return detailed informations about the file
3272                    result.Add("NAME", info.InstrumentName);
3273                    result.Add("FORMAT_FAMILY", engineTypes[i]);
3274                    result.Add("FORMAT_VERSION", info.FormatVersion);
3275                    result.Add("PRODUCT", info.Product);
3276                    result.Add("ARTISTS", info.Artists);
3277    
3278                    std::stringstream ss;
3279                    bool b = false;
3280                    for (int i = 0; i < 128; i++) {
3281                        if (info.KeyBindings[i]) {
3282                            if (b) ss << ',';
3283                            ss << i; b = true;
3284                        }
3285                    }
3286                    result.Add("KEY_BINDINGS", ss.str());
3287    
3288                    b = false;
3289                    std::stringstream ss2;
3290                    for (int i = 0; i < 128; i++) {
3291                        if (info.KeySwitchBindings[i]) {
3292                            if (b) ss2 << ',';
3293                            ss2 << i; b = true;
3294                        }
3295                    }
3296                    result.Add("KEYSWITCH_BINDINGS", ss2.str());
3297                    // no more need to ask other engine types
3298                    bFound = true;
3299                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3300            } catch (Exception e) {
3301                // usually NOOP, as exception is thrown if engine doesn't support file
3302                if (bFatalErr) result.Error(e);
3303            }
3304            if (pEngine) EngineFactory::Destroy(pEngine);
3305        }
3306    
3307        if (!bFound && !bFatalErr) result.Error("Unknown file format");
3308        return result.Produce();
3309    }
3310    
3311    void LSCPServer::VerifyFile(String Filename) {
3312        #if WIN32
3313        WIN32_FIND_DATA win32FileAttributeData;
3314        BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
3315        if (!res) {
3316            std::stringstream ss;
3317            ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
3318            throw Exception(ss.str());
3319        }
3320        if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
3321            throw Exception("Directory is specified");
3322        }
3323        #else
3324        File f(Filename);
3325        if(!f.Exist()) throw Exception(f.GetErrorMsg());
3326        if (f.IsDirectory()) throw Exception("Directory is specified");
3327        #endif
3328    }
3329    
3330  /**  /**
3331   * Will be called by the parser to subscribe a client (frontend) on the   * Will be called by the parser to subscribe a client (frontend) on the
3332   * server for receiving event messages.   * server for receiving event messages.
# Line 2252  String LSCPServer::UnsubscribeNotificati Line 3353  String LSCPServer::UnsubscribeNotificati
3353      return result.Produce();      return result.Produce();
3354  }  }
3355    
3356  static int select_callback(void * lscpResultSet, int argc,  String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3357                          char **argv, char **azColName)      dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3358  {      LSCPResultSet result;
3359      LSCPResultSet* resultSet = (LSCPResultSet*) lscpResultSet;  #if HAVE_SQLITE3
3360      resultSet->Add(argc, argv);      try {
3361      return 0;          InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
3362        } catch (Exception e) {
3363             result.Error(e);
3364        }
3365    #else
3366        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3367    #endif
3368        return result.Produce();
3369  }  }
3370    
3371  String LSCPServer::QueryDatabase(String query) {  String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3372        dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3373      LSCPResultSet result;      LSCPResultSet result;
3374  #if HAVE_SQLITE3  #if HAVE_SQLITE3
3375      char* zErrMsg = NULL;      try {
3376      sqlite3 *db;          InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3377      String selectStr = "SELECT " + query;      } catch (Exception e) {
3378             result.Error(e);
3379        }
3380    #else
3381        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3382    #endif
3383        return result.Produce();
3384    }
3385    
3386      int rc = sqlite3_open("linuxsampler.db", &db);  String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3387      if (rc == SQLITE_OK)      dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3388      {      LSCPResultSet result;
3389              rc = sqlite3_exec(db, selectStr.c_str(), select_callback, &result, &zErrMsg);  #if HAVE_SQLITE3
3390        try {
3391            result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
3392        } catch (Exception e) {
3393             result.Error(e);
3394      }      }
3395      if ( rc != SQLITE_OK )  #else
3396      {      result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3397              result.Error(String(zErrMsg), rc);  #endif
3398        return result.Produce();
3399    }
3400    
3401    String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
3402        dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3403        LSCPResultSet result;
3404    #if HAVE_SQLITE3
3405        try {
3406            String list;
3407            StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
3408    
3409            for (int i = 0; i < dirs->size(); i++) {
3410                if (list != "") list += ",";
3411                list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
3412            }
3413    
3414            result.Add(list);
3415        } catch (Exception e) {
3416             result.Error(e);
3417        }
3418    #else
3419        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3420    #endif
3421        return result.Produce();
3422    }
3423    
3424    String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
3425        dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
3426        LSCPResultSet result;
3427    #if HAVE_SQLITE3
3428        try {
3429            DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
3430    
3431            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3432            result.Add("CREATED", info.Created);
3433            result.Add("MODIFIED", info.Modified);
3434        } catch (Exception e) {
3435             result.Error(e);
3436      }      }
     sqlite3_close(db);  
3437  #else  #else
3438      result.Error(String("SQLITE3 was not installed when linuxsampler was built. SELECT statement is not available."), 0);      result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3439  #endif  #endif
3440      return result.Produce();      return result.Produce();
3441  }  }
3442    
3443    String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
3444        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
3445        LSCPResultSet result;
3446    #if HAVE_SQLITE3
3447        try {
3448            InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
3449        } catch (Exception e) {
3450             result.Error(e);
3451        }
3452    #else
3453        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3454    #endif
3455        return result.Produce();
3456    }
3457    
3458    String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
3459        dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3460        LSCPResultSet result;
3461    #if HAVE_SQLITE3
3462        try {
3463            InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
3464        } catch (Exception e) {
3465             result.Error(e);
3466        }
3467    #else
3468        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3469    #endif
3470        return result.Produce();
3471    }
3472    
3473    String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
3474        dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3475        LSCPResultSet result;
3476    #if HAVE_SQLITE3
3477        try {
3478            InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
3479        } catch (Exception e) {
3480             result.Error(e);
3481        }
3482    #else
3483        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3484    #endif
3485        return result.Produce();
3486    }
3487    
3488    String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3489        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3490        LSCPResultSet result;
3491    #if HAVE_SQLITE3
3492        try {
3493            InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3494        } catch (Exception e) {
3495             result.Error(e);
3496        }
3497    #else
3498        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3499    #endif
3500        return result.Produce();
3501    }
3502    
3503    String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3504        dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
3505        LSCPResultSet result;
3506    #if HAVE_SQLITE3
3507        try {
3508            int id;
3509            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3510            id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
3511            if (bBackground) result = id;
3512        } catch (Exception e) {
3513             result.Error(e);
3514        }
3515    #else
3516        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3517    #endif
3518        return result.Produce();
3519    }
3520    
3521    String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground, bool insDir) {
3522        dmsg(2,("LSCPServer: AddDbInstruments(ScanMode=%s,DbDir=%s,FsDir=%s,bBackground=%d,insDir=%d)\n", ScanMode.c_str(), DbDir.c_str(), FsDir.c_str(), bBackground, insDir));
3523        LSCPResultSet result;
3524    #if HAVE_SQLITE3
3525        try {
3526            int id;
3527            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3528            if (ScanMode.compare("RECURSIVE") == 0) {
3529                id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground, insDir);
3530            } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
3531                id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground, insDir);
3532            } else if (ScanMode.compare("FLAT") == 0) {
3533                id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground, insDir);
3534            } else {
3535                throw Exception("Unknown scan mode: " + ScanMode);
3536            }
3537    
3538            if (bBackground) result = id;
3539        } catch (Exception e) {
3540             result.Error(e);
3541        }
3542    #else
3543        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3544    #endif
3545        return result.Produce();
3546    }
3547    
3548    String LSCPServer::RemoveDbInstrument(String Instr) {
3549        dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
3550        LSCPResultSet result;
3551    #if HAVE_SQLITE3
3552        try {
3553            InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
3554        } catch (Exception e) {
3555             result.Error(e);
3556        }
3557    #else
3558        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3559    #endif
3560        return result.Produce();
3561    }
3562    
3563    String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
3564        dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3565        LSCPResultSet result;
3566    #if HAVE_SQLITE3
3567        try {
3568            result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
3569        } catch (Exception e) {
3570             result.Error(e);
3571        }
3572    #else
3573        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3574    #endif
3575        return result.Produce();
3576    }
3577    
3578    String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
3579        dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3580        LSCPResultSet result;
3581    #if HAVE_SQLITE3
3582        try {
3583            String list;
3584            StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
3585    
3586            for (int i = 0; i < instrs->size(); i++) {
3587                if (list != "") list += ",";
3588                list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
3589            }
3590    
3591            result.Add(list);
3592        } catch (Exception e) {
3593             result.Error(e);
3594        }
3595    #else
3596        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3597    #endif
3598        return result.Produce();
3599    }
3600    
3601    String LSCPServer::GetDbInstrumentInfo(String Instr) {
3602        dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
3603        LSCPResultSet result;
3604    #if HAVE_SQLITE3
3605        try {
3606            DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
3607    
3608            result.Add("INSTRUMENT_FILE", info.InstrFile);
3609            result.Add("INSTRUMENT_NR", info.InstrNr);
3610            result.Add("FORMAT_FAMILY", info.FormatFamily);
3611            result.Add("FORMAT_VERSION", info.FormatVersion);
3612            result.Add("SIZE", (int)info.Size);
3613            result.Add("CREATED", info.Created);
3614            result.Add("MODIFIED", info.Modified);
3615            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3616            result.Add("IS_DRUM", info.IsDrum);
3617            result.Add("PRODUCT", _escapeLscpResponse(info.Product));
3618            result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
3619            result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
3620        } catch (Exception e) {
3621             result.Error(e);
3622        }
3623    #else
3624        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3625    #endif
3626        return result.Produce();
3627    }
3628    
3629    String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
3630        dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
3631        LSCPResultSet result;
3632    #if HAVE_SQLITE3
3633        try {
3634            ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
3635    
3636            result.Add("FILES_TOTAL", job.FilesTotal);
3637            result.Add("FILES_SCANNED", job.FilesScanned);
3638            result.Add("SCANNING", job.Scanning);
3639            result.Add("STATUS", job.Status);
3640        } catch (Exception e) {
3641             result.Error(e);
3642        }
3643    #else
3644        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3645    #endif
3646        return result.Produce();
3647    }
3648    
3649    String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
3650        dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
3651        LSCPResultSet result;
3652    #if HAVE_SQLITE3
3653        try {
3654            InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
3655        } catch (Exception e) {
3656             result.Error(e);
3657        }
3658    #else
3659        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3660    #endif
3661        return result.Produce();
3662    }
3663    
3664    String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
3665        dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3666        LSCPResultSet result;
3667    #if HAVE_SQLITE3
3668        try {
3669            InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
3670        } catch (Exception e) {
3671             result.Error(e);
3672        }
3673    #else
3674        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3675    #endif
3676        return result.Produce();
3677    }
3678    
3679    String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3680        dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3681        LSCPResultSet result;
3682    #if HAVE_SQLITE3
3683        try {
3684            InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3685        } catch (Exception e) {
3686             result.Error(e);
3687        }
3688    #else
3689        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3690    #endif
3691        return result.Produce();
3692    }
3693    
3694    String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3695        dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3696        LSCPResultSet result;
3697    #if HAVE_SQLITE3
3698        try {
3699            InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3700        } catch (Exception e) {
3701             result.Error(e);
3702        }
3703    #else
3704        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3705    #endif
3706        return result.Produce();
3707    }
3708    
3709    String LSCPServer::SetDbInstrumentFilePath(String OldPath, String NewPath) {
3710        dmsg(2,("LSCPServer: SetDbInstrumentFilePath(OldPath=%s,NewPath=%s)\n", OldPath.c_str(), NewPath.c_str()));
3711        LSCPResultSet result;
3712    #if HAVE_SQLITE3
3713        try {
3714            InstrumentsDb::GetInstrumentsDb()->SetInstrumentFilePath(OldPath, NewPath);
3715        } catch (Exception e) {
3716             result.Error(e);
3717        }
3718    #else
3719        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3720    #endif
3721        return result.Produce();
3722    }
3723    
3724    String LSCPServer::FindLostDbInstrumentFiles() {
3725        dmsg(2,("LSCPServer: FindLostDbInstrumentFiles()\n"));
3726        LSCPResultSet result;
3727    #if HAVE_SQLITE3
3728        try {
3729            String list;
3730            StringListPtr pLostFiles = InstrumentsDb::GetInstrumentsDb()->FindLostInstrumentFiles();
3731    
3732            for (int i = 0; i < pLostFiles->size(); i++) {
3733                if (list != "") list += ",";
3734                list += "'" + pLostFiles->at(i) + "'";
3735            }
3736    
3737            result.Add(list);
3738        } catch (Exception e) {
3739             result.Error(e);
3740        }
3741    #else
3742        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3743    #endif
3744        return result.Produce();
3745    }
3746    
3747    String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3748        dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3749        LSCPResultSet result;
3750    #if HAVE_SQLITE3
3751        try {
3752            SearchQuery Query;
3753            std::map<String,String>::iterator iter;
3754            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3755                if (iter->first.compare("NAME") == 0) {
3756                    Query.Name = iter->second;
3757                } else if (iter->first.compare("CREATED") == 0) {
3758                    Query.SetCreated(iter->second);
3759                } else if (iter->first.compare("MODIFIED") == 0) {
3760                    Query.SetModified(iter->second);
3761                } else if (iter->first.compare("DESCRIPTION") == 0) {
3762                    Query.Description = iter->second;
3763                } else {
3764                    throw Exception("Unknown search criteria: " + iter->first);
3765                }
3766            }
3767    
3768            String list;
3769            StringListPtr pDirectories =
3770                InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3771    
3772            for (int i = 0; i < pDirectories->size(); i++) {
3773                if (list != "") list += ",";
3774                list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3775            }
3776    
3777            result.Add(list);
3778        } catch (Exception e) {
3779             result.Error(e);
3780        }
3781    #else
3782        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3783    #endif
3784        return result.Produce();
3785    }
3786    
3787    String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
3788        dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
3789        LSCPResultSet result;
3790    #if HAVE_SQLITE3
3791        try {
3792            SearchQuery Query;
3793            std::map<String,String>::iterator iter;
3794            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3795                if (iter->first.compare("NAME") == 0) {
3796                    Query.Name = iter->second;
3797                } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
3798                    Query.SetFormatFamilies(iter->second);
3799                } else if (iter->first.compare("SIZE") == 0) {
3800                    Query.SetSize(iter->second);
3801                } else if (iter->first.compare("CREATED") == 0) {
3802                    Query.SetCreated(iter->second);
3803                } else if (iter->first.compare("MODIFIED") == 0) {
3804                    Query.SetModified(iter->second);
3805                } else if (iter->first.compare("DESCRIPTION") == 0) {
3806                    Query.Description = iter->second;
3807                } else if (iter->first.compare("IS_DRUM") == 0) {
3808                    if (!strcasecmp(iter->second.c_str(), "true")) {
3809                        Query.InstrType = SearchQuery::DRUM;
3810                    } else {
3811                        Query.InstrType = SearchQuery::CHROMATIC;
3812                    }
3813                } else if (iter->first.compare("PRODUCT") == 0) {
3814                     Query.Product = iter->second;
3815                } else if (iter->first.compare("ARTISTS") == 0) {
3816                     Query.Artists = iter->second;
3817                } else if (iter->first.compare("KEYWORDS") == 0) {
3818                     Query.Keywords = iter->second;
3819                } else {
3820                    throw Exception("Unknown search criteria: " + iter->first);
3821                }
3822            }
3823    
3824            String list;
3825            StringListPtr pInstruments =
3826                InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
3827    
3828            for (int i = 0; i < pInstruments->size(); i++) {
3829                if (list != "") list += ",";
3830                list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
3831            }
3832    
3833            result.Add(list);
3834        } catch (Exception e) {
3835             result.Error(e);
3836        }
3837    #else
3838        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3839    #endif
3840        return result.Produce();
3841    }
3842    
3843    String LSCPServer::FormatInstrumentsDb() {
3844        dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
3845        LSCPResultSet result;
3846    #if HAVE_SQLITE3
3847        try {
3848            InstrumentsDb::GetInstrumentsDb()->Format();
3849        } catch (Exception e) {
3850             result.Error(e);
3851        }
3852    #else
3853        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3854    #endif
3855        return result.Produce();
3856    }
3857    
3858    
3859  /**  /**
3860   * Will be called by the parser to enable or disable echo mode; if echo   * Will be called by the parser to enable or disable echo mode; if echo
3861   * mode is enabled, all commands from the client will (immediately) be   * mode is enabled, all commands from the client will (immediately) be
# Line 2301  String LSCPServer::SetEcho(yyparse_param Line 3874  String LSCPServer::SetEcho(yyparse_param
3874      }      }
3875      return result.Produce();      return result.Produce();
3876  }  }
3877    
3878    }

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

  ViewVC Help
Powered by ViewVC