/[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 1536 - (hide annotations) (download)
Mon Dec 3 16:41:17 2007 UTC (16 years, 3 months ago) by schoenebeck
File size: 121106 byte(s)
* added index bounds check to quite new LSCP command
  "GET FILE INSTRUMENT INFO"

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

  ViewVC Help
Powered by ViewVC