/[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 1026 - (hide annotations) (download)
Sun Jan 14 17:10:59 2007 UTC (13 years, 1 month ago) by schoenebeck
File size: 90524 byte(s)
* extended response of LSCP command "GET FX_SEND INFO" to return the FX
  Send's MIDI controller and current send level and added two new LSCP
  commands "SET FX_SEND MIDI_CONTROLLER" and "SET FX_SEND LEVEL"
  respectively

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 1005 #include "../common/global.h"
28 schoenebeck 35
29 schoenebeck 411 #include <fcntl.h>
30    
31 schoenebeck 401 #if HAVE_SQLITE3
32     # include "sqlite3.h"
33 senkov 397 #endif
34    
35 schoenebeck 411 #include "../engines/EngineFactory.h"
36 schoenebeck 660 #include "../engines/EngineChannelFactory.h"
37 schoenebeck 203 #include "../drivers/audio/AudioOutputDeviceFactory.h"
38     #include "../drivers/midi/MidiInputDeviceFactory.h"
39 schoenebeck 53
40 senkov 170 /**
41     * Below are a few static members of the LSCPServer class.
42     * The big assumption here is that LSCPServer is going to remain a singleton.
43     * These members are used to support client connections.
44     * Class handles multiple connections at the same time using select() and non-blocking recv()
45     * Commands are processed by a single LSCPServer thread.
46     * Notifications are delivered either by the thread that originated them
47     * or (if the resultset is currently in progress) by the LSCPServer thread
48     * after the resultset was sent out.
49     * This makes sure that resultsets can not be interrupted by notifications.
50     * This also makes sure that the thread sending notification is not blocked
51     * by the LSCPServer thread.
52     */
53     fd_set LSCPServer::fdSet;
54     int LSCPServer::currentSocket = -1;
55 schoenebeck 210 std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();
56 senkov 170 std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();
57     std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();
58     std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();
59     Mutex LSCPServer::NotifyMutex = Mutex();
60     Mutex LSCPServer::NotifyBufferMutex = Mutex();
61     Mutex LSCPServer::SubscriptionMutex = Mutex();
62 senkov 360 Mutex LSCPServer::RTNotifyMutex = Mutex();
63 senkov 170
64 senkov 667 LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4) {
65     SocketAddress.sin_family = AF_INET;
66     SocketAddress.sin_addr.s_addr = addr;
67     SocketAddress.sin_port = port;
68 schoenebeck 53 this->pSampler = pSampler;
69 iliev 981 LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT");
70     LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO");
71     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT");
72     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO");
73 schoenebeck 556 LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
74 senkov 170 LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
75     LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
76     LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
77 schoenebeck 556 LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
78 iliev 981 LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
79     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
80     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
81     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
82 senkov 170 LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
83 iliev 778 LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
84 schoenebeck 475 hSocket = -1;
85 schoenebeck 35 }
86    
87 schoenebeck 475 LSCPServer::~LSCPServer() {
88     if (hSocket >= 0) close(hSocket);
89     }
90    
91 schoenebeck 211 /**
92     * Blocks the calling thread until the LSCP Server is initialized and
93     * accepting socket connections, if the server is already initialized then
94     * this method will return immediately.
95     * @param TimeoutSeconds - optional: max. wait time in seconds
96     * (default: 0s)
97     * @param TimeoutNanoSeconds - optional: max wait time in nano seconds
98     * (default: 0ns)
99     * @returns 0 on success, a value less than 0 if timeout exceeded
100     */
101     int LSCPServer::WaitUntilInitialized(long TimeoutSeconds, long TimeoutNanoSeconds) {
102     return Initialized.WaitAndUnlockIf(false, TimeoutSeconds, TimeoutNanoSeconds);
103     }
104    
105 schoenebeck 35 int LSCPServer::Main() {
106 schoenebeck 475 hSocket = socket(AF_INET, SOCK_STREAM, 0);
107 schoenebeck 35 if (hSocket < 0) {
108     std::cerr << "LSCPServer: Could not create server socket." << std::endl;
109 schoenebeck 53 //return -1;
110     exit(EXIT_FAILURE);
111 schoenebeck 35 }
112    
113     if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
114 schoenebeck 227 std::cerr << "LSCPServer: Could not bind server socket, retrying for " << ToString(LSCP_SERVER_BIND_TIMEOUT) << " seconds...";
115     for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds
116     if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
117     if (trial > LSCP_SERVER_BIND_TIMEOUT) {
118     std::cerr << "gave up!" << std::endl;
119     close(hSocket);
120     //return -1;
121     exit(EXIT_FAILURE);
122     }
123     else sleep(1); // sleep 1s
124     }
125     else break; // success
126     }
127 schoenebeck 35 }
128    
129     listen(hSocket, 1);
130 schoenebeck 211 Initialized.Set(true);
131 schoenebeck 35
132     // now wait for client connections and handle their requests
133     sockaddr_in client;
134     int length = sizeof(client);
135 senkov 170 FD_ZERO(&fdSet);
136     FD_SET(hSocket, &fdSet);
137     int maxSessions = hSocket;
138 schoenebeck 203
139 iliev 793 timeval timeout;
140    
141 schoenebeck 35 while (true) {
142 iliev 793 // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
143     {
144     std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
145     std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
146     std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
147     for (; itEngineChannel != itEnd; ++itEngineChannel) {
148     if ((*itEngineChannel)->StatusChanged()) {
149     SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->iSamplerChannelIndex));
150     }
151     }
152     }
153    
154     //Now let's deliver late notifies (if any)
155     NotifyBufferMutex.Lock();
156     for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
157 wylder 814 #ifdef MSG_NOSIGNAL
158 iliev 793 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
159 wylder 814 #else
160     send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
161     #endif
162 iliev 793 }
163 persson 836 bufferedNotifies.clear();
164 iliev 793 NotifyBufferMutex.Unlock();
165    
166     fd_set selectSet = fdSet;
167     timeout.tv_sec = 0;
168     timeout.tv_usec = 100000;
169    
170     int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
171    
172 senkov 170 if (retval == 0)
173 senkov 198 continue; //Nothing try again
174 senkov 170 if (retval == -1) {
175     std::cerr << "LSCPServer: Socket select error." << std::endl;
176     close(hSocket);
177     exit(EXIT_FAILURE);
178     }
179 schoenebeck 203
180 senkov 170 //Accept new connections now (if any)
181     if (FD_ISSET(hSocket, &selectSet)) {
182     int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
183     if (socket < 0) {
184     std::cerr << "LSCPServer: Client connection failed." << std::endl;
185     exit(EXIT_FAILURE);
186     }
187 schoenebeck 35
188 senkov 170 if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
189     std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
190     exit(EXIT_FAILURE);
191     }
192 schoenebeck 35
193 schoenebeck 210 // Parser initialization
194     yyparse_param_t yyparse_param;
195     yyparse_param.pServer = this;
196     yyparse_param.hSession = socket;
197    
198     Sessions.push_back(yyparse_param);
199 senkov 170 FD_SET(socket, &fdSet);
200     if (socket > maxSessions)
201     maxSessions = socket;
202     dmsg(1,("LSCPServer: Client connection established on socket:%d.\n", socket));
203     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection established on socket", socket));
204     continue; //Maybe this was the only selected socket, better select again
205     }
206 schoenebeck 35
207 senkov 170 //Something was selected and it was not the hSocket, so it must be some command(s) coming.
208 schoenebeck 210 for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
209     if (FD_ISSET((*iter).hSession, &selectSet)) { //Was it this socket?
210 senkov 170 if (GetLSCPCommand(iter)) { //Have we read the entire command?
211     dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
212 schoenebeck 219 int dummy; // just a temporary hack to fulfill the restart() function prototype
213     restart(NULL, dummy); // restart the 'scanner'
214 schoenebeck 210 currentSocket = (*iter).hSession; //a hack
215 schoenebeck 475 dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
216 schoenebeck 210 if ((*iter).bVerbose) { // if echo mode enabled
217     AnswerClient(bufferedCommands[currentSocket]);
218     }
219     int result = yyparse(&(*iter));
220 senkov 170 currentSocket = -1; //continuation of a hack
221     dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
222     if (result == LSCP_QUIT) { //Was it a quit command by any chance?
223     CloseConnection(iter);
224     }
225     }
226     //socket may have been closed, iter may be invalid, get out of the loop for now.
227     //we'll be back if there is data.
228 schoenebeck 203 break;
229 senkov 170 }
230     }
231 schoenebeck 35 }
232     }
233    
234 schoenebeck 210 void LSCPServer::CloseConnection( std::vector<yyparse_param_t>::iterator iter ) {
235     int socket = (*iter).hSession;
236 senkov 170 dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));
237     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
238 schoenebeck 210 Sessions.erase(iter);
239 senkov 170 FD_CLR(socket, &fdSet);
240     SubscriptionMutex.Lock(); //Must unsubscribe this socket from all events (if any)
241     for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
242     iter->second.remove(socket);
243     }
244     SubscriptionMutex.Unlock();
245     NotifyMutex.Lock();
246     bufferedCommands.erase(socket);
247     bufferedNotifies.erase(socket);
248     close(socket);
249     NotifyMutex.Unlock();
250     }
251    
252 senkov 360 int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {
253     int subs = 0;
254     SubscriptionMutex.Lock();
255     for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();
256     iter != events.end(); iter++)
257     {
258     subs += eventSubscriptions.count(*iter);
259     }
260     SubscriptionMutex.Unlock();
261     return subs;
262     }
263    
264 senkov 170 void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
265     SubscriptionMutex.Lock();
266     if (eventSubscriptions.count(event.GetType()) == 0) {
267     SubscriptionMutex.Unlock(); //Nobody is subscribed to this event
268     return;
269     }
270     std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();
271     std::list<int>::iterator end = eventSubscriptions[event.GetType()].end();
272     String notify = event.Produce();
273    
274     while (true) {
275     if (NotifyMutex.Trylock()) {
276     for(;iter != end; iter++)
277 wylder 814 #ifdef MSG_NOSIGNAL
278 iliev 707 send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
279 wylder 814 #else
280     send(*iter, notify.c_str(), notify.size(), 0);
281     #endif
282 senkov 170 NotifyMutex.Unlock();
283     break;
284     } else {
285     if (NotifyBufferMutex.Trylock()) {
286     for(;iter != end; iter++)
287     bufferedNotifies[*iter] += notify;
288     NotifyBufferMutex.Unlock();
289     break;
290     }
291     }
292     }
293     SubscriptionMutex.Unlock();
294     }
295    
296     extern int GetLSCPCommand( void *buf, int max_size ) {
297     String command = LSCPServer::bufferedCommands[LSCPServer::currentSocket];
298     if (command.size() == 0) { //Parser wants input but we have nothing.
299     strcpy((char*) buf, "\n"); //So give it an empty command
300     return 1; //to keep it happy.
301     }
302    
303     if (max_size < command.size()) {
304     std::cerr << "getLSCPCommand: Flex buffer too small, ignoring the command." << std::endl;
305     return 0; //This will never happen
306     }
307    
308     strcpy((char*) buf, command.c_str());
309     LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);
310     return command.size();
311     }
312    
313 schoenebeck 35 /**
314 senkov 170 * Will be called to try to read the command from the socket
315     * If command is read, it will return true. Otherwise false is returned.
316     * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.
317     */
318 schoenebeck 210 bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
319     int socket = (*iter).hSession;
320 senkov 170 char c;
321     int i = 0;
322     while (true) {
323     int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now
324     if (result == 0) { //socket was selected, so 0 here means client has closed the connection
325     CloseConnection(iter);
326     break;
327     }
328     if (result == 1) {
329 schoenebeck 203 if (c == '\r')
330 senkov 170 continue; //Ignore CR
331     if (c == '\n') {
332 senkov 184 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
333 iliev 907 bufferedCommands[socket] += "\r\n";
334 senkov 170 return true; //Complete command was read
335     }
336     bufferedCommands[socket] += c;
337     }
338     if (result == -1) {
339     if (errno == EAGAIN) //Would block, try again later.
340     return false;
341     switch(errno) {
342     case EBADF:
343     dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
344     break;
345     case ECONNREFUSED:
346     dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
347     break;
348     case ENOTCONN:
349     dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
350     break;
351     case ENOTSOCK:
352     dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
353     break;
354     case EAGAIN:
355     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"));
356 schoenebeck 203 break;
357     case EINTR:
358 senkov 170 dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
359 schoenebeck 203 break;
360     case EFAULT:
361     dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
362     break;
363     case EINVAL:
364     dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
365     break;
366     case ENOMEM:
367     dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
368     break;
369     default:
370     dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
371     break;
372     }
373 senkov 170 CloseConnection(iter);
374     break;
375     }
376     }
377     return false;
378     }
379    
380     /**
381 schoenebeck 35 * Will be called by the parser whenever it wants to send an answer to the
382     * client / frontend.
383     *
384     * @param ReturnMessage - message that will be send to the client
385     */
386     void LSCPServer::AnswerClient(String ReturnMessage) {
387     dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
388 senkov 170 if (currentSocket != -1) {
389     NotifyMutex.Lock();
390 wylder 814 #ifdef MSG_NOSIGNAL
391 iliev 707 send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
392 wylder 814 #else
393     send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
394     #endif
395 senkov 170 NotifyMutex.Unlock();
396     }
397 schoenebeck 35 }
398    
399 capela 143 /**
400     * Find a created audio output device index.
401     */
402     int LSCPServer::GetAudioOutputDeviceIndex ( AudioOutputDevice *pDevice )
403     {
404     // Search for the created device to get its index
405     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
406     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
407     for (; iter != devices.end(); iter++) {
408     if (iter->second == pDevice)
409     return iter->first;
410     }
411     // Not found.
412     return -1;
413     }
414    
415 senkov 155 /**
416     * Find a created midi input device index.
417     */
418     int LSCPServer::GetMidiInputDeviceIndex ( MidiInputDevice *pDevice )
419     {
420     // Search for the created device to get its index
421     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
422     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
423     for (; iter != devices.end(); iter++) {
424     if (iter->second == pDevice)
425     return iter->first;
426     }
427     // Not found.
428     return -1;
429     }
430    
431 schoenebeck 123 String LSCPServer::CreateAudioOutputDevice(String Driver, std::map<String,String> Parameters) {
432     dmsg(2,("LSCPServer: CreateAudioOutputDevice(Driver=%s)\n", Driver.c_str()));
433     LSCPResultSet result;
434     try {
435     AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
436     // search for the created device to get its index
437 capela 143 int index = GetAudioOutputDeviceIndex(pDevice);
438 schoenebeck 880 if (index == -1) throw Exception("Internal error: could not find created audio output device.");
439 schoenebeck 123 result = index; // success
440     }
441 schoenebeck 880 catch (Exception e) {
442 schoenebeck 123 result.Error(e);
443     }
444     return result.Produce();
445     }
446    
447 senkov 155 String LSCPServer::CreateMidiInputDevice(String Driver, std::map<String,String> Parameters) {
448     dmsg(2,("LSCPServer: CreateMidiInputDevice(Driver=%s)\n", Driver.c_str()));
449     LSCPResultSet result;
450     try {
451     MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
452     // search for the created device to get its index
453     int index = GetMidiInputDeviceIndex(pDevice);
454 schoenebeck 880 if (index == -1) throw Exception("Internal error: could not find created midi input device.");
455 senkov 155 result = index; // success
456     }
457 schoenebeck 880 catch (Exception e) {
458 senkov 155 result.Error(e);
459     }
460     return result.Produce();
461     }
462    
463 schoenebeck 123 String LSCPServer::DestroyAudioOutputDevice(uint DeviceIndex) {
464     dmsg(2,("LSCPServer: DestroyAudioOutputDevice(DeviceIndex=%d)\n", DeviceIndex));
465     LSCPResultSet result;
466     try {
467     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
468 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
469 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
470     pSampler->DestroyAudioOutputDevice(pDevice);
471     }
472 schoenebeck 880 catch (Exception e) {
473 schoenebeck 123 result.Error(e);
474     }
475     return result.Produce();
476     }
477    
478 senkov 155 String LSCPServer::DestroyMidiInputDevice(uint DeviceIndex) {
479     dmsg(2,("LSCPServer: DestroyMidiInputDevice(DeviceIndex=%d)\n", DeviceIndex));
480     LSCPResultSet result;
481     try {
482     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
483 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
484 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
485     pSampler->DestroyMidiInputDevice(pDevice);
486     }
487 schoenebeck 880 catch (Exception e) {
488 senkov 155 result.Error(e);
489     }
490     return result.Produce();
491     }
492    
493 schoenebeck 35 /**
494     * Will be called by the parser to load an instrument.
495     */
496 capela 137 String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel, bool bBackground) {
497 schoenebeck 53 dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
498 senkov 120 LSCPResultSet result;
499 schoenebeck 53 try {
500     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
501 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
502 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
503 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
504 schoenebeck 223 if (!pSamplerChannel->GetAudioOutputDevice())
505 schoenebeck 880 throw Exception("No audio output device connected to sampler channel");
506 capela 137 if (bBackground) {
507 schoenebeck 947 InstrumentManager::instrument_id_t id;
508     id.FileName = Filename;
509     id.Index = uiInstrument;
510     InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
511 capela 137 }
512 schoenebeck 392 else {
513 schoenebeck 411 // tell the engine channel which instrument to load
514     pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrument);
515 schoenebeck 392 // actually start to load the instrument (blocks until completed)
516 schoenebeck 411 pEngineChannel->LoadInstrument();
517 schoenebeck 392 }
518 schoenebeck 53 }
519 schoenebeck 880 catch (Exception e) {
520 senkov 120 result.Error(e);
521 schoenebeck 53 }
522 senkov 120 return result.Produce();
523 schoenebeck 35 }
524    
525     /**
526 schoenebeck 411 * Will be called by the parser to assign a sampler engine type to a
527     * sampler channel.
528 schoenebeck 35 */
529 schoenebeck 411 String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
530 schoenebeck 705 dmsg(2,("LSCPServer: SetEngineType(EngineName=%s,uiSamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
531 senkov 120 LSCPResultSet result;
532 schoenebeck 475 try {
533 schoenebeck 53 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
534 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
535 senkov 360 LockRTNotify();
536 schoenebeck 411 pSamplerChannel->SetEngineType(EngineName);
537 schoenebeck 705 if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
538 senkov 360 UnlockRTNotify();
539 schoenebeck 53 }
540 schoenebeck 880 catch (Exception e) {
541 senkov 120 result.Error(e);
542 schoenebeck 53 }
543 senkov 120 return result.Produce();
544 schoenebeck 35 }
545    
546     /**
547     * Will be called by the parser to get the amount of sampler channels.
548     */
549     String LSCPServer::GetChannels() {
550     dmsg(2,("LSCPServer: GetChannels()\n"));
551 senkov 120 LSCPResultSet result;
552     result.Add(pSampler->SamplerChannels());
553     return result.Produce();
554 schoenebeck 35 }
555    
556     /**
557 schoenebeck 209 * Will be called by the parser to get the list of sampler channels.
558     */
559     String LSCPServer::ListChannels() {
560     dmsg(2,("LSCPServer: ListChannels()\n"));
561     String list;
562     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
563     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
564     for (; iter != channels.end(); iter++) {
565     if (list != "") list += ",";
566     list += ToString(iter->first);
567     }
568     LSCPResultSet result;
569     result.Add(list);
570     return result.Produce();
571     }
572    
573     /**
574 schoenebeck 35 * Will be called by the parser to add a sampler channel.
575     */
576     String LSCPServer::AddChannel() {
577     dmsg(2,("LSCPServer: AddChannel()\n"));
578 persson 841 LockRTNotify();
579 schoenebeck 53 SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
580 persson 841 UnlockRTNotify();
581 senkov 120 LSCPResultSet result(pSamplerChannel->Index());
582     return result.Produce();
583 schoenebeck 35 }
584    
585     /**
586     * Will be called by the parser to remove a sampler channel.
587     */
588 schoenebeck 53 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
589     dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
590 senkov 120 LSCPResultSet result;
591 senkov 360 LockRTNotify();
592 schoenebeck 53 pSampler->RemoveSamplerChannel(uiSamplerChannel);
593 senkov 360 UnlockRTNotify();
594 senkov 120 return result.Produce();
595 schoenebeck 35 }
596    
597     /**
598 capela 527 * Will be called by the parser to get the amount of all available engines.
599 schoenebeck 35 */
600     String LSCPServer::GetAvailableEngines() {
601     dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
602 schoenebeck 905 LSCPResultSet result;
603     try {
604     int n = EngineFactory::AvailableEngineTypes().size();
605     result.Add(n);
606     }
607     catch (Exception e) {
608     result.Error(e);
609     }
610 senkov 120 return result.Produce();
611 schoenebeck 35 }
612    
613     /**
614 capela 527 * Will be called by the parser to get a list of all available engines.
615     */
616     String LSCPServer::ListAvailableEngines() {
617     dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
618 schoenebeck 905 LSCPResultSet result;
619     try {
620     String s = EngineFactory::AvailableEngineTypesAsString();
621     result.Add(s);
622     }
623     catch (Exception e) {
624     result.Error(e);
625     }
626 capela 527 return result.Produce();
627     }
628    
629     /**
630 schoenebeck 411 * Will be called by the parser to get descriptions for a particular
631     * sampler engine.
632 schoenebeck 35 */
633     String LSCPServer::GetEngineInfo(String EngineName) {
634     dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
635 senkov 120 LSCPResultSet result;
636 persson 841 LockRTNotify();
637 schoenebeck 53 try {
638 schoenebeck 411 Engine* pEngine = EngineFactory::Create(EngineName);
639     result.Add("DESCRIPTION", pEngine->Description());
640     result.Add("VERSION", pEngine->Version());
641 schoenebeck 660 EngineFactory::Destroy(pEngine);
642 schoenebeck 53 }
643 schoenebeck 880 catch (Exception e) {
644 senkov 120 result.Error(e);
645 schoenebeck 53 }
646 persson 841 UnlockRTNotify();
647 senkov 120 return result.Produce();
648 schoenebeck 35 }
649    
650     /**
651     * Will be called by the parser to get informations about a particular
652     * sampler channel.
653     */
654 schoenebeck 53 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
655     dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
656 senkov 120 LSCPResultSet result;
657 senkov 113 try {
658     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
659 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
660 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
661 schoenebeck 123
662 senkov 117 //Defaults values
663     String EngineName = "NONE";
664 schoenebeck 225 float Volume = 0.0f;
665 senkov 117 String InstrumentFileName = "NONE";
666 senkov 376 String InstrumentName = "NONE";
667 capela 133 int InstrumentIndex = -1;
668     int InstrumentStatus = -1;
669 schoenebeck 225 int AudioOutputChannels = 0;
670     String AudioRouting;
671 schoenebeck 705 int Mute = 0;
672     bool Solo = false;
673 schoenebeck 973 String MidiInstrumentMap;
674 schoenebeck 123
675 schoenebeck 475 if (pEngineChannel) {
676     EngineName = pEngineChannel->EngineName();
677 schoenebeck 411 AudioOutputChannels = pEngineChannel->Channels();
678     Volume = pEngineChannel->Volume();
679     InstrumentStatus = pEngineChannel->InstrumentStatus();
680     InstrumentIndex = pEngineChannel->InstrumentIndex();
681     if (InstrumentIndex != -1) {
682     InstrumentFileName = pEngineChannel->InstrumentFileName();
683     InstrumentName = pEngineChannel->InstrumentName();
684     }
685     for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
686 schoenebeck 225 if (AudioRouting != "") AudioRouting += ",";
687 schoenebeck 411 AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
688 schoenebeck 225 }
689 schoenebeck 705 Mute = pEngineChannel->GetMute();
690     Solo = pEngineChannel->GetSolo();
691 schoenebeck 973 if (pEngineChannel->UsesNoMidiInstrumentMap())
692     MidiInstrumentMap = "NONE";
693     else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
694     MidiInstrumentMap = "DEFAULT";
695     else
696     MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
697 senkov 113 }
698 senkov 117
699     result.Add("ENGINE_NAME", EngineName);
700     result.Add("VOLUME", Volume);
701    
702 capela 143 //Some not-so-hardcoded stuff to make GUI look good
703     result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
704 schoenebeck 225 result.Add("AUDIO_OUTPUT_CHANNELS", AudioOutputChannels);
705     result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
706 senkov 113
707 capela 159 result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
708     result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
709 schoenebeck 675 if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
710 schoenebeck 274 else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
711 capela 159
712 senkov 117 result.Add("INSTRUMENT_FILE", InstrumentFileName);
713     result.Add("INSTRUMENT_NR", InstrumentIndex);
714 senkov 376 result.Add("INSTRUMENT_NAME", InstrumentName);
715 capela 133 result.Add("INSTRUMENT_STATUS", InstrumentStatus);
716 schoenebeck 705 result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
717     result.Add("SOLO", Solo);
718 schoenebeck 973 result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
719 senkov 113 }
720 schoenebeck 880 catch (Exception e) {
721 senkov 120 result.Error(e);
722 senkov 113 }
723 senkov 120 return result.Produce();
724 schoenebeck 35 }
725    
726     /**
727     * Will be called by the parser to get the amount of active voices on a
728     * particular sampler channel.
729     */
730 schoenebeck 53 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
731     dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
732 senkov 120 LSCPResultSet result;
733 schoenebeck 53 try {
734     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
735 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
736 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
737 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine loaded on sampler channel");
738     if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
739 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->VoiceCount());
740 schoenebeck 53 }
741 schoenebeck 880 catch (Exception e) {
742 senkov 120 result.Error(e);
743 schoenebeck 53 }
744 senkov 120 return result.Produce();
745 schoenebeck 35 }
746    
747     /**
748     * Will be called by the parser to get the amount of active disk streams on a
749     * particular sampler channel.
750     */
751 schoenebeck 53 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
752     dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
753 senkov 120 LSCPResultSet result;
754 schoenebeck 53 try {
755     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
756 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
757 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
758 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
759     if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
760 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
761 schoenebeck 53 }
762 schoenebeck 880 catch (Exception e) {
763 senkov 120 result.Error(e);
764 schoenebeck 53 }
765 senkov 120 return result.Produce();
766 schoenebeck 35 }
767    
768     /**
769     * Will be called by the parser to get the buffer fill states of all disk
770     * streams on a particular sampler channel.
771     */
772 schoenebeck 53 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
773     dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
774 senkov 120 LSCPResultSet result;
775 schoenebeck 53 try {
776     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
777 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
778 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
779 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
780     if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
781 schoenebeck 411 if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
782 senkov 129 else {
783     switch (ResponseType) {
784     case fill_response_bytes:
785 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillBytes());
786     break;
787 senkov 129 case fill_response_percentage:
788 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
789     break;
790 senkov 129 default:
791 schoenebeck 880 throw Exception("Unknown fill response type");
792 senkov 129 }
793     }
794 schoenebeck 53 }
795 schoenebeck 880 catch (Exception e) {
796 senkov 120 result.Error(e);
797 schoenebeck 53 }
798 senkov 120 return result.Produce();
799 schoenebeck 35 }
800    
801 schoenebeck 123 String LSCPServer::GetAvailableAudioOutputDrivers() {
802     dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
803 senkov 120 LSCPResultSet result;
804 schoenebeck 53 try {
805 capela 527 int n = AudioOutputDeviceFactory::AvailableDrivers().size();
806     result.Add(n);
807     }
808 schoenebeck 880 catch (Exception e) {
809 capela 527 result.Error(e);
810     }
811     return result.Produce();
812     }
813    
814     String LSCPServer::ListAvailableAudioOutputDrivers() {
815     dmsg(2,("LSCPServer: ListAvailableAudioOutputDrivers()\n"));
816     LSCPResultSet result;
817     try {
818 schoenebeck 123 String s = AudioOutputDeviceFactory::AvailableDriversAsString();
819     result.Add(s);
820 schoenebeck 53 }
821 schoenebeck 880 catch (Exception e) {
822 schoenebeck 123 result.Error(e);
823 schoenebeck 53 }
824 senkov 120 return result.Produce();
825 schoenebeck 35 }
826    
827 senkov 155 String LSCPServer::GetAvailableMidiInputDrivers() {
828     dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
829     LSCPResultSet result;
830     try {
831 capela 527 int n = MidiInputDeviceFactory::AvailableDrivers().size();
832     result.Add(n);
833     }
834 schoenebeck 880 catch (Exception e) {
835 capela 527 result.Error(e);
836     }
837     return result.Produce();
838     }
839    
840     String LSCPServer::ListAvailableMidiInputDrivers() {
841     dmsg(2,("LSCPServer: ListAvailableMidiInputDrivers()\n"));
842     LSCPResultSet result;
843     try {
844 senkov 155 String s = MidiInputDeviceFactory::AvailableDriversAsString();
845     result.Add(s);
846     }
847 schoenebeck 880 catch (Exception e) {
848 senkov 155 result.Error(e);
849     }
850     return result.Produce();
851     }
852    
853     String LSCPServer::GetMidiInputDriverInfo(String Driver) {
854     dmsg(2,("LSCPServer: GetMidiInputDriverInfo(Driver=%s)\n",Driver.c_str()));
855     LSCPResultSet result;
856     try {
857     result.Add("DESCRIPTION", MidiInputDeviceFactory::GetDriverDescription(Driver));
858     result.Add("VERSION", MidiInputDeviceFactory::GetDriverVersion(Driver));
859    
860     std::map<String,DeviceCreationParameter*> parameters = MidiInputDeviceFactory::GetAvailableDriverParameters(Driver);
861     if (parameters.size()) { // if there are parameters defined for this driver
862     String s;
863     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
864     for (;iter != parameters.end(); iter++) {
865     if (s != "") s += ",";
866     s += iter->first;
867     }
868     result.Add("PARAMETERS", s);
869     }
870     }
871 schoenebeck 880 catch (Exception e) {
872 senkov 155 result.Error(e);
873     }
874     return result.Produce();
875     }
876    
877 schoenebeck 123 String LSCPServer::GetAudioOutputDriverInfo(String Driver) {
878     dmsg(2,("LSCPServer: GetAudioOutputDriverInfo(Driver=%s)\n",Driver.c_str()));
879     LSCPResultSet result;
880     try {
881     result.Add("DESCRIPTION", AudioOutputDeviceFactory::GetDriverDescription(Driver));
882     result.Add("VERSION", AudioOutputDeviceFactory::GetDriverVersion(Driver));
883    
884     std::map<String,DeviceCreationParameter*> parameters = AudioOutputDeviceFactory::GetAvailableDriverParameters(Driver);
885     if (parameters.size()) { // if there are parameters defined for this driver
886     String s;
887     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
888     for (;iter != parameters.end(); iter++) {
889     if (s != "") s += ",";
890     s += iter->first;
891     }
892     result.Add("PARAMETERS", s);
893     }
894     }
895 schoenebeck 880 catch (Exception e) {
896 schoenebeck 123 result.Error(e);
897     }
898     return result.Produce();
899     }
900    
901 senkov 155 String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
902 schoenebeck 226 dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
903 senkov 155 LSCPResultSet result;
904     try {
905     DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
906     result.Add("TYPE", pParameter->Type());
907     result.Add("DESCRIPTION", pParameter->Description());
908 schoenebeck 223 result.Add("MANDATORY", pParameter->Mandatory());
909     result.Add("FIX", pParameter->Fix());
910     result.Add("MULTIPLICITY", pParameter->Multiplicity());
911 schoenebeck 226 optional<String> oDepends = pParameter->Depends();
912     optional<String> oDefault = pParameter->Default(DependencyList);
913     optional<String> oRangeMin = pParameter->RangeMin(DependencyList);
914     optional<String> oRangeMax = pParameter->RangeMax(DependencyList);
915     optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
916     if (oDepends) result.Add("DEPENDS", *oDepends);
917     if (oDefault) result.Add("DEFAULT", *oDefault);
918     if (oRangeMin) result.Add("RANGE_MIN", *oRangeMin);
919     if (oRangeMax) result.Add("RANGE_MAX", *oRangeMax);
920     if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
921 senkov 155 }
922 schoenebeck 880 catch (Exception e) {
923 senkov 155 result.Error(e);
924     }
925     return result.Produce();
926     }
927    
928 schoenebeck 123 String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
929 schoenebeck 226 dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
930 schoenebeck 123 LSCPResultSet result;
931     try {
932     DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
933     result.Add("TYPE", pParameter->Type());
934     result.Add("DESCRIPTION", pParameter->Description());
935 schoenebeck 223 result.Add("MANDATORY", pParameter->Mandatory());
936     result.Add("FIX", pParameter->Fix());
937     result.Add("MULTIPLICITY", pParameter->Multiplicity());
938 schoenebeck 226 optional<String> oDepends = pParameter->Depends();
939     optional<String> oDefault = pParameter->Default(DependencyList);
940     optional<String> oRangeMin = pParameter->RangeMin(DependencyList);
941     optional<String> oRangeMax = pParameter->RangeMax(DependencyList);
942     optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
943     if (oDepends) result.Add("DEPENDS", *oDepends);
944     if (oDefault) result.Add("DEFAULT", *oDefault);
945     if (oRangeMin) result.Add("RANGE_MIN", *oRangeMin);
946     if (oRangeMax) result.Add("RANGE_MAX", *oRangeMax);
947     if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
948 schoenebeck 123 }
949 schoenebeck 880 catch (Exception e) {
950 schoenebeck 123 result.Error(e);
951     }
952     return result.Produce();
953     }
954    
955     String LSCPServer::GetAudioOutputDeviceCount() {
956     dmsg(2,("LSCPServer: GetAudioOutputDeviceCount()\n"));
957     LSCPResultSet result;
958     try {
959     uint count = pSampler->AudioOutputDevices();
960 senkov 138 result.Add(count); // success
961 schoenebeck 123 }
962 schoenebeck 880 catch (Exception e) {
963 schoenebeck 123 result.Error(e);
964     }
965     return result.Produce();
966     }
967    
968 senkov 155 String LSCPServer::GetMidiInputDeviceCount() {
969     dmsg(2,("LSCPServer: GetMidiInputDeviceCount()\n"));
970     LSCPResultSet result;
971     try {
972     uint count = pSampler->MidiInputDevices();
973     result.Add(count); // success
974     }
975 schoenebeck 880 catch (Exception e) {
976 senkov 155 result.Error(e);
977     }
978     return result.Produce();
979     }
980    
981 schoenebeck 123 String LSCPServer::GetAudioOutputDevices() {
982     dmsg(2,("LSCPServer: GetAudioOutputDevices()\n"));
983     LSCPResultSet result;
984     try {
985     String s;
986     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
987     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
988     for (; iter != devices.end(); iter++) {
989     if (s != "") s += ",";
990     s += ToString(iter->first);
991     }
992     result.Add(s);
993     }
994 schoenebeck 880 catch (Exception e) {
995 schoenebeck 123 result.Error(e);
996     }
997     return result.Produce();
998     }
999    
1000 senkov 155 String LSCPServer::GetMidiInputDevices() {
1001     dmsg(2,("LSCPServer: GetMidiInputDevices()\n"));
1002     LSCPResultSet result;
1003     try {
1004     String s;
1005     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1006     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1007     for (; iter != devices.end(); iter++) {
1008     if (s != "") s += ",";
1009     s += ToString(iter->first);
1010     }
1011     result.Add(s);
1012     }
1013 schoenebeck 880 catch (Exception e) {
1014 senkov 155 result.Error(e);
1015     }
1016     return result.Produce();
1017     }
1018    
1019 schoenebeck 123 String LSCPServer::GetAudioOutputDeviceInfo(uint DeviceIndex) {
1020     dmsg(2,("LSCPServer: GetAudioOutputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1021     LSCPResultSet result;
1022     try {
1023     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1024 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1025 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
1026 schoenebeck 221 result.Add("DRIVER", pDevice->Driver());
1027 schoenebeck 123 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1028     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1029     for (; iter != parameters.end(); iter++) {
1030     result.Add(iter->first, iter->second->Value());
1031     }
1032     }
1033 schoenebeck 880 catch (Exception e) {
1034 schoenebeck 123 result.Error(e);
1035     }
1036     return result.Produce();
1037     }
1038    
1039 senkov 155 String LSCPServer::GetMidiInputDeviceInfo(uint DeviceIndex) {
1040     dmsg(2,("LSCPServer: GetMidiInputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1041     LSCPResultSet result;
1042     try {
1043     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1044 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1045 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1046 schoenebeck 221 result.Add("DRIVER", pDevice->Driver());
1047 senkov 155 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1048     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1049     for (; iter != parameters.end(); iter++) {
1050     result.Add(iter->first, iter->second->Value());
1051     }
1052     }
1053 schoenebeck 880 catch (Exception e) {
1054 senkov 155 result.Error(e);
1055     }
1056     return result.Produce();
1057     }
1058     String LSCPServer::GetMidiInputPortInfo(uint DeviceIndex, uint PortIndex) {
1059     dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
1060     LSCPResultSet result;
1061     try {
1062 schoenebeck 223 // get MIDI input device
1063 senkov 155 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1064 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1065 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1066 schoenebeck 223
1067     // get MIDI port
1068 schoenebeck 221 MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1069 schoenebeck 880 if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1070 schoenebeck 223
1071     // return the values of all MIDI port parameters
1072 schoenebeck 221 std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1073     std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1074 senkov 155 for (; iter != parameters.end(); iter++) {
1075     result.Add(iter->first, iter->second->Value());
1076     }
1077     }
1078 schoenebeck 880 catch (Exception e) {
1079 senkov 155 result.Error(e);
1080     }
1081     return result.Produce();
1082     }
1083    
1084 schoenebeck 123 String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
1085     dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%d,ChannelId)\n",DeviceId,ChannelId));
1086     LSCPResultSet result;
1087     try {
1088     // get audio output device
1089     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1090 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1091 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1092    
1093     // get audio channel
1094     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1095 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1096 schoenebeck 123
1097     // return the values of all audio channel parameters
1098     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1099     std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1100     for (; iter != parameters.end(); iter++) {
1101     result.Add(iter->first, iter->second->Value());
1102     }
1103     }
1104 schoenebeck 880 catch (Exception e) {
1105 schoenebeck 123 result.Error(e);
1106     }
1107     return result.Produce();
1108     }
1109    
1110 senkov 185 String LSCPServer::GetMidiInputPortParameterInfo(uint DeviceId, uint PortId, String ParameterName) {
1111     dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
1112     LSCPResultSet result;
1113     try {
1114 schoenebeck 223 // get MIDI input device
1115     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1116 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1117 schoenebeck 223 MidiInputDevice* pDevice = devices[DeviceId];
1118 senkov 185
1119 schoenebeck 221 // get midi port
1120     MidiInputPort* pPort = pDevice->GetPort(PortId);
1121 schoenebeck 880 if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1122 senkov 185
1123 schoenebeck 223 // get desired port parameter
1124     std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1125 schoenebeck 880 if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1126 schoenebeck 223 DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1127 schoenebeck 203
1128 senkov 185 // return all fields of this audio channel parameter
1129     result.Add("TYPE", pParameter->Type());
1130     result.Add("DESCRIPTION", pParameter->Description());
1131     result.Add("FIX", pParameter->Fix());
1132     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1133 schoenebeck 223 if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
1134     if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
1135     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1136 senkov 185 }
1137 schoenebeck 880 catch (Exception e) {
1138 senkov 185 result.Error(e);
1139     }
1140     return result.Produce();
1141     }
1142    
1143 schoenebeck 123 String LSCPServer::GetAudioOutputChannelParameterInfo(uint DeviceId, uint ChannelId, String ParameterName) {
1144     dmsg(2,("LSCPServer: GetAudioOutputChannelParameterInfo(DeviceId=%d,ChannelId=%d,ParameterName=%s)\n",DeviceId,ChannelId,ParameterName.c_str()));
1145     LSCPResultSet result;
1146     try {
1147     // get audio output device
1148     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1149 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1150 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1151    
1152     // get audio channel
1153     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1154 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1155 schoenebeck 123
1156     // get desired audio channel parameter
1157     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1158 schoenebeck 880 if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1159 schoenebeck 123 DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1160    
1161     // return all fields of this audio channel parameter
1162     result.Add("TYPE", pParameter->Type());
1163     result.Add("DESCRIPTION", pParameter->Description());
1164     result.Add("FIX", pParameter->Fix());
1165     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1166 schoenebeck 223 if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
1167     if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
1168     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1169 schoenebeck 123 }
1170 schoenebeck 880 catch (Exception e) {
1171 schoenebeck 123 result.Error(e);
1172     }
1173     return result.Produce();
1174     }
1175    
1176     String LSCPServer::SetAudioOutputChannelParameter(uint DeviceId, uint ChannelId, String ParamKey, String ParamVal) {
1177     dmsg(2,("LSCPServer: SetAudioOutputChannelParameter(DeviceId=%d,ChannelId=%d,ParamKey=%s,ParamVal=%s)\n",DeviceId,ChannelId,ParamKey.c_str(),ParamVal.c_str()));
1178     LSCPResultSet result;
1179     try {
1180     // get audio output device
1181     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1182 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1183 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1184    
1185     // get audio channel
1186     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1187 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1188 schoenebeck 123
1189     // get desired audio channel parameter
1190     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1191 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1192 schoenebeck 123 DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1193    
1194     // set new channel parameter value
1195     pParameter->SetValue(ParamVal);
1196 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1197 schoenebeck 123 }
1198 schoenebeck 880 catch (Exception e) {
1199 schoenebeck 123 result.Error(e);
1200     }
1201     return result.Produce();
1202     }
1203    
1204     String LSCPServer::SetAudioOutputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1205     dmsg(2,("LSCPServer: SetAudioOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1206     LSCPResultSet result;
1207     try {
1208     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1209 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1210 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
1211     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1212 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1213 schoenebeck 123 parameters[ParamKey]->SetValue(ParamVal);
1214 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1215 schoenebeck 123 }
1216 schoenebeck 880 catch (Exception e) {
1217 schoenebeck 123 result.Error(e);
1218     }
1219     return result.Produce();
1220     }
1221    
1222 senkov 155 String LSCPServer::SetMidiInputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1223     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1224     LSCPResultSet result;
1225     try {
1226     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1227 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1228 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1229     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1230 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1231 senkov 155 parameters[ParamKey]->SetValue(ParamVal);
1232 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1233 senkov 155 }
1234 schoenebeck 880 catch (Exception e) {
1235 senkov 155 result.Error(e);
1236     }
1237     return result.Produce();
1238     }
1239    
1240     String LSCPServer::SetMidiInputPortParameter(uint DeviceIndex, uint PortIndex, String ParamKey, String ParamVal) {
1241     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1242     LSCPResultSet result;
1243     try {
1244 schoenebeck 223 // get MIDI input device
1245 senkov 155 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1246 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1247 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1248 schoenebeck 223
1249     // get MIDI port
1250 schoenebeck 221 MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1251 schoenebeck 880 if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1252 schoenebeck 223
1253     // set port parameter value
1254 schoenebeck 221 std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1255 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1256 senkov 155 parameters[ParamKey]->SetValue(ParamVal);
1257 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1258 senkov 155 }
1259 schoenebeck 880 catch (Exception e) {
1260 senkov 155 result.Error(e);
1261     }
1262     return result.Produce();
1263     }
1264    
1265 schoenebeck 35 /**
1266     * Will be called by the parser to change the audio output channel for
1267     * playback on a particular sampler channel.
1268     */
1269 schoenebeck 123 String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1270     dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1271 schoenebeck 225 LSCPResultSet result;
1272     try {
1273     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1274 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1275 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1276 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1277     if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1278 schoenebeck 411 pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1279 schoenebeck 225 }
1280 schoenebeck 880 catch (Exception e) {
1281 schoenebeck 225 result.Error(e);
1282     }
1283     return result.Produce();
1284 schoenebeck 35 }
1285    
1286 capela 159 String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1287     dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1288     LSCPResultSet result;
1289 persson 841 LockRTNotify();
1290 capela 159 try {
1291     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1292 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1293 capela 159 std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1294 schoenebeck 880 if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1295 capela 159 AudioOutputDevice* pDevice = devices[AudioDeviceId];
1296     pSamplerChannel->SetAudioOutputDevice(pDevice);
1297     }
1298 schoenebeck 880 catch (Exception e) {
1299 capela 159 result.Error(e);
1300     }
1301 persson 841 UnlockRTNotify();
1302 capela 159 return result.Produce();
1303     }
1304    
1305 capela 143 String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1306     dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1307     LSCPResultSet result;
1308 persson 841 LockRTNotify();
1309 capela 143 try {
1310     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1311 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1312 capela 143 // Driver type name aliasing...
1313 schoenebeck 226 if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1314     if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1315 capela 143 // Check if there's one audio output device already created
1316     // for the intended audio driver type (AudioOutputDriver)...
1317     AudioOutputDevice *pDevice = NULL;
1318     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1319     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1320     for (; iter != devices.end(); iter++) {
1321     if ((iter->second)->Driver() == AudioOutputDriver) {
1322     pDevice = iter->second;
1323     break;
1324     }
1325     }
1326     // If it doesn't exist, create a new one with default parameters...
1327     if (pDevice == NULL) {
1328     std::map<String,String> params;
1329     pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1330     }
1331     // Must have a device...
1332     if (pDevice == NULL)
1333 schoenebeck 880 throw Exception("Internal error: could not create audio output device.");
1334 capela 143 // Set it as the current channel device...
1335     pSamplerChannel->SetAudioOutputDevice(pDevice);
1336     }
1337 schoenebeck 880 catch (Exception e) {
1338 capela 143 result.Error(e);
1339     }
1340 persson 841 UnlockRTNotify();
1341 capela 143 return result.Produce();
1342     }
1343    
1344 capela 159 String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
1345     dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
1346 senkov 120 LSCPResultSet result;
1347 schoenebeck 53 try {
1348     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1349 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1350 capela 159 pSamplerChannel->SetMidiInputPort(MIDIPort);
1351 schoenebeck 53 }
1352 schoenebeck 880 catch (Exception e) {
1353 senkov 120 result.Error(e);
1354 schoenebeck 53 }
1355 senkov 120 return result.Produce();
1356 schoenebeck 53 }
1357    
1358 capela 159 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
1359     dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
1360 senkov 120 LSCPResultSet result;
1361 senkov 68 try {
1362     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1363 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1364 schoenebeck 675 pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
1365 senkov 68 }
1366 schoenebeck 880 catch (Exception e) {
1367 senkov 120 result.Error(e);
1368 senkov 68 }
1369 senkov 120 return result.Produce();
1370 schoenebeck 35 }
1371    
1372 capela 159 String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
1373     dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
1374 schoenebeck 123 LSCPResultSet result;
1375     try {
1376 capela 159 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1377 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1378 capela 159 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1379 schoenebeck 880 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1380 capela 159 MidiInputDevice* pDevice = devices[MIDIDeviceId];
1381     pSamplerChannel->SetMidiInputDevice(pDevice);
1382 schoenebeck 123 }
1383 schoenebeck 880 catch (Exception e) {
1384 schoenebeck 123 result.Error(e);
1385     }
1386     return result.Produce();
1387     }
1388    
1389 capela 159 String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
1390     dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
1391     LSCPResultSet result;
1392     try {
1393     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1394 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1395 capela 159 // Driver type name aliasing...
1396 schoenebeck 226 if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
1397 capela 159 // Check if there's one MIDI input device already created
1398     // for the intended MIDI driver type (MidiInputDriver)...
1399     MidiInputDevice *pDevice = NULL;
1400     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1401     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1402     for (; iter != devices.end(); iter++) {
1403     if ((iter->second)->Driver() == MidiInputDriver) {
1404     pDevice = iter->second;
1405     break;
1406     }
1407     }
1408     // If it doesn't exist, create a new one with default parameters...
1409     if (pDevice == NULL) {
1410     std::map<String,String> params;
1411     pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1412     // Make it with at least one initial port.
1413     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1414 schoenebeck 221 parameters["PORTS"]->SetValue("1");
1415 capela 159 }
1416     // Must have a device...
1417     if (pDevice == NULL)
1418 schoenebeck 880 throw Exception("Internal error: could not create MIDI input device.");
1419 capela 159 // Set it as the current channel device...
1420     pSamplerChannel->SetMidiInputDevice(pDevice);
1421     }
1422 schoenebeck 880 catch (Exception e) {
1423 capela 159 result.Error(e);
1424     }
1425     return result.Produce();
1426     }
1427    
1428 schoenebeck 35 /**
1429 capela 159 * Will be called by the parser to change the MIDI input device, port and channel on which
1430     * engine of a particular sampler channel should listen to.
1431     */
1432     String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
1433     dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
1434     LSCPResultSet result;
1435     try {
1436     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1437 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1438 capela 159 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1439 schoenebeck 880 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1440 capela 159 MidiInputDevice* pDevice = devices[MIDIDeviceId];
1441 schoenebeck 675 pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
1442 capela 159 }
1443 schoenebeck 880 catch (Exception e) {
1444 capela 159 result.Error(e);
1445     }
1446     return result.Produce();
1447     }
1448    
1449     /**
1450 schoenebeck 35 * Will be called by the parser to change the global volume factor on a
1451     * particular sampler channel.
1452     */
1453 schoenebeck 225 String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
1454     dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
1455 senkov 120 LSCPResultSet result;
1456 schoenebeck 53 try {
1457     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1458 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1459 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1460 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1461 schoenebeck 411 pEngineChannel->Volume(dVolume);
1462 schoenebeck 53 }
1463 schoenebeck 880 catch (Exception e) {
1464 senkov 120 result.Error(e);
1465 schoenebeck 53 }
1466 senkov 120 return result.Produce();
1467 schoenebeck 35 }
1468    
1469     /**
1470 schoenebeck 705 * Will be called by the parser to mute/unmute particular sampler channel.
1471     */
1472     String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
1473     dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
1474     LSCPResultSet result;
1475     try {
1476     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1477 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1478 schoenebeck 705
1479     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1480 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1481 schoenebeck 705
1482     if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
1483     else pEngineChannel->SetMute(1);
1484 schoenebeck 880 } catch (Exception e) {
1485 schoenebeck 705 result.Error(e);
1486     }
1487     return result.Produce();
1488     }
1489    
1490     /**
1491     * Will be called by the parser to solo particular sampler channel.
1492     */
1493     String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
1494     dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
1495     LSCPResultSet result;
1496     try {
1497     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1498 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1499 schoenebeck 705
1500     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1501 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
1502 schoenebeck 705
1503     bool oldSolo = pEngineChannel->GetSolo();
1504     bool hadSoloChannel = HasSoloChannel();
1505 schoenebeck 1009
1506 schoenebeck 705 pEngineChannel->SetSolo(bSolo);
1507 schoenebeck 1009
1508 schoenebeck 705 if(!oldSolo && bSolo) {
1509     if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
1510     if(!hadSoloChannel) MuteNonSoloChannels();
1511     }
1512 schoenebeck 1009
1513 schoenebeck 705 if(oldSolo && !bSolo) {
1514     if(!HasSoloChannel()) UnmuteChannels();
1515     else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
1516     }
1517 schoenebeck 880 } catch (Exception e) {
1518 schoenebeck 705 result.Error(e);
1519     }
1520     return result.Produce();
1521     }
1522    
1523     /**
1524     * Determines whether there is at least one solo channel in the channel list.
1525     *
1526     * @returns true if there is at least one solo channel in the channel list,
1527     * false otherwise.
1528     */
1529     bool LSCPServer::HasSoloChannel() {
1530     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1531     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1532     for (; iter != channels.end(); iter++) {
1533     EngineChannel* c = iter->second->GetEngineChannel();
1534     if(c && c->GetSolo()) return true;
1535     }
1536    
1537     return false;
1538     }
1539    
1540     /**
1541     * Mutes all unmuted non-solo channels. Notice that the channels are muted
1542     * with -1 which indicates that they are muted because of the presence
1543     * of a solo channel(s). Channels muted with -1 will be automatically unmuted
1544     * when there are no solo channels left.
1545     */
1546     void LSCPServer::MuteNonSoloChannels() {
1547     dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
1548     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1549     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1550     for (; iter != channels.end(); iter++) {
1551     EngineChannel* c = iter->second->GetEngineChannel();
1552     if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
1553     }
1554     }
1555    
1556     /**
1557     * Unmutes all channels that are muted because of the presence
1558     * of a solo channel(s).
1559     */
1560     void LSCPServer::UnmuteChannels() {
1561     dmsg(2,("LSCPServer: UnmuteChannels()\n"));
1562     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1563     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1564     for (; iter != channels.end(); iter++) {
1565     EngineChannel* c = iter->second->GetEngineChannel();
1566     if(c && c->GetMute() == -1) c->SetMute(0);
1567     }
1568     }
1569    
1570 schoenebeck 973 String LSCPServer::AddOrReplaceMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg, String EngineType, String InstrumentFile, uint InstrumentIndex, float Volume, MidiInstrumentMapper::mode_t LoadMode, String Name) {
1571 schoenebeck 947 dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
1572    
1573     midi_prog_index_t idx;
1574 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1575     idx.midi_bank_lsb = MidiBank & 0x7f;
1576 schoenebeck 947 idx.midi_prog = MidiProg;
1577    
1578     MidiInstrumentMapper::entry_t entry;
1579     entry.EngineName = EngineType;
1580     entry.InstrumentFile = InstrumentFile;
1581     entry.InstrumentIndex = InstrumentIndex;
1582     entry.LoadMode = LoadMode;
1583     entry.Volume = Volume;
1584     entry.Name = Name;
1585    
1586     LSCPResultSet result;
1587     try {
1588     // PERSISTENT mapping commands might bloock for a long time, so in
1589     // that case we add/replace the mapping in another thread
1590     bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT);
1591 schoenebeck 973 MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
1592 schoenebeck 947 } catch (Exception e) {
1593     result.Error(e);
1594     }
1595     return result.Produce();
1596     }
1597    
1598 schoenebeck 973 String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
1599 schoenebeck 947 dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
1600    
1601     midi_prog_index_t idx;
1602 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1603     idx.midi_bank_lsb = MidiBank & 0x7f;
1604 schoenebeck 947 idx.midi_prog = MidiProg;
1605    
1606     LSCPResultSet result;
1607     try {
1608 schoenebeck 973 MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
1609 schoenebeck 947 } catch (Exception e) {
1610     result.Error(e);
1611     }
1612     return result.Produce();
1613     }
1614    
1615 schoenebeck 973 String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
1616     dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
1617 schoenebeck 947 LSCPResultSet result;
1618 schoenebeck 973 try {
1619     result.Add(MidiInstrumentMapper::Entries(MidiMapID).size());
1620     } catch (Exception e) {
1621     result.Error(e);
1622     }
1623 schoenebeck 947 return result.Produce();
1624     }
1625    
1626 schoenebeck 973
1627     String LSCPServer::GetAllMidiInstrumentMappings() {
1628     dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
1629     LSCPResultSet result;
1630     std::vector<int> maps = MidiInstrumentMapper::Maps();
1631     int totalMappings = 0;
1632     for (int i = 0; i < maps.size(); i++) {
1633     try {
1634     totalMappings += MidiInstrumentMapper::Entries(maps[i]).size();
1635     } catch (Exception e) { /*NOOP*/ }
1636     }
1637     result.Add(totalMappings);
1638     return result.Produce();
1639     }
1640    
1641     String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
1642 schoenebeck 947 dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
1643     LSCPResultSet result;
1644     try {
1645     midi_prog_index_t idx;
1646 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
1647     idx.midi_bank_lsb = MidiBank & 0x7f;
1648 schoenebeck 947 idx.midi_prog = MidiProg;
1649    
1650 schoenebeck 973 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
1651 schoenebeck 947 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.find(idx);
1652     if (iter == mappings.end()) result.Error("there is no map entry with that index");
1653     else { // found
1654     result.Add("NAME", iter->second.Name);
1655     result.Add("ENGINE_NAME", iter->second.EngineName);
1656     result.Add("INSTRUMENT_FILE", iter->second.InstrumentFile);
1657     result.Add("INSTRUMENT_NR", (int) iter->second.InstrumentIndex);
1658     String instrumentName;
1659     Engine* pEngine = EngineFactory::Create(iter->second.EngineName);
1660     if (pEngine) {
1661     if (pEngine->GetInstrumentManager()) {
1662     InstrumentManager::instrument_id_t instrID;
1663     instrID.FileName = iter->second.InstrumentFile;
1664     instrID.Index = iter->second.InstrumentIndex;
1665     instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
1666     }
1667     EngineFactory::Destroy(pEngine);
1668     }
1669     result.Add("INSTRUMENT_NAME", instrumentName);
1670     switch (iter->second.LoadMode) {
1671     case MidiInstrumentMapper::ON_DEMAND:
1672     result.Add("LOAD_MODE", "ON_DEMAND");
1673     break;
1674     case MidiInstrumentMapper::ON_DEMAND_HOLD:
1675     result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
1676     break;
1677     case MidiInstrumentMapper::PERSISTENT:
1678     result.Add("LOAD_MODE", "PERSISTENT");
1679     break;
1680     default:
1681     throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
1682     }
1683     result.Add("VOLUME", iter->second.Volume);
1684     }
1685     } catch (Exception e) {
1686     result.Error(e);
1687     }
1688     return result.Produce();
1689     }
1690    
1691 schoenebeck 973 String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
1692     dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
1693 schoenebeck 947 LSCPResultSet result;
1694     try {
1695     String s;
1696 schoenebeck 973 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
1697 schoenebeck 947 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
1698     for (; iter != mappings.end(); iter++) {
1699     if (s.size()) s += ",";
1700 schoenebeck 973 s += "{" + ToString(MidiMapID) + ","
1701 schoenebeck 1007 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
1702 schoenebeck 973 + ToString(int(iter->first.midi_prog)) + "}";
1703 schoenebeck 947 }
1704     result.Add(s);
1705     } catch (Exception e) {
1706     result.Error(e);
1707     }
1708     return result.Produce();
1709     }
1710    
1711 schoenebeck 973 String LSCPServer::ListAllMidiInstrumentMappings() {
1712     dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
1713     LSCPResultSet result;
1714     try {
1715     std::vector<int> maps = MidiInstrumentMapper::Maps();
1716     String s;
1717     for (int i = 0; i < maps.size(); i++) {
1718     std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
1719     std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
1720     for (; iter != mappings.end(); iter++) {
1721     if (s.size()) s += ",";
1722     s += "{" + ToString(maps[i]) + ","
1723 schoenebeck 1009 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
1724 schoenebeck 973 + ToString(int(iter->first.midi_prog)) + "}";
1725     }
1726     }
1727     result.Add(s);
1728     } catch (Exception e) {
1729     result.Error(e);
1730     }
1731     return result.Produce();
1732     }
1733    
1734     String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
1735 schoenebeck 947 dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
1736     LSCPResultSet result;
1737     try {
1738 schoenebeck 973 MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
1739 schoenebeck 947 } catch (Exception e) {
1740     result.Error(e);
1741     }
1742     return result.Produce();
1743     }
1744    
1745 schoenebeck 973 String LSCPServer::ClearAllMidiInstrumentMappings() {
1746     dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
1747     LSCPResultSet result;
1748     try {
1749     std::vector<int> maps = MidiInstrumentMapper::Maps();
1750     for (int i = 0; i < maps.size(); i++)
1751     MidiInstrumentMapper::RemoveAllEntries(maps[i]);
1752     } catch (Exception e) {
1753     result.Error(e);
1754     }
1755     return result.Produce();
1756     }
1757    
1758     String LSCPServer::AddMidiInstrumentMap(String MapName) {
1759     dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
1760     LSCPResultSet result;
1761     try {
1762     int MapID = MidiInstrumentMapper::AddMap(MapName);
1763     result = LSCPResultSet(MapID);
1764     } catch (Exception e) {
1765     result.Error(e);
1766     }
1767     return result.Produce();
1768     }
1769    
1770     String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
1771     dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
1772     LSCPResultSet result;
1773     try {
1774     MidiInstrumentMapper::RemoveMap(MidiMapID);
1775     } catch (Exception e) {
1776     result.Error(e);
1777     }
1778     return result.Produce();
1779     }
1780    
1781     String LSCPServer::RemoveAllMidiInstrumentMaps() {
1782     dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
1783     LSCPResultSet result;
1784     try {
1785     MidiInstrumentMapper::RemoveAllMaps();
1786     } catch (Exception e) {
1787     result.Error(e);
1788     }
1789     return result.Produce();
1790     }
1791    
1792     String LSCPServer::GetMidiInstrumentMaps() {
1793     dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
1794     LSCPResultSet result;
1795     try {
1796     result.Add(MidiInstrumentMapper::Maps().size());
1797     } catch (Exception e) {
1798     result.Error(e);
1799     }
1800     return result.Produce();
1801     }
1802    
1803     String LSCPServer::ListMidiInstrumentMaps() {
1804     dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
1805     LSCPResultSet result;
1806     try {
1807     std::vector<int> maps = MidiInstrumentMapper::Maps();
1808     String sList;
1809     for (int i = 0; i < maps.size(); i++) {
1810     if (sList != "") sList += ",";
1811     sList += ToString(maps[i]);
1812     }
1813     result.Add(sList);
1814     } catch (Exception e) {
1815     result.Error(e);
1816     }
1817     return result.Produce();
1818     }
1819    
1820     String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
1821     dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
1822     LSCPResultSet result;
1823     try {
1824     result.Add("NAME", MidiInstrumentMapper::MapName(MidiMapID));
1825     } catch (Exception e) {
1826     result.Error(e);
1827     }
1828     return result.Produce();
1829     }
1830    
1831     String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
1832     dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
1833     LSCPResultSet result;
1834     try {
1835     MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
1836     } catch (Exception e) {
1837     result.Error(e);
1838     }
1839     return result.Produce();
1840     }
1841    
1842 schoenebeck 705 /**
1843 schoenebeck 973 * Set the MIDI instrument map the given sampler channel shall use for
1844     * handling MIDI program change messages. There are the following two
1845     * special (negative) values:
1846     *
1847     * - (-1) : set to NONE (ignore program changes)
1848     * - (-2) : set to DEFAULT map
1849     */
1850     String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
1851     dmsg(2,("LSCPServer: SetChannelMap()\n"));
1852     LSCPResultSet result;
1853     try {
1854     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1855     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1856    
1857     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1858     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1859    
1860     if (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
1861     else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
1862     else pEngineChannel->SetMidiInstrumentMap(MidiMapID);
1863     } catch (Exception e) {
1864     result.Error(e);
1865     }
1866     return result.Produce();
1867     }
1868    
1869 schoenebeck 1001 String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
1870     dmsg(2,("LSCPServer: CreateFxSend()\n"));
1871     LSCPResultSet result;
1872     try {
1873     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1874     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1875    
1876     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1877     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1878    
1879     FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
1880     if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
1881    
1882     result = LSCPResultSet(pFxSend->Id()); // success
1883     } catch (Exception e) {
1884     result.Error(e);
1885     }
1886     return result.Produce();
1887     }
1888    
1889     String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
1890     dmsg(2,("LSCPServer: DestroyFxSend()\n"));
1891     LSCPResultSet result;
1892     try {
1893     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1894     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1895    
1896     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1897     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1898    
1899     FxSend* pFxSend = NULL;
1900     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
1901     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
1902     pFxSend = pEngineChannel->GetFxSend(i);
1903     break;
1904     }
1905     }
1906     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
1907     pEngineChannel->RemoveFxSend(pFxSend);
1908     } catch (Exception e) {
1909     result.Error(e);
1910     }
1911     return result.Produce();
1912     }
1913    
1914     String LSCPServer::GetFxSends(uint uiSamplerChannel) {
1915     dmsg(2,("LSCPServer: GetFxSends()\n"));
1916     LSCPResultSet result;
1917     try {
1918     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1919     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1920    
1921     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1922     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1923    
1924     result.Add(pEngineChannel->GetFxSendCount());
1925     } catch (Exception e) {
1926     result.Error(e);
1927     }
1928     return result.Produce();
1929     }
1930    
1931     String LSCPServer::ListFxSends(uint uiSamplerChannel) {
1932     dmsg(2,("LSCPServer: ListFxSends()\n"));
1933     LSCPResultSet result;
1934     String list;
1935     try {
1936     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1937     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1938    
1939     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1940     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1941    
1942     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
1943     FxSend* pFxSend = pEngineChannel->GetFxSend(i);
1944     if (list != "") list += ",";
1945     list += ToString(pFxSend->Id());
1946     }
1947     result.Add(list);
1948     } catch (Exception e) {
1949     result.Error(e);
1950     }
1951     return result.Produce();
1952     }
1953    
1954     String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
1955     dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
1956     LSCPResultSet result;
1957     try {
1958     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1959     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1960    
1961     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1962     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
1963    
1964     FxSend* pFxSend = NULL;
1965     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
1966     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
1967     pFxSend = pEngineChannel->GetFxSend(i);
1968     break;
1969     }
1970     }
1971     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
1972    
1973     // gather audio routing informations
1974     String AudioRouting;
1975     for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
1976     if (AudioRouting != "") AudioRouting += ",";
1977     AudioRouting += ToString(pFxSend->DestinationChannel(chan));
1978     }
1979    
1980     // success
1981     result.Add("NAME", pFxSend->Name());
1982 schoenebeck 1026 result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
1983     result.Add("LEVEL", ToString(pFxSend->Level()));
1984 schoenebeck 1001 result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
1985     } catch (Exception e) {
1986     result.Error(e);
1987     }
1988     return result.Produce();
1989     }
1990    
1991     String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
1992     dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
1993     LSCPResultSet result;
1994     try {
1995     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1996     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1997    
1998     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1999     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
2000    
2001     FxSend* pFxSend = NULL;
2002     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2003     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2004     pFxSend = pEngineChannel->GetFxSend(i);
2005     break;
2006     }
2007     }
2008     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2009    
2010     pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2011     } catch (Exception e) {
2012     result.Error(e);
2013     }
2014     return result.Produce();
2015     }
2016    
2017 schoenebeck 1026 String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2018     dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2019     LSCPResultSet result;
2020     try {
2021     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2022     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2023    
2024     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2025     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
2026    
2027     FxSend* pFxSend = NULL;
2028     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2029     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2030     pFxSend = pEngineChannel->GetFxSend(i);
2031     break;
2032     }
2033     }
2034     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2035    
2036     pFxSend->SetMidiController(MidiController);
2037     } catch (Exception e) {
2038     result.Error(e);
2039     }
2040     return result.Produce();
2041     }
2042    
2043     String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2044     dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2045     LSCPResultSet result;
2046     try {
2047     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2048     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2049    
2050     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2051     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
2052    
2053     FxSend* pFxSend = NULL;
2054     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2055     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2056     pFxSend = pEngineChannel->GetFxSend(i);
2057     break;
2058     }
2059     }
2060     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2061    
2062     pFxSend->SetLevel((float)dLevel);
2063     } catch (Exception e) {
2064     result.Error(e);
2065     }
2066     return result.Produce();
2067     }
2068    
2069 schoenebeck 973 /**
2070 schoenebeck 35 * Will be called by the parser to reset a particular sampler channel.
2071     */
2072 schoenebeck 53 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
2073     dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
2074 senkov 120 LSCPResultSet result;
2075 schoenebeck 53 try {
2076     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
2077 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
2078 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
2079 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel");
2080 schoenebeck 670 pEngineChannel->Reset();
2081 schoenebeck 53 }
2082 schoenebeck 880 catch (Exception e) {
2083 senkov 120 result.Error(e);
2084 schoenebeck 53 }
2085 senkov 120 return result.Produce();
2086 schoenebeck 35 }
2087    
2088     /**
2089 schoenebeck 212 * Will be called by the parser to reset the whole sampler.
2090     */
2091     String LSCPServer::ResetSampler() {
2092     dmsg(2,("LSCPServer: ResetSampler()\n"));
2093     pSampler->Reset();
2094     LSCPResultSet result;
2095     return result.Produce();
2096     }
2097    
2098     /**
2099 schoenebeck 563 * Will be called by the parser to return general informations about this
2100     * sampler.
2101     */
2102     String LSCPServer::GetServerInfo() {
2103     dmsg(2,("LSCPServer: GetServerInfo()\n"));
2104     LSCPResultSet result;
2105     result.Add("DESCRIPTION", "LinuxSampler - modular, streaming capable sampler");
2106 schoenebeck 570 result.Add("VERSION", VERSION);
2107 schoenebeck 947 result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));