/[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 198 by senkov, Tue Jul 13 15:36:16 2004 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 - 2010 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
10   *   the Free Software Foundation; either version 2 of the License, or     *   *   the Free Software Foundation; either version 2 of the License, or     *
11   *   (at your option) any later version.                                   *   *   (at your option) any later version.                                   *
12   *                                                                         *   *                                                                         *
13   *   This program is distributed in the hope that it will be useful,       *   *   This library is distributed in the hope that it will be useful,       *
14   *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *   *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16   *   GNU General Public License for more details.                          *   *   GNU General Public License for more details.                          *
17   *                                                                         *   *                                                                         *
18   *   You should have received a copy of the GNU General Public License     *   *   You should have received a copy of the GNU General Public License     *
19   *   along with this program; if not, write to the Free Software           *   *   along with this library; if not, write to the Free Software           *
20   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21   *   MA  02111-1307  USA                                                   *   *   MA  02111-1307  USA                                                   *
22   ***************************************************************************/   ***************************************************************************/
23    
24    #include <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"
31    
32  #include "../engines/gig/Engine.h"  #if defined(WIN32)
33  #include "../audiodriver/AudioOutputDeviceFactory.h"  #include <windows.h>
34  #include "../mididriver/MidiInputDeviceFactory.h"  #else
35    #include <fcntl.h>
36    #endif
37    
38    #if ! HAVE_SQLITE3
39    #define DOESNT_HAVE_SQLITE3 "No database support. SQLITE3 was not installed when linuxsampler was built."
40    #endif
41    
42    #include "../engines/EngineFactory.h"
43    #include "../engines/EngineChannelFactory.h"
44    #include "../drivers/audio/AudioOutputDeviceFactory.h"
45    #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 43  Line 97 
97   */   */
98  fd_set LSCPServer::fdSet;  fd_set LSCPServer::fdSet;
99  int LSCPServer::currentSocket = -1;  int LSCPServer::currentSocket = -1;
100  std::vector<int> LSCPServer::hSessions = std::vector<int>();  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> >();
105  Mutex LSCPServer::NotifyMutex = Mutex();  Mutex LSCPServer::NotifyMutex = Mutex();
106  Mutex LSCPServer::NotifyBufferMutex = Mutex();  Mutex LSCPServer::NotifyBufferMutex = Mutex();
107  Mutex LSCPServer::SubscriptionMutex = Mutex();  Mutex LSCPServer::SubscriptionMutex = Mutex();
108    Mutex LSCPServer::RTNotifyMutex = Mutex();
109    
110  LSCPServer::LSCPServer(Sampler* pSampler) : Thread(false, 0, -4) {  LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4), eventHandler(this) {
111        SocketAddress.sin_family      = AF_INET;
112        SocketAddress.sin_addr.s_addr = addr;
113        SocketAddress.sin_port        = port;
114      this->pSampler = pSampler;      this->pSampler = pSampler;
115      LSCPEvent::RegisterEvent(LSCPEvent::event_channels, "CHANNELS");      LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT");
116        LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO");
117        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT");
118        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO");
119        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
120      LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
121      LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");      LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
122      LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");      LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
123      LSCPEvent::RegisterEvent(LSCPEvent::event_info, "INFO");      LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
124        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_count, "FX_SEND_COUNT");
125        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_info, "FX_SEND_INFO");
126        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
127        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
128        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
129        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
130        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_count, "DB_INSTRUMENT_DIRECTORY_COUNT");
131        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_info, "DB_INSTRUMENT_DIRECTORY_INFO");
132        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_count, "DB_INSTRUMENT_COUNT");
133        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_info, "DB_INSTRUMENT_INFO");
134        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instrs_job_info, "DB_INSTRUMENTS_JOB_INFO");
135      LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");      LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
136        LSCPEvent::RegisterEvent(LSCPEvent::event_total_stream_count, "TOTAL_STREAM_COUNT");
137        LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
138        LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");
139        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_midi, "CHANNEL_MIDI");
140        LSCPEvent::RegisterEvent(LSCPEvent::event_device_midi, "DEVICE_MIDI");
141        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_count, "EFFECT_INSTANCE_COUNT");
142        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_info, "EFFECT_INSTANCE_INFO");
143        LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_count, "SEND_EFFECT_CHAIN_COUNT");
144        LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_info, "SEND_EFFECT_CHAIN_INFO");
145        hSocket = -1;
146    }
147    
148    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);
155    #endif
156    }
157    
158    LSCPServer::EventHandler::EventHandler(LSCPServer* pParent) {
159        this->pParent = pParent;
160    }
161    
162    LSCPServer::EventHandler::~EventHandler() {
163        std::vector<midi_listener_entry> l = channelMidiListeners;
164        channelMidiListeners.clear();
165        for (int i = 0; i < l.size(); i++)
166            delete l[i].pMidiListener;
167    }
168    
169    void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {
170        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));
171    }
172    
173    void LSCPServer::EventHandler::ChannelAdded(SamplerChannel* pChannel) {
174        pChannel->AddEngineChangeListener(this);
175    }
176    
177    void LSCPServer::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) {
178        if (!pChannel->GetEngineChannel()) return;
179        EngineToBeChanged(pChannel->Index());
180    }
181    
182    void LSCPServer::EventHandler::EngineToBeChanged(int ChannelId) {
183        SamplerChannel* pSamplerChannel =
184            pParent->pSampler->GetSamplerChannel(ChannelId);
185        if (!pSamplerChannel) return;
186        EngineChannel* pEngineChannel =
187            pSamplerChannel->GetEngineChannel();
188        if (!pEngineChannel) return;
189        for (std::vector<midi_listener_entry>::iterator iter = channelMidiListeners.begin(); iter != channelMidiListeners.end(); ++iter) {
190            if ((*iter).pEngineChannel == pEngineChannel) {
191                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
192                pEngineChannel->Disconnect(pMidiListener);
193                channelMidiListeners.erase(iter);
194                delete pMidiListener;
195                return;
196            }
197        }
198    }
199    
200    void LSCPServer::EventHandler::EngineChanged(int ChannelId) {
201        SamplerChannel* pSamplerChannel =
202            pParent->pSampler->GetSamplerChannel(ChannelId);
203        if (!pSamplerChannel) return;
204        EngineChannel* pEngineChannel =
205            pSamplerChannel->GetEngineChannel();
206        if (!pEngineChannel) return;
207        VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
208        pEngineChannel->Connect(pMidiListener);
209        midi_listener_entry entry = {
210            pSamplerChannel, pEngineChannel, pMidiListener
211        };
212        channelMidiListeners.push_back(entry);
213    }
214    
215    void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {
216        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));
217    }
218    
219    void LSCPServer::EventHandler::MidiDeviceCountChanged(int NewCount) {
220        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));
221    }
222    
223    void LSCPServer::EventHandler::MidiDeviceToBeDestroyed(MidiInputDevice* pDevice) {
224        pDevice->RemoveMidiPortCountListener(this);
225        for (int i = 0; i < pDevice->PortCount(); ++i)
226            MidiPortToBeRemoved(pDevice->GetPort(i));
227    }
228    
229    void LSCPServer::EventHandler::MidiDeviceCreated(MidiInputDevice* pDevice) {
230        pDevice->AddMidiPortCountListener(this);
231        for (int i = 0; i < pDevice->PortCount(); ++i)
232            MidiPortAdded(pDevice->GetPort(i));
233    }
234    
235    void LSCPServer::EventHandler::MidiPortCountChanged(int NewCount) {
236        // yet unused
237    }
238    
239    void LSCPServer::EventHandler::MidiPortToBeRemoved(MidiInputPort* pPort) {
240        for (std::vector<device_midi_listener_entry>::iterator iter = deviceMidiListeners.begin(); iter != deviceMidiListeners.end(); ++iter) {
241            if ((*iter).pPort == pPort) {
242                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
243                pPort->Disconnect(pMidiListener);
244                deviceMidiListeners.erase(iter);
245                delete pMidiListener;
246                return;
247            }
248        }
249    }
250    
251    void LSCPServer::EventHandler::MidiPortAdded(MidiInputPort* pPort) {
252        // find out the device ID
253        std::map<uint, MidiInputDevice*> devices =
254            pParent->pSampler->GetMidiInputDevices();
255        for (
256            std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
257            iter != devices.end(); ++iter
258        ) {
259            if (iter->second == pPort->GetDevice()) { // found
260                VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
261                pPort->Connect(pMidiListener);
262                device_midi_listener_entry entry = {
263                    pPort, pMidiListener, iter->first
264                };
265                deviceMidiListeners.push_back(entry);
266                return;
267            }
268        }
269    }
270    
271    void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {
272        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));
273    }
274    
275    void LSCPServer::EventHandler::MidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
276        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_info, MapId, Bank, Program));
277    }
278    
279    void LSCPServer::EventHandler::MidiInstrumentMapCountChanged(int NewCount) {
280        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, NewCount));
281    }
282    
283    void LSCPServer::EventHandler::MidiInstrumentMapInfoChanged(int MapId) {
284        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_info, MapId));
285    }
286    
287    void LSCPServer::EventHandler::FxSendCountChanged(int ChannelId, int NewCount) {
288        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_count, ChannelId, NewCount));
289    }
290    
291    void LSCPServer::EventHandler::VoiceCountChanged(int ChannelId, int NewCount) {
292        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, ChannelId, NewCount));
293    }
294    
295    void LSCPServer::EventHandler::StreamCountChanged(int ChannelId, int NewCount) {
296        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, ChannelId, NewCount));
297    }
298    
299    void LSCPServer::EventHandler::BufferFillChanged(int ChannelId, String FillData) {
300        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, ChannelId, FillData));
301    }
302    
303    void LSCPServer::EventHandler::TotalVoiceCountChanged(int NewCount) {
304        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));
305    }
306    
307    void LSCPServer::EventHandler::TotalStreamCountChanged(int NewCount) {
308        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_stream_count, NewCount));
309    }
310    
311    #if HAVE_SQLITE3
312    void LSCPServer::DbInstrumentsEventHandler::DirectoryCountChanged(String Dir) {
313        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_count, InstrumentsDb::toEscapedPath(Dir)));
314    }
315    
316    void LSCPServer::DbInstrumentsEventHandler::DirectoryInfoChanged(String Dir) {
317        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, InstrumentsDb::toEscapedPath(Dir)));
318    }
319    
320    void LSCPServer::DbInstrumentsEventHandler::DirectoryNameChanged(String Dir, String NewName) {
321        Dir = "'" + InstrumentsDb::toEscapedPath(Dir) + "'";
322        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
323        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, "NAME", Dir, NewName));
324    }
325    
326    void LSCPServer::DbInstrumentsEventHandler::InstrumentCountChanged(String Dir) {
327        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_count, InstrumentsDb::toEscapedPath(Dir)));
328    }
329    
330    void LSCPServer::DbInstrumentsEventHandler::InstrumentInfoChanged(String Instr) {
331        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, InstrumentsDb::toEscapedPath(Instr)));
332    }
333    
334    void LSCPServer::DbInstrumentsEventHandler::InstrumentNameChanged(String Instr, String NewName) {
335        Instr = "'" + InstrumentsDb::toEscapedPath(Instr) + "'";
336        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
337        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, "NAME", Instr, NewName));
338    }
339    
340    void LSCPServer::DbInstrumentsEventHandler::JobStatusChanged(int JobId) {
341        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instrs_job_info, JobId));
342    }
343    #endif // HAVE_SQLITE3
344    
345    void LSCPServer::RemoveListeners() {
346        pSampler->RemoveChannelCountListener(&eventHandler);
347        pSampler->RemoveAudioDeviceCountListener(&eventHandler);
348        pSampler->RemoveMidiDeviceCountListener(&eventHandler);
349        pSampler->RemoveVoiceCountListener(&eventHandler);
350        pSampler->RemoveStreamCountListener(&eventHandler);
351        pSampler->RemoveBufferFillListener(&eventHandler);
352        pSampler->RemoveTotalStreamCountListener(&eventHandler);
353        pSampler->RemoveTotalVoiceCountListener(&eventHandler);
354        pSampler->RemoveFxSendCountListener(&eventHandler);
355        MidiInstrumentMapper::RemoveMidiInstrumentCountListener(&eventHandler);
356        MidiInstrumentMapper::RemoveMidiInstrumentInfoListener(&eventHandler);
357        MidiInstrumentMapper::RemoveMidiInstrumentMapCountListener(&eventHandler);
358        MidiInstrumentMapper::RemoveMidiInstrumentMapInfoListener(&eventHandler);
359    #if HAVE_SQLITE3
360        InstrumentsDb::GetInstrumentsDb()->RemoveInstrumentsDbListener(&dbInstrumentsEventHandler);
361    #endif
362    }
363    
364    /**
365     * Blocks the calling thread until the LSCP Server is initialized and
366     * accepting socket connections, if the server is already initialized then
367     * this method will return immediately.
368     * @param TimeoutSeconds     - optional: max. wait time in seconds
369     *                             (default: 0s)
370     * @param TimeoutNanoSeconds - optional: max wait time in nano seconds
371     *                             (default: 0ns)
372     * @returns  0 on success, a value less than 0 if timeout exceeded
373     */
374    int LSCPServer::WaitUntilInitialized(long TimeoutSeconds, long TimeoutNanoSeconds) {
375        return Initialized.WaitAndUnlockIf(false, TimeoutSeconds, TimeoutNanoSeconds);
376  }  }
377    
378  int LSCPServer::Main() {  int LSCPServer::Main() {
379      int hSocket = socket(AF_INET, SOCK_STREAM, 0);          #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);
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;
391          //return -1;          //return -1;
392          exit(EXIT_FAILURE);          exit(EXIT_FAILURE);
393      }      }
394    
     SocketAddress.sin_family      = AF_INET;  
     SocketAddress.sin_port        = htons(LSCP_PORT);  
     SocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);  
   
395      if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {      if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
396          std::cerr << "LSCPServer: Could not bind server socket." << std::endl;          std::cerr << "LSCPServer: Could not bind server socket, retrying for " << ToString(LSCP_SERVER_BIND_TIMEOUT) << " seconds...";
397          close(hSocket);          for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds
398          //return -1;              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
399          exit(EXIT_FAILURE);                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {
400                        std::cerr << "gave up!" << std::endl;
401                        #if defined(WIN32)
402                        closesocket(hSocket);
403                        #else
404                        close(hSocket);
405                        #endif
406                        //return -1;
407                        exit(EXIT_FAILURE);
408                    }
409                    else sleep(1); // sleep 1s
410                }
411                else break; // success
412            }
413      }      }
414    
415      listen(hSocket, 1);      listen(hSocket, 1);
416      dmsg(1,("LSCPServer: Server running.\n")); // server running      Initialized.Set(true);
417    
418        // Registering event listeners
419        pSampler->AddChannelCountListener(&eventHandler);
420        pSampler->AddAudioDeviceCountListener(&eventHandler);
421        pSampler->AddMidiDeviceCountListener(&eventHandler);
422        pSampler->AddVoiceCountListener(&eventHandler);
423        pSampler->AddStreamCountListener(&eventHandler);
424        pSampler->AddBufferFillListener(&eventHandler);
425        pSampler->AddTotalStreamCountListener(&eventHandler);
426        pSampler->AddTotalVoiceCountListener(&eventHandler);
427        pSampler->AddFxSendCountListener(&eventHandler);
428        MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);
429        MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);
430        MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);
431        MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);
432    #if HAVE_SQLITE3
433        InstrumentsDb::GetInstrumentsDb()->AddInstrumentsDbListener(&dbInstrumentsEventHandler);
434    #endif
435      // now wait for client connections and handle their requests      // now wait for client connections and handle their requests
436      sockaddr_in client;      sockaddr_in client;
437      int length = sizeof(client);      int length = sizeof(client);
438      FD_ZERO(&fdSet);      FD_ZERO(&fdSet);
439      FD_SET(hSocket, &fdSet);      FD_SET(hSocket, &fdSet);
440      int maxSessions = hSocket;      int maxSessions = hSocket;
441    
442      // Parser initialization      timeval timeout;
     yyparse_param_t yyparse_param;  
     yyparse_param.pServer = this;  
443    
444      while (true) {      while (true) {
445          fd_set selectSet = fdSet;          #if CONFIG_PTHREAD_TESTCANCEL
446          int retval = select(maxSessions+1, &selectSet, NULL, NULL, NULL);                  TestCancel();
447          if (retval == 0)          #endif
448            // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
449            {
450                std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
451                std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
452                std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
453                for (; itEngineChannel != itEnd; ++itEngineChannel) {
454                    if ((*itEngineChannel)->StatusChanged()) {
455                        SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->GetSamplerChannel()->Index()));
456                    }
457    
458                    for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
459                        FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
460                        if(fxs != NULL && fxs->IsInfoChanged()) {
461                            int chn = (*itEngineChannel)->GetSamplerChannel()->Index();
462                            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));
463                            fxs->SetInfoChanged(false);
464                        }
465                    }
466                }
467            }
468    
469            // check if MIDI data arrived on some engine channel
470            for (int i = 0; i < eventHandler.channelMidiListeners.size(); ++i) {
471                const EventHandler::midi_listener_entry entry =
472                    eventHandler.channelMidiListeners[i];
473                VirtualMidiDevice* pMidiListener = entry.pMidiListener;
474                if (pMidiListener->NotesChanged()) {
475                    for (int iNote = 0; iNote < 128; iNote++) {
476                        if (pMidiListener->NoteChanged(iNote)) {
477                            const bool bActive = pMidiListener->NoteIsActive(iNote);
478                            LSCPServer::SendLSCPNotify(
479                                LSCPEvent(
480                                    LSCPEvent::event_channel_midi,
481                                    entry.pSamplerChannel->Index(),
482                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
483                                    iNote,
484                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
485                                            : pMidiListener->NoteOffVelocity(iNote)
486                                )
487                            );
488                        }
489                    }
490                }
491            }
492    
493            // check if MIDI data arrived on some MIDI device
494            for (int i = 0; i < eventHandler.deviceMidiListeners.size(); ++i) {
495                const EventHandler::device_midi_listener_entry entry =
496                    eventHandler.deviceMidiListeners[i];
497                VirtualMidiDevice* pMidiListener = entry.pMidiListener;
498                if (pMidiListener->NotesChanged()) {
499                    for (int iNote = 0; iNote < 128; iNote++) {
500                        if (pMidiListener->NoteChanged(iNote)) {
501                            const bool bActive = pMidiListener->NoteIsActive(iNote);
502                            LSCPServer::SendLSCPNotify(
503                                LSCPEvent(
504                                    LSCPEvent::event_device_midi,
505                                    entry.uiDeviceID,
506                                    entry.pPort->GetPortNumber(),
507                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
508                                    iNote,
509                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
510                                            : pMidiListener->NoteOffVelocity(iNote)
511                                )
512                            );
513                        }
514                    }
515                }
516            }
517    
518            //Now let's deliver late notifies (if any)
519            NotifyBufferMutex.Lock();
520            for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
521    #ifdef MSG_NOSIGNAL
522                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
523    #else
524                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
525    #endif
526            }
527            bufferedNotifies.clear();
528            NotifyBufferMutex.Unlock();
529    
530            fd_set selectSet = fdSet;
531            timeout.tv_sec  = 0;
532            timeout.tv_usec = 100000;
533    
534            int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
535    
536            if (retval == 0 || (retval == -1 && errno == EINTR))
537                  continue; //Nothing try again                  continue; //Nothing try again
538          if (retval == -1) {          if (retval == -1) {
539                  std::cerr << "LSCPServer: Socket select error." << std::endl;                  std::cerr << "LSCPServer: Socket select error." << std::endl;
540                    #if defined(WIN32)
541                    closesocket(hSocket);
542                    #else
543                  close(hSocket);                  close(hSocket);
544                    #endif
545                  exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
546          }          }
547            
548          //Accept new connections now (if any)          //Accept new connections now (if any)
549          if (FD_ISSET(hSocket, &selectSet)) {          if (FD_ISSET(hSocket, &selectSet)) {
550                  int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);                  int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
# Line 113  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
577                    yyparse_param_t yyparse_param;
578                    yyparse_param.pServer  = this;
579                    yyparse_param.hSession = socket;
580    
581                  hSessions.push_back(socket);                  Sessions.push_back(yyparse_param);
582                  FD_SET(socket, &fdSet);                  FD_SET(socket, &fdSet);
583                  if (socket > maxSessions)                  if (socket > maxSessions)
584                          maxSessions = socket;                          maxSessions = socket;
# Line 128  int LSCPServer::Main() { Line 588  int LSCPServer::Main() {
588          }          }
589    
590          //Something was selected and it was not the hSocket, so it must be some command(s) coming.          //Something was selected and it was not the hSocket, so it must be some command(s) coming.
591          for (std::vector<int>::iterator iter = hSessions.begin(); iter !=  hSessions.end(); iter++) {          for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
592                  if (FD_ISSET(*iter, &selectSet)) {      //Was it this socket?                  if (FD_ISSET((*iter).hSession, &selectSet)) {   //Was it this socket?
593                          if (GetLSCPCommand(iter)) {     //Have we read the entire command?                          if (GetLSCPCommand(iter)) {     //Have we read the entire command?
594                                  dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));                                  dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
595                                  yylex_init(&yyparse_param.pScanner);                                  int dummy; // just a temporary hack to fulfill the restart() function prototype
596                                  currentSocket = *iter;  //a hack                                  restart(NULL, dummy); // restart the 'scanner'
597                                  int result = yyparse(&yyparse_param);                                  currentSocket = (*iter).hSession;  //a hack
598                                    itCurrentSession = iter; // another hack
599                                    dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
600                                    if ((*iter).bVerbose) { // if echo mode enabled
601                                        AnswerClient(bufferedCommands[currentSocket]);
602                                    }
603                                    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 143  int LSCPServer::Main() { Line 610  int LSCPServer::Main() {
610                          }                          }
611                          //socket may have been closed, iter may be invalid, get out of the loop for now.                          //socket may have been closed, iter may be invalid, get out of the loop for now.
612                          //we'll be back if there is data.                          //we'll be back if there is data.
613                          break;                          break;
614                  }                  }
615          }          }
   
         //Now let's deliver late notifies (if any)  
         NotifyBufferMutex.Lock();  
         for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {  
                 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);  
                 bufferedNotifies.erase(iterNotify);  
         }  
         NotifyBufferMutex.Unlock();  
616      }      }
     //It will never get here anyway  
     //yylex_destroy(yyparse_param.pScanner);  
617  }  }
618    
619  void LSCPServer::CloseConnection( std::vector<int>::iterator iter ) {  void LSCPServer::CloseConnection( std::vector<yyparse_param_t>::iterator iter ) {
620          int socket = *iter;          int socket = (*iter).hSession;
621          dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));          dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));
622          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));          LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
623          hSessions.erase(iter);          Sessions.erase(iter);
624          FD_CLR(socket,  &fdSet);          FD_CLR(socket,  &fdSet);
625          SubscriptionMutex.Lock(); //Must unsubscribe this socket from all events (if any)          SubscriptionMutex.Lock(); //Must unsubscribe this socket from all events (if any)
626          for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {          for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
# Line 173  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 ) {
658            int subs = 0;
659            SubscriptionMutex.Lock();
660            for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();
661                            iter != events.end(); iter++)
662            {
663                    subs += eventSubscriptions.count(*iter);
664            }
665            SubscriptionMutex.Unlock();
666            return subs;
667    }
668    
669  void LSCPServer::SendLSCPNotify( LSCPEvent event ) {  void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
670          SubscriptionMutex.Lock();          SubscriptionMutex.Lock();
671          if (eventSubscriptions.count(event.GetType()) == 0) {          if (eventSubscriptions.count(event.GetType()) == 0) {
# Line 190  void LSCPServer::SendLSCPNotify( LSCPEve Line 679  void LSCPServer::SendLSCPNotify( LSCPEve
679          while (true) {          while (true) {
680                  if (NotifyMutex.Trylock()) {                  if (NotifyMutex.Trylock()) {
681                          for(;iter != end; iter++)                          for(;iter != end; iter++)
682    #ifdef MSG_NOSIGNAL
683                                    send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
684    #else
685                                  send(*iter, notify.c_str(), notify.size(), 0);                                  send(*iter, notify.c_str(), notify.size(), 0);
686    #endif
687                          NotifyMutex.Unlock();                          NotifyMutex.Unlock();
688                          break;                          break;
689                  } else {                  } else {
# Line 222  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.
725   * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.   * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.
726   */   */
727  bool LSCPServer::GetLSCPCommand( std::vector<int>::iterator iter ) {  bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
728          int socket = *iter;          int socket = (*iter).hSession;
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;
740                  }                  }
741                  if (result == 1) {                  if (result == 1) {
742                          if (c == '\r')                          if (c == '\r')
743                                  continue; //Ignore CR                                  continue; //Ignore CR
744                          if (c == '\n') {                          if (c == '\n') {
745                                  LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));                                  LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
746                                  bufferedCommands[socket] += "\n";                                  bufferedCommands[socket] += "\r\n";
747                                  return true; //Complete command was read                                  return true; //Complete command was read
748                          }                          }
749                          bufferedCommands[socket] += c;                          bufferedCommands[socket] += c;
750                  }                  }
751                    #if defined(WIN32)
752                    if (result == SOCKET_ERROR) {
753                        int wsa_lasterror = WSAGetLastError();
754                            if (wsa_lasterror == WSAEWOULDBLOCK) //Would block, try again later.
755                                    return false;
756                            dmsg(2,("LSCPScanner: Socket error after recv() Error %d.\n", wsa_lasterror));
757                            CloseConnection(iter);
758                            break;
759                    }
760                    #else
761                  if (result == -1) {                  if (result == -1) {
762                          if (errno == EAGAIN) //Would block, try again later.                          if (errno == EAGAIN) //Would block, try again later.
763                                  return false;                                  return false;
# Line 265  bool LSCPServer::GetLSCPCommand( std::ve Line 776  bool LSCPServer::GetLSCPCommand( std::ve
776                                          break;                                          break;
777                                  case EAGAIN:                                  case EAGAIN:
778                                          dmsg(2,("LSCPScanner: The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.\n"));                                          dmsg(2,("LSCPScanner: The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.\n"));
779                                          break;                                          break;
780                                  case EINTR:                                  case EINTR:
781                                          dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));                                          dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
782                                          break;                                          break;
783                                  case EFAULT:                                  case EFAULT:
784                                          dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));                                          dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
785                                          break;                                          break;
786                                  case EINVAL:                                  case EINVAL:
787                                          dmsg(2,("LSCPScanner: Invalid argument passed.\n"));                                          dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
788                                          break;                                          break;
789                                  case ENOMEM:                                  case ENOMEM:
790                                          dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));                                          dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
791                                          break;                                          break;
792                                  default:                                  default:
793                                          dmsg(2,("LSCPScanner: Unknown recv() error.\n"));                                          dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
794                                          break;                                          break;
795                          }                          }
796                          CloseConnection(iter);                          CloseConnection(iter);
797                          break;                          break;
798                  }                  }
799                    #endif
800          }          }
801          return false;          return false;
802  }  }
# Line 299  void LSCPServer::AnswerClient(String Ret Line 811  void LSCPServer::AnswerClient(String Ret
811      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
812      if (currentSocket != -1) {      if (currentSocket != -1) {
813              NotifyMutex.Lock();              NotifyMutex.Lock();
814    #ifdef MSG_NOSIGNAL
815                send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
816    #else
817              send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);              send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
818    #endif
819              NotifyMutex.Unlock();              NotifyMutex.Unlock();
820      }      }
821  }  }
# Line 343  String LSCPServer::CreateAudioOutputDevi Line 859  String LSCPServer::CreateAudioOutputDevi
859          AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);          AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
860          // search for the created device to get its index          // search for the created device to get its index
861          int index = GetAudioOutputDeviceIndex(pDevice);          int index = GetAudioOutputDeviceIndex(pDevice);
862          if (index == -1) throw LinuxSamplerException("Internal error: could not find created audio output device.");          if (index == -1) throw Exception("Internal error: could not find created audio output device.");
863          result = index; // success          result = index; // success
864      }      }
865      catch (LinuxSamplerException e) {      catch (Exception e) {
866          result.Error(e);          result.Error(e);
867      }      }
868      return result.Produce();      return result.Produce();
# Line 359  String LSCPServer::CreateMidiInputDevice Line 875  String LSCPServer::CreateMidiInputDevice
875          MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);          MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
876          // search for the created device to get its index          // search for the created device to get its index
877          int index = GetMidiInputDeviceIndex(pDevice);          int index = GetMidiInputDeviceIndex(pDevice);
878          if (index == -1) throw LinuxSamplerException("Internal error: could not find created midi input device.");          if (index == -1) throw Exception("Internal error: could not find created midi input device.");
879          result = index; // success          result = index; // success
880      }      }
881      catch (LinuxSamplerException e) {      catch (Exception e) {
882          result.Error(e);          result.Error(e);
883      }      }
884      return result.Produce();      return result.Produce();
# Line 373  String LSCPServer::DestroyAudioOutputDev Line 889  String LSCPServer::DestroyAudioOutputDev
889      LSCPResultSet result;      LSCPResultSet result;
890      try {      try {
891          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
892          if (!devices[DeviceIndex]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
893          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
894          pSampler->DestroyAudioOutputDevice(pDevice);          pSampler->DestroyAudioOutputDevice(pDevice);
895      }      }
896      catch (LinuxSamplerException e) {      catch (Exception e) {
897          result.Error(e);          result.Error(e);
898      }      }
899      return result.Produce();      return result.Produce();
# Line 388  String LSCPServer::DestroyMidiInputDevic Line 904  String LSCPServer::DestroyMidiInputDevic
904      LSCPResultSet result;      LSCPResultSet result;
905      try {      try {
906          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
907            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
908          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
         if (!pDevice) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");  
909          pSampler->DestroyMidiInputDevice(pDevice);          pSampler->DestroyMidiInputDevice(pDevice);
910      }      }
911      catch (LinuxSamplerException e) {      catch (Exception e) {
912          result.Error(e);          result.Error(e);
913      }      }
914      return result.Produce();      return result.Produce();
915  }  }
916    
917    EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
918        SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
919        if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
920    
921        EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
922        if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
923    
924        return pEngineChannel;
925    }
926    
927  /**  /**
928   * Will be called by the parser to load an instrument.   * Will be called by the parser to load an instrument.
929   */   */
# Line 406  String LSCPServer::LoadInstrument(String Line 932  String LSCPServer::LoadInstrument(String
932      LSCPResultSet result;      LSCPResultSet result;
933      try {      try {
934          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
935          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
936          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
937          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
938          if (pSamplerChannel->GetAudioOutputDevice() == NULL)          if (!pSamplerChannel->GetAudioOutputDevice())
939              throw LinuxSamplerException("No audio output device on channel");              throw Exception("No audio output device connected to sampler channel");
940          if (bBackground) {          if (bBackground) {
941              LSCPLoadInstrument *pLoadInstrument = new LSCPLoadInstrument(pEngine, Filename.c_str(), uiInstrument);              InstrumentManager::instrument_id_t id;
942              pLoadInstrument->StartThread();              id.FileName = Filename;
943                id.Index    = uiInstrument;
944                InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
945            }
946            else {
947                // tell the engine channel which instrument to load
948                pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrument);
949                // actually start to load the instrument (blocks until completed)
950                pEngineChannel->LoadInstrument();
951          }          }
         else pEngine->LoadInstrument(Filename.c_str(), uiInstrument);  
952      }      }
953      catch (LinuxSamplerException e) {      catch (Exception e) {
954           result.Error(e);           result.Error(e);
955      }      }
956      return result.Produce();      return result.Produce();
957  }  }
958    
959  /**  /**
960   * Will be called by the parser to load and deploy an engine.   * Will be called by the parser to assign a sampler engine type to a
961     * sampler channel.
962   */   */
963  String LSCPServer::LoadEngine(String EngineName, uint uiSamplerChannel) {  String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
964      dmsg(2,("LSCPServer: LoadEngine(EngineName=%s,SamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));      dmsg(2,("LSCPServer: SetEngineType(EngineName=%s,uiSamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
965      LSCPResultSet result;      LSCPResultSet result;
966      try {      try {
         Engine::type_t type;  
         if ((EngineName == "GigEngine") || (EngineName == "gig")) type = Engine::type_gig;  
         else throw LinuxSamplerException("Unknown engine type");  
967          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
968          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
969          pSamplerChannel->LoadEngine(type);          LockRTNotify();
970            pSamplerChannel->SetEngineType(EngineName);
971            if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
972            UnlockRTNotify();
973      }      }
974      catch (LinuxSamplerException e) {      catch (Exception e) {
975           result.Error(e);           result.Error(e);
976      }      }
977      return result.Produce();      return result.Produce();
# Line 454  String LSCPServer::GetChannels() { Line 988  String LSCPServer::GetChannels() {
988  }  }
989    
990  /**  /**
991     * Will be called by the parser to get the list of sampler channels.
992     */
993    String LSCPServer::ListChannels() {
994        dmsg(2,("LSCPServer: ListChannels()\n"));
995        String list;
996        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
997        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
998        for (; iter != channels.end(); iter++) {
999            if (list != "") list += ",";
1000            list += ToString(iter->first);
1001        }
1002        LSCPResultSet result;
1003        result.Add(list);
1004        return result.Produce();
1005    }
1006    
1007    /**
1008   * Will be called by the parser to add a sampler channel.   * Will be called by the parser to add a sampler channel.
1009   */   */
1010  String LSCPServer::AddChannel() {  String LSCPServer::AddChannel() {
1011      dmsg(2,("LSCPServer: AddChannel()\n"));      dmsg(2,("LSCPServer: AddChannel()\n"));
1012        LockRTNotify();
1013      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
1014        UnlockRTNotify();
1015      LSCPResultSet result(pSamplerChannel->Index());      LSCPResultSet result(pSamplerChannel->Index());
1016      return result.Produce();      return result.Produce();
1017  }  }
# Line 469  String LSCPServer::AddChannel() { Line 1022  String LSCPServer::AddChannel() {
1022  String LSCPServer::RemoveChannel(uint uiSamplerChannel) {  String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
1023      dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
1024      LSCPResultSet result;      LSCPResultSet result;
1025        LockRTNotify();
1026      pSampler->RemoveSamplerChannel(uiSamplerChannel);      pSampler->RemoveSamplerChannel(uiSamplerChannel);
1027        UnlockRTNotify();
1028      return result.Produce();      return result.Produce();
1029  }  }
1030    
1031  /**  /**
1032   * Will be called by the parser to get all available engines.   * Will be called by the parser to get the amount of all available engines.
1033   */   */
1034  String LSCPServer::GetAvailableEngines() {  String LSCPServer::GetAvailableEngines() {
1035      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
1036      LSCPResultSet result("GigEngine");      LSCPResultSet result;
1037        try {
1038            int n = EngineFactory::AvailableEngineTypes().size();
1039            result.Add(n);
1040        }
1041        catch (Exception e) {
1042            result.Error(e);
1043        }
1044      return result.Produce();      return result.Produce();
1045  }  }
1046    
1047  /**  /**
1048   * Will be called by the parser to get descriptions for a particular engine.   * Will be called by the parser to get a list of all available engines.
1049     */
1050    String LSCPServer::ListAvailableEngines() {
1051        dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
1052        LSCPResultSet result;
1053        try {
1054            String s = EngineFactory::AvailableEngineTypesAsString();
1055            result.Add(s);
1056        }
1057        catch (Exception e) {
1058            result.Error(e);
1059        }
1060        return result.Produce();
1061    }
1062    
1063    /**
1064     * Will be called by the parser to get descriptions for a particular
1065     * sampler engine.
1066   */   */
1067  String LSCPServer::GetEngineInfo(String EngineName) {  String LSCPServer::GetEngineInfo(String EngineName) {
1068      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
1069      LSCPResultSet result;      LSCPResultSet result;
1070        LockRTNotify();
1071      try {      try {
1072          if ((EngineName == "GigEngine") || (EngineName == "gig")) {          Engine* pEngine = EngineFactory::Create(EngineName);
1073              Engine* pEngine = new LinuxSampler::gig::Engine;          result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
1074              result.Add(pEngine->Description());          result.Add("VERSION",     pEngine->Version());
1075              result.Add(pEngine->Version());          EngineFactory::Destroy(pEngine);
             delete pEngine;  
         }  
         else throw LinuxSamplerException("Unknown engine type");  
1076      }      }
1077      catch (LinuxSamplerException e) {      catch (Exception e) {
1078           result.Error(e);           result.Error(e);
1079      }      }
1080        UnlockRTNotify();
1081      return result.Produce();      return result.Produce();
1082  }  }
1083    
# Line 512  String LSCPServer::GetChannelInfo(uint u Line 1090  String LSCPServer::GetChannelInfo(uint u
1090      LSCPResultSet result;      LSCPResultSet result;
1091      try {      try {
1092          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1093          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1094          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1095    
1096          //Defaults values          //Defaults values
1097          String EngineName = "NONE";          String EngineName = "NONE";
1098          float Volume = 0;          float Volume = 0.0f;
1099          String InstrumentFileName = "NONE";          String InstrumentFileName = "NONE";
1100            String InstrumentName = "NONE";
1101          int InstrumentIndex = -1;          int InstrumentIndex = -1;
1102          int InstrumentStatus = -1;          int InstrumentStatus = -1;
1103            int AudioOutputChannels = 0;
1104          if (pEngine) {          String AudioRouting;
1105              EngineName =  pEngine->EngineName();          int Mute = 0;
1106              Volume = pEngine->Volume();          bool Solo = false;
1107              InstrumentStatus = pEngine->InstrumentStatus();          String MidiInstrumentMap = "NONE";
1108              InstrumentIndex = pEngine->InstrumentIndex();  
1109              if (InstrumentIndex != -1)          if (pEngineChannel) {
1110                  InstrumentFileName = pEngine->InstrumentFileName();              EngineName          = pEngineChannel->EngineName();
1111                AudioOutputChannels = pEngineChannel->Channels();
1112                Volume              = pEngineChannel->Volume();
1113                InstrumentStatus    = pEngineChannel->InstrumentStatus();
1114                InstrumentIndex     = pEngineChannel->InstrumentIndex();
1115                if (InstrumentIndex != -1) {
1116                    InstrumentFileName = pEngineChannel->InstrumentFileName();
1117                    InstrumentName     = pEngineChannel->InstrumentName();
1118                }
1119                for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
1120                    if (AudioRouting != "") AudioRouting += ",";
1121                    AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
1122                }
1123                Mute = pEngineChannel->GetMute();
1124                Solo = pEngineChannel->GetSolo();
1125                if (pEngineChannel->UsesNoMidiInstrumentMap())
1126                    MidiInstrumentMap = "NONE";
1127                else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
1128                    MidiInstrumentMap = "DEFAULT";
1129                else
1130                    MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
1131          }          }
1132    
1133          result.Add("ENGINE_NAME", EngineName);          result.Add("ENGINE_NAME", EngineName);
# Line 536  String LSCPServer::GetChannelInfo(uint u Line 1135  String LSCPServer::GetChannelInfo(uint u
1135    
1136          //Some not-so-hardcoded stuff to make GUI look good          //Some not-so-hardcoded stuff to make GUI look good
1137          result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));          result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
1138          result.Add("AUDIO_OUTPUT_CHANNELS", "2");          result.Add("AUDIO_OUTPUT_CHANNELS", AudioOutputChannels);
1139          result.Add("AUDIO_OUTPUT_ROUTING", "0,1");          result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
1140    
1141          result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));          result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
1142          result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());          result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
1143          result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());          if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
1144            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", _escapeLscpResponse(InstrumentName));
1160          result.Add("INSTRUMENT_STATUS", InstrumentStatus);          result.Add("INSTRUMENT_STATUS", InstrumentStatus);
1161            result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
1162            result.Add("SOLO", Solo);
1163            result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
1164      }      }
1165      catch (LinuxSamplerException e) {      catch (Exception e) {
1166           result.Error(e);           result.Error(e);
1167      }      }
1168      return result.Produce();      return result.Produce();
# Line 561  String LSCPServer::GetVoiceCount(uint ui Line 1176  String LSCPServer::GetVoiceCount(uint ui
1176      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
1177      LSCPResultSet result;      LSCPResultSet result;
1178      try {      try {
1179          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1180          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1181          Engine* pEngine = pSamplerChannel->GetEngine();          result.Add(pEngineChannel->GetEngine()->VoiceCount());
         if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");  
         result.Add(pEngine->VoiceCount());  
1182      }      }
1183      catch (LinuxSamplerException e) {      catch (Exception e) {
1184           result.Error(e);           result.Error(e);
1185      }      }
1186      return result.Produce();      return result.Produce();
# Line 581  String LSCPServer::GetStreamCount(uint u Line 1194  String LSCPServer::GetStreamCount(uint u
1194      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
1195      LSCPResultSet result;      LSCPResultSet result;
1196      try {      try {
1197          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1198          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1199          Engine* pEngine = pSamplerChannel->GetEngine();          result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
         if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");  
         result.Add(pEngine->DiskStreamCount());  
1200      }      }
1201      catch (LinuxSamplerException e) {      catch (Exception e) {
1202           result.Error(e);           result.Error(e);
1203      }      }
1204      return result.Produce();      return result.Produce();
# Line 601  String LSCPServer::GetBufferFill(fill_re Line 1212  String LSCPServer::GetBufferFill(fill_re
1212      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
1213      LSCPResultSet result;      LSCPResultSet result;
1214      try {      try {
1215          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1216          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1217          Engine* pEngine = pSamplerChannel->GetEngine();          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
         if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");  
         if (!pEngine->DiskStreamSupported())  
             result.Add("NA");  
1218          else {          else {
1219              switch (ResponseType) {              switch (ResponseType) {
1220                  case fill_response_bytes:                  case fill_response_bytes:
1221                      result.Add(pEngine->DiskStreamBufferFillBytes());                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillBytes());
1222                      break;                      break;
1223                  case fill_response_percentage:                  case fill_response_percentage:
1224                      result.Add(pEngine->DiskStreamBufferFillPercentage());                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
1225                      break;                      break;
1226                  default:                  default:
1227                      throw LinuxSamplerException("Unknown fill response type");                      throw Exception("Unknown fill response type");
1228              }              }
1229          }          }
1230      }      }
1231      catch (LinuxSamplerException e) {      catch (Exception e) {
1232           result.Error(e);           result.Error(e);
1233      }      }
1234      return result.Produce();      return result.Produce();
# Line 630  String LSCPServer::GetAvailableAudioOutp Line 1238  String LSCPServer::GetAvailableAudioOutp
1238      dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));      dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
1239      LSCPResultSet result;      LSCPResultSet result;
1240      try {      try {
1241            int n = AudioOutputDeviceFactory::AvailableDrivers().size();
1242            result.Add(n);
1243        }
1244        catch (Exception e) {
1245            result.Error(e);
1246        }
1247        return result.Produce();
1248    }
1249    
1250    String LSCPServer::ListAvailableAudioOutputDrivers() {
1251        dmsg(2,("LSCPServer: ListAvailableAudioOutputDrivers()\n"));
1252        LSCPResultSet result;
1253        try {
1254          String s = AudioOutputDeviceFactory::AvailableDriversAsString();          String s = AudioOutputDeviceFactory::AvailableDriversAsString();
1255          result.Add(s);          result.Add(s);
1256      }      }
1257      catch (LinuxSamplerException e) {      catch (Exception e) {
1258          result.Error(e);          result.Error(e);
1259      }      }
1260      return result.Produce();      return result.Produce();
# Line 643  String LSCPServer::GetAvailableMidiInput Line 1264  String LSCPServer::GetAvailableMidiInput
1264      dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));      dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
1265      LSCPResultSet result;      LSCPResultSet result;
1266      try {      try {
1267            int n = MidiInputDeviceFactory::AvailableDrivers().size();
1268            result.Add(n);
1269        }
1270        catch (Exception e) {
1271            result.Error(e);
1272        }
1273        return result.Produce();
1274    }
1275    
1276    String LSCPServer::ListAvailableMidiInputDrivers() {
1277        dmsg(2,("LSCPServer: ListAvailableMidiInputDrivers()\n"));
1278        LSCPResultSet result;
1279        try {
1280          String s = MidiInputDeviceFactory::AvailableDriversAsString();          String s = MidiInputDeviceFactory::AvailableDriversAsString();
1281          result.Add(s);          result.Add(s);
1282      }      }
1283      catch (LinuxSamplerException e) {      catch (Exception e) {
1284          result.Error(e);          result.Error(e);
1285      }      }
1286      return result.Produce();      return result.Produce();
# Line 666  String LSCPServer::GetMidiInputDriverInf Line 1300  String LSCPServer::GetMidiInputDriverInf
1300              for (;iter != parameters.end(); iter++) {              for (;iter != parameters.end(); iter++) {
1301                  if (s != "") s += ",";                  if (s != "") s += ",";
1302                  s += iter->first;                  s += iter->first;
1303                    delete iter->second;
1304              }              }
1305              result.Add("PARAMETERS", s);              result.Add("PARAMETERS", s);
1306          }          }
1307      }      }
1308      catch (LinuxSamplerException e) {      catch (Exception e) {
1309          result.Error(e);          result.Error(e);
1310      }      }
1311      return result.Produce();      return result.Produce();
# Line 690  String LSCPServer::GetAudioOutputDriverI Line 1325  String LSCPServer::GetAudioOutputDriverI
1325              for (;iter != parameters.end(); iter++) {              for (;iter != parameters.end(); iter++) {
1326                  if (s != "") s += ",";                  if (s != "") s += ",";
1327                  s += iter->first;                  s += iter->first;
1328                    delete iter->second;
1329              }              }
1330              result.Add("PARAMETERS", s);              result.Add("PARAMETERS", s);
1331          }          }
1332      }      }
1333      catch (LinuxSamplerException e) {      catch (Exception e) {
1334          result.Error(e);          result.Error(e);
1335      }      }
1336      return result.Produce();      return result.Produce();
1337  }  }
1338    
1339  String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {  String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1340      dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s)\n",Driver.c_str(),Parameter.c_str()));      dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
1341      LSCPResultSet result;      LSCPResultSet result;
1342      try {      try {
1343          DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);          DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
# Line 710  String LSCPServer::GetMidiInputDriverPar Line 1346  String LSCPServer::GetMidiInputDriverPar
1346          result.Add("MANDATORY",    pParameter->Mandatory());          result.Add("MANDATORY",    pParameter->Mandatory());
1347          result.Add("FIX",          pParameter->Fix());          result.Add("FIX",          pParameter->Fix());
1348          result.Add("MULTIPLICITY", pParameter->Multiplicity());          result.Add("MULTIPLICITY", pParameter->Multiplicity());
1349          if (pParameter->Depends())       result.Add("DEPENDS",       pParameter->Depends());          optional<String> oDepends       = pParameter->Depends();
1350          if (pParameter->Default())       result.Add("DEFAULT",       pParameter->Default());          optional<String> oDefault       = pParameter->Default(DependencyList);
1351          if (pParameter->RangeMin())      result.Add("RANGE_MIN",     pParameter->RangeMin());          optional<String> oRangeMin      = pParameter->RangeMin(DependencyList);
1352          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     pParameter->RangeMax());          optional<String> oRangeMax      = pParameter->RangeMax(DependencyList);
1353          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", pParameter->Possibilities());          optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1354            if (oDepends)       result.Add("DEPENDS",       *oDepends);
1355            if (oDefault)       result.Add("DEFAULT",       *oDefault);
1356            if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1357            if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1358            if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1359            delete pParameter;
1360      }      }
1361      catch (LinuxSamplerException e) {      catch (Exception e) {
1362          result.Error(e);          result.Error(e);
1363      }      }
1364      return result.Produce();      return result.Produce();
1365  }  }
1366    
1367  String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {  String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1368      dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s)\n",Driver.c_str(),Parameter.c_str()));      dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
1369      LSCPResultSet result;      LSCPResultSet result;
1370      try {      try {
1371          DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);          DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
# Line 732  String LSCPServer::GetAudioOutputDriverP Line 1374  String LSCPServer::GetAudioOutputDriverP
1374          result.Add("MANDATORY",    pParameter->Mandatory());          result.Add("MANDATORY",    pParameter->Mandatory());
1375          result.Add("FIX",          pParameter->Fix());          result.Add("FIX",          pParameter->Fix());
1376          result.Add("MULTIPLICITY", pParameter->Multiplicity());          result.Add("MULTIPLICITY", pParameter->Multiplicity());
1377          if (pParameter->Depends())       result.Add("DEPENDS",       pParameter->Depends());          optional<String> oDepends       = pParameter->Depends();
1378          if (pParameter->Default())       result.Add("DEFAULT",       pParameter->Default());          optional<String> oDefault       = pParameter->Default(DependencyList);
1379          if (pParameter->RangeMin())      result.Add("RANGE_MIN",     pParameter->RangeMin());          optional<String> oRangeMin      = pParameter->RangeMin(DependencyList);
1380          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     pParameter->RangeMax());          optional<String> oRangeMax      = pParameter->RangeMax(DependencyList);
1381          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", pParameter->Possibilities());          optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1382            if (oDepends)       result.Add("DEPENDS",       *oDepends);
1383            if (oDefault)       result.Add("DEFAULT",       *oDefault);
1384            if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1385            if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1386            if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1387            delete pParameter;
1388      }      }
1389      catch (LinuxSamplerException e) {      catch (Exception e) {
1390          result.Error(e);          result.Error(e);
1391      }      }
1392      return result.Produce();      return result.Produce();
# Line 751  String LSCPServer::GetAudioOutputDeviceC Line 1399  String LSCPServer::GetAudioOutputDeviceC
1399          uint count = pSampler->AudioOutputDevices();          uint count = pSampler->AudioOutputDevices();
1400          result.Add(count); // success          result.Add(count); // success
1401      }      }
1402      catch (LinuxSamplerException e) {      catch (Exception e) {
1403          result.Error(e);          result.Error(e);
1404      }      }
1405      return result.Produce();      return result.Produce();
# Line 764  String LSCPServer::GetMidiInputDeviceCou Line 1412  String LSCPServer::GetMidiInputDeviceCou
1412          uint count = pSampler->MidiInputDevices();          uint count = pSampler->MidiInputDevices();
1413          result.Add(count); // success          result.Add(count); // success
1414      }      }
1415      catch (LinuxSamplerException e) {      catch (Exception e) {
1416          result.Error(e);          result.Error(e);
1417      }      }
1418      return result.Produce();      return result.Produce();
# Line 783  String LSCPServer::GetAudioOutputDevices Line 1431  String LSCPServer::GetAudioOutputDevices
1431          }          }
1432          result.Add(s);          result.Add(s);
1433      }      }
1434      catch (LinuxSamplerException e) {      catch (Exception e) {
1435          result.Error(e);          result.Error(e);
1436      }      }
1437      return result.Produce();      return result.Produce();
# Line 802  String LSCPServer::GetMidiInputDevices() Line 1450  String LSCPServer::GetMidiInputDevices()
1450          }          }
1451          result.Add(s);          result.Add(s);
1452      }      }
1453      catch (LinuxSamplerException e) {      catch (Exception e) {
1454          result.Error(e);          result.Error(e);
1455      }      }
1456      return result.Produce();      return result.Produce();
# Line 813  String LSCPServer::GetAudioOutputDeviceI Line 1461  String LSCPServer::GetAudioOutputDeviceI
1461      LSCPResultSet result;      LSCPResultSet result;
1462      try {      try {
1463          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1464          if (!devices[DeviceIndex]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1465          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
1466          result.Add("driver", pDevice->Driver());          result.Add("DRIVER", pDevice->Driver());
1467          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1468          std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();          std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1469          for (; iter != parameters.end(); iter++) {          for (; iter != parameters.end(); iter++) {
1470              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1471          }          }
1472      }      }
1473      catch (LinuxSamplerException e) {      catch (Exception e) {
1474          result.Error(e);          result.Error(e);
1475      }      }
1476      return result.Produce();      return result.Produce();
# Line 833  String LSCPServer::GetMidiInputDeviceInf Line 1481  String LSCPServer::GetMidiInputDeviceInf
1481      LSCPResultSet result;      LSCPResultSet result;
1482      try {      try {
1483          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1484            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1485          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1486          if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");          result.Add("DRIVER", pDevice->Driver());
         result.Add("driver", pDevice->Driver());  
1487          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1488          std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();          std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1489          for (; iter != parameters.end(); iter++) {          for (; iter != parameters.end(); iter++) {
1490              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1491          }          }
1492      }      }
1493      catch (LinuxSamplerException e) {      catch (Exception e) {
1494          result.Error(e);          result.Error(e);
1495      }      }
1496      return result.Produce();      return result.Produce();
# Line 851  String LSCPServer::GetMidiInputPortInfo( Line 1499  String LSCPServer::GetMidiInputPortInfo(
1499      dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));      dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
1500      LSCPResultSet result;      LSCPResultSet result;
1501      try {      try {
1502            // get MIDI input device
1503          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1504            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1505          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1506          if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");  
1507          MidiInputDevice::MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);          // get MIDI port
1508          if (!pMidiInputPort) throw LinuxSamplerException("There is no MIDI input port with index " + ToString(PortIndex) + ".");          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1509          std::map<String,DeviceCreationParameter*> parameters = pMidiInputPort->DeviceParameters();          if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1510          std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();  
1511            // return the values of all MIDI port parameters
1512            std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1513            std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1514          for (; iter != parameters.end(); iter++) {          for (; iter != parameters.end(); iter++) {
1515              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1516          }          }
1517      }      }
1518      catch (LinuxSamplerException e) {      catch (Exception e) {
1519          result.Error(e);          result.Error(e);
1520      }      }
1521      return result.Produce();      return result.Produce();
# Line 874  String LSCPServer::GetAudioOutputChannel Line 1527  String LSCPServer::GetAudioOutputChannel
1527      try {      try {
1528          // get audio output device          // get audio output device
1529          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1530          if (!devices[DeviceId]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");          if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1531          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1532    
1533          // get audio channel          // get audio channel
1534          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1535          if (!pChannel) throw LinuxSamplerException("Audio ouotput device does not have channel " + ToString(ChannelId) + ".");          if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1536    
1537          // return the values of all audio channel parameters          // return the values of all audio channel parameters
1538          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
# Line 888  String LSCPServer::GetAudioOutputChannel Line 1541  String LSCPServer::GetAudioOutputChannel
1541              result.Add(iter->first, iter->second->Value());              result.Add(iter->first, iter->second->Value());
1542          }          }
1543      }      }
1544      catch (LinuxSamplerException e) {      catch (Exception e) {
1545          result.Error(e);          result.Error(e);
1546      }      }
1547      return result.Produce();      return result.Produce();
# Line 898  String LSCPServer::GetMidiInputPortParam Line 1551  String LSCPServer::GetMidiInputPortParam
1551      dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));      dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
1552      LSCPResultSet result;      LSCPResultSet result;
1553      try {      try {
1554          // get audio output device          // get MIDI input device
1555          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1556          if (!devices[DeviceId]) throw LinuxSamplerException("There is no midi input device with index " + ToString(DeviceId) + ".");          if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1557          MidiInputDevice* pDevice = devices[DeviceId];          MidiInputDevice* pDevice = devices[DeviceId];
1558    
1559          // get midi port          // get midi port
1560          MidiInputDevice::MidiInputPort* pPort = pDevice->GetPort(PortId);          MidiInputPort* pPort = pDevice->GetPort(PortId);
1561          if (!pPort) throw LinuxSamplerException("Midi input device does not have port " + ToString(PortId) + ".");          if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1562    
1563          // get desired port parameter          // get desired port parameter
1564          std::map<String,DeviceCreationParameter*> parameters = pPort->DeviceParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1565          if (!parameters[ParameterName]) throw LinuxSamplerException("Midi port does not provice a parameters '" + ParameterName + "'.");          if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1566          DeviceCreationParameter* pParameter = parameters[ParameterName];          DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1567            
1568          // return all fields of this audio channel parameter          // return all fields of this audio channel parameter
1569          result.Add("TYPE",         pParameter->Type());          result.Add("TYPE",         pParameter->Type());
1570          result.Add("DESCRIPTION",  pParameter->Description());          result.Add("DESCRIPTION",  pParameter->Description());
1571          result.Add("FIX",          pParameter->Fix());          result.Add("FIX",          pParameter->Fix());
1572          result.Add("MULTIPLICITY", pParameter->Multiplicity());          result.Add("MULTIPLICITY", pParameter->Multiplicity());
1573          if (pParameter->RangeMin())      result.Add("RANGE_MIN",     pParameter->RangeMin());          if (pParameter->RangeMin())      result.Add("RANGE_MIN",     *pParameter->RangeMin());
1574          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     pParameter->RangeMax());          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1575          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", pParameter->Possibilities());          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1576      }      }
1577      catch (LinuxSamplerException e) {      catch (Exception e) {
1578          result.Error(e);          result.Error(e);
1579      }      }
1580      return result.Produce();      return result.Produce();
# Line 933  String LSCPServer::GetAudioOutputChannel Line 1586  String LSCPServer::GetAudioOutputChannel
1586      try {      try {
1587          // get audio output device          // get audio output device
1588          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1589          if (!devices[DeviceId]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");          if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1590          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1591    
1592          // get audio channel          // get audio channel
1593          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1594          if (!pChannel) throw LinuxSamplerException("Audio output device does not have channel " + ToString(ChannelId) + ".");          if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1595    
1596          // get desired audio channel parameter          // get desired audio channel parameter
1597          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1598          if (!parameters[ParameterName]) throw LinuxSamplerException("Audio channel does not provide a parameter '" + ParameterName + "'.");          if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1599          DeviceRuntimeParameter* pParameter = parameters[ParameterName];          DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1600    
1601          // return all fields of this audio channel parameter          // return all fields of this audio channel parameter
# Line 950  String LSCPServer::GetAudioOutputChannel Line 1603  String LSCPServer::GetAudioOutputChannel
1603          result.Add("DESCRIPTION",  pParameter->Description());          result.Add("DESCRIPTION",  pParameter->Description());
1604          result.Add("FIX",          pParameter->Fix());          result.Add("FIX",          pParameter->Fix());
1605          result.Add("MULTIPLICITY", pParameter->Multiplicity());          result.Add("MULTIPLICITY", pParameter->Multiplicity());
1606          if (pParameter->RangeMin())      result.Add("RANGE_MIN",     pParameter->RangeMin());          if (pParameter->RangeMin())      result.Add("RANGE_MIN",     *pParameter->RangeMin());
1607          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     pParameter->RangeMax());          if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1608          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", pParameter->Possibilities());          if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1609      }      }
1610      catch (LinuxSamplerException e) {      catch (Exception e) {
1611          result.Error(e);          result.Error(e);
1612      }      }
1613      return result.Produce();      return result.Produce();
# Line 966  String LSCPServer::SetAudioOutputChannel Line 1619  String LSCPServer::SetAudioOutputChannel
1619      try {      try {
1620          // get audio output device          // get audio output device
1621          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1622          if (!devices[DeviceId]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");          if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1623          AudioOutputDevice* pDevice = devices[DeviceId];          AudioOutputDevice* pDevice = devices[DeviceId];
1624    
1625          // get audio channel          // get audio channel
1626          AudioChannel* pChannel = pDevice->Channel(ChannelId);          AudioChannel* pChannel = pDevice->Channel(ChannelId);
1627          if (!pChannel) throw LinuxSamplerException("Audio output device does not have channel " + ToString(ChannelId) + ".");          if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1628    
1629          // get desired audio channel parameter          // get desired audio channel parameter
1630          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();          std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1631          if (!parameters[ParamKey]) throw LinuxSamplerException("Audio channel does not provide a parameter '" + ParamKey + "'.");          if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1632          DeviceRuntimeParameter* pParameter = parameters[ParamKey];          DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1633    
1634          // set new channel parameter value          // set new channel parameter value
1635          pParameter->SetValue(ParamVal);          pParameter->SetValue(ParamVal);
1636            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1637      }      }
1638      catch (LinuxSamplerException e) {      catch (Exception e) {
1639          result.Error(e);          result.Error(e);
1640      }      }
1641      return result.Produce();      return result.Produce();
# Line 992  String LSCPServer::SetAudioOutputDeviceP Line 1646  String LSCPServer::SetAudioOutputDeviceP
1646      LSCPResultSet result;      LSCPResultSet result;
1647      try {      try {
1648          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1649          if (!devices[DeviceIndex]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1650          AudioOutputDevice* pDevice = devices[DeviceIndex];          AudioOutputDevice* pDevice = devices[DeviceIndex];
1651          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1652          if (!parameters[ParamKey]) throw LinuxSamplerException("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");          if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1653          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1654            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1655      }      }
1656      catch (LinuxSamplerException e) {      catch (Exception e) {
1657          result.Error(e);          result.Error(e);
1658      }      }
1659      return result.Produce();      return result.Produce();
# Line 1009  String LSCPServer::SetMidiInputDevicePar Line 1664  String LSCPServer::SetMidiInputDevicePar
1664      LSCPResultSet result;      LSCPResultSet result;
1665      try {      try {
1666          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1667          if (!devices[DeviceIndex]) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");          if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1668          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1669          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();          std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1670          if (!parameters[ParamKey]) throw LinuxSamplerException("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");          if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1671          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1672            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1673      }      }
1674      catch (LinuxSamplerException e) {      catch (Exception e) {
1675          result.Error(e);          result.Error(e);
1676      }      }
1677      return result.Produce();      return result.Produce();
# Line 1025  String LSCPServer::SetMidiInputPortParam Line 1681  String LSCPServer::SetMidiInputPortParam
1681      dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));      dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1682      LSCPResultSet result;      LSCPResultSet result;
1683      try {      try {
1684            // get MIDI input device
1685          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1686            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1687          MidiInputDevice* pDevice = devices[DeviceIndex];          MidiInputDevice* pDevice = devices[DeviceIndex];
1688          if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");  
1689          MidiInputDevice::MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);          // get MIDI port
1690          if (!pMidiInputPort) throw LinuxSamplerException("There is no MIDI input port with index " + ToString(PortIndex) + ".");          MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1691          std::map<String,DeviceCreationParameter*> parameters = pMidiInputPort->DeviceParameters();          if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1692          if (!parameters[ParamKey]) throw LinuxSamplerException("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");  
1693            // set port parameter value
1694            std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1695            if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1696          parameters[ParamKey]->SetValue(ParamVal);          parameters[ParamKey]->SetValue(ParamVal);
1697            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1698      }      }
1699      catch (LinuxSamplerException e) {      catch (Exception e) {
1700          result.Error(e);          result.Error(e);
1701      }      }
1702      return result.Produce();      return result.Produce();
# Line 1046  String LSCPServer::SetMidiInputPortParam Line 1708  String LSCPServer::SetMidiInputPortParam
1708   */   */
1709  String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1710      dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1711      return "ERR:0:Not implemented yet.\r\n"; //FIXME: Add support for this in resultset class?      LSCPResultSet result;
1712        try {
1713            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1714            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1715            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1716            if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1717            if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1718            pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1719        }
1720        catch (Exception e) {
1721             result.Error(e);
1722        }
1723        return result.Produce();
1724  }  }
1725    
1726  String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1727      dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1728      LSCPResultSet result;      LSCPResultSet result;
1729        LockRTNotify();
1730      try {      try {
1731          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1732          if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1733          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();          std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1734            if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1735          AudioOutputDevice* pDevice = devices[AudioDeviceId];          AudioOutputDevice* pDevice = devices[AudioDeviceId];
         if (!pDevice) throw LinuxSamplerException("There is no audio output device with index " + ToString(AudioDeviceId));  
1736          pSamplerChannel->SetAudioOutputDevice(pDevice);          pSamplerChannel->SetAudioOutputDevice(pDevice);
1737      }      }
1738      catch (LinuxSamplerException e) {      catch (Exception e) {
1739           result.Error(e);           result.Error(e);
1740      }      }
1741        UnlockRTNotify();
1742      return result.Produce();      return result.Produce();
1743  }  }
1744    
1745  String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1746      dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1747      LSCPResultSet result;      LSCPResultSet result;
1748        LockRTNotify();
1749      try {      try {
1750          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1751          if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1752          // Driver type name aliasing...          // Driver type name aliasing...
1753          if (AudioOutputDriver == "ALSA") AudioOutputDriver = "Alsa";          if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1754          if (AudioOutputDriver == "JACK") AudioOutputDriver = "Jack";                  if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1755          // Check if there's one audio output device already created          // Check if there's one audio output device already created
1756          // for the intended audio driver type (AudioOutputDriver)...          // for the intended audio driver type (AudioOutputDriver)...
1757          AudioOutputDevice *pDevice = NULL;          AudioOutputDevice *pDevice = NULL;
# Line 1093  String LSCPServer::SetAudioOutputType(St Line 1770  String LSCPServer::SetAudioOutputType(St
1770          }          }
1771          // Must have a device...          // Must have a device...
1772          if (pDevice == NULL)          if (pDevice == NULL)
1773              throw LinuxSamplerException("Internal error: could not create audio output device.");              throw Exception("Internal error: could not create audio output device.");
1774          // Set it as the current channel device...          // Set it as the current channel device...
1775          pSamplerChannel->SetAudioOutputDevice(pDevice);          pSamplerChannel->SetAudioOutputDevice(pDevice);
1776      }      }
1777      catch (LinuxSamplerException e) {      catch (Exception e) {
1778           result.Error(e);           result.Error(e);
1779      }      }
1780        UnlockRTNotify();
1781      return result.Produce();      return result.Produce();
1782  }  }
1783    
# Line 1108  String LSCPServer::SetMIDIInputPort(uint Line 1786  String LSCPServer::SetMIDIInputPort(uint
1786      LSCPResultSet result;      LSCPResultSet result;
1787      try {      try {
1788          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1789          if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1790          pSamplerChannel->SetMidiInputPort(MIDIPort);          pSamplerChannel->SetMidiInputPort(MIDIPort);
1791      }      }
1792      catch (LinuxSamplerException e) {      catch (Exception e) {
1793           result.Error(e);           result.Error(e);
1794      }      }
1795      return result.Produce();      return result.Produce();
# Line 1122  String LSCPServer::SetMIDIInputChannel(u Line 1800  String LSCPServer::SetMIDIInputChannel(u
1800      LSCPResultSet result;      LSCPResultSet result;
1801      try {      try {
1802          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1803          if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1804          pSamplerChannel->SetMidiInputChannel((MidiInputDevice::MidiInputPort::midi_chan_t) MIDIChannel);          pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
1805      }      }
1806      catch (LinuxSamplerException e) {      catch (Exception e) {
1807           result.Error(e);           result.Error(e);
1808      }      }
1809      return result.Produce();      return result.Produce();
# Line 1136  String LSCPServer::SetMIDIInputDevice(ui Line 1814  String LSCPServer::SetMIDIInputDevice(ui
1814      LSCPResultSet result;      LSCPResultSet result;
1815      try {      try {
1816          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1817          if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1818          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1819            if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1820          MidiInputDevice* pDevice = devices[MIDIDeviceId];          MidiInputDevice* pDevice = devices[MIDIDeviceId];
         if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(MIDIDeviceId));  
1821          pSamplerChannel->SetMidiInputDevice(pDevice);          pSamplerChannel->SetMidiInputDevice(pDevice);
1822      }      }
1823      catch (LinuxSamplerException e) {      catch (Exception e) {
1824           result.Error(e);           result.Error(e);
1825      }      }
1826      return result.Produce();      return result.Produce();
# Line 1153  String LSCPServer::SetMIDIInputType(Stri Line 1831  String LSCPServer::SetMIDIInputType(Stri
1831      LSCPResultSet result;      LSCPResultSet result;
1832      try {      try {
1833          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1834          if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1835          // Driver type name aliasing...          // Driver type name aliasing...
1836          if (MidiInputDriver == "ALSA") MidiInputDriver = "Alsa";          if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
1837          // Check if there's one MIDI input device already created          // Check if there's one MIDI input device already created
1838          // for the intended MIDI driver type (MidiInputDriver)...          // for the intended MIDI driver type (MidiInputDriver)...
1839          MidiInputDevice *pDevice = NULL;          MidiInputDevice *pDevice = NULL;
# Line 1173  String LSCPServer::SetMIDIInputType(Stri Line 1851  String LSCPServer::SetMIDIInputType(Stri
1851              pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);              pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1852              // Make it with at least one initial port.              // Make it with at least one initial port.
1853              std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();              std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
             parameters["ports"]->SetValue("1");  
1854          }          }
1855          // Must have a device...          // Must have a device...
1856          if (pDevice == NULL)          if (pDevice == NULL)
1857              throw LinuxSamplerException("Internal error: could not create MIDI input device.");              throw Exception("Internal error: could not create MIDI input device.");
1858          // Set it as the current channel device...          // Set it as the current channel device...
1859          pSamplerChannel->SetMidiInputDevice(pDevice);          pSamplerChannel->SetMidiInputDevice(pDevice);
1860      }      }
1861      catch (LinuxSamplerException e) {      catch (Exception e) {
1862           result.Error(e);           result.Error(e);
1863      }      }
1864      return result.Produce();      return result.Produce();
# Line 1196  String LSCPServer::SetMIDIInput(uint MID Line 1873  String LSCPServer::SetMIDIInput(uint MID
1873      LSCPResultSet result;      LSCPResultSet result;
1874      try {      try {
1875          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1876          if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1877          std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();          std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();
1878            if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1879          MidiInputDevice* pDevice = devices[MIDIDeviceId];          MidiInputDevice* pDevice = devices[MIDIDeviceId];
1880          if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(MIDIDeviceId));          pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
         pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (MidiInputDevice::MidiInputPort::midi_chan_t) MIDIChannel);  
1881      }      }
1882      catch (LinuxSamplerException e) {      catch (Exception e) {
1883           result.Error(e);           result.Error(e);
1884      }      }
1885      return result.Produce();      return result.Produce();
# Line 1212  String LSCPServer::SetMIDIInput(uint MID Line 1889  String LSCPServer::SetMIDIInput(uint MID
1889   * Will be called by the parser to change the global volume factor on a   * Will be called by the parser to change the global volume factor on a
1890   * particular sampler channel.   * particular sampler channel.
1891   */   */
1892  String LSCPServer::SetVolume(double Volume, uint uiSamplerChannel) {  String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
1893      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", Volume, 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);
1897          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          pEngineChannel->Volume(dVolume);
         Engine* pEngine = pSamplerChannel->GetEngine();  
         if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");  
         pEngine->Volume(Volume);  
1898      }      }
1899      catch (LinuxSamplerException e) {      catch (Exception e) {
1900           result.Error(e);           result.Error(e);
1901      }      }
1902      return result.Produce();      return result.Produce();
1903  }  }
1904    
1905  /**  /**
1906     * Will be called by the parser to mute/unmute particular sampler channel.
1907     */
1908    String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
1909        dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
1910        LSCPResultSet result;
1911        try {
1912            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1913    
1914            if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
1915            else pEngineChannel->SetMute(1);
1916        } catch (Exception e) {
1917            result.Error(e);
1918        }
1919        return result.Produce();
1920    }
1921    
1922    /**
1923     * Will be called by the parser to solo particular sampler channel.
1924     */
1925    String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
1926        dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
1927        LSCPResultSet result;
1928        try {
1929            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1930    
1931            bool oldSolo = pEngineChannel->GetSolo();
1932            bool hadSoloChannel = HasSoloChannel();
1933    
1934            pEngineChannel->SetSolo(bSolo);
1935    
1936            if(!oldSolo && bSolo) {
1937                if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
1938                if(!hadSoloChannel) MuteNonSoloChannels();
1939            }
1940    
1941            if(oldSolo && !bSolo) {
1942                if(!HasSoloChannel()) UnmuteChannels();
1943                else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
1944            }
1945        } catch (Exception e) {
1946            result.Error(e);
1947        }
1948        return result.Produce();
1949    }
1950    
1951    /**
1952     * Determines whether there is at least one solo channel in the channel list.
1953     *
1954     * @returns true if there is at least one solo channel in the channel list,
1955     * false otherwise.
1956     */
1957    bool LSCPServer::HasSoloChannel() {
1958        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1959        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1960        for (; iter != channels.end(); iter++) {
1961            EngineChannel* c = iter->second->GetEngineChannel();
1962            if(c && c->GetSolo()) return true;
1963        }
1964    
1965        return false;
1966    }
1967    
1968    /**
1969     * Mutes all unmuted non-solo channels. Notice that the channels are muted
1970     * with -1 which indicates that they are muted because of the presence
1971     * of a solo channel(s). Channels muted with -1 will be automatically unmuted
1972     * when there are no solo channels left.
1973     */
1974    void LSCPServer::MuteNonSoloChannels() {
1975        dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
1976        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1977        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1978        for (; iter != channels.end(); iter++) {
1979            EngineChannel* c = iter->second->GetEngineChannel();
1980            if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
1981        }
1982    }
1983    
1984    /**
1985     * Unmutes all channels that are muted because of the presence
1986     * of a solo channel(s).
1987     */
1988    void  LSCPServer::UnmuteChannels() {
1989        dmsg(2,("LSCPServer: UnmuteChannels()\n"));
1990        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1991        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1992        for (; iter != channels.end(); iter++) {
1993            EngineChannel* c = iter->second->GetEngineChannel();
1994            if(c && c->GetMute() == -1) c->SetMute(0);
1995        }
1996    }
1997    
1998    String LSCPServer::AddOrReplaceMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg, String EngineType, String InstrumentFile, uint InstrumentIndex, float Volume, MidiInstrumentMapper::mode_t LoadMode, String Name, bool bModal) {
1999        dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
2000    
2001        midi_prog_index_t idx;
2002        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2003        idx.midi_bank_lsb = MidiBank & 0x7f;
2004        idx.midi_prog     = MidiProg;
2005    
2006        MidiInstrumentMapper::entry_t entry;
2007        entry.EngineName      = EngineType;
2008        entry.InstrumentFile  = InstrumentFile;
2009        entry.InstrumentIndex = InstrumentIndex;
2010        entry.LoadMode        = LoadMode;
2011        entry.Volume          = Volume;
2012        entry.Name            = Name;
2013    
2014        LSCPResultSet result;
2015        try {
2016            // PERSISTENT mapping commands might block for a long time, so in
2017            // that case we add/replace the mapping in another thread in case
2018            // the NON_MODAL argument was supplied, non persistent mappings
2019            // should return immediately, so we don't need to do that for them
2020            bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
2021            MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
2022        } catch (Exception e) {
2023            result.Error(e);
2024        }
2025        return result.Produce();
2026    }
2027    
2028    String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2029        dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
2030    
2031        midi_prog_index_t idx;
2032        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2033        idx.midi_bank_lsb = MidiBank & 0x7f;
2034        idx.midi_prog     = MidiProg;
2035    
2036        LSCPResultSet result;
2037        try {
2038            MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
2039        } catch (Exception e) {
2040            result.Error(e);
2041        }
2042        return result.Produce();
2043    }
2044    
2045    String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
2046        dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
2047        LSCPResultSet result;
2048        try {
2049            result.Add(MidiInstrumentMapper::GetInstrumentCount(MidiMapID));
2050        } catch (Exception e) {
2051            result.Error(e);
2052        }
2053        return result.Produce();
2054    }
2055    
2056    
2057    String LSCPServer::GetAllMidiInstrumentMappings() {
2058        dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
2059        LSCPResultSet result;
2060        try {
2061            result.Add(MidiInstrumentMapper::GetInstrumentCount());
2062        } catch (Exception e) {
2063            result.Error(e);
2064        }
2065        return result.Produce();
2066    }
2067    
2068    String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2069        dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
2070        LSCPResultSet result;
2071        try {
2072            MidiInstrumentMapper::entry_t entry = MidiInstrumentMapper::GetEntry(MidiMapID, MidiBank, MidiProg);
2073            // convert the filename into the correct encoding as defined for LSCP
2074            // (especially in terms of special characters -> escape sequences)
2075    #if WIN32
2076            const String instrumentFileName = Path::fromWindows(entry.InstrumentFile).toLscp();
2077    #else
2078            // assuming POSIX
2079            const String instrumentFileName = Path::fromPosix(entry.InstrumentFile).toLscp();
2080    #endif
2081    
2082            result.Add("NAME", _escapeLscpResponse(entry.Name));
2083            result.Add("ENGINE_NAME", entry.EngineName);
2084            result.Add("INSTRUMENT_FILE", instrumentFileName);
2085            result.Add("INSTRUMENT_NR", (int) entry.InstrumentIndex);
2086            String instrumentName;
2087            Engine* pEngine = EngineFactory::Create(entry.EngineName);
2088            if (pEngine) {
2089                if (pEngine->GetInstrumentManager()) {
2090                    InstrumentManager::instrument_id_t instrID;
2091                    instrID.FileName = entry.InstrumentFile;
2092                    instrID.Index    = entry.InstrumentIndex;
2093                    instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
2094                }
2095                EngineFactory::Destroy(pEngine);
2096            }
2097            result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2098            switch (entry.LoadMode) {
2099                case MidiInstrumentMapper::ON_DEMAND:
2100                    result.Add("LOAD_MODE", "ON_DEMAND");
2101                    break;
2102                case MidiInstrumentMapper::ON_DEMAND_HOLD:
2103                    result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2104                    break;
2105                case MidiInstrumentMapper::PERSISTENT:
2106                    result.Add("LOAD_MODE", "PERSISTENT");
2107                    break;
2108                default:
2109                    throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2110            }
2111            result.Add("VOLUME", entry.Volume);
2112        } catch (Exception e) {
2113            result.Error(e);
2114        }
2115        return result.Produce();
2116    }
2117    
2118    String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
2119        dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
2120        LSCPResultSet result;
2121        try {
2122            String s;
2123            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
2124            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2125            for (; iter != mappings.end(); iter++) {
2126                if (s.size()) s += ",";
2127                s += "{" + ToString(MidiMapID) + ","
2128                         + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2129                         + ToString(int(iter->first.midi_prog)) + "}";
2130            }
2131            result.Add(s);
2132        } catch (Exception e) {
2133            result.Error(e);
2134        }
2135        return result.Produce();
2136    }
2137    
2138    String LSCPServer::ListAllMidiInstrumentMappings() {
2139        dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
2140        LSCPResultSet result;
2141        try {
2142            std::vector<int> maps = MidiInstrumentMapper::Maps();
2143            String s;
2144            for (int i = 0; i < maps.size(); i++) {
2145                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
2146                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2147                for (; iter != mappings.end(); iter++) {
2148                    if (s.size()) s += ",";
2149                    s += "{" + ToString(maps[i]) + ","
2150                             + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2151                             + ToString(int(iter->first.midi_prog)) + "}";
2152                }
2153            }
2154            result.Add(s);
2155        } catch (Exception e) {
2156            result.Error(e);
2157        }
2158        return result.Produce();
2159    }
2160    
2161    String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
2162        dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
2163        LSCPResultSet result;
2164        try {
2165            MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
2166        } catch (Exception e) {
2167            result.Error(e);
2168        }
2169        return result.Produce();
2170    }
2171    
2172    String LSCPServer::ClearAllMidiInstrumentMappings() {
2173        dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
2174        LSCPResultSet result;
2175        try {
2176            std::vector<int> maps = MidiInstrumentMapper::Maps();
2177            for (int i = 0; i < maps.size(); i++)
2178                MidiInstrumentMapper::RemoveAllEntries(maps[i]);
2179        } catch (Exception e) {
2180            result.Error(e);
2181        }
2182        return result.Produce();
2183    }
2184    
2185    String LSCPServer::AddMidiInstrumentMap(String MapName) {
2186        dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
2187        LSCPResultSet result;
2188        try {
2189            int MapID = MidiInstrumentMapper::AddMap(MapName);
2190            result = LSCPResultSet(MapID);
2191        } catch (Exception e) {
2192            result.Error(e);
2193        }
2194        return result.Produce();
2195    }
2196    
2197    String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
2198        dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
2199        LSCPResultSet result;
2200        try {
2201            MidiInstrumentMapper::RemoveMap(MidiMapID);
2202        } catch (Exception e) {
2203            result.Error(e);
2204        }
2205        return result.Produce();
2206    }
2207    
2208    String LSCPServer::RemoveAllMidiInstrumentMaps() {
2209        dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
2210        LSCPResultSet result;
2211        try {
2212            MidiInstrumentMapper::RemoveAllMaps();
2213        } catch (Exception e) {
2214            result.Error(e);
2215        }
2216        return result.Produce();
2217    }
2218    
2219    String LSCPServer::GetMidiInstrumentMaps() {
2220        dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
2221        LSCPResultSet result;
2222        try {
2223            result.Add(MidiInstrumentMapper::Maps().size());
2224        } catch (Exception e) {
2225            result.Error(e);
2226        }
2227        return result.Produce();
2228    }
2229    
2230    String LSCPServer::ListMidiInstrumentMaps() {
2231        dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
2232        LSCPResultSet result;
2233        try {
2234            std::vector<int> maps = MidiInstrumentMapper::Maps();
2235            String sList;
2236            for (int i = 0; i < maps.size(); i++) {
2237                if (sList != "") sList += ",";
2238                sList += ToString(maps[i]);
2239            }
2240            result.Add(sList);
2241        } catch (Exception e) {
2242            result.Error(e);
2243        }
2244        return result.Produce();
2245    }
2246    
2247    String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
2248        dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2249        LSCPResultSet result;
2250        try {
2251            result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2252            result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2253        } catch (Exception e) {
2254            result.Error(e);
2255        }
2256        return result.Produce();
2257    }
2258    
2259    String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2260        dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2261        LSCPResultSet result;
2262        try {
2263            MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2264        } catch (Exception e) {
2265            result.Error(e);
2266        }
2267        return result.Produce();
2268    }
2269    
2270    /**
2271     * Set the MIDI instrument map the given sampler channel shall use for
2272     * handling MIDI program change messages. There are the following two
2273     * special (negative) values:
2274     *
2275     *    - (-1) :  set to NONE (ignore program changes)
2276     *    - (-2) :  set to DEFAULT map
2277     */
2278    String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2279        dmsg(2,("LSCPServer: SetChannelMap()\n"));
2280        LSCPResultSet result;
2281        try {
2282            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2283    
2284            if      (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2285            else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2286            else                      pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2287        } catch (Exception e) {
2288            result.Error(e);
2289        }
2290        return result.Produce();
2291    }
2292    
2293    String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2294        dmsg(2,("LSCPServer: CreateFxSend()\n"));
2295        LSCPResultSet result;
2296        try {
2297            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2298    
2299            FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2300            if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2301    
2302            result = LSCPResultSet(pFxSend->Id()); // success
2303        } catch (Exception e) {
2304            result.Error(e);
2305        }
2306        return result.Produce();
2307    }
2308    
2309    String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2310        dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2311        LSCPResultSet result;
2312        try {
2313            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2314    
2315            FxSend* pFxSend = NULL;
2316            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2317                if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2318                    pFxSend = pEngineChannel->GetFxSend(i);
2319                    break;
2320                }
2321            }
2322            if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2323            pEngineChannel->RemoveFxSend(pFxSend);
2324        } catch (Exception e) {
2325            result.Error(e);
2326        }
2327        return result.Produce();
2328    }
2329    
2330    String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2331        dmsg(2,("LSCPServer: GetFxSends()\n"));
2332        LSCPResultSet result;
2333        try {
2334            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2335    
2336            result.Add(pEngineChannel->GetFxSendCount());
2337        } catch (Exception e) {
2338            result.Error(e);
2339        }
2340        return result.Produce();
2341    }
2342    
2343    String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2344        dmsg(2,("LSCPServer: ListFxSends()\n"));
2345        LSCPResultSet result;
2346        String list;
2347        try {
2348            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2349    
2350            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2351                FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2352                if (list != "") list += ",";
2353                list += ToString(pFxSend->Id());
2354            }
2355            result.Add(list);
2356        } catch (Exception e) {
2357            result.Error(e);
2358        }
2359        return result.Produce();
2360    }
2361    
2362    FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2363        EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2364    
2365        FxSend* pFxSend = NULL;
2366        for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2367            if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2368                pFxSend = pEngineChannel->GetFxSend(i);
2369                break;
2370            }
2371        }
2372        if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2373        return pFxSend;
2374    }
2375    
2376    String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2377        dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2378        LSCPResultSet result;
2379        try {
2380            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2381            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2382    
2383            // gather audio routing informations
2384            String AudioRouting;
2385            for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2386                if (AudioRouting != "") AudioRouting += ",";
2387                AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2388            }
2389    
2390            const String sEffectRouting =
2391                (pFxSend->DestinationEffectChain() >= 0 && pFxSend->DestinationEffectChainPosition() >= 0)
2392                    ? ToString(pFxSend->DestinationEffectChain()) + "," + ToString(pFxSend->DestinationEffectChainPosition())
2393                    : "NONE";
2394    
2395            // success
2396            result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2397            result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2398            result.Add("LEVEL", ToString(pFxSend->Level()));
2399            result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2400            result.Add("EFFECT", sEffectRouting);
2401        } catch (Exception e) {
2402            result.Error(e);
2403        }
2404        return result.Produce();
2405    }
2406    
2407    String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2408        dmsg(2,("LSCPServer: SetFxSendName()\n"));
2409        LSCPResultSet result;
2410        try {
2411            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2412    
2413            pFxSend->SetName(Name);
2414            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2415        } catch (Exception e) {
2416            result.Error(e);
2417        }
2418        return result.Produce();
2419    }
2420    
2421    String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2422        dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2423        LSCPResultSet result;
2424        try {
2425            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2426    
2427            pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2428            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2429        } catch (Exception e) {
2430            result.Error(e);
2431        }
2432        return result.Produce();
2433    }
2434    
2435    String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2436        dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2437        LSCPResultSet result;
2438        try {
2439            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2440    
2441            pFxSend->SetMidiController(MidiController);
2442            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2443        } catch (Exception e) {
2444            result.Error(e);
2445        }
2446        return result.Produce();
2447    }
2448    
2449    String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2450        dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2451        LSCPResultSet result;
2452        try {
2453            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2454    
2455            pFxSend->SetLevel((float)dLevel);
2456            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2457        } catch (Exception e) {
2458            result.Error(e);
2459        }
2460        return result.Produce();
2461    }
2462    
2463    String LSCPServer::SetFxSendEffect(uint uiSamplerChannel, uint FxSendID, int iSendEffectChain, int iEffectChainPosition) {
2464        dmsg(2,("LSCPServer: SetFxSendEffect(%d,%d)\n", iSendEffectChain, iEffectChainPosition));
2465        LSCPResultSet result;
2466        try {
2467            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2468    
2469            pFxSend->SetDestinationEffect(iSendEffectChain, iEffectChainPosition);
2470            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2471        } catch (Exception e) {
2472            result.Error(e);
2473        }
2474        return result.Produce();
2475    }
2476    
2477    String LSCPServer::GetAvailableEffects() {
2478        dmsg(2,("LSCPServer: GetAvailableEffects()\n"));
2479        LSCPResultSet result;
2480        try {
2481            int n = EffectFactory::AvailableEffectsCount();
2482            result.Add(n);
2483        }
2484        catch (Exception e) {
2485            result.Error(e);
2486        }
2487        return result.Produce();
2488    }
2489    
2490    String LSCPServer::ListAvailableEffects() {
2491        dmsg(2,("LSCPServer: ListAvailableEffects()\n"));
2492        LSCPResultSet result;
2493        String list;
2494        try {
2495            //FIXME: for now we simply enumerate from 0 .. EffectFactory::AvailableEffectsCount() here, in future we should use unique IDs for effects during the whole sampler session. This issue comes into game when the user forces a reload of available effect plugins
2496            int n = EffectFactory::AvailableEffectsCount();
2497            for (int i = 0; i < n; i++) {
2498                if (i) list += ",";
2499                list += ToString(i);
2500            }
2501        }
2502        catch (Exception e) {
2503            result.Error(e);
2504        }
2505        result.Add(list);
2506        return result.Produce();
2507    }
2508    
2509    String LSCPServer::GetEffectInfo(int iEffectIndex) {
2510        dmsg(2,("LSCPServer: GetEffectInfo(%d)\n", iEffectIndex));
2511        LSCPResultSet result;
2512        try {
2513            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2514            if (!pEffectInfo)
2515                throw Exception("There is no effect with index " + ToString(iEffectIndex));
2516    
2517            // convert the filename into the correct encoding as defined for LSCP
2518            // (especially in terms of special characters -> escape sequences)
2519    #if WIN32
2520            const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2521    #else
2522            // assuming POSIX
2523            const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2524    #endif
2525    
2526            result.Add("SYSTEM", pEffectInfo->EffectSystem());
2527            result.Add("MODULE", dllFileName);
2528            result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2529            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2530        }
2531        catch (Exception e) {
2532            result.Error(e);
2533        }
2534        return result.Produce();    
2535    }
2536    
2537    String LSCPServer::GetEffectInstanceInfo(int iEffectInstance) {
2538        dmsg(2,("LSCPServer: GetEffectInstanceInfo(%d)\n", iEffectInstance));
2539        LSCPResultSet result;
2540        try {
2541            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2542            if (!pEffect)
2543                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2544    
2545            EffectInfo* pEffectInfo = pEffect->GetEffectInfo();
2546    
2547            // convert the filename into the correct encoding as defined for LSCP
2548            // (especially in terms of special characters -> escape sequences)
2549    #if WIN32
2550            const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2551    #else
2552            // assuming POSIX
2553            const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2554    #endif
2555    
2556            result.Add("SYSTEM", pEffectInfo->EffectSystem());
2557            result.Add("MODULE", dllFileName);
2558            result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2559            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2560            result.Add("INPUT_CONTROLS", ToString(pEffect->InputControlCount()));
2561        }
2562        catch (Exception e) {
2563            result.Error(e);
2564        }
2565        return result.Produce();
2566    }
2567    
2568    String LSCPServer::GetEffectInstanceInputControlInfo(int iEffectInstance, int iInputControlIndex) {
2569        dmsg(2,("LSCPServer: GetEffectInstanceInputControlInfo(%d,%d)\n", iEffectInstance, iInputControlIndex));
2570        LSCPResultSet result;
2571        try {
2572            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2573            if (!pEffect)
2574                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2575    
2576            EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2577            if (!pEffectControl)
2578                throw Exception(
2579                    "Effect instance " + ToString(iEffectInstance) +
2580                    " does not have an input control with index " +
2581                    ToString(iInputControlIndex)
2582                );
2583    
2584            result.Add("DESCRIPTION", _escapeLscpResponse(pEffectControl->Description()));
2585            result.Add("VALUE", pEffectControl->Value());
2586            if (pEffectControl->MinValue())
2587                 result.Add("RANGE_MIN", *pEffectControl->MinValue());
2588            if (pEffectControl->MaxValue())
2589                 result.Add("RANGE_MAX", *pEffectControl->MaxValue());
2590            if (!pEffectControl->Possibilities().empty())
2591                 result.Add("POSSIBILITIES", pEffectControl->Possibilities());
2592            if (pEffectControl->DefaultValue())
2593                 result.Add("DEFAULT", *pEffectControl->DefaultValue());
2594        } catch (Exception e) {
2595            result.Error(e);
2596        }
2597        return result.Produce();
2598    }
2599    
2600    String LSCPServer::SetEffectInstanceInputControlValue(int iEffectInstance, int iInputControlIndex, double dValue) {
2601        dmsg(2,("LSCPServer: SetEffectInstanceInputControlValue(%d,%d,%f)\n", iEffectInstance, iInputControlIndex, dValue));
2602        LSCPResultSet result;
2603        try {
2604            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2605            if (!pEffect)
2606                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2607    
2608            EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2609            if (!pEffectControl)
2610                throw Exception(
2611                    "Effect instance " + ToString(iEffectInstance) +
2612                    " does not have an input control with index " +
2613                    ToString(iInputControlIndex)
2614                );
2615    
2616            pEffectControl->SetValue(dValue);
2617            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_info, iEffectInstance));
2618        } catch (Exception e) {
2619            result.Error(e);
2620        }
2621        return result.Produce();
2622    }
2623    
2624    String LSCPServer::CreateEffectInstance(int iEffectIndex) {
2625        dmsg(2,("LSCPServer: CreateEffectInstance(%d)\n", iEffectIndex));
2626        LSCPResultSet result;
2627        try {
2628            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2629            if (!pEffectInfo)
2630                throw Exception("There is no effect with index " + ToString(iEffectIndex));
2631            Effect* pEffect = EffectFactory::Create(pEffectInfo);
2632            result = pEffect->ID(); // success
2633            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2634        } catch (Exception e) {
2635            result.Error(e);
2636        }
2637        return result.Produce();
2638    }
2639    
2640    String LSCPServer::CreateEffectInstance(String effectSystem, String module, String effectName) {
2641        dmsg(2,("LSCPServer: CreateEffectInstance('%s','%s','%s')\n", effectSystem.c_str(), module.c_str(), effectName.c_str()));
2642        LSCPResultSet result;
2643        try {
2644            // to allow loading the same LSCP session file on different systems
2645            // successfully, probably with different effect plugin DLL paths or even
2646            // running completely different operating systems, we do the following
2647            // for finding the right effect:
2648            //
2649            // first try to search for an exact match of the effect plugin DLL
2650            // (a.k.a 'module'), to avoid picking the wrong DLL with the same
2651            // effect name ...
2652            EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_MATCH_EXACTLY);
2653            // ... if no effect with exactly matchin DLL filename was found, then
2654            // try to lower the restrictions of matching the effect plugin DLL
2655            // filename and try again and again ...
2656            if (!pEffectInfo) {
2657                dmsg(2,("no exact module match, trying MODULE_IGNORE_PATH\n"));
2658                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH);
2659            }
2660            if (!pEffectInfo) {
2661                dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE\n"));
2662                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE);
2663            }
2664            if (!pEffectInfo) {
2665                dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE | MODULE_IGNORE_EXTENSION\n"));
2666                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE | EffectFactory::MODULE_IGNORE_EXTENSION);
2667            }
2668            // ... if there was still no effect found, then completely ignore the
2669            // DLL plugin filename argument and just search for the matching effect
2670            // system type and effect name
2671            if (!pEffectInfo) {
2672                dmsg(2,("no module match, trying MODULE_IGNORE_ALL\n"));
2673                pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_ALL);
2674            }
2675            if (!pEffectInfo)
2676                throw Exception("There is no such effect '" + effectSystem + "' '" + module + "' '" + effectName + "'");
2677    
2678            Effect* pEffect = EffectFactory::Create(pEffectInfo);
2679            result = LSCPResultSet(pEffect->ID());
2680            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2681        } catch (Exception e) {
2682            result.Error(e);
2683        }
2684        return result.Produce();
2685    }
2686    
2687    String LSCPServer::DestroyEffectInstance(int iEffectInstance) {
2688        dmsg(2,("LSCPServer: DestroyEffectInstance(%d)\n", iEffectInstance));
2689        LSCPResultSet result;
2690        try {
2691            Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2692            if (!pEffect)
2693                throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2694            EffectFactory::Destroy(pEffect);
2695            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2696        } catch (Exception e) {
2697            result.Error(e);
2698        }
2699        return result.Produce();
2700    }
2701    
2702    String LSCPServer::GetEffectInstances() {
2703        dmsg(2,("LSCPServer: GetEffectInstances()\n"));
2704        LSCPResultSet result;
2705        try {
2706            int n = EffectFactory::EffectInstancesCount();
2707            result.Add(n);
2708        } catch (Exception e) {
2709            result.Error(e);
2710        }
2711        return result.Produce();
2712    }
2713    
2714    String LSCPServer::ListEffectInstances() {
2715        dmsg(2,("LSCPServer: ListEffectInstances()\n"));
2716        LSCPResultSet result;
2717        String list;
2718        try {
2719            int n = EffectFactory::EffectInstancesCount();
2720            for (int i = 0; i < n; i++) {
2721                Effect* pEffect = EffectFactory::GetEffectInstance(i);
2722                if (i) list += ",";
2723                list += ToString(pEffect->ID());
2724            }
2725        } catch (Exception e) {
2726            result.Error(e);
2727        }
2728        result.Add(list);
2729        return result.Produce();
2730    }
2731    
2732    String LSCPServer::GetSendEffectChains(int iAudioOutputDevice) {
2733        dmsg(2,("LSCPServer: GetSendEffectChains(%d)\n", iAudioOutputDevice));
2734        LSCPResultSet result;
2735        try {
2736            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2737            if (!devices.count(iAudioOutputDevice))
2738                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2739            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2740            int n = pDevice->SendEffectChainCount();
2741            result.Add(n);
2742        } catch (Exception e) {
2743            result.Error(e);
2744        }
2745        return result.Produce();
2746    }
2747    
2748    String LSCPServer::ListSendEffectChains(int iAudioOutputDevice) {
2749        dmsg(2,("LSCPServer: ListSendEffectChains(%d)\n", iAudioOutputDevice));
2750        LSCPResultSet result;
2751        String list;
2752        try {
2753            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2754            if (!devices.count(iAudioOutputDevice))
2755                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2756            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2757            int n = pDevice->SendEffectChainCount();
2758            for (int i = 0; i < n; i++) {
2759                EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2760                if (i) list += ",";
2761                list += ToString(pEffectChain->ID());
2762            }
2763        } catch (Exception e) {
2764            result.Error(e);
2765        }
2766        result.Add(list);
2767        return result.Produce();
2768    }
2769    
2770    String LSCPServer::AddSendEffectChain(int iAudioOutputDevice) {
2771        dmsg(2,("LSCPServer: AddSendEffectChain(%d)\n", iAudioOutputDevice));
2772        LSCPResultSet result;
2773        try {
2774            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2775            if (!devices.count(iAudioOutputDevice))
2776                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2777            AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2778            EffectChain* pEffectChain = pDevice->AddSendEffectChain();
2779            result = pEffectChain->ID();
2780            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2781        } catch (Exception e) {
2782            result.Error(e);
2783        }
2784        return result.Produce();
2785    }
2786    
2787    String LSCPServer::RemoveSendEffectChain(int iAudioOutputDevice, int iSendEffectChain) {
2788        dmsg(2,("LSCPServer: RemoveSendEffectChain(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2789        LSCPResultSet result;
2790        try {
2791            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2792            if (!devices.count(iAudioOutputDevice))
2793                throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2794            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;
2937                }
2938            }
2939            
2940            if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
2941    
2942            if (MidiMsg == "NOTE_ON") {
2943                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) {
2958            result.Error(e);
2959        }
2960        return result.Produce();
2961    }
2962    
2963    /**
2964   * Will be called by the parser to reset a particular sampler channel.   * Will be called by the parser to reset a particular sampler channel.
2965   */   */
2966  String LSCPServer::ResetChannel(uint uiSamplerChannel) {  String LSCPServer::ResetChannel(uint uiSamplerChannel) {
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);
2971          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          pEngineChannel->Reset();
         Engine* pEngine = pSamplerChannel->GetEngine();  
         if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");  
         pEngine->Reset();  
2972      }      }
2973      catch (LinuxSamplerException e) {      catch (Exception e) {
2974           result.Error(e);           result.Error(e);
2975      }      }
2976      return result.Produce();      return result.Produce();
2977  }  }
2978    
2979  /**  /**
2980     * Will be called by the parser to reset the whole sampler.
2981     */
2982    String LSCPServer::ResetSampler() {
2983        dmsg(2,("LSCPServer: ResetSampler()\n"));
2984        pSampler->Reset();
2985        LSCPResultSet result;
2986        return result.Produce();
2987    }
2988    
2989    /**
2990     * Will be called by the parser to return general informations about this
2991     * sampler.
2992     */
2993    String LSCPServer::GetServerInfo() {
2994        dmsg(2,("LSCPServer: GetServerInfo()\n"));
2995        const std::string description =
2996            _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
2997        LSCPResultSet result;
2998        result.Add("DESCRIPTION", description);
2999        result.Add("VERSION", VERSION);
3000        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();
3018    }
3019    
3020    /**
3021     * Will be called by the parser to return the current number of all active voices.
3022     */
3023    String LSCPServer::GetTotalVoiceCount() {
3024        dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
3025        LSCPResultSet result;
3026        result.Add(pSampler->GetVoiceCount());
3027        return result.Produce();
3028    }
3029    
3030    /**
3031     * Will be called by the parser to return the maximum number of voices.
3032     */
3033    String LSCPServer::GetTotalVoiceCountMax() {
3034        dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3035        LSCPResultSet result;
3036        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();
3110    }
3111    
3112    String LSCPServer::GetGlobalVolume() {
3113        LSCPResultSet result;
3114        result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
3115        return result.Produce();
3116    }
3117    
3118    String LSCPServer::SetGlobalVolume(double dVolume) {
3119        LSCPResultSet result;
3120        try {
3121            if (dVolume < 0) throw Exception("Volume may not be negative");
3122            GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3123            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3124        } catch (Exception e) {
3125            result.Error(e);
3126        }
3127        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.
3305   */   */
# Line 1273  String LSCPServer::UnsubscribeNotificati Line 3325  String LSCPServer::UnsubscribeNotificati
3325      return result.Produce();      return result.Produce();
3326  }  }
3327    
3328    String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3329        dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3330        LSCPResultSet result;
3331    #if HAVE_SQLITE3
3332        try {
3333            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  // Instrument loader constructor.  String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3344  LSCPLoadInstrument::LSCPLoadInstrument(Engine* pEngine, String Filename, uint uiInstrument)      dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3345      : Thread(false, 0, -4)      LSCPResultSet result;
3346  {  #if HAVE_SQLITE3
3347      this->pEngine = pEngine;      try {
3348      this->Filename = Filename;          InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3349      this->uiInstrument = uiInstrument;      } 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  // Instrument loader process.  String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3359  int LSCPLoadInstrument::Main()      dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3360  {      LSCPResultSet result;
3361    #if HAVE_SQLITE3
3362      try {      try {
3363          pEngine->LoadInstrument(Filename.c_str(), uiInstrument);          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::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3461        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3462        LSCPResultSet result;
3463    #if HAVE_SQLITE3
3464        try {
3465            InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3466        } 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      catch (LinuxSamplerException e) {  String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3476          e.PrintMessage();      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      // Always re-enable the engine.          if (bBackground) result = id;
3511      pEngine->Enable();      } 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            result.Add(list);
3564        } catch (Exception e) {
3565             result.Error(e);
3566        }
3567    #else
3568        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3569    #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        }
3595    #else
3596        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3597    #endif
3598        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
3833     * mode is enabled, all commands from the client will (immediately) be
3834     * echoed back to the client.
3835     */
3836    String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
3837        dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
3838        LSCPResultSet result;
3839        try {
3840            if      (boolean_value == 0) pSession->bVerbose = false;
3841            else if (boolean_value == 1) pSession->bVerbose = true;
3842            else throw Exception("Not a boolean value, must either be 0 or 1");
3843        }
3844        catch (Exception e) {
3845             result.Error(e);
3846        }
3847        return result.Produce();
3848    }
3849    
     // FIXME: Shoot ourselves on the foot?  
     delete this;  
3850  }  }

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

  ViewVC Help
Powered by ViewVC