/[svn]/linuxsampler/trunk/src/network/lscpserver.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/network/lscpserver.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1537 - (hide annotations) (download)
Mon Dec 3 18:30:47 2007 UTC (16 years, 4 months ago) by senoner
File size: 121650 byte(s)
* win32 port: common/Path.cpp :
 - fixed missing drive letter in toLscp()
 network/lscpserver.cpp:
 - added win32 support in VerifyFile()

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

  ViewVC Help
Powered by ViewVC