/[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 2188 by iliev, Fri Jun 24 19:39:11 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);
             switch (iter->second.LoadMode) {  
                 case MidiInstrumentMapper::ON_DEMAND:  
                     result.Add("LOAD_MODE", "ON_DEMAND");  
                     break;  
                 case MidiInstrumentMapper::ON_DEMAND_HOLD:  
                     result.Add("LOAD_MODE", "ON_DEMAND_HOLD");  
                     break;  
                 case MidiInstrumentMapper::PERSISTENT:  
                     result.Add("LOAD_MODE", "PERSISTENT");  
                     break;  
                 default:  
                     throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");  
             }  
             result.Add("VOLUME", iter->second.Volume);  
2096          }          }
2097            result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2098            switch (entry.LoadMode) {
2099                case MidiInstrumentMapper::ON_DEMAND:
2100                    result.Add("LOAD_MODE", "ON_DEMAND");
2101                    break;
2102                case MidiInstrumentMapper::ON_DEMAND_HOLD:
2103                    result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2104                    break;
2105                case MidiInstrumentMapper::PERSISTENT:
2106                    result.Add("LOAD_MODE", "PERSISTENT");
2107                    break;
2108                default:
2109                    throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2110            }
2111            result.Add("VOLUME", entry.Volume);
2112      } catch (Exception e) {      } 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            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2795            for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
2796                EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2797                if (pEffectChain->ID() == iSendEffectChain) {
2798                    pDevice->RemoveSendEffectChain(i);
2799                    LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2800                    return result.Produce();
2801                }
2802            }
2803            throw Exception(
2804                "There is no send effect chain with ID " +
2805                ToString(iSendEffectChain) + " for audio output device " +
2806                ToString(iAudioOutputDevice) + "."
2807            );
2808        } catch (Exception e) {
2809            result.Error(e);
2810        }
2811        return result.Produce();
2812    }
2813    
2814    static EffectChain* _getSendEffectChain(Sampler* pSampler, int iAudioOutputDevice, int iSendEffectChain) throw (Exception) {
2815        std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2816        if (!devices.count(iAudioOutputDevice))
2817            throw Exception(
2818                "There is no audio output device with index " +
2819                ToString(iAudioOutputDevice) + "."
2820            );
2821        AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2822        for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
2823            EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2824            if (pEffectChain->ID() == iSendEffectChain) {
2825                return pEffectChain;
2826            }
2827        }
2828        throw Exception(
2829            "There is no send effect chain with ID " +
2830            ToString(iSendEffectChain) + " for audio output device " +
2831            ToString(iAudioOutputDevice) + "."
2832        );
2833    }
2834    
2835    String LSCPServer::GetSendEffectChainInfo(int iAudioOutputDevice, int iSendEffectChain) {
2836        dmsg(2,("LSCPServer: GetSendEffectChainInfo(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2837        LSCPResultSet result;
2838        try {
2839            EffectChain* pEffectChain =
2840                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2841            String sEffectSequence;
2842            for (int i = 0; i < pEffectChain->EffectCount(); i++) {
2843                if (i) sEffectSequence += ",";
2844                sEffectSequence += ToString(pEffectChain->GetEffect(i)->ID());
2845            }
2846            result.Add("EFFECT_COUNT", pEffectChain->EffectCount());
2847            result.Add("EFFECT_SEQUENCE", sEffectSequence);
2848        } catch (Exception e) {
2849            result.Error(e);
2850        }
2851        return result.Produce();
2852    }
2853    
2854    String LSCPServer::AppendSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectInstance) {
2855        dmsg(2,("LSCPServer: AppendSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectInstance));
2856        LSCPResultSet result;
2857        try {
2858            EffectChain* pEffectChain =
2859                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2860            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2861            if (!pEffect)
2862                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2863            pEffectChain->AppendEffect(pEffect);
2864            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2865        } catch (Exception e) {
2866            result.Error(e);
2867        }
2868        return result.Produce();
2869    }
2870    
2871    String LSCPServer::InsertSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition, int iEffectInstance) {
2872        dmsg(2,("LSCPServer: InsertSendEffectChainEffect(%d,%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition, iEffectInstance));
2873        LSCPResultSet result;
2874        try {
2875            EffectChain* pEffectChain =
2876                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2877            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2878            if (!pEffect)
2879                throw Exception("There is no effect instance with index " + ToString(iEffectInstance));
2880            pEffectChain->InsertEffect(pEffect, iEffectChainPosition);
2881            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2882        } catch (Exception e) {
2883            result.Error(e);
2884        }
2885        return result.Produce();
2886    }
2887    
2888    String LSCPServer::RemoveSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition) {
2889        dmsg(2,("LSCPServer: RemoveSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition));
2890        LSCPResultSet result;
2891        try {
2892            EffectChain* pEffectChain =
2893                _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2894            pEffectChain->RemoveEffect(iEffectChainPosition);
2895            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2896        } catch (Exception e) {
2897            result.Error(e);
2898        }
2899        return result.Produce();
2900    }
2901    
2902    String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
2903        dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
2904        LSCPResultSet result;
2905        try {
2906            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2907            if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
2908            Engine* pEngine = pEngineChannel->GetEngine();
2909            InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
2910            if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
2911            InstrumentManager::instrument_id_t instrumentID;
2912            instrumentID.FileName = pEngineChannel->InstrumentFileName();
2913            instrumentID.Index    = pEngineChannel->InstrumentIndex();
2914            pInstrumentManager->LaunchInstrumentEditor(instrumentID);
2915        } catch (Exception e) {
2916            result.Error(e);
2917        }
2918        return result.Produce();
2919    }
2920    
2921    String LSCPServer::SendChannelMidiData(String MidiMsg, uint uiSamplerChannel, uint Arg1, uint Arg2) {
2922        dmsg(2,("LSCPServer: SendChannelMidiData(MidiMsg=%s,uiSamplerChannel=%d,Arg1=%d,Arg2=%d)\n", MidiMsg.c_str(), uiSamplerChannel, Arg1, Arg2));
2923        LSCPResultSet result;
2924        try {
2925            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2926    
2927            if (Arg1 > 127 || Arg2 > 127) {
2928                throw Exception("Invalid MIDI message");
2929            }
2930    
2931            VirtualMidiDevice* pMidiDevice = NULL;
2932            std::vector<EventHandler::midi_listener_entry>::iterator iter = eventHandler.channelMidiListeners.begin();
2933            for (; iter != eventHandler.channelMidiListeners.end(); ++iter) {
2934                if ((*iter).pEngineChannel == pEngineChannel) {
2935                    pMidiDevice = (*iter).pMidiListener;
2936                  break;                  break;
2937              }              }
2938          }          }
2939          if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");          
2940            if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
2941    
2942          pFxSend->SetLevel((float)dLevel);          if (MidiMsg == "NOTE_ON") {
2943          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));              pMidiDevice->SendNoteOnToDevice(Arg1, Arg2);
2944                bool b = pMidiDevice->SendNoteOnToSampler(Arg1, Arg2);
2945                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2946            } else if (MidiMsg == "NOTE_OFF") {
2947                pMidiDevice->SendNoteOffToDevice(Arg1, Arg2);
2948                bool b = pMidiDevice->SendNoteOffToSampler(Arg1, Arg2);
2949                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2950            } else if (MidiMsg == "CC") {
2951                pMidiDevice->SendCCToDevice(Arg1, Arg2);
2952                bool b = pMidiDevice->SendCCToSampler(Arg1, Arg2);
2953                if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2954            } else {
2955                throw Exception("Unknown MIDI message type: " + MidiMsg);
2956            }
2957      } catch (Exception e) {      } catch (Exception e) {
2958          result.Error(e);          result.Error(e);
2959      }      }
# Line 2153  String LSCPServer::ResetChannel(uint uiS Line 2967  String LSCPServer::ResetChannel(uint uiS
2967      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
2968      LSCPResultSet result;      LSCPResultSet result;
2969      try {      try {
2970          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");  
2971          pEngineChannel->Reset();          pEngineChannel->Reset();
2972      }      }
2973      catch (Exception e) {      catch (Exception e) {
# Line 2181  String LSCPServer::ResetSampler() { Line 2992  String LSCPServer::ResetSampler() {
2992   */   */
2993  String LSCPServer::GetServerInfo() {  String LSCPServer::GetServerInfo() {
2994      dmsg(2,("LSCPServer: GetServerInfo()\n"));      dmsg(2,("LSCPServer: GetServerInfo()\n"));
2995        const std::string description =
2996            _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
2997      LSCPResultSet result;      LSCPResultSet result;
2998      result.Add("DESCRIPTION", "LinuxSampler - modular, streaming capable sampler");      result.Add("DESCRIPTION", description);
2999      result.Add("VERSION", VERSION);      result.Add("VERSION", VERSION);
3000      result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));      result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
3001    #if HAVE_SQLITE3
3002        result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
3003    #else
3004        result.Add("INSTRUMENTS_DB_SUPPORT", "no");
3005    #endif
3006    
3007        return result.Produce();
3008    }
3009    
3010    /**
3011     * Will be called by the parser to return the current number of all active streams.
3012     */
3013    String LSCPServer::GetTotalStreamCount() {
3014        dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
3015        LSCPResultSet result;
3016        result.Add(pSampler->GetDiskStreamCount());
3017      return result.Produce();      return result.Produce();
3018  }  }
3019    
# Line 2204  String LSCPServer::GetTotalVoiceCount() Line 3033  String LSCPServer::GetTotalVoiceCount()
3033  String LSCPServer::GetTotalVoiceCountMax() {  String LSCPServer::GetTotalVoiceCountMax() {
3034      dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));      dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3035      LSCPResultSet result;      LSCPResultSet result;
3036      result.Add(EngineFactory::EngineInstances().size() * CONFIG_MAX_VOICES);      result.Add(EngineFactory::EngineInstances().size() * GLOBAL_MAX_VOICES);
3037        return result.Produce();
3038    }
3039    
3040    /**
3041     * Will be called by the parser to return the sampler global maximum
3042     * allowed number of voices.
3043     */
3044    String LSCPServer::GetGlobalMaxVoices() {
3045        dmsg(2,("LSCPServer: GetGlobalMaxVoices()\n"));
3046        LSCPResultSet result;
3047        result.Add(GLOBAL_MAX_VOICES);
3048        return result.Produce();
3049    }
3050    
3051    /**
3052     * Will be called by the parser to set the sampler global maximum number of
3053     * voices.
3054     */
3055    String LSCPServer::SetGlobalMaxVoices(int iVoices) {
3056        dmsg(2,("LSCPServer: SetGlobalMaxVoices(%d)\n", iVoices));
3057        LSCPResultSet result;
3058        try {
3059            if (iVoices < 1) throw Exception("Maximum voices may not be less than 1");
3060            GLOBAL_MAX_VOICES = iVoices; // see common/global_private.cpp
3061            const std::set<Engine*>& engines = EngineFactory::EngineInstances();
3062            if (engines.size() > 0) {
3063                std::set<Engine*>::iterator iter = engines.begin();
3064                std::set<Engine*>::iterator end  = engines.end();
3065                for (; iter != end; ++iter) {
3066                    (*iter)->SetMaxVoices(iVoices);
3067                }
3068            }
3069            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOICES", GLOBAL_MAX_VOICES));
3070        } catch (Exception e) {
3071            result.Error(e);
3072        }
3073        return result.Produce();
3074    }
3075    
3076    /**
3077     * Will be called by the parser to return the sampler global maximum
3078     * allowed number of disk streams.
3079     */
3080    String LSCPServer::GetGlobalMaxStreams() {
3081        dmsg(2,("LSCPServer: GetGlobalMaxStreams()\n"));
3082        LSCPResultSet result;
3083        result.Add(GLOBAL_MAX_STREAMS);
3084        return result.Produce();
3085    }
3086    
3087    /**
3088     * Will be called by the parser to set the sampler global maximum number of
3089     * disk streams.
3090     */
3091    String LSCPServer::SetGlobalMaxStreams(int iStreams) {
3092        dmsg(2,("LSCPServer: SetGlobalMaxStreams(%d)\n", iStreams));
3093        LSCPResultSet result;
3094        try {
3095            if (iStreams < 0) throw Exception("Maximum disk streams may not be negative");
3096            GLOBAL_MAX_STREAMS = iStreams; // see common/global_private.cpp
3097            const std::set<Engine*>& engines = EngineFactory::EngineInstances();
3098            if (engines.size() > 0) {
3099                std::set<Engine*>::iterator iter = engines.begin();
3100                std::set<Engine*>::iterator end  = engines.end();
3101                for (; iter != end; ++iter) {
3102                    (*iter)->SetMaxDiskStreams(iStreams);
3103                }
3104            }
3105            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "STREAMS", GLOBAL_MAX_STREAMS));
3106        } catch (Exception e) {
3107            result.Error(e);
3108        }
3109      return result.Produce();      return result.Produce();
3110  }  }
3111    
# Line 2218  String LSCPServer::SetGlobalVolume(doubl Line 3119  String LSCPServer::SetGlobalVolume(doubl
3119      LSCPResultSet result;      LSCPResultSet result;
3120      try {      try {
3121          if (dVolume < 0) throw Exception("Volume may not be negative");          if (dVolume < 0) throw Exception("Volume may not be negative");
3122          GLOBAL_VOLUME = dVolume; // see common/global.cpp          GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3123          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3124      } catch (Exception e) {      } catch (Exception e) {
3125          result.Error(e);          result.Error(e);
# Line 2226  String LSCPServer::SetGlobalVolume(doubl Line 3127  String LSCPServer::SetGlobalVolume(doubl
3127      return result.Produce();      return result.Produce();
3128  }  }
3129    
3130    String LSCPServer::GetFileInstruments(String Filename) {
3131        dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
3132        LSCPResultSet result;
3133        try {
3134            VerifyFile(Filename);
3135        } catch (Exception e) {
3136            result.Error(e);
3137            return result.Produce();
3138        }
3139        // try to find a sampler engine that can handle the file
3140        bool bFound = false;
3141        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3142        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3143            Engine* pEngine = NULL;
3144            try {
3145                pEngine = EngineFactory::Create(engineTypes[i]);
3146                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3147                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3148                if (pManager) {
3149                    std::vector<InstrumentManager::instrument_id_t> IDs =
3150                        pManager->GetInstrumentFileContent(Filename);
3151                    // return the amount of instruments in the file
3152                    result.Add(IDs.size());
3153                    // no more need to ask other engine types
3154                    bFound = true;
3155                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3156            } catch (Exception e) {
3157                // NOOP, as exception is thrown if engine doesn't support file
3158            }
3159            if (pEngine) EngineFactory::Destroy(pEngine);
3160        }
3161    
3162        if (!bFound) result.Error("Unknown file format");
3163        return result.Produce();
3164    }
3165    
3166    String LSCPServer::ListFileInstruments(String Filename) {
3167        dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
3168        LSCPResultSet result;
3169        try {
3170            VerifyFile(Filename);
3171        } catch (Exception e) {
3172            result.Error(e);
3173            return result.Produce();
3174        }
3175        // try to find a sampler engine that can handle the file
3176        bool bFound = false;
3177        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3178        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3179            Engine* pEngine = NULL;
3180            try {
3181                pEngine = EngineFactory::Create(engineTypes[i]);
3182                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3183                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3184                if (pManager) {
3185                    std::vector<InstrumentManager::instrument_id_t> IDs =
3186                        pManager->GetInstrumentFileContent(Filename);
3187                    // return a list of IDs of the instruments in the file
3188                    String s;
3189                    for (int j = 0; j < IDs.size(); j++) {
3190                        if (s.size()) s += ",";
3191                        s += ToString(IDs[j].Index);
3192                    }
3193                    result.Add(s);
3194                    // no more need to ask other engine types
3195                    bFound = true;
3196                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3197            } catch (Exception e) {
3198                // NOOP, as exception is thrown if engine doesn't support file
3199            }
3200            if (pEngine) EngineFactory::Destroy(pEngine);
3201        }
3202    
3203        if (!bFound) result.Error("Unknown file format");
3204        return result.Produce();
3205    }
3206    
3207    String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
3208        dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
3209        LSCPResultSet result;
3210        try {
3211            VerifyFile(Filename);
3212        } catch (Exception e) {
3213            result.Error(e);
3214            return result.Produce();
3215        }
3216        InstrumentManager::instrument_id_t id;
3217        id.FileName = Filename;
3218        id.Index    = InstrumentID;
3219        // try to find a sampler engine that can handle the file
3220        bool bFound = false;
3221        bool bFatalErr = false;
3222        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3223        for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
3224            Engine* pEngine = NULL;
3225            try {
3226                pEngine = EngineFactory::Create(engineTypes[i]);
3227                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3228                InstrumentManager* pManager = pEngine->GetInstrumentManager();
3229                if (pManager) {
3230                    // check if the instrument index is valid
3231                    // FIXME: this won't work if an engine only supports parts of the instrument file
3232                    std::vector<InstrumentManager::instrument_id_t> IDs =
3233                        pManager->GetInstrumentFileContent(Filename);
3234                    if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
3235                        std::stringstream ss;
3236                        ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
3237                        bFatalErr = true;
3238                        throw Exception(ss.str());
3239                    }
3240                    // get the info of the requested instrument
3241                    InstrumentManager::instrument_info_t info =
3242                        pManager->GetInstrumentInfo(id);
3243                    // return detailed informations about the file
3244                    result.Add("NAME", info.InstrumentName);
3245                    result.Add("FORMAT_FAMILY", engineTypes[i]);
3246                    result.Add("FORMAT_VERSION", info.FormatVersion);
3247                    result.Add("PRODUCT", info.Product);
3248                    result.Add("ARTISTS", info.Artists);
3249    
3250                    std::stringstream ss;
3251                    bool b = false;
3252                    for (int i = 0; i < 128; i++) {
3253                        if (info.KeyBindings[i]) {
3254                            if (b) ss << ',';
3255                            ss << i; b = true;
3256                        }
3257                    }
3258                    result.Add("KEY_BINDINGS", ss.str());
3259    
3260                    b = false;
3261                    std::stringstream ss2;
3262                    for (int i = 0; i < 128; i++) {
3263                        if (info.KeySwitchBindings[i]) {
3264                            if (b) ss2 << ',';
3265                            ss2 << i; b = true;
3266                        }
3267                    }
3268                    result.Add("KEYSWITCH_BINDINGS", ss2.str());
3269                    // no more need to ask other engine types
3270                    bFound = true;
3271                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3272            } catch (Exception e) {
3273                // usually NOOP, as exception is thrown if engine doesn't support file
3274                if (bFatalErr) result.Error(e);
3275            }
3276            if (pEngine) EngineFactory::Destroy(pEngine);
3277        }
3278    
3279        if (!bFound && !bFatalErr) result.Error("Unknown file format");
3280        return result.Produce();
3281    }
3282    
3283    void LSCPServer::VerifyFile(String Filename) {
3284        #if WIN32
3285        WIN32_FIND_DATA win32FileAttributeData;
3286        BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
3287        if (!res) {
3288            std::stringstream ss;
3289            ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
3290            throw Exception(ss.str());
3291        }
3292        if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
3293            throw Exception("Directory is specified");
3294        }
3295        #else
3296        File f(Filename);
3297        if(!f.Exist()) throw Exception(f.GetErrorMsg());
3298        if (f.IsDirectory()) throw Exception("Directory is specified");
3299        #endif
3300    }
3301    
3302  /**  /**
3303   * 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
3304   * server for receiving event messages.   * server for receiving event messages.
# Line 2252  String LSCPServer::UnsubscribeNotificati Line 3325  String LSCPServer::UnsubscribeNotificati
3325      return result.Produce();      return result.Produce();
3326  }  }
3327    
3328  static int select_callback(void * lscpResultSet, int argc,  String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3329                          char **argv, char **azColName)      dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3330  {      LSCPResultSet result;
3331      LSCPResultSet* resultSet = (LSCPResultSet*) lscpResultSet;  #if HAVE_SQLITE3
3332      resultSet->Add(argc, argv);      try {
3333      return 0;          InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
3334        } catch (Exception e) {
3335             result.Error(e);
3336        }
3337    #else
3338        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3339    #endif
3340        return result.Produce();
3341    }
3342    
3343    String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3344        dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3345        LSCPResultSet result;
3346    #if HAVE_SQLITE3
3347        try {
3348            InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3349        } catch (Exception e) {
3350             result.Error(e);
3351        }
3352    #else
3353        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3354    #endif
3355        return result.Produce();
3356    }
3357    
3358    String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3359        dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3360        LSCPResultSet result;
3361    #if HAVE_SQLITE3
3362        try {
3363            result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
3364        } catch (Exception e) {
3365             result.Error(e);
3366        }
3367    #else
3368        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3369    #endif
3370        return result.Produce();
3371    }
3372    
3373    String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
3374        dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3375        LSCPResultSet result;
3376    #if HAVE_SQLITE3
3377        try {
3378            String list;
3379            StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
3380    
3381            for (int i = 0; i < dirs->size(); i++) {
3382                if (list != "") list += ",";
3383                list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
3384            }
3385    
3386            result.Add(list);
3387        } catch (Exception e) {
3388             result.Error(e);
3389        }
3390    #else
3391        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3392    #endif
3393        return result.Produce();
3394    }
3395    
3396    String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
3397        dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
3398        LSCPResultSet result;
3399    #if HAVE_SQLITE3
3400        try {
3401            DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
3402    
3403            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3404            result.Add("CREATED", info.Created);
3405            result.Add("MODIFIED", info.Modified);
3406        } catch (Exception e) {
3407             result.Error(e);
3408        }
3409    #else
3410        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3411    #endif
3412        return result.Produce();
3413    }
3414    
3415    String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
3416        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
3417        LSCPResultSet result;
3418    #if HAVE_SQLITE3
3419        try {
3420            InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
3421        } catch (Exception e) {
3422             result.Error(e);
3423        }
3424    #else
3425        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3426    #endif
3427        return result.Produce();
3428    }
3429    
3430    String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
3431        dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3432        LSCPResultSet result;
3433    #if HAVE_SQLITE3
3434        try {
3435            InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
3436        } catch (Exception e) {
3437             result.Error(e);
3438        }
3439    #else
3440        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3441    #endif
3442        return result.Produce();
3443    }
3444    
3445    String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
3446        dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3447        LSCPResultSet result;
3448    #if HAVE_SQLITE3
3449        try {
3450            InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
3451        } catch (Exception e) {
3452             result.Error(e);
3453        }
3454    #else
3455        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3456    #endif
3457        return result.Produce();
3458  }  }
3459    
3460  String LSCPServer::QueryDatabase(String query) {  String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3461        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3462      LSCPResultSet result;      LSCPResultSet result;
3463  #if HAVE_SQLITE3  #if HAVE_SQLITE3
3464      char* zErrMsg = NULL;      try {
3465      sqlite3 *db;          InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3466      String selectStr = "SELECT " + query;      } catch (Exception e) {
3467             result.Error(e);
3468        }
3469    #else
3470        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3471    #endif
3472        return result.Produce();
3473    }
3474    
3475    String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3476        dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
3477        LSCPResultSet result;
3478    #if HAVE_SQLITE3
3479        try {
3480            int id;
3481            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3482            id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
3483            if (bBackground) result = id;
3484        } catch (Exception e) {
3485             result.Error(e);
3486        }
3487    #else
3488        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3489    #endif
3490        return result.Produce();
3491    }
3492    
3493    String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground, bool insDir) {
3494        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));
3495        LSCPResultSet result;
3496    #if HAVE_SQLITE3
3497        try {
3498            int id;
3499            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3500            if (ScanMode.compare("RECURSIVE") == 0) {
3501                id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground, insDir);
3502            } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
3503                id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground, insDir);
3504            } else if (ScanMode.compare("FLAT") == 0) {
3505                id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground, insDir);
3506            } else {
3507                throw Exception("Unknown scan mode: " + ScanMode);
3508            }
3509    
3510            if (bBackground) result = id;
3511        } catch (Exception e) {
3512             result.Error(e);
3513        }
3514    #else
3515        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3516    #endif
3517        return result.Produce();
3518    }
3519    
3520    String LSCPServer::RemoveDbInstrument(String Instr) {
3521        dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
3522        LSCPResultSet result;
3523    #if HAVE_SQLITE3
3524        try {
3525            InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
3526        } catch (Exception e) {
3527             result.Error(e);
3528        }
3529    #else
3530        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3531    #endif
3532        return result.Produce();
3533    }
3534    
3535    String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
3536        dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3537        LSCPResultSet result;
3538    #if HAVE_SQLITE3
3539        try {
3540            result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
3541        } catch (Exception e) {
3542             result.Error(e);
3543        }
3544    #else
3545        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3546    #endif
3547        return result.Produce();
3548    }
3549    
3550    String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
3551        dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3552        LSCPResultSet result;
3553    #if HAVE_SQLITE3
3554        try {
3555            String list;
3556            StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
3557    
3558            for (int i = 0; i < instrs->size(); i++) {
3559                if (list != "") list += ",";
3560                list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
3561            }
3562    
3563      int rc = sqlite3_open("linuxsampler.db", &db);          result.Add(list);
3564      if (rc == SQLITE_OK)      } catch (Exception e) {
3565      {           result.Error(e);
             rc = sqlite3_exec(db, selectStr.c_str(), select_callback, &result, &zErrMsg);  
3566      }      }
3567      if ( rc != SQLITE_OK )  #else
3568      {      result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3569              result.Error(String(zErrMsg), rc);  #endif
3570        return result.Produce();
3571    }
3572    
3573    String LSCPServer::GetDbInstrumentInfo(String Instr) {
3574        dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
3575        LSCPResultSet result;
3576    #if HAVE_SQLITE3
3577        try {
3578            DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
3579    
3580            result.Add("INSTRUMENT_FILE", info.InstrFile);
3581            result.Add("INSTRUMENT_NR", info.InstrNr);
3582            result.Add("FORMAT_FAMILY", info.FormatFamily);
3583            result.Add("FORMAT_VERSION", info.FormatVersion);
3584            result.Add("SIZE", (int)info.Size);
3585            result.Add("CREATED", info.Created);
3586            result.Add("MODIFIED", info.Modified);
3587            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3588            result.Add("IS_DRUM", info.IsDrum);
3589            result.Add("PRODUCT", _escapeLscpResponse(info.Product));
3590            result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
3591            result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
3592        } catch (Exception e) {
3593             result.Error(e);
3594      }      }
     sqlite3_close(db);  
3595  #else  #else
3596      result.Error(String("SQLITE3 was not installed when linuxsampler was built. SELECT statement is not available."), 0);      result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3597  #endif  #endif
3598      return result.Produce();      return result.Produce();
3599  }  }
3600    
3601    String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
3602        dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
3603        LSCPResultSet result;
3604    #if HAVE_SQLITE3
3605        try {
3606            ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
3607    
3608            result.Add("FILES_TOTAL", job.FilesTotal);
3609            result.Add("FILES_SCANNED", job.FilesScanned);
3610            result.Add("SCANNING", job.Scanning);
3611            result.Add("STATUS", job.Status);
3612        } catch (Exception e) {
3613             result.Error(e);
3614        }
3615    #else
3616        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3617    #endif
3618        return result.Produce();
3619    }
3620    
3621    String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
3622        dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
3623        LSCPResultSet result;
3624    #if HAVE_SQLITE3
3625        try {
3626            InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
3627        } catch (Exception e) {
3628             result.Error(e);
3629        }
3630    #else
3631        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3632    #endif
3633        return result.Produce();
3634    }
3635    
3636    String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
3637        dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3638        LSCPResultSet result;
3639    #if HAVE_SQLITE3
3640        try {
3641            InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
3642        } catch (Exception e) {
3643             result.Error(e);
3644        }
3645    #else
3646        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3647    #endif
3648        return result.Produce();
3649    }
3650    
3651    String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3652        dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3653        LSCPResultSet result;
3654    #if HAVE_SQLITE3
3655        try {
3656            InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3657        } catch (Exception e) {
3658             result.Error(e);
3659        }
3660    #else
3661        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3662    #endif
3663        return result.Produce();
3664    }
3665    
3666    String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3667        dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3668        LSCPResultSet result;
3669    #if HAVE_SQLITE3
3670        try {
3671            InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3672        } catch (Exception e) {
3673             result.Error(e);
3674        }
3675    #else
3676        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3677    #endif
3678        return result.Produce();
3679    }
3680    
3681    String LSCPServer::SetDbInstrumentFilePath(String OldPath, String NewPath) {
3682        dmsg(2,("LSCPServer: SetDbInstrumentFilePath(OldPath=%s,NewPath=%s)\n", OldPath.c_str(), NewPath.c_str()));
3683        LSCPResultSet result;
3684    #if HAVE_SQLITE3
3685        try {
3686            InstrumentsDb::GetInstrumentsDb()->SetInstrumentFilePath(OldPath, NewPath);
3687        } catch (Exception e) {
3688             result.Error(e);
3689        }
3690    #else
3691        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3692    #endif
3693        return result.Produce();
3694    }
3695    
3696    String LSCPServer::FindLostDbInstrumentFiles() {
3697        dmsg(2,("LSCPServer: FindLostDbInstrumentFiles()\n"));
3698        LSCPResultSet result;
3699    #if HAVE_SQLITE3
3700        try {
3701            String list;
3702            StringListPtr pLostFiles = InstrumentsDb::GetInstrumentsDb()->FindLostInstrumentFiles();
3703    
3704            for (int i = 0; i < pLostFiles->size(); i++) {
3705                if (list != "") list += ",";
3706                list += "'" + pLostFiles->at(i) + "'";
3707            }
3708    
3709            result.Add(list);
3710        } catch (Exception e) {
3711             result.Error(e);
3712        }
3713    #else
3714        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3715    #endif
3716        return result.Produce();
3717    }
3718    
3719    String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3720        dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3721        LSCPResultSet result;
3722    #if HAVE_SQLITE3
3723        try {
3724            SearchQuery Query;
3725            std::map<String,String>::iterator iter;
3726            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3727                if (iter->first.compare("NAME") == 0) {
3728                    Query.Name = iter->second;
3729                } else if (iter->first.compare("CREATED") == 0) {
3730                    Query.SetCreated(iter->second);
3731                } else if (iter->first.compare("MODIFIED") == 0) {
3732                    Query.SetModified(iter->second);
3733                } else if (iter->first.compare("DESCRIPTION") == 0) {
3734                    Query.Description = iter->second;
3735                } else {
3736                    throw Exception("Unknown search criteria: " + iter->first);
3737                }
3738            }
3739    
3740            String list;
3741            StringListPtr pDirectories =
3742                InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3743    
3744            for (int i = 0; i < pDirectories->size(); i++) {
3745                if (list != "") list += ",";
3746                list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3747            }
3748    
3749            result.Add(list);
3750        } catch (Exception e) {
3751             result.Error(e);
3752        }
3753    #else
3754        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3755    #endif
3756        return result.Produce();
3757    }
3758    
3759    String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
3760        dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
3761        LSCPResultSet result;
3762    #if HAVE_SQLITE3
3763        try {
3764            SearchQuery Query;
3765            std::map<String,String>::iterator iter;
3766            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3767                if (iter->first.compare("NAME") == 0) {
3768                    Query.Name = iter->second;
3769                } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
3770                    Query.SetFormatFamilies(iter->second);
3771                } else if (iter->first.compare("SIZE") == 0) {
3772                    Query.SetSize(iter->second);
3773                } else if (iter->first.compare("CREATED") == 0) {
3774                    Query.SetCreated(iter->second);
3775                } else if (iter->first.compare("MODIFIED") == 0) {
3776                    Query.SetModified(iter->second);
3777                } else if (iter->first.compare("DESCRIPTION") == 0) {
3778                    Query.Description = iter->second;
3779                } else if (iter->first.compare("IS_DRUM") == 0) {
3780                    if (!strcasecmp(iter->second.c_str(), "true")) {
3781                        Query.InstrType = SearchQuery::DRUM;
3782                    } else {
3783                        Query.InstrType = SearchQuery::CHROMATIC;
3784                    }
3785                } else if (iter->first.compare("PRODUCT") == 0) {
3786                     Query.Product = iter->second;
3787                } else if (iter->first.compare("ARTISTS") == 0) {
3788                     Query.Artists = iter->second;
3789                } else if (iter->first.compare("KEYWORDS") == 0) {
3790                     Query.Keywords = iter->second;
3791                } else {
3792                    throw Exception("Unknown search criteria: " + iter->first);
3793                }
3794            }
3795    
3796            String list;
3797            StringListPtr pInstruments =
3798                InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
3799    
3800            for (int i = 0; i < pInstruments->size(); i++) {
3801                if (list != "") list += ",";
3802                list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
3803            }
3804    
3805            result.Add(list);
3806        } catch (Exception e) {
3807             result.Error(e);
3808        }
3809    #else
3810        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3811    #endif
3812        return result.Produce();
3813    }
3814    
3815    String LSCPServer::FormatInstrumentsDb() {
3816        dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
3817        LSCPResultSet result;
3818    #if HAVE_SQLITE3
3819        try {
3820            InstrumentsDb::GetInstrumentsDb()->Format();
3821        } catch (Exception e) {
3822             result.Error(e);
3823        }
3824    #else
3825        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3826    #endif
3827        return result.Produce();
3828    }
3829    
3830    
3831  /**  /**
3832   * 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
3833   * 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 3846  String LSCPServer::SetEcho(yyparse_param
3846      }      }
3847      return result.Produce();      return result.Produce();
3848  }  }
3849    
3850    }

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

  ViewVC Help
Powered by ViewVC