/[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 53 by schoenebeck, Mon Apr 26 17:15:51 2004 UTC revision 1686 by schoenebeck, Thu Feb 14 14:58:50 2008 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003 by Benno Senoner and Christian Schoenebeck         *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005 - 2008 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 "lscpserver.h"  #include "lscpserver.h"
25    #include "lscpresultset.h"
26    #include "lscpevent.h"
27    
28  #include "../engines/gig/Engine.h"  #if defined(WIN32)
29    #include <windows.h>
30    #else
31    #include <fcntl.h>
32    #endif
33    
34    #if ! HAVE_SQLITE3
35    #define DOESNT_HAVE_SQLITE3 "No database support. SQLITE3 was not installed when linuxsampler was built."
36    #endif
37    
38    #include "../engines/EngineFactory.h"
39    #include "../engines/EngineChannelFactory.h"
40    #include "../drivers/audio/AudioOutputDeviceFactory.h"
41    #include "../drivers/midi/MidiInputDeviceFactory.h"
42    
43  LSCPServer::LSCPServer(Sampler* pSampler) : Thread(false, 0, -4) {  
44    /**
45     * Returns a copy of the given string where all special characters are
46     * replaced by LSCP escape sequences ("\xHH"). This function shall be used
47     * to escape LSCP response fields in case the respective response field is
48     * actually defined as using escape sequences in the LSCP specs.
49     *
50     * @e Caution: DO NOT use this function for escaping path based responses,
51     * use the Path class (src/common/Path.h) for this instead!
52     */
53    static String _escapeLscpResponse(String txt) {
54        for (int i = 0; i < txt.length(); i++) {
55            const char c = txt.c_str()[i];
56            if (
57                !(c >= '0' && c <= '9') &&
58                !(c >= 'a' && c <= 'z') &&
59                !(c >= 'A' && c <= 'Z') &&
60                !(c == ' ') && !(c == '!') && !(c == '#') && !(c == '$') &&
61                !(c == '%') && !(c == '&') && !(c == '(') && !(c == ')') &&
62                !(c == '*') && !(c == '+') && !(c == ',') && !(c == '-') &&
63                !(c == '.') && !(c == '/') && !(c == ':') && !(c == ';') &&
64                !(c == '<') && !(c == '=') && !(c == '>') && !(c == '?') &&
65                !(c == '@') && !(c == '[') && !(c == ']') &&
66                !(c == '^') && !(c == '_') && !(c == '`') && !(c == '{') &&
67                !(c == '|') && !(c == '}') && !(c == '~')
68            ) {
69                // convert the "special" character into a "\xHH" LSCP escape sequence
70                char buf[5];
71                snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
72                txt.replace(i, 1, buf);
73                i += 3;
74            }
75        }
76        return txt;
77    }
78    
79    /**
80     * Below are a few static members of the LSCPServer class.
81     * The big assumption here is that LSCPServer is going to remain a singleton.
82     * These members are used to support client connections.
83     * Class handles multiple connections at the same time using select() and non-blocking recv()
84     * Commands are processed by a single LSCPServer thread.
85     * Notifications are delivered either by the thread that originated them
86     * or (if the resultset is currently in progress) by the LSCPServer thread
87     * after the resultset was sent out.
88     * This makes sure that resultsets can not be interrupted by notifications.
89     * This also makes sure that the thread sending notification is not blocked
90     * by the LSCPServer thread.
91     */
92    fd_set LSCPServer::fdSet;
93    int LSCPServer::currentSocket = -1;
94    std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();
95    std::vector<yyparse_param_t>::iterator itCurrentSession = std::vector<yyparse_param_t>::iterator();
96    std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();
97    std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();
98    std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();
99    Mutex LSCPServer::NotifyMutex = Mutex();
100    Mutex LSCPServer::NotifyBufferMutex = Mutex();
101    Mutex LSCPServer::SubscriptionMutex = Mutex();
102    Mutex LSCPServer::RTNotifyMutex = Mutex();
103    
104    LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4), eventHandler(this) {
105        SocketAddress.sin_family      = AF_INET;
106        SocketAddress.sin_addr.s_addr = addr;
107        SocketAddress.sin_port        = port;
108      this->pSampler = pSampler;      this->pSampler = pSampler;
109        LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT");
110        LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO");
111        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT");
112        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO");
113        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
114        LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
115        LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
116        LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
117        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
118        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_count, "FX_SEND_COUNT");
119        LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_info, "FX_SEND_INFO");
120        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
121        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
122        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
123        LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
124        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_count, "DB_INSTRUMENT_DIRECTORY_COUNT");
125        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_info, "DB_INSTRUMENT_DIRECTORY_INFO");
126        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_count, "DB_INSTRUMENT_COUNT");
127        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_info, "DB_INSTRUMENT_INFO");
128        LSCPEvent::RegisterEvent(LSCPEvent::event_db_instrs_job_info, "DB_INSTRUMENTS_JOB_INFO");
129        LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
130        LSCPEvent::RegisterEvent(LSCPEvent::event_total_stream_count, "TOTAL_STREAM_COUNT");
131        LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
132        LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");
133        LSCPEvent::RegisterEvent(LSCPEvent::event_channel_midi, "CHANNEL_MIDI");
134        hSocket = -1;
135    }
136    
137    LSCPServer::~LSCPServer() {
138    #if defined(WIN32)
139        if (hSocket >= 0) closesocket(hSocket);
140    #else
141        if (hSocket >= 0) close(hSocket);
142    #endif
143    }
144    
145    LSCPServer::EventHandler::EventHandler(LSCPServer* pParent) {
146        this->pParent = pParent;
147    }
148    
149    LSCPServer::EventHandler::~EventHandler() {
150        std::vector<midi_listener_entry> l = channelMidiListeners;
151        channelMidiListeners.clear();
152        for (int i = 0; i < l.size(); i++)
153            delete l[i].pMidiListener;
154    }
155    
156    void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {
157        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));
158    }
159    
160    void LSCPServer::EventHandler::ChannelAdded(SamplerChannel* pChannel) {
161        pChannel->AddEngineChangeListener(this);
162    }
163    
164    void LSCPServer::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) {
165        if (!pChannel->GetEngineChannel()) return;
166        EngineToBeChanged(pChannel->Index());
167    }
168    
169    void LSCPServer::EventHandler::EngineToBeChanged(int ChannelId) {
170        SamplerChannel* pSamplerChannel =
171            pParent->pSampler->GetSamplerChannel(ChannelId);
172        if (!pSamplerChannel) return;
173        EngineChannel* pEngineChannel =
174            pSamplerChannel->GetEngineChannel();
175        if (!pEngineChannel) return;
176        for (std::vector<midi_listener_entry>::iterator iter = channelMidiListeners.begin(); iter != channelMidiListeners.end(); ++iter) {
177            if ((*iter).pEngineChannel == pEngineChannel) {
178                VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
179                pEngineChannel->Disconnect(pMidiListener);
180                channelMidiListeners.erase(iter);
181                delete pMidiListener;
182                return;
183            }
184        }
185    }
186    
187    void LSCPServer::EventHandler::EngineChanged(int ChannelId) {
188        SamplerChannel* pSamplerChannel =
189            pParent->pSampler->GetSamplerChannel(ChannelId);
190        if (!pSamplerChannel) return;
191        EngineChannel* pEngineChannel =
192            pSamplerChannel->GetEngineChannel();
193        if (!pEngineChannel) return;
194        VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
195        pEngineChannel->Connect(pMidiListener);
196        midi_listener_entry entry = {
197            pSamplerChannel, pEngineChannel, pMidiListener
198        };
199        channelMidiListeners.push_back(entry);
200    }
201    
202    void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {
203        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));
204    }
205    
206    void LSCPServer::EventHandler::MidiDeviceCountChanged(int NewCount) {
207        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));
208    }
209    
210    void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {
211        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));
212    }
213    
214    void LSCPServer::EventHandler::MidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
215        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_info, MapId, Bank, Program));
216    }
217    
218    void LSCPServer::EventHandler::MidiInstrumentMapCountChanged(int NewCount) {
219        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, NewCount));
220    }
221    
222    void LSCPServer::EventHandler::MidiInstrumentMapInfoChanged(int MapId) {
223        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_info, MapId));
224    }
225    
226    void LSCPServer::EventHandler::FxSendCountChanged(int ChannelId, int NewCount) {
227        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_count, ChannelId, NewCount));
228    }
229    
230    void LSCPServer::EventHandler::VoiceCountChanged(int ChannelId, int NewCount) {
231        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, ChannelId, NewCount));
232    }
233    
234    void LSCPServer::EventHandler::StreamCountChanged(int ChannelId, int NewCount) {
235        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, ChannelId, NewCount));
236    }
237    
238    void LSCPServer::EventHandler::BufferFillChanged(int ChannelId, String FillData) {
239        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, ChannelId, FillData));
240    }
241    
242    void LSCPServer::EventHandler::TotalVoiceCountChanged(int NewCount) {
243        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));
244    }
245    
246    void LSCPServer::EventHandler::TotalStreamCountChanged(int NewCount) {
247        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_stream_count, NewCount));
248    }
249    
250    #if HAVE_SQLITE3
251    void LSCPServer::DbInstrumentsEventHandler::DirectoryCountChanged(String Dir) {
252        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_count, InstrumentsDb::toEscapedPath(Dir)));
253    }
254    
255    void LSCPServer::DbInstrumentsEventHandler::DirectoryInfoChanged(String Dir) {
256        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, InstrumentsDb::toEscapedPath(Dir)));
257    }
258    
259    void LSCPServer::DbInstrumentsEventHandler::DirectoryNameChanged(String Dir, String NewName) {
260        Dir = "'" + InstrumentsDb::toEscapedPath(Dir) + "'";
261        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
262        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, "NAME", Dir, NewName));
263    }
264    
265    void LSCPServer::DbInstrumentsEventHandler::InstrumentCountChanged(String Dir) {
266        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_count, InstrumentsDb::toEscapedPath(Dir)));
267    }
268    
269    void LSCPServer::DbInstrumentsEventHandler::InstrumentInfoChanged(String Instr) {
270        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, InstrumentsDb::toEscapedPath(Instr)));
271    }
272    
273    void LSCPServer::DbInstrumentsEventHandler::InstrumentNameChanged(String Instr, String NewName) {
274        Instr = "'" + InstrumentsDb::toEscapedPath(Instr) + "'";
275        NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
276        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, "NAME", Instr, NewName));
277    }
278    
279    void LSCPServer::DbInstrumentsEventHandler::JobStatusChanged(int JobId) {
280        LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instrs_job_info, JobId));
281    }
282    #endif // HAVE_SQLITE3
283    
284    
285    /**
286     * Blocks the calling thread until the LSCP Server is initialized and
287     * accepting socket connections, if the server is already initialized then
288     * this method will return immediately.
289     * @param TimeoutSeconds     - optional: max. wait time in seconds
290     *                             (default: 0s)
291     * @param TimeoutNanoSeconds - optional: max wait time in nano seconds
292     *                             (default: 0ns)
293     * @returns  0 on success, a value less than 0 if timeout exceeded
294     */
295    int LSCPServer::WaitUntilInitialized(long TimeoutSeconds, long TimeoutNanoSeconds) {
296        return Initialized.WaitAndUnlockIf(false, TimeoutSeconds, TimeoutNanoSeconds);
297  }  }
298    
299  int LSCPServer::Main() {  int LSCPServer::Main() {
300            #if defined(WIN32)
301            WSADATA wsaData;
302            int iResult;
303            iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
304            if (iResult != 0) {
305                    std::cerr << "LSCPServer: WSAStartup failed: " << iResult << "\n";
306                    exit(EXIT_FAILURE);
307            }
308            #endif
309      hSocket = socket(AF_INET, SOCK_STREAM, 0);      hSocket = socket(AF_INET, SOCK_STREAM, 0);
310      if (hSocket < 0) {      if (hSocket < 0) {
311          std::cerr << "LSCPServer: Could not create server socket." << std::endl;          std::cerr << "LSCPServer: Could not create server socket." << std::endl;
# Line 36  int LSCPServer::Main() { Line 313  int LSCPServer::Main() {
313          exit(EXIT_FAILURE);          exit(EXIT_FAILURE);
314      }      }
315    
     SocketAddress.sin_family      = AF_INET;  
     SocketAddress.sin_port        = htons(LSCP_PORT);  
     SocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);  
   
316      if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {      if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
317          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...";
318          close(hSocket);          for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds
319          //return -1;              if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
320          exit(EXIT_FAILURE);                  if (trial > LSCP_SERVER_BIND_TIMEOUT) {
321                        std::cerr << "gave up!" << std::endl;
322                        #if defined(WIN32)
323                        closesocket(hSocket);
324                        #else
325                        close(hSocket);
326                        #endif
327                        //return -1;
328                        exit(EXIT_FAILURE);
329                    }
330                    else sleep(1); // sleep 1s
331                }
332                else break; // success
333            }
334      }      }
335    
336      listen(hSocket, 1);      listen(hSocket, 1);
337      dmsg(1,("LSCPServer: Server running.\n")); // server running      Initialized.Set(true);
338    
339        // Registering event listeners
340        pSampler->AddChannelCountListener(&eventHandler);
341        pSampler->AddAudioDeviceCountListener(&eventHandler);
342        pSampler->AddMidiDeviceCountListener(&eventHandler);
343        pSampler->AddVoiceCountListener(&eventHandler);
344        pSampler->AddStreamCountListener(&eventHandler);
345        pSampler->AddBufferFillListener(&eventHandler);
346        pSampler->AddTotalStreamCountListener(&eventHandler);
347        pSampler->AddTotalVoiceCountListener(&eventHandler);
348        pSampler->AddFxSendCountListener(&eventHandler);
349        MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);
350        MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);
351        MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);
352        MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);
353    #if HAVE_SQLITE3
354        InstrumentsDb::GetInstrumentsDb()->AddInstrumentsDbListener(&dbInstrumentsEventHandler);
355    #endif
356      // now wait for client connections and handle their requests      // now wait for client connections and handle their requests
357      sockaddr_in client;      sockaddr_in client;
358      int length = sizeof(client);      int length = sizeof(client);
359        FD_ZERO(&fdSet);
360        FD_SET(hSocket, &fdSet);
361        int maxSessions = hSocket;
362    
363        timeval timeout;
364    
365      while (true) {      while (true) {
366          hSession = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);          #if CONFIG_PTHREAD_TESTCANCEL
367          if (hSession < 0) {                  TestCancel();
368              std::cerr << "LSCPServer: Client connection failed." << std::endl;          #endif
369              close(hSocket);          // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
370              //return -1;          {
371              exit(EXIT_FAILURE);              std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
372          }              std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
373                std::set<EngineChannel*>::iterator itEnd           = engineChannels.end();
374          dmsg(1,("LSCPServer: Client connection established.\n"));              for (; itEngineChannel != itEnd; ++itEngineChannel) {
375          //send(hSession, "Welcome!\r\n", 10, 0);                  if ((*itEngineChannel)->StatusChanged()) {
376                        SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->iSamplerChannelIndex));
377          // Parser invocation                  }
378          yyparse_param_t yyparse_param;  
379          yyparse_param.pServer = this;                  for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
380          yylex_init(&yyparse_param.pScanner);                      FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
381          while (yyparse(&yyparse_param) == LSCP_SYNTAX_ERROR); // recall parser in case of syntax error                      if(fxs != NULL && fxs->IsInfoChanged()) {
382          yylex_destroy(yyparse_param.pScanner);                          int chn = (*itEngineChannel)->iSamplerChannelIndex;
383                            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));
384                            fxs->SetInfoChanged(false);
385                        }
386                    }
387                }
388            }
389    
390          close(hSession);          // check if MIDI data arrived on some engine channel
391          dmsg(1,("LSCPServer: Client connection terminated.\n"));          for (int i = 0; i < eventHandler.channelMidiListeners.size(); ++i) {
392      }              const EventHandler::midi_listener_entry entry =
393                    eventHandler.channelMidiListeners[i];
394                VirtualMidiDevice* pMidiListener = entry.pMidiListener;
395                if (pMidiListener->NotesChanged()) {
396                    for (int iNote = 0; iNote < 128; iNote++) {
397                        if (pMidiListener->NoteChanged(iNote)) {
398                            const bool bActive = pMidiListener->NoteIsActive(iNote);
399                            LSCPServer::SendLSCPNotify(
400                                LSCPEvent(
401                                    LSCPEvent::event_channel_midi,
402                                    entry.pSamplerChannel->Index(),
403                                    std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
404                                    iNote,
405                                    bActive ? pMidiListener->NoteOnVelocity(iNote)
406                                            : pMidiListener->NoteOffVelocity(iNote)
407                                )
408                            );
409                        }
410                    }
411                }
412            }
413    
414            //Now let's deliver late notifies (if any)
415            NotifyBufferMutex.Lock();
416            for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
417    #ifdef MSG_NOSIGNAL
418                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
419    #else
420                    send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
421    #endif
422            }
423            bufferedNotifies.clear();
424            NotifyBufferMutex.Unlock();
425    
426            fd_set selectSet = fdSet;
427            timeout.tv_sec  = 0;
428            timeout.tv_usec = 100000;
429    
430            int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
431    
432            if (retval == 0)
433                    continue; //Nothing try again
434            if (retval == -1) {
435                    std::cerr << "LSCPServer: Socket select error." << std::endl;
436                    #if defined(WIN32)
437                    closesocket(hSocket);
438                    #else
439                    close(hSocket);
440                    #endif
441                    exit(EXIT_FAILURE);
442            }
443    
444            //Accept new connections now (if any)
445            if (FD_ISSET(hSocket, &selectSet)) {
446                    int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
447                    if (socket < 0) {
448                            std::cerr << "LSCPServer: Client connection failed." << std::endl;
449                            exit(EXIT_FAILURE);
450                    }
451    
452                    #if defined(WIN32)
453                    u_long nonblock_io = 1;
454                    if( ioctlsocket(socket, FIONBIO, &nonblock_io) ) {
455                      std::cerr << "LSCPServer: ioctlsocket: set FIONBIO failed. Error " << WSAGetLastError() << std::endl;
456                      exit(EXIT_FAILURE);
457                    }
458            #else
459                    if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
460                            std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
461                            exit(EXIT_FAILURE);
462                    }
463                    #endif
464    
465                    // Parser initialization
466                    yyparse_param_t yyparse_param;
467                    yyparse_param.pServer  = this;
468                    yyparse_param.hSession = socket;
469    
470                    Sessions.push_back(yyparse_param);
471                    FD_SET(socket, &fdSet);
472                    if (socket > maxSessions)
473                            maxSessions = socket;
474                    dmsg(1,("LSCPServer: Client connection established on socket:%d.\n", socket));
475                    LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection established on socket", socket));
476                    continue; //Maybe this was the only selected socket, better select again
477            }
478    
479            //Something was selected and it was not the hSocket, so it must be some command(s) coming.
480            for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
481                    if (FD_ISSET((*iter).hSession, &selectSet)) {   //Was it this socket?
482                            if (GetLSCPCommand(iter)) {     //Have we read the entire command?
483                                    dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
484                                    int dummy; // just a temporary hack to fulfill the restart() function prototype
485                                    restart(NULL, dummy); // restart the 'scanner'
486                                    currentSocket = (*iter).hSession;  //a hack
487                                    itCurrentSession = iter; // another hack
488                                    dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
489                                    if ((*iter).bVerbose) { // if echo mode enabled
490                                        AnswerClient(bufferedCommands[currentSocket]);
491                                    }
492                                    int result = yyparse(&(*iter));
493                                    currentSocket = -1;     //continuation of a hack
494                                    itCurrentSession = Sessions.end(); // hack as well
495                                    dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
496                                    if (result == LSCP_QUIT) { //Was it a quit command by any chance?
497                                            CloseConnection(iter);
498                                    }
499                            }
500                            //socket may have been closed, iter may be invalid, get out of the loop for now.
501                            //we'll be back if there is data.
502                            break;
503                    }
504            }
505        }
506    }
507    
508    void LSCPServer::CloseConnection( std::vector<yyparse_param_t>::iterator iter ) {
509            int socket = (*iter).hSession;
510            dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));
511            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
512            Sessions.erase(iter);
513            FD_CLR(socket,  &fdSet);
514            SubscriptionMutex.Lock(); //Must unsubscribe this socket from all events (if any)
515            for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
516                    iter->second.remove(socket);
517            }
518            SubscriptionMutex.Unlock();
519            NotifyMutex.Lock();
520            bufferedCommands.erase(socket);
521            bufferedNotifies.erase(socket);
522            #if defined(WIN32)
523            closesocket(socket);
524            #else
525            close(socket);
526            #endif
527            NotifyMutex.Unlock();
528    }
529    
530    void LSCPServer::LockRTNotify() {
531        RTNotifyMutex.Lock();
532    }
533    
534    void LSCPServer::UnlockRTNotify() {
535        RTNotifyMutex.Unlock();
536    }
537    
538    int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {
539            int subs = 0;
540            SubscriptionMutex.Lock();
541            for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();
542                            iter != events.end(); iter++)
543            {
544                    subs += eventSubscriptions.count(*iter);
545            }
546            SubscriptionMutex.Unlock();
547            return subs;
548    }
549    
550    void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
551            SubscriptionMutex.Lock();
552            if (eventSubscriptions.count(event.GetType()) == 0) {
553                    SubscriptionMutex.Unlock();     //Nobody is subscribed to this event
554                    return;
555            }
556            std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();
557            std::list<int>::iterator end = eventSubscriptions[event.GetType()].end();
558            String notify = event.Produce();
559    
560            while (true) {
561                    if (NotifyMutex.Trylock()) {
562                            for(;iter != end; iter++)
563    #ifdef MSG_NOSIGNAL
564                                    send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
565    #else
566                                    send(*iter, notify.c_str(), notify.size(), 0);
567    #endif
568                            NotifyMutex.Unlock();
569                            break;
570                    } else {
571                            if (NotifyBufferMutex.Trylock()) {
572                                    for(;iter != end; iter++)
573                                            bufferedNotifies[*iter] += notify;
574                                    NotifyBufferMutex.Unlock();
575                                    break;
576                            }
577                    }
578            }
579            SubscriptionMutex.Unlock();
580    }
581    
582    extern int GetLSCPCommand( void *buf, int max_size ) {
583            String command = LSCPServer::bufferedCommands[LSCPServer::currentSocket];
584            if (command.size() == 0) {              //Parser wants input but we have nothing.
585                    strcpy((char*) buf, "\n");      //So give it an empty command
586                    return 1;                       //to keep it happy.
587            }
588    
589            if (max_size < command.size()) {
590                    std::cerr << "getLSCPCommand: Flex buffer too small, ignoring the command." << std::endl;
591                    return 0;       //This will never happen
592            }
593    
594            strcpy((char*) buf, command.c_str());
595            LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);
596            return command.size();
597    }
598    
599    extern yyparse_param_t* GetCurrentYaccSession() {
600        return &(*itCurrentSession);
601    }
602    
603    /**
604     * Will be called to try to read the command from the socket
605     * If command is read, it will return true. Otherwise false is returned.
606     * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.
607     */
608    bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
609            int socket = (*iter).hSession;
610            char c;
611            int i = 0;
612            while (true) {
613                    #if defined(WIN32)
614                    int result = recv(socket, (char *)&c, 1, 0); //Read one character at a time for now
615                    #else
616                    int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now
617                    #endif
618                    if (result == 0) { //socket was selected, so 0 here means client has closed the connection
619                            CloseConnection(iter);
620                            break;
621                    }
622                    if (result == 1) {
623                            if (c == '\r')
624                                    continue; //Ignore CR
625                            if (c == '\n') {
626                                    LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
627                                    bufferedCommands[socket] += "\r\n";
628                                    return true; //Complete command was read
629                            }
630                            bufferedCommands[socket] += c;
631                    }
632                    #if defined(WIN32)
633                    if (result == SOCKET_ERROR) {
634                        int wsa_lasterror = WSAGetLastError();
635                            if (wsa_lasterror == WSAEWOULDBLOCK) //Would block, try again later.
636                                    return false;
637                            dmsg(2,("LSCPScanner: Socket error after recv() Error %d.\n", wsa_lasterror));
638                            CloseConnection(iter);
639                            break;
640                    }
641                    #else
642                    if (result == -1) {
643                            if (errno == EAGAIN) //Would block, try again later.
644                                    return false;
645                            switch(errno) {
646                                    case EBADF:
647                                            dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
648                                            break;
649                                    case ECONNREFUSED:
650                                            dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
651                                            break;
652                                    case ENOTCONN:
653                                            dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
654                                            break;
655                                    case ENOTSOCK:
656                                            dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
657                                            break;
658                                    case EAGAIN:
659                                            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"));
660                                            break;
661                                    case EINTR:
662                                            dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
663                                            break;
664                                    case EFAULT:
665                                            dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
666                                            break;
667                                    case EINVAL:
668                                            dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
669                                            break;
670                                    case ENOMEM:
671                                            dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
672                                            break;
673                                    default:
674                                            dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
675                                            break;
676                            }
677                            CloseConnection(iter);
678                            break;
679                    }
680                    #endif
681            }
682            return false;
683  }  }
684    
685  /**  /**
# Line 85  int LSCPServer::Main() { Line 690  int LSCPServer::Main() {
690   */   */
691  void LSCPServer::AnswerClient(String ReturnMessage) {  void LSCPServer::AnswerClient(String ReturnMessage) {
692      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));      dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
693      send(hSession, ReturnMessage.c_str(), ReturnMessage.size(), 0);      if (currentSocket != -1) {
694                NotifyMutex.Lock();
695    #ifdef MSG_NOSIGNAL
696                send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
697    #else
698                send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
699    #endif
700                NotifyMutex.Unlock();
701        }
702    }
703    
704    /**
705     * Find a created audio output device index.
706     */
707    int LSCPServer::GetAudioOutputDeviceIndex ( AudioOutputDevice *pDevice )
708    {
709        // Search for the created device to get its index
710        std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
711        std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
712        for (; iter != devices.end(); iter++) {
713            if (iter->second == pDevice)
714                return iter->first;
715        }
716        // Not found.
717        return -1;
718    }
719    
720    /**
721     * Find a created midi input device index.
722     */
723    int LSCPServer::GetMidiInputDeviceIndex ( MidiInputDevice *pDevice )
724    {
725        // Search for the created device to get its index
726        std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
727        std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
728        for (; iter != devices.end(); iter++) {
729            if (iter->second == pDevice)
730                return iter->first;
731        }
732        // Not found.
733        return -1;
734    }
735    
736    String LSCPServer::CreateAudioOutputDevice(String Driver, std::map<String,String> Parameters) {
737        dmsg(2,("LSCPServer: CreateAudioOutputDevice(Driver=%s)\n", Driver.c_str()));
738        LSCPResultSet result;
739        try {
740            AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
741            // search for the created device to get its index
742            int index = GetAudioOutputDeviceIndex(pDevice);
743            if (index == -1) throw Exception("Internal error: could not find created audio output device.");
744            result = index; // success
745        }
746        catch (Exception e) {
747            result.Error(e);
748        }
749        return result.Produce();
750    }
751    
752    String LSCPServer::CreateMidiInputDevice(String Driver, std::map<String,String> Parameters) {
753        dmsg(2,("LSCPServer: CreateMidiInputDevice(Driver=%s)\n", Driver.c_str()));
754        LSCPResultSet result;
755        try {
756            MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
757            // search for the created device to get its index
758            int index = GetMidiInputDeviceIndex(pDevice);
759            if (index == -1) throw Exception("Internal error: could not find created midi input device.");
760            result = index; // success
761        }
762        catch (Exception e) {
763            result.Error(e);
764        }
765        return result.Produce();
766    }
767    
768    String LSCPServer::DestroyAudioOutputDevice(uint DeviceIndex) {
769        dmsg(2,("LSCPServer: DestroyAudioOutputDevice(DeviceIndex=%d)\n", DeviceIndex));
770        LSCPResultSet result;
771        try {
772            std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
773            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
774            AudioOutputDevice* pDevice = devices[DeviceIndex];
775            pSampler->DestroyAudioOutputDevice(pDevice);
776        }
777        catch (Exception e) {
778            result.Error(e);
779        }
780        return result.Produce();
781    }
782    
783    String LSCPServer::DestroyMidiInputDevice(uint DeviceIndex) {
784        dmsg(2,("LSCPServer: DestroyMidiInputDevice(DeviceIndex=%d)\n", DeviceIndex));
785        LSCPResultSet result;
786        try {
787            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
788            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
789            MidiInputDevice* pDevice = devices[DeviceIndex];
790            pSampler->DestroyMidiInputDevice(pDevice);
791        }
792        catch (Exception e) {
793            result.Error(e);
794        }
795        return result.Produce();
796    }
797    
798    EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
799        SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
800        if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
801    
802        EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
803        if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
804    
805        return pEngineChannel;
806  }  }
807    
808  /**  /**
809   * Will be called by the parser to load an instrument.   * Will be called by the parser to load an instrument.
810   */   */
811  String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel) {  String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel, bool bBackground) {
812      dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));      dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
813      result_t result;      LSCPResultSet result;
814      try {      try {
815          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
816          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
817          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
818          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
819          pEngine->LoadInstrument(Filename.c_str(), uiInstrument);          if (!pSamplerChannel->GetAudioOutputDevice())
820          result.type = result_type_success;              throw Exception("No audio output device connected to sampler channel");
821            if (bBackground) {
822                InstrumentManager::instrument_id_t id;
823                id.FileName = Filename;
824                id.Index    = uiInstrument;
825                InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
826            }
827            else {
828                // tell the engine channel which instrument to load
829                pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrument);
830                // actually start to load the instrument (blocks until completed)
831                pEngineChannel->LoadInstrument();
832            }
833      }      }
834      catch (LinuxSamplerException e) {      catch (Exception e) {
835           e.PrintMessage();           result.Error(e);
          result.type    = result_type_error;  
          result.code    = LSCP_ERR_UNKNOWN;  
          result.message = e.Message();  
836      }      }
837      return ConvertResult(result);      return result.Produce();
838  }  }
839    
840  /**  /**
841   * 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
842     * sampler channel.
843   */   */
844  String LSCPServer::LoadEngine(String EngineName, uint uiSamplerChannel) {  String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
845      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));
846      result_t result;      LSCPResultSet result;
847      try {      try {
         engine_type_t type;  
         if (EngineName == "gig") type = engine_type_gig;  
         else throw LinuxSamplerException("Unknown engine type");  
848          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
849          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
850          pSamplerChannel->LoadEngine(type);          LockRTNotify();
851          result.type = result_type_success;          pSamplerChannel->SetEngineType(EngineName);
852            if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
853            UnlockRTNotify();
854      }      }
855      catch (LinuxSamplerException e) {      catch (Exception e) {
856           e.PrintMessage();           result.Error(e);
          result.type    = result_type_error;  
          result.code    = LSCP_ERR_UNKNOWN;  
          result.message = e.Message();  
857      }      }
858      return ConvertResult(result);      return result.Produce();
859  }  }
860    
861  /**  /**
# Line 140  String LSCPServer::LoadEngine(String Eng Line 863  String LSCPServer::LoadEngine(String Eng
863   */   */
864  String LSCPServer::GetChannels() {  String LSCPServer::GetChannels() {
865      dmsg(2,("LSCPServer: GetChannels()\n"));      dmsg(2,("LSCPServer: GetChannels()\n"));
866      return ToString(pSampler->SamplerChannels()) + "\r\n";      LSCPResultSet result;
867        result.Add(pSampler->SamplerChannels());
868        return result.Produce();
869    }
870    
871    /**
872     * Will be called by the parser to get the list of sampler channels.
873     */
874    String LSCPServer::ListChannels() {
875        dmsg(2,("LSCPServer: ListChannels()\n"));
876        String list;
877        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
878        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
879        for (; iter != channels.end(); iter++) {
880            if (list != "") list += ",";
881            list += ToString(iter->first);
882        }
883        LSCPResultSet result;
884        result.Add(list);
885        return result.Produce();
886  }  }
887    
888  /**  /**
# Line 148  String LSCPServer::GetChannels() { Line 890  String LSCPServer::GetChannels() {
890   */   */
891  String LSCPServer::AddChannel() {  String LSCPServer::AddChannel() {
892      dmsg(2,("LSCPServer: AddChannel()\n"));      dmsg(2,("LSCPServer: AddChannel()\n"));
893        LockRTNotify();
894      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();      SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
895      return "OK[" + ToString(pSamplerChannel->Index()) + "]\r\n";      UnlockRTNotify();
896        LSCPResultSet result(pSamplerChannel->Index());
897        return result.Produce();
898  }  }
899    
900  /**  /**
# Line 157  String LSCPServer::AddChannel() { Line 902  String LSCPServer::AddChannel() {
902   */   */
903  String LSCPServer::RemoveChannel(uint uiSamplerChannel) {  String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
904      dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
905        LSCPResultSet result;
906        LockRTNotify();
907      pSampler->RemoveSamplerChannel(uiSamplerChannel);      pSampler->RemoveSamplerChannel(uiSamplerChannel);
908      return "OK\r\n";      UnlockRTNotify();
909        return result.Produce();
910  }  }
911    
912  /**  /**
913   * 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.
914   */   */
915  String LSCPServer::GetAvailableEngines() {  String LSCPServer::GetAvailableEngines() {
916      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));      dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
917      return "gig\r\n";      LSCPResultSet result;
918        try {
919            int n = EngineFactory::AvailableEngineTypes().size();
920            result.Add(n);
921        }
922        catch (Exception e) {
923            result.Error(e);
924        }
925        return result.Produce();
926  }  }
927    
928  /**  /**
929   * 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.
930     */
931    String LSCPServer::ListAvailableEngines() {
932        dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
933        LSCPResultSet result;
934        try {
935            String s = EngineFactory::AvailableEngineTypesAsString();
936            result.Add(s);
937        }
938        catch (Exception e) {
939            result.Error(e);
940        }
941        return result.Produce();
942    }
943    
944    /**
945     * Will be called by the parser to get descriptions for a particular
946     * sampler engine.
947   */   */
948  String LSCPServer::GetEngineInfo(String EngineName) {  String LSCPServer::GetEngineInfo(String EngineName) {
949      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));      dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
950      result_t result;      LSCPResultSet result;
951        LockRTNotify();
952      try {      try {
953          if (EngineName == "gig") {          Engine* pEngine = EngineFactory::Create(EngineName);
954              Engine* pEngine = new LinuxSampler::gig::Engine;          result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
955              String info = pEngine->Description() + "\r\n";          result.Add("VERSION",     pEngine->Version());
956              delete pEngine;          EngineFactory::Destroy(pEngine);
             return info; // success  
         }  
         else throw LinuxSamplerException("Unknown engine type");  
     }  
     catch (LinuxSamplerException e) {  
          e.PrintMessage();  
          result.type    = result_type_error;  
          result.code    = LSCP_ERR_UNKNOWN;  
          result.message = e.Message();  
957      }      }
958      return ConvertResult(result);      catch (Exception e) {
959             result.Error(e);
960        }
961        UnlockRTNotify();
962        return result.Produce();
963  }  }
964    
965  /**  /**
# Line 199  String LSCPServer::GetEngineInfo(String Line 968  String LSCPServer::GetEngineInfo(String
968   */   */
969  String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {  String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
970      dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
971      return "ERR:0:Not implemented yet.\r\n";      LSCPResultSet result;
972        try {
973            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
974            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
975            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
976    
977            //Defaults values
978            String EngineName = "NONE";
979            float Volume = 0.0f;
980            String InstrumentFileName = "NONE";
981            String InstrumentName = "NONE";
982            int InstrumentIndex = -1;
983            int InstrumentStatus = -1;
984            int AudioOutputChannels = 0;
985            String AudioRouting;
986            int Mute = 0;
987            bool Solo = false;
988            String MidiInstrumentMap = "NONE";
989    
990            if (pEngineChannel) {
991                EngineName          = pEngineChannel->EngineName();
992                AudioOutputChannels = pEngineChannel->Channels();
993                Volume              = pEngineChannel->Volume();
994                InstrumentStatus    = pEngineChannel->InstrumentStatus();
995                InstrumentIndex     = pEngineChannel->InstrumentIndex();
996                if (InstrumentIndex != -1) {
997                    InstrumentFileName = pEngineChannel->InstrumentFileName();
998                    InstrumentName     = pEngineChannel->InstrumentName();
999                }
1000                for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
1001                    if (AudioRouting != "") AudioRouting += ",";
1002                    AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
1003                }
1004                Mute = pEngineChannel->GetMute();
1005                Solo = pEngineChannel->GetSolo();
1006                if (pEngineChannel->UsesNoMidiInstrumentMap())
1007                    MidiInstrumentMap = "NONE";
1008                else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
1009                    MidiInstrumentMap = "DEFAULT";
1010                else
1011                    MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
1012            }
1013    
1014            result.Add("ENGINE_NAME", EngineName);
1015            result.Add("VOLUME", Volume);
1016    
1017            //Some not-so-hardcoded stuff to make GUI look good
1018            result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
1019            result.Add("AUDIO_OUTPUT_CHANNELS", AudioOutputChannels);
1020            result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
1021    
1022            result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
1023            result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
1024            if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
1025            else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
1026    
1027            // convert the filename into the correct encoding as defined for LSCP
1028            // (especially in terms of special characters -> escape sequences)
1029            if (InstrumentFileName != "NONE" && InstrumentFileName != "") {
1030    #if WIN32
1031                InstrumentFileName = Path::fromWindows(InstrumentFileName).toLscp();
1032    #else
1033                // assuming POSIX
1034                InstrumentFileName = Path::fromPosix(InstrumentFileName).toLscp();
1035    #endif
1036            }
1037    
1038            result.Add("INSTRUMENT_FILE", InstrumentFileName);
1039            result.Add("INSTRUMENT_NR", InstrumentIndex);
1040            result.Add("INSTRUMENT_NAME", _escapeLscpResponse(InstrumentName));
1041            result.Add("INSTRUMENT_STATUS", InstrumentStatus);
1042            result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
1043            result.Add("SOLO", Solo);
1044            result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
1045        }
1046        catch (Exception e) {
1047             result.Error(e);
1048        }
1049        return result.Produce();
1050  }  }
1051    
1052  /**  /**
# Line 208  String LSCPServer::GetChannelInfo(uint u Line 1055  String LSCPServer::GetChannelInfo(uint u
1055   */   */
1056  String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {  String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
1057      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
1058      result_t result;      LSCPResultSet result;
1059      try {      try {
1060          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1061          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1062          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1063          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine loaded on sampler channel");
1064          return ToString(pEngine->VoiceCount()) + "\r\n"; // success          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1065            result.Add(pEngineChannel->GetEngine()->VoiceCount());
1066      }      }
1067      catch (LinuxSamplerException e) {      catch (Exception e) {
1068           e.PrintMessage();           result.Error(e);
          result.type    = result_type_error;  
          result.code    = LSCP_ERR_UNKNOWN;  
          result.message = e.Message();  
1069      }      }
1070      return ConvertResult(result);      return result.Produce();
1071  }  }
1072    
1073  /**  /**
# Line 231  String LSCPServer::GetVoiceCount(uint ui Line 1076  String LSCPServer::GetVoiceCount(uint ui
1076   */   */
1077  String LSCPServer::GetStreamCount(uint uiSamplerChannel) {  String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
1078      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
1079      result_t result;      LSCPResultSet result;
1080      try {      try {
1081          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1082          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1083          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1084          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1085          return ToString(pEngine->DiskStreamCount()) + "\r\n"; // success          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1086            result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
1087      }      }
1088      catch (LinuxSamplerException e) {      catch (Exception e) {
1089           e.PrintMessage();           result.Error(e);
          result.type    = result_type_error;  
          result.code    = LSCP_ERR_UNKNOWN;  
          result.message = e.Message();  
1090      }      }
1091      return ConvertResult(result);      return result.Produce();
1092  }  }
1093    
1094  /**  /**
# Line 254  String LSCPServer::GetStreamCount(uint u Line 1097  String LSCPServer::GetStreamCount(uint u
1097   */   */
1098  String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {  String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
1099      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));      dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
1100      result_t result;      LSCPResultSet result;
1101      try {      try {
1102          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1103          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1104          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1105          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1106          if (!pEngine->DiskStreamSupported()) return "NA\r\n";          if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1107          switch (ResponseType) {          if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
1108              case fill_response_bytes:          else {
1109                  return ToString(pEngine->DiskStreamBufferFillBytes()) + "\r\n"; // success              switch (ResponseType) {
1110              case fill_response_percentage:                  case fill_response_bytes:
1111                  return ToString(pEngine->DiskStreamBufferFillPercentage()) + "\r\n"; // success                      result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillBytes());
1112              default:                      break;
1113                  throw LinuxSamplerException("Unknown fill response type");                  case fill_response_percentage:
1114                        result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
1115                        break;
1116                    default:
1117                        throw Exception("Unknown fill response type");
1118                }
1119            }
1120        }
1121        catch (Exception e) {
1122             result.Error(e);
1123        }
1124        return result.Produce();
1125    }
1126    
1127    String LSCPServer::GetAvailableAudioOutputDrivers() {
1128        dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
1129        LSCPResultSet result;
1130        try {
1131            int n = AudioOutputDeviceFactory::AvailableDrivers().size();
1132            result.Add(n);
1133        }
1134        catch (Exception e) {
1135            result.Error(e);
1136        }
1137        return result.Produce();
1138    }
1139    
1140    String LSCPServer::ListAvailableAudioOutputDrivers() {
1141        dmsg(2,("LSCPServer: ListAvailableAudioOutputDrivers()\n"));
1142        LSCPResultSet result;
1143        try {
1144            String s = AudioOutputDeviceFactory::AvailableDriversAsString();
1145            result.Add(s);
1146        }
1147        catch (Exception e) {
1148            result.Error(e);
1149        }
1150        return result.Produce();
1151    }
1152    
1153    String LSCPServer::GetAvailableMidiInputDrivers() {
1154        dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
1155        LSCPResultSet result;
1156        try {
1157            int n = MidiInputDeviceFactory::AvailableDrivers().size();
1158            result.Add(n);
1159        }
1160        catch (Exception e) {
1161            result.Error(e);
1162        }
1163        return result.Produce();
1164    }
1165    
1166    String LSCPServer::ListAvailableMidiInputDrivers() {
1167        dmsg(2,("LSCPServer: ListAvailableMidiInputDrivers()\n"));
1168        LSCPResultSet result;
1169        try {
1170            String s = MidiInputDeviceFactory::AvailableDriversAsString();
1171            result.Add(s);
1172        }
1173        catch (Exception e) {
1174            result.Error(e);
1175        }
1176        return result.Produce();
1177    }
1178    
1179    String LSCPServer::GetMidiInputDriverInfo(String Driver) {
1180        dmsg(2,("LSCPServer: GetMidiInputDriverInfo(Driver=%s)\n",Driver.c_str()));
1181        LSCPResultSet result;
1182        try {
1183            result.Add("DESCRIPTION", MidiInputDeviceFactory::GetDriverDescription(Driver));
1184            result.Add("VERSION",     MidiInputDeviceFactory::GetDriverVersion(Driver));
1185    
1186            std::map<String,DeviceCreationParameter*> parameters = MidiInputDeviceFactory::GetAvailableDriverParameters(Driver);
1187            if (parameters.size()) { // if there are parameters defined for this driver
1188                String s;
1189                std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1190                for (;iter != parameters.end(); iter++) {
1191                    if (s != "") s += ",";
1192                    s += iter->first;
1193                }
1194                result.Add("PARAMETERS", s);
1195          }          }
1196      }      }
1197      catch (LinuxSamplerException e) {      catch (Exception e) {
1198           e.PrintMessage();          result.Error(e);
          result.type    = result_type_error;  
          result.code    = LSCP_ERR_UNKNOWN;  
          result.message = e.Message();  
1199      }      }
1200      return ConvertResult(result);      return result.Produce();
1201  }  }
1202    
1203  /**  String LSCPServer::GetAudioOutputDriverInfo(String Driver) {
1204   * Will be called by the parser to change the audio output type on a      dmsg(2,("LSCPServer: GetAudioOutputDriverInfo(Driver=%s)\n",Driver.c_str()));
1205   * particular sampler channel.      LSCPResultSet result;
1206   */      try {
1207  String LSCPServer::SetAudioOutputType(audio_output_type_t AudioOutputType, uint uiSamplerChannel) {          result.Add("DESCRIPTION", AudioOutputDeviceFactory::GetDriverDescription(Driver));
1208      dmsg(2,("LSCPServer: SetAudioOutputType(AudioOutputType=%d, SamplerChannel=%d)\n", AudioOutputType, uiSamplerChannel));          result.Add("VERSION",     AudioOutputDeviceFactory::GetDriverVersion(Driver));
1209      result_t result;  
1210      try {          std::map<String,DeviceCreationParameter*> parameters = AudioOutputDeviceFactory::GetAvailableDriverParameters(Driver);
1211          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          if (parameters.size()) { // if there are parameters defined for this driver
1212          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");              String s;
1213          pSamplerChannel->SetAudioOutputDevice(AudioOutputType);              std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1214          result.type = result_type_success;              for (;iter != parameters.end(); iter++) {
1215      }                  if (s != "") s += ",";
1216      catch (LinuxSamplerException e) {                  s += iter->first;
1217           e.PrintMessage();              }
1218           result.type    = result_type_error;              result.Add("PARAMETERS", s);
1219           result.code    = LSCP_ERR_UNKNOWN;          }
1220           result.message = e.Message();      }
1221        catch (Exception e) {
1222            result.Error(e);
1223        }
1224        return result.Produce();
1225    }
1226    
1227    String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1228        dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
1229        LSCPResultSet result;
1230        try {
1231            DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
1232            result.Add("TYPE",         pParameter->Type());
1233            result.Add("DESCRIPTION",  pParameter->Description());
1234            result.Add("MANDATORY",    pParameter->Mandatory());
1235            result.Add("FIX",          pParameter->Fix());
1236            result.Add("MULTIPLICITY", pParameter->Multiplicity());
1237            optional<String> oDepends       = pParameter->Depends();
1238            optional<String> oDefault       = pParameter->Default(DependencyList);
1239            optional<String> oRangeMin      = pParameter->RangeMin(DependencyList);
1240            optional<String> oRangeMax      = pParameter->RangeMax(DependencyList);
1241            optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1242            if (oDepends)       result.Add("DEPENDS",       *oDepends);
1243            if (oDefault)       result.Add("DEFAULT",       *oDefault);
1244            if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1245            if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1246            if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1247        }
1248        catch (Exception e) {
1249            result.Error(e);
1250        }
1251        return result.Produce();
1252    }
1253    
1254    String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1255        dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
1256        LSCPResultSet result;
1257        try {
1258            DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
1259            result.Add("TYPE",         pParameter->Type());
1260            result.Add("DESCRIPTION",  pParameter->Description());
1261            result.Add("MANDATORY",    pParameter->Mandatory());
1262            result.Add("FIX",          pParameter->Fix());
1263            result.Add("MULTIPLICITY", pParameter->Multiplicity());
1264            optional<String> oDepends       = pParameter->Depends();
1265            optional<String> oDefault       = pParameter->Default(DependencyList);
1266            optional<String> oRangeMin      = pParameter->RangeMin(DependencyList);
1267            optional<String> oRangeMax      = pParameter->RangeMax(DependencyList);
1268            optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1269            if (oDepends)       result.Add("DEPENDS",       *oDepends);
1270            if (oDefault)       result.Add("DEFAULT",       *oDefault);
1271            if (oRangeMin)      result.Add("RANGE_MIN",     *oRangeMin);
1272            if (oRangeMax)      result.Add("RANGE_MAX",     *oRangeMax);
1273            if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1274        }
1275        catch (Exception e) {
1276            result.Error(e);
1277        }
1278        return result.Produce();
1279    }
1280    
1281    String LSCPServer::GetAudioOutputDeviceCount() {
1282        dmsg(2,("LSCPServer: GetAudioOutputDeviceCount()\n"));
1283        LSCPResultSet result;
1284        try {
1285            uint count = pSampler->AudioOutputDevices();
1286            result.Add(count); // success
1287        }
1288        catch (Exception e) {
1289            result.Error(e);
1290        }
1291        return result.Produce();
1292    }
1293    
1294    String LSCPServer::GetMidiInputDeviceCount() {
1295        dmsg(2,("LSCPServer: GetMidiInputDeviceCount()\n"));
1296        LSCPResultSet result;
1297        try {
1298            uint count = pSampler->MidiInputDevices();
1299            result.Add(count); // success
1300        }
1301        catch (Exception e) {
1302            result.Error(e);
1303        }
1304        return result.Produce();
1305    }
1306    
1307    String LSCPServer::GetAudioOutputDevices() {
1308        dmsg(2,("LSCPServer: GetAudioOutputDevices()\n"));
1309        LSCPResultSet result;
1310        try {
1311            String s;
1312            std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1313            std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1314            for (; iter != devices.end(); iter++) {
1315                if (s != "") s += ",";
1316                s += ToString(iter->first);
1317            }
1318            result.Add(s);
1319        }
1320        catch (Exception e) {
1321            result.Error(e);
1322        }
1323        return result.Produce();
1324    }
1325    
1326    String LSCPServer::GetMidiInputDevices() {
1327        dmsg(2,("LSCPServer: GetMidiInputDevices()\n"));
1328        LSCPResultSet result;
1329        try {
1330            String s;
1331            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1332            std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1333            for (; iter != devices.end(); iter++) {
1334                if (s != "") s += ",";
1335                s += ToString(iter->first);
1336            }
1337            result.Add(s);
1338        }
1339        catch (Exception e) {
1340            result.Error(e);
1341        }
1342        return result.Produce();
1343    }
1344    
1345    String LSCPServer::GetAudioOutputDeviceInfo(uint DeviceIndex) {
1346        dmsg(2,("LSCPServer: GetAudioOutputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1347        LSCPResultSet result;
1348        try {
1349            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1350            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1351            AudioOutputDevice* pDevice = devices[DeviceIndex];
1352            result.Add("DRIVER", pDevice->Driver());
1353            std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1354            std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1355            for (; iter != parameters.end(); iter++) {
1356                result.Add(iter->first, iter->second->Value());
1357            }
1358        }
1359        catch (Exception e) {
1360            result.Error(e);
1361        }
1362        return result.Produce();
1363    }
1364    
1365    String LSCPServer::GetMidiInputDeviceInfo(uint DeviceIndex) {
1366        dmsg(2,("LSCPServer: GetMidiInputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1367        LSCPResultSet result;
1368        try {
1369            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1370            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1371            MidiInputDevice* pDevice = devices[DeviceIndex];
1372            result.Add("DRIVER", pDevice->Driver());
1373            std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1374            std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1375            for (; iter != parameters.end(); iter++) {
1376                result.Add(iter->first, iter->second->Value());
1377            }
1378        }
1379        catch (Exception e) {
1380            result.Error(e);
1381        }
1382        return result.Produce();
1383    }
1384    String LSCPServer::GetMidiInputPortInfo(uint DeviceIndex, uint PortIndex) {
1385        dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
1386        LSCPResultSet result;
1387        try {
1388            // get MIDI input device
1389            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1390            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1391            MidiInputDevice* pDevice = devices[DeviceIndex];
1392    
1393            // get MIDI port
1394            MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1395            if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1396    
1397            // return the values of all MIDI port parameters
1398            std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1399            std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1400            for (; iter != parameters.end(); iter++) {
1401                result.Add(iter->first, iter->second->Value());
1402            }
1403        }
1404        catch (Exception e) {
1405            result.Error(e);
1406        }
1407        return result.Produce();
1408    }
1409    
1410    String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
1411        dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%d,ChannelId)\n",DeviceId,ChannelId));
1412        LSCPResultSet result;
1413        try {
1414            // get audio output device
1415            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1416            if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1417            AudioOutputDevice* pDevice = devices[DeviceId];
1418    
1419            // get audio channel
1420            AudioChannel* pChannel = pDevice->Channel(ChannelId);
1421            if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1422    
1423            // return the values of all audio channel parameters
1424            std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1425            std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1426            for (; iter != parameters.end(); iter++) {
1427                result.Add(iter->first, iter->second->Value());
1428            }
1429        }
1430        catch (Exception e) {
1431            result.Error(e);
1432        }
1433        return result.Produce();
1434    }
1435    
1436    String LSCPServer::GetMidiInputPortParameterInfo(uint DeviceId, uint PortId, String ParameterName) {
1437        dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
1438        LSCPResultSet result;
1439        try {
1440            // get MIDI input device
1441            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1442            if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1443            MidiInputDevice* pDevice = devices[DeviceId];
1444    
1445            // get midi port
1446            MidiInputPort* pPort = pDevice->GetPort(PortId);
1447            if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1448    
1449            // get desired port parameter
1450            std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1451            if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1452            DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1453    
1454            // return all fields of this audio channel parameter
1455            result.Add("TYPE",         pParameter->Type());
1456            result.Add("DESCRIPTION",  pParameter->Description());
1457            result.Add("FIX",          pParameter->Fix());
1458            result.Add("MULTIPLICITY", pParameter->Multiplicity());
1459            if (pParameter->RangeMin())      result.Add("RANGE_MIN",     *pParameter->RangeMin());
1460            if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1461            if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1462        }
1463        catch (Exception e) {
1464            result.Error(e);
1465        }
1466        return result.Produce();
1467    }
1468    
1469    String LSCPServer::GetAudioOutputChannelParameterInfo(uint DeviceId, uint ChannelId, String ParameterName) {
1470        dmsg(2,("LSCPServer: GetAudioOutputChannelParameterInfo(DeviceId=%d,ChannelId=%d,ParameterName=%s)\n",DeviceId,ChannelId,ParameterName.c_str()));
1471        LSCPResultSet result;
1472        try {
1473            // get audio output device
1474            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1475            if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1476            AudioOutputDevice* pDevice = devices[DeviceId];
1477    
1478            // get audio channel
1479            AudioChannel* pChannel = pDevice->Channel(ChannelId);
1480            if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1481    
1482            // get desired audio channel parameter
1483            std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1484            if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1485            DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1486    
1487            // return all fields of this audio channel parameter
1488            result.Add("TYPE",         pParameter->Type());
1489            result.Add("DESCRIPTION",  pParameter->Description());
1490            result.Add("FIX",          pParameter->Fix());
1491            result.Add("MULTIPLICITY", pParameter->Multiplicity());
1492            if (pParameter->RangeMin())      result.Add("RANGE_MIN",     *pParameter->RangeMin());
1493            if (pParameter->RangeMax())      result.Add("RANGE_MAX",     *pParameter->RangeMax());
1494            if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1495        }
1496        catch (Exception e) {
1497            result.Error(e);
1498        }
1499        return result.Produce();
1500    }
1501    
1502    String LSCPServer::SetAudioOutputChannelParameter(uint DeviceId, uint ChannelId, String ParamKey, String ParamVal) {
1503        dmsg(2,("LSCPServer: SetAudioOutputChannelParameter(DeviceId=%d,ChannelId=%d,ParamKey=%s,ParamVal=%s)\n",DeviceId,ChannelId,ParamKey.c_str(),ParamVal.c_str()));
1504        LSCPResultSet result;
1505        try {
1506            // get audio output device
1507            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1508            if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1509            AudioOutputDevice* pDevice = devices[DeviceId];
1510    
1511            // get audio channel
1512            AudioChannel* pChannel = pDevice->Channel(ChannelId);
1513            if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1514    
1515            // get desired audio channel parameter
1516            std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1517            if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1518            DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1519    
1520            // set new channel parameter value
1521            pParameter->SetValue(ParamVal);
1522            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1523        }
1524        catch (Exception e) {
1525            result.Error(e);
1526        }
1527        return result.Produce();
1528    }
1529    
1530    String LSCPServer::SetAudioOutputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1531        dmsg(2,("LSCPServer: SetAudioOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1532        LSCPResultSet result;
1533        try {
1534            std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1535            if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1536            AudioOutputDevice* pDevice = devices[DeviceIndex];
1537            std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1538            if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1539            parameters[ParamKey]->SetValue(ParamVal);
1540            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1541        }
1542        catch (Exception e) {
1543            result.Error(e);
1544        }
1545        return result.Produce();
1546    }
1547    
1548    String LSCPServer::SetMidiInputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1549        dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1550        LSCPResultSet result;
1551        try {
1552            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1553            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1554            MidiInputDevice* pDevice = devices[DeviceIndex];
1555            std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1556            if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1557            parameters[ParamKey]->SetValue(ParamVal);
1558            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1559        }
1560        catch (Exception e) {
1561            result.Error(e);
1562        }
1563        return result.Produce();
1564    }
1565    
1566    String LSCPServer::SetMidiInputPortParameter(uint DeviceIndex, uint PortIndex, String ParamKey, String ParamVal) {
1567        dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1568        LSCPResultSet result;
1569        try {
1570            // get MIDI input device
1571            std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1572            if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1573            MidiInputDevice* pDevice = devices[DeviceIndex];
1574    
1575            // get MIDI port
1576            MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1577            if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1578    
1579            // set port parameter value
1580            std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1581            if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1582            parameters[ParamKey]->SetValue(ParamVal);
1583            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1584        }
1585        catch (Exception e) {
1586            result.Error(e);
1587      }      }
1588      return ConvertResult(result);      return result.Produce();
1589  }  }
1590    
1591  /**  /**
1592   * Will be called by the parser to change the audio output channel for   * Will be called by the parser to change the audio output channel for
1593   * playback on a particular sampler channel.   * playback on a particular sampler channel.
1594   */   */
1595  String LSCPServer::SetAudioOutputChannel(uint AudioOutputChannel, uint uiSamplerChannel) {  String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1596      dmsg(2,("LSCPServer: SetAudioOutputChannel(AudioOutputChannel=%d, SamplerChannel=%d)\n", AudioOutputChannel, uiSamplerChannel));      dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1597      return "ERR:0:Not implemented yet.\r\n";      LSCPResultSet result;
1598        try {
1599            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1600            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1601            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1602            if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1603            if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1604            pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1605        }
1606        catch (Exception e) {
1607             result.Error(e);
1608        }
1609        return result.Produce();
1610    }
1611    
1612    String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1613        dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1614        LSCPResultSet result;
1615        LockRTNotify();
1616        try {
1617            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1618            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1619            std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1620            if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1621            AudioOutputDevice* pDevice = devices[AudioDeviceId];
1622            pSamplerChannel->SetAudioOutputDevice(pDevice);
1623        }
1624        catch (Exception e) {
1625             result.Error(e);
1626        }
1627        UnlockRTNotify();
1628        return result.Produce();
1629    }
1630    
1631    String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1632        dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1633        LSCPResultSet result;
1634        LockRTNotify();
1635        try {
1636            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1637            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1638            // Driver type name aliasing...
1639            if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1640            if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1641            // Check if there's one audio output device already created
1642            // for the intended audio driver type (AudioOutputDriver)...
1643            AudioOutputDevice *pDevice = NULL;
1644            std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1645            std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1646            for (; iter != devices.end(); iter++) {
1647                if ((iter->second)->Driver() == AudioOutputDriver) {
1648                    pDevice = iter->second;
1649                    break;
1650                }
1651            }
1652            // If it doesn't exist, create a new one with default parameters...
1653            if (pDevice == NULL) {
1654                std::map<String,String> params;
1655                pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1656            }
1657            // Must have a device...
1658            if (pDevice == NULL)
1659                throw Exception("Internal error: could not create audio output device.");
1660            // Set it as the current channel device...
1661            pSamplerChannel->SetAudioOutputDevice(pDevice);
1662        }
1663        catch (Exception e) {
1664             result.Error(e);
1665        }
1666        UnlockRTNotify();
1667        return result.Produce();
1668    }
1669    
1670    String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
1671        dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
1672        LSCPResultSet result;
1673        try {
1674            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1675            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1676            pSamplerChannel->SetMidiInputPort(MIDIPort);
1677        }
1678        catch (Exception e) {
1679             result.Error(e);
1680        }
1681        return result.Produce();
1682  }  }
1683    
1684  String LSCPServer::SetMIDIInputType(midi_input_type_t MidiInputType, uint uiSamplerChannel) {  String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
1685      dmsg(2,("LSCPServer: SetMIDIInputType(MidiInputType=%d, SamplerChannel=%d)\n", MidiInputType, uiSamplerChannel));      dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
1686      result_t result;      LSCPResultSet result;
1687      try {      try {
1688          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1689          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1690          pSamplerChannel->SetMidiInputDevice(MidiInputType);          pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
         result.type = result_type_success;  
1691      }      }
1692      catch (LinuxSamplerException e) {      catch (Exception e) {
1693           e.PrintMessage();           result.Error(e);
          result.type    = result_type_error;  
          result.code    = LSCP_ERR_UNKNOWN;  
          result.message = e.Message();  
1694      }      }
1695      return ConvertResult(result);      return result.Produce();
1696  }  }
1697    
1698  /**  String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
1699   * Will be called by the parser to change the MIDI input port on which the      dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
1700   * engine of a particular sampler channel should listen to.      LSCPResultSet result;
1701   */      try {
1702  String LSCPServer::SetMIDIInputPort(String MIDIInputPort, uint uiSamplerchannel) {          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1703      dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIInputPort=%s, Samplerchannel=%d)\n", MIDIInputPort.c_str(), uiSamplerchannel));          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1704      return "ERR:0:Not implemented yet.\r\n";          std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1705            if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1706            MidiInputDevice* pDevice = devices[MIDIDeviceId];
1707            pSamplerChannel->SetMidiInputDevice(pDevice);
1708        }
1709        catch (Exception e) {
1710             result.Error(e);
1711        }
1712        return result.Produce();
1713    }
1714    
1715    String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
1716        dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
1717        LSCPResultSet result;
1718        try {
1719            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1720            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1721            // Driver type name aliasing...
1722            if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
1723            // Check if there's one MIDI input device already created
1724            // for the intended MIDI driver type (MidiInputDriver)...
1725            MidiInputDevice *pDevice = NULL;
1726            std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1727            std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1728            for (; iter != devices.end(); iter++) {
1729                if ((iter->second)->Driver() == MidiInputDriver) {
1730                    pDevice = iter->second;
1731                    break;
1732                }
1733            }
1734            // If it doesn't exist, create a new one with default parameters...
1735            if (pDevice == NULL) {
1736                std::map<String,String> params;
1737                pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1738                // Make it with at least one initial port.
1739                std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1740                parameters["PORTS"]->SetValue("1");
1741            }
1742            // Must have a device...
1743            if (pDevice == NULL)
1744                throw Exception("Internal error: could not create MIDI input device.");
1745            // Set it as the current channel device...
1746            pSamplerChannel->SetMidiInputDevice(pDevice);
1747        }
1748        catch (Exception e) {
1749             result.Error(e);
1750        }
1751        return result.Produce();
1752  }  }
1753    
1754  /**  /**
1755   * Will be called by the parser to change the MIDI input channel on which the   * Will be called by the parser to change the MIDI input device, port and channel on which
1756   * engine of a particular sampler channel should listen to.   * engine of a particular sampler channel should listen to.
1757   */   */
1758  String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {  String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
1759      dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n", MIDIChannel, uiSamplerChannel));      dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
1760      return "ERR:0:Not implemented yet.\r\n";      LSCPResultSet result;
1761        try {
1762            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1763            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1764            std::map<uint, MidiInputDevice*> devices =  pSampler->GetMidiInputDevices();
1765            if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1766            MidiInputDevice* pDevice = devices[MIDIDeviceId];
1767            pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
1768        }
1769        catch (Exception e) {
1770             result.Error(e);
1771        }
1772        return result.Produce();
1773  }  }
1774    
1775  /**  /**
1776   * 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
1777   * particular sampler channel.   * particular sampler channel.
1778   */   */
1779  String LSCPServer::SetVolume(double Volume, uint uiSamplerChannel) {  String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
1780      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", Volume, uiSamplerChannel));      dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
1781      result_t result;      LSCPResultSet result;
1782      try {      try {
1783          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1784          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1785          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1786          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1787          pEngine->Volume(Volume);          pEngineChannel->Volume(dVolume);
1788          result.type = result_type_success;      }
1789      }      catch (Exception e) {
1790      catch (LinuxSamplerException e) {           result.Error(e);
1791           e.PrintMessage();      }
1792           result.type    = result_type_error;      return result.Produce();
1793           result.code    = LSCP_ERR_UNKNOWN;  }
1794           result.message = e.Message();  
1795    /**
1796     * Will be called by the parser to mute/unmute particular sampler channel.
1797     */
1798    String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
1799        dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
1800        LSCPResultSet result;
1801        try {
1802            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1803            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1804    
1805            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1806            if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1807    
1808            if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
1809            else pEngineChannel->SetMute(1);
1810        } catch (Exception e) {
1811            result.Error(e);
1812        }
1813        return result.Produce();
1814    }
1815    
1816    /**
1817     * Will be called by the parser to solo particular sampler channel.
1818     */
1819    String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
1820        dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
1821        LSCPResultSet result;
1822        try {
1823            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1824            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1825    
1826            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1827            if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1828    
1829            bool oldSolo = pEngineChannel->GetSolo();
1830            bool hadSoloChannel = HasSoloChannel();
1831    
1832            pEngineChannel->SetSolo(bSolo);
1833    
1834            if(!oldSolo && bSolo) {
1835                if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
1836                if(!hadSoloChannel) MuteNonSoloChannels();
1837            }
1838    
1839            if(oldSolo && !bSolo) {
1840                if(!HasSoloChannel()) UnmuteChannels();
1841                else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
1842            }
1843        } catch (Exception e) {
1844            result.Error(e);
1845      }      }
1846      return ConvertResult(result);      return result.Produce();
1847    }
1848    
1849    /**
1850     * Determines whether there is at least one solo channel in the channel list.
1851     *
1852     * @returns true if there is at least one solo channel in the channel list,
1853     * false otherwise.
1854     */
1855    bool LSCPServer::HasSoloChannel() {
1856        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1857        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1858        for (; iter != channels.end(); iter++) {
1859            EngineChannel* c = iter->second->GetEngineChannel();
1860            if(c && c->GetSolo()) return true;
1861        }
1862    
1863        return false;
1864    }
1865    
1866    /**
1867     * Mutes all unmuted non-solo channels. Notice that the channels are muted
1868     * with -1 which indicates that they are muted because of the presence
1869     * of a solo channel(s). Channels muted with -1 will be automatically unmuted
1870     * when there are no solo channels left.
1871     */
1872    void LSCPServer::MuteNonSoloChannels() {
1873        dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
1874        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1875        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1876        for (; iter != channels.end(); iter++) {
1877            EngineChannel* c = iter->second->GetEngineChannel();
1878            if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
1879        }
1880    }
1881    
1882    /**
1883     * Unmutes all channels that are muted because of the presence
1884     * of a solo channel(s).
1885     */
1886    void  LSCPServer::UnmuteChannels() {
1887        dmsg(2,("LSCPServer: UnmuteChannels()\n"));
1888        std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1889        std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1890        for (; iter != channels.end(); iter++) {
1891            EngineChannel* c = iter->second->GetEngineChannel();
1892            if(c && c->GetMute() == -1) c->SetMute(0);
1893        }
1894    }
1895    
1896    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) {
1897        dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
1898    
1899        midi_prog_index_t idx;
1900        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1901        idx.midi_bank_lsb = MidiBank & 0x7f;
1902        idx.midi_prog     = MidiProg;
1903    
1904        MidiInstrumentMapper::entry_t entry;
1905        entry.EngineName      = EngineType;
1906        entry.InstrumentFile  = InstrumentFile;
1907        entry.InstrumentIndex = InstrumentIndex;
1908        entry.LoadMode        = LoadMode;
1909        entry.Volume          = Volume;
1910        entry.Name            = Name;
1911    
1912        LSCPResultSet result;
1913        try {
1914            // PERSISTENT mapping commands might block for a long time, so in
1915            // that case we add/replace the mapping in another thread in case
1916            // the NON_MODAL argument was supplied, non persistent mappings
1917            // should return immediately, so we don't need to do that for them
1918            bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
1919            MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
1920        } catch (Exception e) {
1921            result.Error(e);
1922        }
1923        return result.Produce();
1924    }
1925    
1926    String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
1927        dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
1928    
1929        midi_prog_index_t idx;
1930        idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1931        idx.midi_bank_lsb = MidiBank & 0x7f;
1932        idx.midi_prog     = MidiProg;
1933    
1934        LSCPResultSet result;
1935        try {
1936            MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
1937        } catch (Exception e) {
1938            result.Error(e);
1939        }
1940        return result.Produce();
1941    }
1942    
1943    String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
1944        dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
1945        LSCPResultSet result;
1946        try {
1947            result.Add(MidiInstrumentMapper::Entries(MidiMapID).size());
1948        } catch (Exception e) {
1949            result.Error(e);
1950        }
1951        return result.Produce();
1952    }
1953    
1954    
1955    String LSCPServer::GetAllMidiInstrumentMappings() {
1956        dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
1957        LSCPResultSet result;
1958        std::vector<int> maps = MidiInstrumentMapper::Maps();
1959        int totalMappings = 0;
1960        for (int i = 0; i < maps.size(); i++) {
1961            try {
1962                totalMappings += MidiInstrumentMapper::Entries(maps[i]).size();
1963            } catch (Exception e) { /*NOOP*/ }
1964        }
1965        result.Add(totalMappings);
1966        return result.Produce();
1967    }
1968    
1969    String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
1970        dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
1971        LSCPResultSet result;
1972        try {
1973            midi_prog_index_t idx;
1974            idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1975            idx.midi_bank_lsb = MidiBank & 0x7f;
1976            idx.midi_prog     = MidiProg;
1977    
1978            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
1979            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.find(idx);
1980            if (iter == mappings.end()) result.Error("there is no map entry with that index");
1981            else { // found
1982    
1983                // convert the filename into the correct encoding as defined for LSCP
1984                // (especially in terms of special characters -> escape sequences)
1985    #if WIN32
1986                const String instrumentFileName = Path::fromWindows(iter->second.InstrumentFile).toLscp();
1987    #else
1988                // assuming POSIX
1989                const String instrumentFileName = Path::fromPosix(iter->second.InstrumentFile).toLscp();
1990    #endif
1991    
1992                result.Add("NAME", _escapeLscpResponse(iter->second.Name));
1993                result.Add("ENGINE_NAME", iter->second.EngineName);
1994                result.Add("INSTRUMENT_FILE", instrumentFileName);
1995                result.Add("INSTRUMENT_NR", (int) iter->second.InstrumentIndex);
1996                String instrumentName;
1997                Engine* pEngine = EngineFactory::Create(iter->second.EngineName);
1998                if (pEngine) {
1999                    if (pEngine->GetInstrumentManager()) {
2000                        InstrumentManager::instrument_id_t instrID;
2001                        instrID.FileName = iter->second.InstrumentFile;
2002                        instrID.Index    = iter->second.InstrumentIndex;
2003                        instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
2004                    }
2005                    EngineFactory::Destroy(pEngine);
2006                }
2007                result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2008                switch (iter->second.LoadMode) {
2009                    case MidiInstrumentMapper::ON_DEMAND:
2010                        result.Add("LOAD_MODE", "ON_DEMAND");
2011                        break;
2012                    case MidiInstrumentMapper::ON_DEMAND_HOLD:
2013                        result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2014                        break;
2015                    case MidiInstrumentMapper::PERSISTENT:
2016                        result.Add("LOAD_MODE", "PERSISTENT");
2017                        break;
2018                    default:
2019                        throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2020                }
2021                result.Add("VOLUME", iter->second.Volume);
2022            }
2023        } catch (Exception e) {
2024            result.Error(e);
2025        }
2026        return result.Produce();
2027    }
2028    
2029    String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
2030        dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
2031        LSCPResultSet result;
2032        try {
2033            String s;
2034            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
2035            std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2036            for (; iter != mappings.end(); iter++) {
2037                if (s.size()) s += ",";
2038                s += "{" + ToString(MidiMapID) + ","
2039                         + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2040                         + ToString(int(iter->first.midi_prog)) + "}";
2041            }
2042            result.Add(s);
2043        } catch (Exception e) {
2044            result.Error(e);
2045        }
2046        return result.Produce();
2047    }
2048    
2049    String LSCPServer::ListAllMidiInstrumentMappings() {
2050        dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
2051        LSCPResultSet result;
2052        try {
2053            std::vector<int> maps = MidiInstrumentMapper::Maps();
2054            String s;
2055            for (int i = 0; i < maps.size(); i++) {
2056                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
2057                std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2058                for (; iter != mappings.end(); iter++) {
2059                    if (s.size()) s += ",";
2060                    s += "{" + ToString(maps[i]) + ","
2061                             + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2062                             + ToString(int(iter->first.midi_prog)) + "}";
2063                }
2064            }
2065            result.Add(s);
2066        } catch (Exception e) {
2067            result.Error(e);
2068        }
2069        return result.Produce();
2070    }
2071    
2072    String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
2073        dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
2074        LSCPResultSet result;
2075        try {
2076            MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
2077        } catch (Exception e) {
2078            result.Error(e);
2079        }
2080        return result.Produce();
2081    }
2082    
2083    String LSCPServer::ClearAllMidiInstrumentMappings() {
2084        dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
2085        LSCPResultSet result;
2086        try {
2087            std::vector<int> maps = MidiInstrumentMapper::Maps();
2088            for (int i = 0; i < maps.size(); i++)
2089                MidiInstrumentMapper::RemoveAllEntries(maps[i]);
2090        } catch (Exception e) {
2091            result.Error(e);
2092        }
2093        return result.Produce();
2094    }
2095    
2096    String LSCPServer::AddMidiInstrumentMap(String MapName) {
2097        dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
2098        LSCPResultSet result;
2099        try {
2100            int MapID = MidiInstrumentMapper::AddMap(MapName);
2101            result = LSCPResultSet(MapID);
2102        } catch (Exception e) {
2103            result.Error(e);
2104        }
2105        return result.Produce();
2106    }
2107    
2108    String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
2109        dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
2110        LSCPResultSet result;
2111        try {
2112            MidiInstrumentMapper::RemoveMap(MidiMapID);
2113        } catch (Exception e) {
2114            result.Error(e);
2115        }
2116        return result.Produce();
2117    }
2118    
2119    String LSCPServer::RemoveAllMidiInstrumentMaps() {
2120        dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
2121        LSCPResultSet result;
2122        try {
2123            MidiInstrumentMapper::RemoveAllMaps();
2124        } catch (Exception e) {
2125            result.Error(e);
2126        }
2127        return result.Produce();
2128    }
2129    
2130    String LSCPServer::GetMidiInstrumentMaps() {
2131        dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
2132        LSCPResultSet result;
2133        try {
2134            result.Add(MidiInstrumentMapper::Maps().size());
2135        } catch (Exception e) {
2136            result.Error(e);
2137        }
2138        return result.Produce();
2139    }
2140    
2141    String LSCPServer::ListMidiInstrumentMaps() {
2142        dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
2143        LSCPResultSet result;
2144        try {
2145            std::vector<int> maps = MidiInstrumentMapper::Maps();
2146            String sList;
2147            for (int i = 0; i < maps.size(); i++) {
2148                if (sList != "") sList += ",";
2149                sList += ToString(maps[i]);
2150            }
2151            result.Add(sList);
2152        } catch (Exception e) {
2153            result.Error(e);
2154        }
2155        return result.Produce();
2156    }
2157    
2158    String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
2159        dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2160        LSCPResultSet result;
2161        try {
2162            result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2163            result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2164        } catch (Exception e) {
2165            result.Error(e);
2166        }
2167        return result.Produce();
2168    }
2169    
2170    String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2171        dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2172        LSCPResultSet result;
2173        try {
2174            MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2175        } catch (Exception e) {
2176            result.Error(e);
2177        }
2178        return result.Produce();
2179    }
2180    
2181    /**
2182     * Set the MIDI instrument map the given sampler channel shall use for
2183     * handling MIDI program change messages. There are the following two
2184     * special (negative) values:
2185     *
2186     *    - (-1) :  set to NONE (ignore program changes)
2187     *    - (-2) :  set to DEFAULT map
2188     */
2189    String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2190        dmsg(2,("LSCPServer: SetChannelMap()\n"));
2191        LSCPResultSet result;
2192        try {
2193            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2194            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2195    
2196            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2197            if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
2198    
2199            if      (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2200            else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2201            else                      pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2202        } catch (Exception e) {
2203            result.Error(e);
2204        }
2205        return result.Produce();
2206    }
2207    
2208    String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2209        dmsg(2,("LSCPServer: CreateFxSend()\n"));
2210        LSCPResultSet result;
2211        try {
2212            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2213    
2214            FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2215            if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2216    
2217            result = LSCPResultSet(pFxSend->Id()); // success
2218        } catch (Exception e) {
2219            result.Error(e);
2220        }
2221        return result.Produce();
2222    }
2223    
2224    String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2225        dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2226        LSCPResultSet result;
2227        try {
2228            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2229    
2230            FxSend* pFxSend = NULL;
2231            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2232                if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2233                    pFxSend = pEngineChannel->GetFxSend(i);
2234                    break;
2235                }
2236            }
2237            if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2238            pEngineChannel->RemoveFxSend(pFxSend);
2239        } catch (Exception e) {
2240            result.Error(e);
2241        }
2242        return result.Produce();
2243    }
2244    
2245    String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2246        dmsg(2,("LSCPServer: GetFxSends()\n"));
2247        LSCPResultSet result;
2248        try {
2249            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2250    
2251            result.Add(pEngineChannel->GetFxSendCount());
2252        } catch (Exception e) {
2253            result.Error(e);
2254        }
2255        return result.Produce();
2256    }
2257    
2258    String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2259        dmsg(2,("LSCPServer: ListFxSends()\n"));
2260        LSCPResultSet result;
2261        String list;
2262        try {
2263            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2264    
2265            for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2266                FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2267                if (list != "") list += ",";
2268                list += ToString(pFxSend->Id());
2269            }
2270            result.Add(list);
2271        } catch (Exception e) {
2272            result.Error(e);
2273        }
2274        return result.Produce();
2275    }
2276    
2277    FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2278        EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2279    
2280        FxSend* pFxSend = NULL;
2281        for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2282            if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2283                pFxSend = pEngineChannel->GetFxSend(i);
2284                break;
2285            }
2286        }
2287        if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2288        return pFxSend;
2289    }
2290    
2291    String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2292        dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2293        LSCPResultSet result;
2294        try {
2295            EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2296            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2297    
2298            // gather audio routing informations
2299            String AudioRouting;
2300            for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2301                if (AudioRouting != "") AudioRouting += ",";
2302                AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2303            }
2304    
2305            // success
2306            result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2307            result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2308            result.Add("LEVEL", ToString(pFxSend->Level()));
2309            result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2310        } catch (Exception e) {
2311            result.Error(e);
2312        }
2313        return result.Produce();
2314    }
2315    
2316    String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2317        dmsg(2,("LSCPServer: SetFxSendName()\n"));
2318        LSCPResultSet result;
2319        try {
2320            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2321    
2322            pFxSend->SetName(Name);
2323            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2324        } catch (Exception e) {
2325            result.Error(e);
2326        }
2327        return result.Produce();
2328    }
2329    
2330    String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2331        dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2332        LSCPResultSet result;
2333        try {
2334            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2335    
2336            pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2337            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2338        } catch (Exception e) {
2339            result.Error(e);
2340        }
2341        return result.Produce();
2342    }
2343    
2344    String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2345        dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2346        LSCPResultSet result;
2347        try {
2348            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2349    
2350            pFxSend->SetMidiController(MidiController);
2351            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2352        } catch (Exception e) {
2353            result.Error(e);
2354        }
2355        return result.Produce();
2356    }
2357    
2358    String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2359        dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2360        LSCPResultSet result;
2361        try {
2362            FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2363    
2364            pFxSend->SetLevel((float)dLevel);
2365            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2366        } catch (Exception e) {
2367            result.Error(e);
2368        }
2369        return result.Produce();
2370    }
2371    
2372    String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
2373        dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
2374        LSCPResultSet result;
2375        try {
2376            SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2377            if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2378            EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2379            if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
2380            if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
2381            Engine* pEngine = pEngineChannel->GetEngine();
2382            InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
2383            if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
2384            InstrumentManager::instrument_id_t instrumentID;
2385            instrumentID.FileName = pEngineChannel->InstrumentFileName();
2386            instrumentID.Index    = pEngineChannel->InstrumentIndex();
2387            pInstrumentManager->LaunchInstrumentEditor(instrumentID);
2388        } catch (Exception e) {
2389            result.Error(e);
2390        }
2391        return result.Produce();
2392  }  }
2393    
2394  /**  /**
# Line 375  String LSCPServer::SetVolume(double Volu Line 2396  String LSCPServer::SetVolume(double Volu
2396   */   */
2397  String LSCPServer::ResetChannel(uint uiSamplerChannel) {  String LSCPServer::ResetChannel(uint uiSamplerChannel) {
2398      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));      dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
2399      result_t result;      LSCPResultSet result;
2400      try {      try {
2401          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);          SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2402          if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");          if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2403          Engine* pEngine = pSamplerChannel->GetEngine();          EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2404          if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");          if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
2405          pEngine->Reset();          pEngineChannel->Reset();
2406          result.type = result_type_success;      }
2407      }      catch (Exception e) {
2408      catch (LinuxSamplerException e) {           result.Error(e);
2409           e.PrintMessage();      }
2410           result.type    = result_type_error;      return result.Produce();
2411           result.code    = LSCP_ERR_UNKNOWN;  }
2412           result.message = e.Message();  
2413    /**
2414     * Will be called by the parser to reset the whole sampler.
2415     */
2416    String LSCPServer::ResetSampler() {
2417        dmsg(2,("LSCPServer: ResetSampler()\n"));
2418        pSampler->Reset();
2419        LSCPResultSet result;
2420        return result.Produce();
2421    }
2422    
2423    /**
2424     * Will be called by the parser to return general informations about this
2425     * sampler.
2426     */
2427    String LSCPServer::GetServerInfo() {
2428        dmsg(2,("LSCPServer: GetServerInfo()\n"));
2429        const std::string description =
2430            _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
2431        LSCPResultSet result;
2432        result.Add("DESCRIPTION", description);
2433        result.Add("VERSION", VERSION);
2434        result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
2435    #if HAVE_SQLITE3
2436        result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
2437    #else
2438        result.Add("INSTRUMENTS_DB_SUPPORT", "no");
2439    #endif
2440    
2441        return result.Produce();
2442    }
2443    
2444    /**
2445     * Will be called by the parser to return the current number of all active streams.
2446     */
2447    String LSCPServer::GetTotalStreamCount() {
2448        dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
2449        LSCPResultSet result;
2450        result.Add(pSampler->GetDiskStreamCount());
2451        return result.Produce();
2452    }
2453    
2454    /**
2455     * Will be called by the parser to return the current number of all active voices.
2456     */
2457    String LSCPServer::GetTotalVoiceCount() {
2458        dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
2459        LSCPResultSet result;
2460        result.Add(pSampler->GetVoiceCount());
2461        return result.Produce();
2462    }
2463    
2464    /**
2465     * Will be called by the parser to return the maximum number of voices.
2466     */
2467    String LSCPServer::GetTotalVoiceCountMax() {
2468        dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
2469        LSCPResultSet result;
2470        result.Add(EngineFactory::EngineInstances().size() * CONFIG_MAX_VOICES);
2471        return result.Produce();
2472    }
2473    
2474    String LSCPServer::GetGlobalVolume() {
2475        LSCPResultSet result;
2476        result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
2477        return result.Produce();
2478    }
2479    
2480    String LSCPServer::SetGlobalVolume(double dVolume) {
2481        LSCPResultSet result;
2482        try {
2483            if (dVolume < 0) throw Exception("Volume may not be negative");
2484            GLOBAL_VOLUME = dVolume; // see common/global.cpp
2485            LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
2486        } catch (Exception e) {
2487            result.Error(e);
2488        }
2489        return result.Produce();
2490    }
2491    
2492    String LSCPServer::GetFileInstruments(String Filename) {
2493        dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
2494        LSCPResultSet result;
2495        try {
2496            VerifyFile(Filename);
2497        } catch (Exception e) {
2498            result.Error(e);
2499            return result.Produce();
2500        }
2501        // try to find a sampler engine that can handle the file
2502        bool bFound = false;
2503        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
2504        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
2505            Engine* pEngine = NULL;
2506            try {
2507                pEngine = EngineFactory::Create(engineTypes[i]);
2508                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
2509                InstrumentManager* pManager = pEngine->GetInstrumentManager();
2510                if (pManager) {
2511                    std::vector<InstrumentManager::instrument_id_t> IDs =
2512                        pManager->GetInstrumentFileContent(Filename);
2513                    // return the amount of instruments in the file
2514                    result.Add(IDs.size());
2515                    // no more need to ask other engine types
2516                    bFound = true;
2517                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
2518            } catch (Exception e) {
2519                // NOOP, as exception is thrown if engine doesn't support file
2520            }
2521            if (pEngine) EngineFactory::Destroy(pEngine);
2522      }      }
2523      return ConvertResult(result);  
2524        if (!bFound) result.Error("Unknown file format");
2525        return result.Produce();
2526    }
2527    
2528    String LSCPServer::ListFileInstruments(String Filename) {
2529        dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
2530        LSCPResultSet result;
2531        try {
2532            VerifyFile(Filename);
2533        } catch (Exception e) {
2534            result.Error(e);
2535            return result.Produce();
2536        }
2537        // try to find a sampler engine that can handle the file
2538        bool bFound = false;
2539        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
2540        for (int i = 0; !bFound && i < engineTypes.size(); i++) {
2541            Engine* pEngine = NULL;
2542            try {
2543                pEngine = EngineFactory::Create(engineTypes[i]);
2544                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
2545                InstrumentManager* pManager = pEngine->GetInstrumentManager();
2546                if (pManager) {
2547                    std::vector<InstrumentManager::instrument_id_t> IDs =
2548                        pManager->GetInstrumentFileContent(Filename);
2549                    // return a list of IDs of the instruments in the file
2550                    String s;
2551                    for (int j = 0; j < IDs.size(); j++) {
2552                        if (s.size()) s += ",";
2553                        s += ToString(IDs[j].Index);
2554                    }
2555                    result.Add(s);
2556                    // no more need to ask other engine types
2557                    bFound = true;
2558                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
2559            } catch (Exception e) {
2560                // NOOP, as exception is thrown if engine doesn't support file
2561            }
2562            if (pEngine) EngineFactory::Destroy(pEngine);
2563        }
2564    
2565        if (!bFound) result.Error("Unknown file format");
2566        return result.Produce();
2567    }
2568    
2569    String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
2570        dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
2571        LSCPResultSet result;
2572        try {
2573            VerifyFile(Filename);
2574        } catch (Exception e) {
2575            result.Error(e);
2576            return result.Produce();
2577        }
2578        InstrumentManager::instrument_id_t id;
2579        id.FileName = Filename;
2580        id.Index    = InstrumentID;
2581        // try to find a sampler engine that can handle the file
2582        bool bFound = false;
2583        bool bFatalErr = false;
2584        std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
2585        for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
2586            Engine* pEngine = NULL;
2587            try {
2588                pEngine = EngineFactory::Create(engineTypes[i]);
2589                if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
2590                InstrumentManager* pManager = pEngine->GetInstrumentManager();
2591                if (pManager) {
2592                    // check if the instrument index is valid
2593                    // FIXME: this won't work if an engine only supports parts of the instrument file
2594                    std::vector<InstrumentManager::instrument_id_t> IDs =
2595                        pManager->GetInstrumentFileContent(Filename);
2596                    if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
2597                        std::stringstream ss;
2598                        ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
2599                        bFatalErr = true;
2600                        throw Exception(ss.str());
2601                    }
2602                    // get the info of the requested instrument
2603                    InstrumentManager::instrument_info_t info =
2604                        pManager->GetInstrumentInfo(id);
2605                    // return detailed informations about the file
2606                    result.Add("NAME", info.InstrumentName);
2607                    result.Add("FORMAT_FAMILY", engineTypes[i]);
2608                    result.Add("FORMAT_VERSION", info.FormatVersion);
2609                    result.Add("PRODUCT", info.Product);
2610                    result.Add("ARTISTS", info.Artists);
2611                    // no more need to ask other engine types
2612                    bFound = true;
2613                } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
2614            } catch (Exception e) {
2615                // usually NOOP, as exception is thrown if engine doesn't support file
2616                if (bFatalErr) result.Error(e);
2617            }
2618            if (pEngine) EngineFactory::Destroy(pEngine);
2619        }
2620    
2621        if (!bFound && !bFatalErr) result.Error("Unknown file format");
2622        return result.Produce();
2623    }
2624    
2625    void LSCPServer::VerifyFile(String Filename) {
2626        #if WIN32
2627        WIN32_FIND_DATA win32FileAttributeData;
2628        BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
2629        if (!res) {
2630            std::stringstream ss;
2631            ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
2632            throw Exception(ss.str());
2633        }
2634        if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
2635            throw Exception("Directory is specified");
2636        }
2637        #else
2638        struct stat statBuf;
2639        int res = stat(Filename.c_str(), &statBuf);
2640        if (res) {
2641            std::stringstream ss;
2642            ss << "Fail to stat `" << Filename << "`: " << strerror(errno);
2643            throw Exception(ss.str());
2644        }
2645    
2646        if (S_ISDIR(statBuf.st_mode)) {
2647            throw Exception("Directory is specified");
2648        }
2649        #endif
2650  }  }
2651    
2652  /**  /**
2653   * 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
2654   * server for receiving event messages.   * server for receiving event messages.
2655   */   */
2656  String LSCPServer::SubscribeNotification(uint UDPPort) {  String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
2657      dmsg(2,("LSCPServer: SubscribeNotification(UDPPort=%d)\n", UDPPort));      dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
2658      return "ERR:0:Not implemented yet.\r\n";      LSCPResultSet result;
2659        SubscriptionMutex.Lock();
2660        eventSubscriptions[type].push_back(currentSocket);
2661        SubscriptionMutex.Unlock();
2662        return result.Produce();
2663  }  }
2664    
2665  /**  /**
2666   * Will be called by the parser to unsubscribe a client on the server   * Will be called by the parser to unsubscribe a client on the server
2667   * for not receiving further event messages.   * for not receiving further event messages.
2668   */   */
2669  String LSCPServer::UnsubscribeNotification(String SessionID) {  String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
2670      dmsg(2,("LSCPServer: UnsubscribeNotification(SessionID=%s)\n", SessionID.c_str()));      dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
2671      return "ERR:0:Not implemented yet.\r\n";      LSCPResultSet result;
2672        SubscriptionMutex.Lock();
2673        eventSubscriptions[type].remove(currentSocket);
2674        SubscriptionMutex.Unlock();
2675        return result.Produce();
2676    }
2677    
2678    String LSCPServer::AddDbInstrumentDirectory(String Dir) {
2679        dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
2680        LSCPResultSet result;
2681    #if HAVE_SQLITE3
2682        try {
2683            InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
2684        } catch (Exception e) {
2685             result.Error(e);
2686        }
2687    #else
2688        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2689    #endif
2690        return result.Produce();
2691    }
2692    
2693    String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
2694        dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
2695        LSCPResultSet result;
2696    #if HAVE_SQLITE3
2697        try {
2698            InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
2699        } catch (Exception e) {
2700             result.Error(e);
2701        }
2702    #else
2703        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2704    #endif
2705        return result.Produce();
2706    }
2707    
2708    String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
2709        dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
2710        LSCPResultSet result;
2711    #if HAVE_SQLITE3
2712        try {
2713            result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
2714        } catch (Exception e) {
2715             result.Error(e);
2716        }
2717    #else
2718        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2719    #endif
2720        return result.Produce();
2721    }
2722    
2723    String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
2724        dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
2725        LSCPResultSet result;
2726    #if HAVE_SQLITE3
2727        try {
2728            String list;
2729            StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
2730    
2731            for (int i = 0; i < dirs->size(); i++) {
2732                if (list != "") list += ",";
2733                list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
2734            }
2735    
2736            result.Add(list);
2737        } catch (Exception e) {
2738             result.Error(e);
2739        }
2740    #else
2741        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2742    #endif
2743        return result.Produce();
2744    }
2745    
2746    String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
2747        dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
2748        LSCPResultSet result;
2749    #if HAVE_SQLITE3
2750        try {
2751            DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
2752    
2753            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
2754            result.Add("CREATED", info.Created);
2755            result.Add("MODIFIED", info.Modified);
2756        } catch (Exception e) {
2757             result.Error(e);
2758        }
2759    #else
2760        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2761    #endif
2762        return result.Produce();
2763    }
2764    
2765    String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
2766        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
2767        LSCPResultSet result;
2768    #if HAVE_SQLITE3
2769        try {
2770            InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
2771        } catch (Exception e) {
2772             result.Error(e);
2773        }
2774    #else
2775        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2776    #endif
2777        return result.Produce();
2778    }
2779    
2780    String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
2781        dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
2782        LSCPResultSet result;
2783    #if HAVE_SQLITE3
2784        try {
2785            InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
2786        } catch (Exception e) {
2787             result.Error(e);
2788        }
2789    #else
2790        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2791    #endif
2792        return result.Produce();
2793    }
2794    
2795    String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
2796        dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
2797        LSCPResultSet result;
2798    #if HAVE_SQLITE3
2799        try {
2800            InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
2801        } catch (Exception e) {
2802             result.Error(e);
2803        }
2804    #else
2805        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2806    #endif
2807        return result.Produce();
2808    }
2809    
2810    String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
2811        dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
2812        LSCPResultSet result;
2813    #if HAVE_SQLITE3
2814        try {
2815            InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
2816        } catch (Exception e) {
2817             result.Error(e);
2818        }
2819    #else
2820        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2821    #endif
2822        return result.Produce();
2823    }
2824    
2825    String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
2826        dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
2827        LSCPResultSet result;
2828    #if HAVE_SQLITE3
2829        try {
2830            int id;
2831            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
2832            id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
2833            if (bBackground) result = id;
2834        } catch (Exception e) {
2835             result.Error(e);
2836        }
2837    #else
2838        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2839    #endif
2840        return result.Produce();
2841    }
2842    
2843    String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground) {
2844        dmsg(2,("LSCPServer: AddDbInstruments(ScanMode=%s,DbDir=%s,FsDir=%s,bBackground=%d)\n", ScanMode.c_str(), DbDir.c_str(), FsDir.c_str(), bBackground));
2845        LSCPResultSet result;
2846    #if HAVE_SQLITE3
2847        try {
2848            int id;
2849            InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
2850            if (ScanMode.compare("RECURSIVE") == 0) {
2851               id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground);
2852            } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
2853               id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground);
2854            } else if (ScanMode.compare("FLAT") == 0) {
2855               id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground);
2856            } else {
2857                throw Exception("Unknown scan mode: " + ScanMode);
2858            }
2859    
2860            if (bBackground) result = id;
2861        } catch (Exception e) {
2862             result.Error(e);
2863        }
2864    #else
2865        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2866    #endif
2867        return result.Produce();
2868    }
2869    
2870    String LSCPServer::RemoveDbInstrument(String Instr) {
2871        dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
2872        LSCPResultSet result;
2873    #if HAVE_SQLITE3
2874        try {
2875            InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
2876        } catch (Exception e) {
2877             result.Error(e);
2878        }
2879    #else
2880        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2881    #endif
2882        return result.Produce();
2883    }
2884    
2885    String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
2886        dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
2887        LSCPResultSet result;
2888    #if HAVE_SQLITE3
2889        try {
2890            result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
2891        } catch (Exception e) {
2892             result.Error(e);
2893        }
2894    #else
2895        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2896    #endif
2897        return result.Produce();
2898    }
2899    
2900    String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
2901        dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
2902        LSCPResultSet result;
2903    #if HAVE_SQLITE3
2904        try {
2905            String list;
2906            StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
2907    
2908            for (int i = 0; i < instrs->size(); i++) {
2909                if (list != "") list += ",";
2910                list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
2911            }
2912    
2913            result.Add(list);
2914        } catch (Exception e) {
2915             result.Error(e);
2916        }
2917    #else
2918        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2919    #endif
2920        return result.Produce();
2921    }
2922    
2923    String LSCPServer::GetDbInstrumentInfo(String Instr) {
2924        dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
2925        LSCPResultSet result;
2926    #if HAVE_SQLITE3
2927        try {
2928            DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
2929    
2930            result.Add("INSTRUMENT_FILE", info.InstrFile);
2931            result.Add("INSTRUMENT_NR", info.InstrNr);
2932            result.Add("FORMAT_FAMILY", info.FormatFamily);
2933            result.Add("FORMAT_VERSION", info.FormatVersion);
2934            result.Add("SIZE", (int)info.Size);
2935            result.Add("CREATED", info.Created);
2936            result.Add("MODIFIED", info.Modified);
2937            result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
2938            result.Add("IS_DRUM", info.IsDrum);
2939            result.Add("PRODUCT", _escapeLscpResponse(info.Product));
2940            result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
2941            result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
2942        } catch (Exception e) {
2943             result.Error(e);
2944        }
2945    #else
2946        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2947    #endif
2948        return result.Produce();
2949    }
2950    
2951    String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
2952        dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
2953        LSCPResultSet result;
2954    #if HAVE_SQLITE3
2955        try {
2956            ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
2957    
2958            result.Add("FILES_TOTAL", job.FilesTotal);
2959            result.Add("FILES_SCANNED", job.FilesScanned);
2960            result.Add("SCANNING", job.Scanning);
2961            result.Add("STATUS", job.Status);
2962        } catch (Exception e) {
2963             result.Error(e);
2964        }
2965    #else
2966        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2967    #endif
2968        return result.Produce();
2969    }
2970    
2971    String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
2972        dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
2973        LSCPResultSet result;
2974    #if HAVE_SQLITE3
2975        try {
2976            InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
2977        } catch (Exception e) {
2978             result.Error(e);
2979        }
2980    #else
2981        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2982    #endif
2983        return result.Produce();
2984    }
2985    
2986    String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
2987        dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
2988        LSCPResultSet result;
2989    #if HAVE_SQLITE3
2990        try {
2991            InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
2992        } catch (Exception e) {
2993             result.Error(e);
2994        }
2995    #else
2996        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
2997    #endif
2998        return result.Produce();
2999    }
3000    
3001    String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3002        dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3003        LSCPResultSet result;
3004    #if HAVE_SQLITE3
3005        try {
3006            InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3007        } catch (Exception e) {
3008             result.Error(e);
3009        }
3010    #else
3011        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3012    #endif
3013        return result.Produce();
3014    }
3015    
3016    String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3017        dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3018        LSCPResultSet result;
3019    #if HAVE_SQLITE3
3020        try {
3021            InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3022        } catch (Exception e) {
3023             result.Error(e);
3024        }
3025    #else
3026        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3027    #endif
3028        return result.Produce();
3029    }
3030    
3031    String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3032        dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3033        LSCPResultSet result;
3034    #if HAVE_SQLITE3
3035        try {
3036            SearchQuery Query;
3037            std::map<String,String>::iterator iter;
3038            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3039                if (iter->first.compare("NAME") == 0) {
3040                    Query.Name = iter->second;
3041                } else if (iter->first.compare("CREATED") == 0) {
3042                    Query.SetCreated(iter->second);
3043                } else if (iter->first.compare("MODIFIED") == 0) {
3044                    Query.SetModified(iter->second);
3045                } else if (iter->first.compare("DESCRIPTION") == 0) {
3046                    Query.Description = iter->second;
3047                } else {
3048                    throw Exception("Unknown search criteria: " + iter->first);
3049                }
3050            }
3051    
3052            String list;
3053            StringListPtr pDirectories =
3054                InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3055    
3056            for (int i = 0; i < pDirectories->size(); i++) {
3057                if (list != "") list += ",";
3058                list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3059            }
3060    
3061            result.Add(list);
3062        } catch (Exception e) {
3063             result.Error(e);
3064        }
3065    #else
3066        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3067    #endif
3068        return result.Produce();
3069    }
3070    
3071    String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
3072        dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
3073        LSCPResultSet result;
3074    #if HAVE_SQLITE3
3075        try {
3076            SearchQuery Query;
3077            std::map<String,String>::iterator iter;
3078            for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3079                if (iter->first.compare("NAME") == 0) {
3080                    Query.Name = iter->second;
3081                } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
3082                    Query.SetFormatFamilies(iter->second);
3083                } else if (iter->first.compare("SIZE") == 0) {
3084                    Query.SetSize(iter->second);
3085                } else if (iter->first.compare("CREATED") == 0) {
3086                    Query.SetCreated(iter->second);
3087                } else if (iter->first.compare("MODIFIED") == 0) {
3088                    Query.SetModified(iter->second);
3089                } else if (iter->first.compare("DESCRIPTION") == 0) {
3090                    Query.Description = iter->second;
3091                } else if (iter->first.compare("IS_DRUM") == 0) {
3092                    if (!strcasecmp(iter->second.c_str(), "true")) {
3093                        Query.InstrType = SearchQuery::DRUM;
3094                    } else {
3095                        Query.InstrType = SearchQuery::CHROMATIC;
3096                    }
3097                } else if (iter->first.compare("PRODUCT") == 0) {
3098                     Query.Product = iter->second;
3099                } else if (iter->first.compare("ARTISTS") == 0) {
3100                     Query.Artists = iter->second;
3101                } else if (iter->first.compare("KEYWORDS") == 0) {
3102                     Query.Keywords = iter->second;
3103                } else {
3104                    throw Exception("Unknown search criteria: " + iter->first);
3105                }
3106            }
3107    
3108            String list;
3109            StringListPtr pInstruments =
3110                InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
3111    
3112            for (int i = 0; i < pInstruments->size(); i++) {
3113                if (list != "") list += ",";
3114                list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
3115            }
3116    
3117            result.Add(list);
3118        } catch (Exception e) {
3119             result.Error(e);
3120        }
3121    #else
3122        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3123    #endif
3124        return result.Produce();
3125    }
3126    
3127    String LSCPServer::FormatInstrumentsDb() {
3128        dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
3129        LSCPResultSet result;
3130    #if HAVE_SQLITE3
3131        try {
3132            InstrumentsDb::GetInstrumentsDb()->Format();
3133        } catch (Exception e) {
3134             result.Error(e);
3135        }
3136    #else
3137        result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3138    #endif
3139        return result.Produce();
3140    }
3141    
3142    
3143    /**
3144     * Will be called by the parser to enable or disable echo mode; if echo
3145     * mode is enabled, all commands from the client will (immediately) be
3146     * echoed back to the client.
3147     */
3148    String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
3149        dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
3150        LSCPResultSet result;
3151        try {
3152            if      (boolean_value == 0) pSession->bVerbose = false;
3153            else if (boolean_value == 1) pSession->bVerbose = true;
3154            else throw Exception("Not a boolean value, must either be 0 or 1");
3155        }
3156        catch (Exception e) {
3157             result.Error(e);
3158        }
3159        return result.Produce();
3160  }  }

Legend:
Removed from v.53  
changed lines
  Added in v.1686

  ViewVC Help
Powered by ViewVC