/[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 212 - (hide annotations) (download)
Wed Jul 28 14:17:29 2004 UTC (19 years, 8 months ago) by schoenebeck
File size: 57565 byte(s)
* introduced and implemented new LSCP command "RESET" which resets the
  whole sampler instance
* src/drivers/audio/AudioOutputDeviceAlsa.cpp: parameter 'card' now
  returns all available sound cards as possibility, added dependency to
  parameter 'card' to parameters 'fragments' and 'fragmentsize'
* src/drivers/DeviceParameter.cpp: fixed return value(s) for classes
  'DeviceCreationParameterString' and 'DeviceCreationParameterStrings'
  which returned the default value(s) not encapsulated into apostrophes
* src/network/lscpserver.cpp: fixed implementation of LSCP commands
  "GET MIDI_INPUT_DRIVER_PARAMETER INFO" and
  "GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO"

1 schoenebeck 35 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 35 * *
7     * This program is free software; you can redistribute it and/or modify *
8     * it under the terms of the GNU General Public License as published by *
9     * the Free Software Foundation; either version 2 of the License, or *
10     * (at your option) any later version. *
11     * *
12     * This program is distributed in the hope that it will be useful, *
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15     * GNU General Public License for more details. *
16     * *
17     * You should have received a copy of the GNU General Public License *
18     * along with this program; if not, write to the Free Software *
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20     * MA 02111-1307 USA *
21     ***************************************************************************/
22    
23     #include "lscpserver.h"
24 senkov 113 #include "lscpresultset.h"
25 senkov 170 #include "lscpevent.h"
26 schoenebeck 35
27 schoenebeck 53 #include "../engines/gig/Engine.h"
28 schoenebeck 203 #include "../drivers/audio/AudioOutputDeviceFactory.h"
29     #include "../drivers/midi/MidiInputDeviceFactory.h"
30 schoenebeck 53
31 senkov 170 /**
32     * Below are a few static members of the LSCPServer class.
33     * The big assumption here is that LSCPServer is going to remain a singleton.
34     * These members are used to support client connections.
35     * Class handles multiple connections at the same time using select() and non-blocking recv()
36     * Commands are processed by a single LSCPServer thread.
37     * Notifications are delivered either by the thread that originated them
38     * or (if the resultset is currently in progress) by the LSCPServer thread
39     * after the resultset was sent out.
40     * This makes sure that resultsets can not be interrupted by notifications.
41     * This also makes sure that the thread sending notification is not blocked
42     * by the LSCPServer thread.
43     */
44     fd_set LSCPServer::fdSet;
45     int LSCPServer::currentSocket = -1;
46 schoenebeck 210 std::vector<yyparse_param_t> LSCPServer::Sessions = std::vector<yyparse_param_t>();
47 senkov 170 std::map<int,String> LSCPServer::bufferedNotifies = std::map<int,String>();
48     std::map<int,String> LSCPServer::bufferedCommands = std::map<int,String>();
49     std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions = std::map< LSCPEvent::event_t, std::list<int> >();
50     Mutex LSCPServer::NotifyMutex = Mutex();
51     Mutex LSCPServer::NotifyBufferMutex = Mutex();
52     Mutex LSCPServer::SubscriptionMutex = Mutex();
53    
54 schoenebeck 53 LSCPServer::LSCPServer(Sampler* pSampler) : Thread(false, 0, -4) {
55     this->pSampler = pSampler;
56 senkov 170 LSCPEvent::RegisterEvent(LSCPEvent::event_channels, "CHANNELS");
57     LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
58     LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
59     LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
60     LSCPEvent::RegisterEvent(LSCPEvent::event_info, "INFO");
61     LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
62 schoenebeck 35 }
63    
64 schoenebeck 211 /**
65     * Blocks the calling thread until the LSCP Server is initialized and
66     * accepting socket connections, if the server is already initialized then
67     * this method will return immediately.
68     * @param TimeoutSeconds - optional: max. wait time in seconds
69     * (default: 0s)
70     * @param TimeoutNanoSeconds - optional: max wait time in nano seconds
71     * (default: 0ns)
72     * @returns 0 on success, a value less than 0 if timeout exceeded
73     */
74     int LSCPServer::WaitUntilInitialized(long TimeoutSeconds, long TimeoutNanoSeconds) {
75     return Initialized.WaitAndUnlockIf(false, TimeoutSeconds, TimeoutNanoSeconds);
76     }
77    
78 schoenebeck 35 int LSCPServer::Main() {
79 senkov 170 int hSocket = socket(AF_INET, SOCK_STREAM, 0);
80 schoenebeck 35 if (hSocket < 0) {
81     std::cerr << "LSCPServer: Could not create server socket." << std::endl;
82 schoenebeck 53 //return -1;
83     exit(EXIT_FAILURE);
84 schoenebeck 35 }
85    
86     SocketAddress.sin_family = AF_INET;
87     SocketAddress.sin_port = htons(LSCP_PORT);
88     SocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
89    
90     if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
91     std::cerr << "LSCPServer: Could not bind server socket." << std::endl;
92     close(hSocket);
93 schoenebeck 53 //return -1;
94     exit(EXIT_FAILURE);
95 schoenebeck 35 }
96    
97     listen(hSocket, 1);
98 schoenebeck 211 Initialized.Set(true);
99 schoenebeck 35
100     // now wait for client connections and handle their requests
101     sockaddr_in client;
102     int length = sizeof(client);
103 senkov 170 FD_ZERO(&fdSet);
104     FD_SET(hSocket, &fdSet);
105     int maxSessions = hSocket;
106 schoenebeck 203
107 schoenebeck 35 while (true) {
108 senkov 170 fd_set selectSet = fdSet;
109 senkov 198 int retval = select(maxSessions+1, &selectSet, NULL, NULL, NULL);
110 senkov 170 if (retval == 0)
111 senkov 198 continue; //Nothing try again
112 senkov 170 if (retval == -1) {
113     std::cerr << "LSCPServer: Socket select error." << std::endl;
114     close(hSocket);
115     exit(EXIT_FAILURE);
116     }
117 schoenebeck 203
118 senkov 170 //Accept new connections now (if any)
119     if (FD_ISSET(hSocket, &selectSet)) {
120     int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
121     if (socket < 0) {
122     std::cerr << "LSCPServer: Client connection failed." << std::endl;
123     exit(EXIT_FAILURE);
124     }
125 schoenebeck 35
126 senkov 170 if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
127     std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
128     exit(EXIT_FAILURE);
129     }
130 schoenebeck 35
131 schoenebeck 210 // Parser initialization
132     yyparse_param_t yyparse_param;
133     yyparse_param.pServer = this;
134     yyparse_param.hSession = socket;
135    
136     Sessions.push_back(yyparse_param);
137 senkov 170 FD_SET(socket, &fdSet);
138     if (socket > maxSessions)
139     maxSessions = socket;
140     dmsg(1,("LSCPServer: Client connection established on socket:%d.\n", socket));
141     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection established on socket", socket));
142     continue; //Maybe this was the only selected socket, better select again
143     }
144 schoenebeck 35
145 senkov 170 //Something was selected and it was not the hSocket, so it must be some command(s) coming.
146 schoenebeck 210 for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
147     if (FD_ISSET((*iter).hSession, &selectSet)) { //Was it this socket?
148 senkov 170 if (GetLSCPCommand(iter)) { //Have we read the entire command?
149     dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
150 schoenebeck 210 yylex_init(&((*iter).pScanner)); //FIXME: should me moved out of this loop and initialized only when a new session is created
151     currentSocket = (*iter).hSession; //a hack
152     if ((*iter).bVerbose) { // if echo mode enabled
153     AnswerClient(bufferedCommands[currentSocket]);
154     }
155     int result = yyparse(&(*iter));
156 senkov 170 currentSocket = -1; //continuation of a hack
157     dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
158     if (result == LSCP_QUIT) { //Was it a quit command by any chance?
159     CloseConnection(iter);
160     }
161     }
162     //socket may have been closed, iter may be invalid, get out of the loop for now.
163     //we'll be back if there is data.
164 schoenebeck 203 break;
165 senkov 170 }
166     }
167    
168     //Now let's deliver late notifies (if any)
169     NotifyBufferMutex.Lock();
170     for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
171     send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
172     bufferedNotifies.erase(iterNotify);
173     }
174     NotifyBufferMutex.Unlock();
175 schoenebeck 35 }
176 senkov 170 //It will never get here anyway
177     //yylex_destroy(yyparse_param.pScanner);
178 schoenebeck 35 }
179    
180 schoenebeck 210 void LSCPServer::CloseConnection( std::vector<yyparse_param_t>::iterator iter ) {
181     int socket = (*iter).hSession;
182 senkov 170 dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));
183     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
184 schoenebeck 210 Sessions.erase(iter);
185 senkov 170 FD_CLR(socket, &fdSet);
186     SubscriptionMutex.Lock(); //Must unsubscribe this socket from all events (if any)
187     for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
188     iter->second.remove(socket);
189     }
190     SubscriptionMutex.Unlock();
191     NotifyMutex.Lock();
192     bufferedCommands.erase(socket);
193     bufferedNotifies.erase(socket);
194     close(socket);
195     NotifyMutex.Unlock();
196 schoenebeck 210 //yylex_destroy((*iter).pScanner);
197 senkov 170 }
198    
199     void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
200     SubscriptionMutex.Lock();
201     if (eventSubscriptions.count(event.GetType()) == 0) {
202     SubscriptionMutex.Unlock(); //Nobody is subscribed to this event
203     return;
204     }
205     std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();
206     std::list<int>::iterator end = eventSubscriptions[event.GetType()].end();
207     String notify = event.Produce();
208    
209     while (true) {
210     if (NotifyMutex.Trylock()) {
211     for(;iter != end; iter++)
212     send(*iter, notify.c_str(), notify.size(), 0);
213     NotifyMutex.Unlock();
214     break;
215     } else {
216     if (NotifyBufferMutex.Trylock()) {
217     for(;iter != end; iter++)
218     bufferedNotifies[*iter] += notify;
219     NotifyBufferMutex.Unlock();
220     break;
221     }
222     }
223     }
224     SubscriptionMutex.Unlock();
225     }
226    
227     extern int GetLSCPCommand( void *buf, int max_size ) {
228     String command = LSCPServer::bufferedCommands[LSCPServer::currentSocket];
229     if (command.size() == 0) { //Parser wants input but we have nothing.
230     strcpy((char*) buf, "\n"); //So give it an empty command
231     return 1; //to keep it happy.
232     }
233    
234     if (max_size < command.size()) {
235     std::cerr << "getLSCPCommand: Flex buffer too small, ignoring the command." << std::endl;
236     return 0; //This will never happen
237     }
238    
239     strcpy((char*) buf, command.c_str());
240     LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);
241     return command.size();
242     }
243    
244 schoenebeck 35 /**
245 senkov 170 * Will be called to try to read the command from the socket
246     * If command is read, it will return true. Otherwise false is returned.
247     * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.
248     */
249 schoenebeck 210 bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
250     int socket = (*iter).hSession;
251 senkov 170 char c;
252     int i = 0;
253     while (true) {
254     int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now
255     if (result == 0) { //socket was selected, so 0 here means client has closed the connection
256     CloseConnection(iter);
257     break;
258     }
259     if (result == 1) {
260 schoenebeck 203 if (c == '\r')
261 senkov 170 continue; //Ignore CR
262     if (c == '\n') {
263 senkov 184 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
264 senkov 170 bufferedCommands[socket] += "\n";
265     return true; //Complete command was read
266     }
267     bufferedCommands[socket] += c;
268     }
269     if (result == -1) {
270     if (errno == EAGAIN) //Would block, try again later.
271     return false;
272     switch(errno) {
273     case EBADF:
274     dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
275     break;
276     case ECONNREFUSED:
277     dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
278     break;
279     case ENOTCONN:
280     dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
281     break;
282     case ENOTSOCK:
283     dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
284     break;
285     case EAGAIN:
286     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"));
287 schoenebeck 203 break;
288     case EINTR:
289 senkov 170 dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
290 schoenebeck 203 break;
291     case EFAULT:
292     dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
293     break;
294     case EINVAL:
295     dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
296     break;
297     case ENOMEM:
298     dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
299     break;
300     default:
301     dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
302     break;
303     }
304 senkov 170 CloseConnection(iter);
305     break;
306     }
307     }
308     return false;
309     }
310    
311     /**
312 schoenebeck 35 * Will be called by the parser whenever it wants to send an answer to the
313     * client / frontend.
314     *
315     * @param ReturnMessage - message that will be send to the client
316     */
317     void LSCPServer::AnswerClient(String ReturnMessage) {
318     dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
319 senkov 170 if (currentSocket != -1) {
320     NotifyMutex.Lock();
321     send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
322     NotifyMutex.Unlock();
323     }
324 schoenebeck 35 }
325    
326 capela 143 /**
327     * Find a created audio output device index.
328     */
329     int LSCPServer::GetAudioOutputDeviceIndex ( AudioOutputDevice *pDevice )
330     {
331     // Search for the created device to get its index
332     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
333     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
334     for (; iter != devices.end(); iter++) {
335     if (iter->second == pDevice)
336     return iter->first;
337     }
338     // Not found.
339     return -1;
340     }
341    
342 senkov 155 /**
343     * Find a created midi input device index.
344     */
345     int LSCPServer::GetMidiInputDeviceIndex ( MidiInputDevice *pDevice )
346     {
347     // Search for the created device to get its index
348     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
349     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
350     for (; iter != devices.end(); iter++) {
351     if (iter->second == pDevice)
352     return iter->first;
353     }
354     // Not found.
355     return -1;
356     }
357    
358 schoenebeck 123 String LSCPServer::CreateAudioOutputDevice(String Driver, std::map<String,String> Parameters) {
359     dmsg(2,("LSCPServer: CreateAudioOutputDevice(Driver=%s)\n", Driver.c_str()));
360     LSCPResultSet result;
361     try {
362     AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
363     // search for the created device to get its index
364 capela 143 int index = GetAudioOutputDeviceIndex(pDevice);
365 schoenebeck 123 if (index == -1) throw LinuxSamplerException("Internal error: could not find created audio output device.");
366     result = index; // success
367     }
368     catch (LinuxSamplerException e) {
369     result.Error(e);
370     }
371     return result.Produce();
372     }
373    
374 senkov 155 String LSCPServer::CreateMidiInputDevice(String Driver, std::map<String,String> Parameters) {
375     dmsg(2,("LSCPServer: CreateMidiInputDevice(Driver=%s)\n", Driver.c_str()));
376     LSCPResultSet result;
377     try {
378     MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
379     // search for the created device to get its index
380     int index = GetMidiInputDeviceIndex(pDevice);
381     if (index == -1) throw LinuxSamplerException("Internal error: could not find created midi input device.");
382     result = index; // success
383     }
384     catch (LinuxSamplerException e) {
385     result.Error(e);
386     }
387     return result.Produce();
388     }
389    
390 schoenebeck 123 String LSCPServer::DestroyAudioOutputDevice(uint DeviceIndex) {
391     dmsg(2,("LSCPServer: DestroyAudioOutputDevice(DeviceIndex=%d)\n", DeviceIndex));
392     LSCPResultSet result;
393     try {
394     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
395     if (!devices[DeviceIndex]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");
396     AudioOutputDevice* pDevice = devices[DeviceIndex];
397     pSampler->DestroyAudioOutputDevice(pDevice);
398     }
399     catch (LinuxSamplerException e) {
400     result.Error(e);
401     }
402     return result.Produce();
403     }
404    
405 senkov 155 String LSCPServer::DestroyMidiInputDevice(uint DeviceIndex) {
406     dmsg(2,("LSCPServer: DestroyMidiInputDevice(DeviceIndex=%d)\n", DeviceIndex));
407     LSCPResultSet result;
408     try {
409     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
410     MidiInputDevice* pDevice = devices[DeviceIndex];
411     if (!pDevice) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");
412     pSampler->DestroyMidiInputDevice(pDevice);
413     }
414     catch (LinuxSamplerException e) {
415     result.Error(e);
416     }
417     return result.Produce();
418     }
419    
420 schoenebeck 35 /**
421     * Will be called by the parser to load an instrument.
422     */
423 capela 137 String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel, bool bBackground) {
424 schoenebeck 53 dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
425 senkov 120 LSCPResultSet result;
426 schoenebeck 53 try {
427     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
428     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
429     Engine* pEngine = pSamplerChannel->GetEngine();
430     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
431 capela 143 if (pSamplerChannel->GetAudioOutputDevice() == NULL)
432     throw LinuxSamplerException("No audio output device on channel");
433 capela 137 if (bBackground) {
434     LSCPLoadInstrument *pLoadInstrument = new LSCPLoadInstrument(pEngine, Filename.c_str(), uiInstrument);
435     pLoadInstrument->StartThread();
436     }
437     else pEngine->LoadInstrument(Filename.c_str(), uiInstrument);
438 schoenebeck 53 }
439     catch (LinuxSamplerException e) {
440 senkov 120 result.Error(e);
441 schoenebeck 53 }
442 senkov 120 return result.Produce();
443 schoenebeck 35 }
444    
445     /**
446     * Will be called by the parser to load and deploy an engine.
447     */
448 schoenebeck 53 String LSCPServer::LoadEngine(String EngineName, uint uiSamplerChannel) {
449     dmsg(2,("LSCPServer: LoadEngine(EngineName=%s,SamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
450 senkov 120 LSCPResultSet result;
451 schoenebeck 53 try {
452 schoenebeck 64 Engine::type_t type;
453 senkov 120 if ((EngineName == "GigEngine") || (EngineName == "gig")) type = Engine::type_gig;
454 schoenebeck 53 else throw LinuxSamplerException("Unknown engine type");
455     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
456     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
457     pSamplerChannel->LoadEngine(type);
458     }
459     catch (LinuxSamplerException e) {
460 senkov 120 result.Error(e);
461 schoenebeck 53 }
462 senkov 120 return result.Produce();
463 schoenebeck 35 }
464    
465     /**
466     * Will be called by the parser to get the amount of sampler channels.
467     */
468     String LSCPServer::GetChannels() {
469     dmsg(2,("LSCPServer: GetChannels()\n"));
470 senkov 120 LSCPResultSet result;
471     result.Add(pSampler->SamplerChannels());
472     return result.Produce();
473 schoenebeck 35 }
474    
475     /**
476 schoenebeck 209 * Will be called by the parser to get the list of sampler channels.
477     */
478     String LSCPServer::ListChannels() {
479     dmsg(2,("LSCPServer: ListChannels()\n"));
480     String list;
481     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
482     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
483     for (; iter != channels.end(); iter++) {
484     if (list != "") list += ",";
485     list += ToString(iter->first);
486     }
487     LSCPResultSet result;
488     result.Add(list);
489     return result.Produce();
490     }
491    
492     /**
493 schoenebeck 35 * Will be called by the parser to add a sampler channel.
494     */
495     String LSCPServer::AddChannel() {
496     dmsg(2,("LSCPServer: AddChannel()\n"));
497 schoenebeck 53 SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
498 senkov 120 LSCPResultSet result(pSamplerChannel->Index());
499     return result.Produce();
500 schoenebeck 35 }
501    
502     /**
503     * Will be called by the parser to remove a sampler channel.
504     */
505 schoenebeck 53 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
506     dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
507 senkov 120 LSCPResultSet result;
508 schoenebeck 53 pSampler->RemoveSamplerChannel(uiSamplerChannel);
509 senkov 120 return result.Produce();
510 schoenebeck 35 }
511    
512     /**
513     * Will be called by the parser to get all available engines.
514     */
515     String LSCPServer::GetAvailableEngines() {
516     dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
517 senkov 120 LSCPResultSet result("GigEngine");
518     return result.Produce();
519 schoenebeck 35 }
520    
521     /**
522     * Will be called by the parser to get descriptions for a particular engine.
523     */
524     String LSCPServer::GetEngineInfo(String EngineName) {
525     dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
526 senkov 120 LSCPResultSet result;
527 schoenebeck 53 try {
528 senkov 120 if ((EngineName == "GigEngine") || (EngineName == "gig")) {
529 schoenebeck 53 Engine* pEngine = new LinuxSampler::gig::Engine;
530 senkov 120 result.Add(pEngine->Description());
531 schoenebeck 123 result.Add(pEngine->Version());
532 schoenebeck 53 delete pEngine;
533     }
534     else throw LinuxSamplerException("Unknown engine type");
535     }
536     catch (LinuxSamplerException e) {
537 senkov 120 result.Error(e);
538 schoenebeck 53 }
539 senkov 120 return result.Produce();
540 schoenebeck 35 }
541    
542     /**
543     * Will be called by the parser to get informations about a particular
544     * sampler channel.
545     */
546 schoenebeck 53 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
547     dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
548 senkov 120 LSCPResultSet result;
549 senkov 113 try {
550     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
551     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
552     Engine* pEngine = pSamplerChannel->GetEngine();
553 schoenebeck 123
554 senkov 117 //Defaults values
555     String EngineName = "NONE";
556     float Volume = 0;
557     String InstrumentFileName = "NONE";
558 capela 133 int InstrumentIndex = -1;
559     int InstrumentStatus = -1;
560 schoenebeck 123
561 senkov 113 if (pEngine) {
562 senkov 117 EngineName = pEngine->EngineName();
563     Volume = pEngine->Volume();
564 capela 133 InstrumentStatus = pEngine->InstrumentStatus();
565     InstrumentIndex = pEngine->InstrumentIndex();
566     if (InstrumentIndex != -1)
567 senkov 117 InstrumentFileName = pEngine->InstrumentFileName();
568 senkov 113 }
569 senkov 117
570     result.Add("ENGINE_NAME", EngineName);
571     result.Add("VOLUME", Volume);
572    
573 capela 143 //Some not-so-hardcoded stuff to make GUI look good
574     result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
575 senkov 113 result.Add("AUDIO_OUTPUT_CHANNELS", "2");
576     result.Add("AUDIO_OUTPUT_ROUTING", "0,1");
577    
578 capela 159 result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
579     result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
580     result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
581    
582 senkov 117 result.Add("INSTRUMENT_FILE", InstrumentFileName);
583     result.Add("INSTRUMENT_NR", InstrumentIndex);
584 capela 133 result.Add("INSTRUMENT_STATUS", InstrumentStatus);
585 senkov 113 }
586     catch (LinuxSamplerException e) {
587 senkov 120 result.Error(e);
588 senkov 113 }
589 senkov 120 return result.Produce();
590 schoenebeck 35 }
591    
592     /**
593     * Will be called by the parser to get the amount of active voices on a
594     * particular sampler channel.
595     */
596 schoenebeck 53 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
597     dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
598 senkov 120 LSCPResultSet result;
599 schoenebeck 53 try {
600     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
601     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
602     Engine* pEngine = pSamplerChannel->GetEngine();
603     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
604 senkov 120 result.Add(pEngine->VoiceCount());
605 schoenebeck 53 }
606     catch (LinuxSamplerException e) {
607 senkov 120 result.Error(e);
608 schoenebeck 53 }
609 senkov 120 return result.Produce();
610 schoenebeck 35 }
611    
612     /**
613     * Will be called by the parser to get the amount of active disk streams on a
614     * particular sampler channel.
615     */
616 schoenebeck 53 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
617     dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
618 senkov 120 LSCPResultSet result;
619 schoenebeck 53 try {
620     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
621     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
622     Engine* pEngine = pSamplerChannel->GetEngine();
623     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
624 senkov 120 result.Add(pEngine->DiskStreamCount());
625 schoenebeck 53 }
626     catch (LinuxSamplerException e) {
627 senkov 120 result.Error(e);
628 schoenebeck 53 }
629 senkov 120 return result.Produce();
630 schoenebeck 35 }
631    
632     /**
633     * Will be called by the parser to get the buffer fill states of all disk
634     * streams on a particular sampler channel.
635     */
636 schoenebeck 53 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
637     dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
638 senkov 120 LSCPResultSet result;
639 schoenebeck 53 try {
640     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
641     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
642     Engine* pEngine = pSamplerChannel->GetEngine();
643     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
644 senkov 129 if (!pEngine->DiskStreamSupported())
645     result.Add("NA");
646     else {
647     switch (ResponseType) {
648     case fill_response_bytes:
649     result.Add(pEngine->DiskStreamBufferFillBytes());
650     break;
651     case fill_response_percentage:
652     result.Add(pEngine->DiskStreamBufferFillPercentage());
653     break;
654     default:
655     throw LinuxSamplerException("Unknown fill response type");
656     }
657     }
658 schoenebeck 53 }
659     catch (LinuxSamplerException e) {
660 senkov 120 result.Error(e);
661 schoenebeck 53 }
662 senkov 120 return result.Produce();
663 schoenebeck 35 }
664    
665 schoenebeck 123 String LSCPServer::GetAvailableAudioOutputDrivers() {
666     dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
667 senkov 120 LSCPResultSet result;
668 schoenebeck 53 try {
669 schoenebeck 123 String s = AudioOutputDeviceFactory::AvailableDriversAsString();
670     result.Add(s);
671 schoenebeck 53 }
672     catch (LinuxSamplerException e) {
673 schoenebeck 123 result.Error(e);
674 schoenebeck 53 }
675 senkov 120 return result.Produce();
676 schoenebeck 35 }
677    
678 senkov 155 String LSCPServer::GetAvailableMidiInputDrivers() {
679     dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
680     LSCPResultSet result;
681     try {
682     String s = MidiInputDeviceFactory::AvailableDriversAsString();
683     result.Add(s);
684     }
685     catch (LinuxSamplerException e) {
686     result.Error(e);
687     }
688     return result.Produce();
689     }
690    
691     String LSCPServer::GetMidiInputDriverInfo(String Driver) {
692     dmsg(2,("LSCPServer: GetMidiInputDriverInfo(Driver=%s)\n",Driver.c_str()));
693     LSCPResultSet result;
694     try {
695     result.Add("DESCRIPTION", MidiInputDeviceFactory::GetDriverDescription(Driver));
696     result.Add("VERSION", MidiInputDeviceFactory::GetDriverVersion(Driver));
697    
698     std::map<String,DeviceCreationParameter*> parameters = MidiInputDeviceFactory::GetAvailableDriverParameters(Driver);
699     if (parameters.size()) { // if there are parameters defined for this driver
700     String s;
701     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
702     for (;iter != parameters.end(); iter++) {
703     if (s != "") s += ",";
704     s += iter->first;
705     }
706     result.Add("PARAMETERS", s);
707     }
708     }
709     catch (LinuxSamplerException e) {
710     result.Error(e);
711     }
712     return result.Produce();
713     }
714    
715 schoenebeck 123 String LSCPServer::GetAudioOutputDriverInfo(String Driver) {
716     dmsg(2,("LSCPServer: GetAudioOutputDriverInfo(Driver=%s)\n",Driver.c_str()));
717     LSCPResultSet result;
718     try {
719     result.Add("DESCRIPTION", AudioOutputDeviceFactory::GetDriverDescription(Driver));
720     result.Add("VERSION", AudioOutputDeviceFactory::GetDriverVersion(Driver));
721    
722     std::map<String,DeviceCreationParameter*> parameters = AudioOutputDeviceFactory::GetAvailableDriverParameters(Driver);
723     if (parameters.size()) { // if there are parameters defined for this driver
724     String s;
725     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
726     for (;iter != parameters.end(); iter++) {
727     if (s != "") s += ",";
728     s += iter->first;
729     }
730     result.Add("PARAMETERS", s);
731     }
732     }
733     catch (LinuxSamplerException e) {
734     result.Error(e);
735     }
736     return result.Produce();
737     }
738    
739 senkov 155 String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
740     dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s)\n",Driver.c_str(),Parameter.c_str()));
741     LSCPResultSet result;
742     try {
743     DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
744     result.Add("TYPE", pParameter->Type());
745     result.Add("DESCRIPTION", pParameter->Description());
746 schoenebeck 212 result.Add("MANDATORY", (pParameter->Mandatory()) ? "true" : "false");
747     result.Add("FIX", (pParameter->Fix()) ? "true" : "false");
748     result.Add("MULTIPLICITY", (pParameter->Multiplicity()) ? "true" : "false");
749     if (pParameter->Depends()) result.Add("DEPENDS", *pParameter->Depends());
750     if (pParameter->Default()) result.Add("DEFAULT", *pParameter->Default());
751     if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
752     if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
753     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
754 senkov 155 }
755     catch (LinuxSamplerException e) {
756     result.Error(e);
757     }
758     return result.Produce();
759     }
760    
761 schoenebeck 123 String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
762     dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s)\n",Driver.c_str(),Parameter.c_str()));
763     LSCPResultSet result;
764     try {
765     DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
766     result.Add("TYPE", pParameter->Type());
767     result.Add("DESCRIPTION", pParameter->Description());
768 schoenebeck 212 result.Add("MANDATORY", (pParameter->Mandatory()) ? "true" : "false");
769     result.Add("FIX", (pParameter->Fix()) ? "true" : "false");
770     result.Add("MULTIPLICITY", (pParameter->Multiplicity()) ? "true" : "false");
771     if (pParameter->Depends()) result.Add("DEPENDS", *pParameter->Depends());
772     if (pParameter->Default()) result.Add("DEFAULT", *pParameter->Default());
773     if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
774     if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
775     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
776 schoenebeck 123 }
777     catch (LinuxSamplerException e) {
778     result.Error(e);
779     }
780     return result.Produce();
781     }
782    
783     String LSCPServer::GetAudioOutputDeviceCount() {
784     dmsg(2,("LSCPServer: GetAudioOutputDeviceCount()\n"));
785     LSCPResultSet result;
786     try {
787     uint count = pSampler->AudioOutputDevices();
788 senkov 138 result.Add(count); // success
789 schoenebeck 123 }
790     catch (LinuxSamplerException e) {
791     result.Error(e);
792     }
793     return result.Produce();
794     }
795    
796 senkov 155 String LSCPServer::GetMidiInputDeviceCount() {
797     dmsg(2,("LSCPServer: GetMidiInputDeviceCount()\n"));
798     LSCPResultSet result;
799     try {
800     uint count = pSampler->MidiInputDevices();
801     result.Add(count); // success
802     }
803     catch (LinuxSamplerException e) {
804     result.Error(e);
805     }
806     return result.Produce();
807     }
808    
809 schoenebeck 123 String LSCPServer::GetAudioOutputDevices() {
810     dmsg(2,("LSCPServer: GetAudioOutputDevices()\n"));
811     LSCPResultSet result;
812     try {
813     String s;
814     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
815     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
816     for (; iter != devices.end(); iter++) {
817     if (s != "") s += ",";
818     s += ToString(iter->first);
819     }
820     result.Add(s);
821     }
822     catch (LinuxSamplerException e) {
823     result.Error(e);
824     }
825     return result.Produce();
826     }
827    
828 senkov 155 String LSCPServer::GetMidiInputDevices() {
829     dmsg(2,("LSCPServer: GetMidiInputDevices()\n"));
830     LSCPResultSet result;
831     try {
832     String s;
833     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
834     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
835     for (; iter != devices.end(); iter++) {
836     if (s != "") s += ",";
837     s += ToString(iter->first);
838     }
839     result.Add(s);
840     }
841     catch (LinuxSamplerException e) {
842     result.Error(e);
843     }
844     return result.Produce();
845     }
846    
847 schoenebeck 123 String LSCPServer::GetAudioOutputDeviceInfo(uint DeviceIndex) {
848     dmsg(2,("LSCPServer: GetAudioOutputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
849     LSCPResultSet result;
850     try {
851     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
852     if (!devices[DeviceIndex]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");
853     AudioOutputDevice* pDevice = devices[DeviceIndex];
854 capela 143 result.Add("driver", pDevice->Driver());
855 schoenebeck 123 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
856     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
857     for (; iter != parameters.end(); iter++) {
858     result.Add(iter->first, iter->second->Value());
859     }
860     }
861     catch (LinuxSamplerException e) {
862     result.Error(e);
863     }
864     return result.Produce();
865     }
866    
867 senkov 155 String LSCPServer::GetMidiInputDeviceInfo(uint DeviceIndex) {
868     dmsg(2,("LSCPServer: GetMidiInputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
869     LSCPResultSet result;
870     try {
871     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
872     MidiInputDevice* pDevice = devices[DeviceIndex];
873 capela 159 if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
874 senkov 155 result.Add("driver", pDevice->Driver());
875     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
876     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
877     for (; iter != parameters.end(); iter++) {
878     result.Add(iter->first, iter->second->Value());
879     }
880     }
881     catch (LinuxSamplerException e) {
882     result.Error(e);
883     }
884     return result.Produce();
885     }
886     String LSCPServer::GetMidiInputPortInfo(uint DeviceIndex, uint PortIndex) {
887     dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
888     LSCPResultSet result;
889     try {
890     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
891     MidiInputDevice* pDevice = devices[DeviceIndex];
892 capela 159 if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
893 senkov 155 MidiInputDevice::MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
894 capela 159 if (!pMidiInputPort) throw LinuxSamplerException("There is no MIDI input port with index " + ToString(PortIndex) + ".");
895 senkov 155 std::map<String,DeviceCreationParameter*> parameters = pMidiInputPort->DeviceParameters();
896     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
897     for (; iter != parameters.end(); iter++) {
898     result.Add(iter->first, iter->second->Value());
899     }
900     }
901     catch (LinuxSamplerException e) {
902     result.Error(e);
903     }
904     return result.Produce();
905     }
906    
907 schoenebeck 123 String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
908     dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%d,ChannelId)\n",DeviceId,ChannelId));
909     LSCPResultSet result;
910     try {
911     // get audio output device
912     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
913     if (!devices[DeviceId]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");
914     AudioOutputDevice* pDevice = devices[DeviceId];
915    
916     // get audio channel
917     AudioChannel* pChannel = pDevice->Channel(ChannelId);
918     if (!pChannel) throw LinuxSamplerException("Audio ouotput device does not have channel " + ToString(ChannelId) + ".");
919    
920     // return the values of all audio channel parameters
921     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
922     std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
923     for (; iter != parameters.end(); iter++) {
924     result.Add(iter->first, iter->second->Value());
925     }
926     }
927     catch (LinuxSamplerException e) {
928     result.Error(e);
929     }
930     return result.Produce();
931     }
932    
933 senkov 185 String LSCPServer::GetMidiInputPortParameterInfo(uint DeviceId, uint PortId, String ParameterName) {
934     dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
935     LSCPResultSet result;
936     try {
937     // get audio output device
938     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
939     if (!devices[DeviceId]) throw LinuxSamplerException("There is no midi input device with index " + ToString(DeviceId) + ".");
940     MidiInputDevice* pDevice = devices[DeviceId];
941    
942     // get midi port
943     MidiInputDevice::MidiInputPort* pPort = pDevice->GetPort(PortId);
944     if (!pPort) throw LinuxSamplerException("Midi input device does not have port " + ToString(PortId) + ".");
945    
946     // get desired port parameter
947     std::map<String,DeviceCreationParameter*> parameters = pPort->DeviceParameters();
948     if (!parameters[ParameterName]) throw LinuxSamplerException("Midi port does not provice a parameters '" + ParameterName + "'.");
949     DeviceCreationParameter* pParameter = parameters[ParameterName];
950 schoenebeck 203
951 senkov 185 // return all fields of this audio channel parameter
952     result.Add("TYPE", pParameter->Type());
953     result.Add("DESCRIPTION", pParameter->Description());
954     result.Add("FIX", pParameter->Fix());
955     result.Add("MULTIPLICITY", pParameter->Multiplicity());
956     if (pParameter->RangeMin()) result.Add("RANGE_MIN", pParameter->RangeMin());
957     if (pParameter->RangeMax()) result.Add("RANGE_MAX", pParameter->RangeMax());
958     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", pParameter->Possibilities());
959     }
960     catch (LinuxSamplerException e) {
961     result.Error(e);
962     }
963     return result.Produce();
964     }
965    
966 schoenebeck 123 String LSCPServer::GetAudioOutputChannelParameterInfo(uint DeviceId, uint ChannelId, String ParameterName) {
967     dmsg(2,("LSCPServer: GetAudioOutputChannelParameterInfo(DeviceId=%d,ChannelId=%d,ParameterName=%s)\n",DeviceId,ChannelId,ParameterName.c_str()));
968     LSCPResultSet result;
969     try {
970     // get audio output device
971     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
972     if (!devices[DeviceId]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");
973     AudioOutputDevice* pDevice = devices[DeviceId];
974    
975     // get audio channel
976     AudioChannel* pChannel = pDevice->Channel(ChannelId);
977     if (!pChannel) throw LinuxSamplerException("Audio output device does not have channel " + ToString(ChannelId) + ".");
978    
979     // get desired audio channel parameter
980     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
981     if (!parameters[ParameterName]) throw LinuxSamplerException("Audio channel does not provide a parameter '" + ParameterName + "'.");
982     DeviceRuntimeParameter* pParameter = parameters[ParameterName];
983    
984     // return all fields of this audio channel parameter
985     result.Add("TYPE", pParameter->Type());
986     result.Add("DESCRIPTION", pParameter->Description());
987     result.Add("FIX", pParameter->Fix());
988     result.Add("MULTIPLICITY", pParameter->Multiplicity());
989     if (pParameter->RangeMin()) result.Add("RANGE_MIN", pParameter->RangeMin());
990     if (pParameter->RangeMax()) result.Add("RANGE_MAX", pParameter->RangeMax());
991     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", pParameter->Possibilities());
992     }
993     catch (LinuxSamplerException e) {
994     result.Error(e);
995     }
996     return result.Produce();
997     }
998    
999     String LSCPServer::SetAudioOutputChannelParameter(uint DeviceId, uint ChannelId, String ParamKey, String ParamVal) {
1000     dmsg(2,("LSCPServer: SetAudioOutputChannelParameter(DeviceId=%d,ChannelId=%d,ParamKey=%s,ParamVal=%s)\n",DeviceId,ChannelId,ParamKey.c_str(),ParamVal.c_str()));
1001     LSCPResultSet result;
1002     try {
1003     // get audio output device
1004     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1005     if (!devices[DeviceId]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceId) + ".");
1006     AudioOutputDevice* pDevice = devices[DeviceId];
1007    
1008     // get audio channel
1009     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1010     if (!pChannel) throw LinuxSamplerException("Audio output device does not have channel " + ToString(ChannelId) + ".");
1011    
1012     // get desired audio channel parameter
1013     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1014     if (!parameters[ParamKey]) throw LinuxSamplerException("Audio channel does not provide a parameter '" + ParamKey + "'.");
1015     DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1016    
1017     // set new channel parameter value
1018     pParameter->SetValue(ParamVal);
1019     }
1020     catch (LinuxSamplerException e) {
1021     result.Error(e);
1022     }
1023     return result.Produce();
1024     }
1025    
1026     String LSCPServer::SetAudioOutputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1027     dmsg(2,("LSCPServer: SetAudioOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1028     LSCPResultSet result;
1029     try {
1030     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1031     if (!devices[DeviceIndex]) throw LinuxSamplerException("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1032     AudioOutputDevice* pDevice = devices[DeviceIndex];
1033     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1034     if (!parameters[ParamKey]) throw LinuxSamplerException("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1035     parameters[ParamKey]->SetValue(ParamVal);
1036     }
1037     catch (LinuxSamplerException e) {
1038     result.Error(e);
1039     }
1040     return result.Produce();
1041     }
1042    
1043 senkov 155 String LSCPServer::SetMidiInputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1044     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1045     LSCPResultSet result;
1046     try {
1047     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1048 capela 159 if (!devices[DeviceIndex]) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1049 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1050     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1051 capela 159 if (!parameters[ParamKey]) throw LinuxSamplerException("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1052 senkov 155 parameters[ParamKey]->SetValue(ParamVal);
1053     }
1054     catch (LinuxSamplerException e) {
1055     result.Error(e);
1056     }
1057     return result.Produce();
1058     }
1059    
1060     String LSCPServer::SetMidiInputPortParameter(uint DeviceIndex, uint PortIndex, String ParamKey, String ParamVal) {
1061     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1062     LSCPResultSet result;
1063     try {
1064     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1065     MidiInputDevice* pDevice = devices[DeviceIndex];
1066 capela 159 if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1067 senkov 155 MidiInputDevice::MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1068 capela 159 if (!pMidiInputPort) throw LinuxSamplerException("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1069 senkov 155 std::map<String,DeviceCreationParameter*> parameters = pMidiInputPort->DeviceParameters();
1070 capela 159 if (!parameters[ParamKey]) throw LinuxSamplerException("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1071 senkov 155 parameters[ParamKey]->SetValue(ParamVal);
1072     }
1073     catch (LinuxSamplerException e) {
1074     result.Error(e);
1075     }
1076     return result.Produce();
1077     }
1078    
1079 schoenebeck 35 /**
1080     * Will be called by the parser to change the audio output channel for
1081     * playback on a particular sampler channel.
1082     */
1083 schoenebeck 123 String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1084     dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1085 senkov 120 return "ERR:0:Not implemented yet.\r\n"; //FIXME: Add support for this in resultset class?
1086 schoenebeck 35 }
1087    
1088 capela 159 String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1089     dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1090     LSCPResultSet result;
1091     try {
1092     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1093     if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));
1094     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1095     AudioOutputDevice* pDevice = devices[AudioDeviceId];
1096     if (!pDevice) throw LinuxSamplerException("There is no audio output device with index " + ToString(AudioDeviceId));
1097     pSamplerChannel->SetAudioOutputDevice(pDevice);
1098     }
1099     catch (LinuxSamplerException e) {
1100     result.Error(e);
1101     }
1102     return result.Produce();
1103     }
1104    
1105 capela 143 String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1106     dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1107     LSCPResultSet result;
1108     try {
1109     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1110     if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));
1111     // Driver type name aliasing...
1112     if (AudioOutputDriver == "ALSA") AudioOutputDriver = "Alsa";
1113 schoenebeck 203 if (AudioOutputDriver == "JACK") AudioOutputDriver = "Jack";
1114 capela 143 // Check if there's one audio output device already created
1115     // for the intended audio driver type (AudioOutputDriver)...
1116     AudioOutputDevice *pDevice = NULL;
1117     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1118     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1119     for (; iter != devices.end(); iter++) {
1120     if ((iter->second)->Driver() == AudioOutputDriver) {
1121     pDevice = iter->second;
1122     break;
1123     }
1124     }
1125     // If it doesn't exist, create a new one with default parameters...
1126     if (pDevice == NULL) {
1127     std::map<String,String> params;
1128     pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1129     }
1130     // Must have a device...
1131     if (pDevice == NULL)
1132     throw LinuxSamplerException("Internal error: could not create audio output device.");
1133     // Set it as the current channel device...
1134     pSamplerChannel->SetAudioOutputDevice(pDevice);
1135     }
1136     catch (LinuxSamplerException e) {
1137     result.Error(e);
1138     }
1139     return result.Produce();
1140     }
1141    
1142 capela 159 String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
1143     dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
1144 senkov 120 LSCPResultSet result;
1145 schoenebeck 53 try {
1146     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1147 capela 159 if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));
1148     pSamplerChannel->SetMidiInputPort(MIDIPort);
1149 schoenebeck 53 }
1150     catch (LinuxSamplerException e) {
1151 senkov 120 result.Error(e);
1152 schoenebeck 53 }
1153 senkov 120 return result.Produce();
1154 schoenebeck 53 }
1155    
1156 capela 159 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
1157     dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
1158 senkov 120 LSCPResultSet result;
1159 senkov 68 try {
1160     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1161 senkov 155 if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));
1162 capela 159 pSamplerChannel->SetMidiInputChannel((MidiInputDevice::MidiInputPort::midi_chan_t) MIDIChannel);
1163 senkov 68 }
1164     catch (LinuxSamplerException e) {
1165 senkov 120 result.Error(e);
1166 senkov 68 }
1167 senkov 120 return result.Produce();
1168 schoenebeck 35 }
1169    
1170 capela 159 String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
1171     dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
1172 schoenebeck 123 LSCPResultSet result;
1173     try {
1174 capela 159 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1175     if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));
1176     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1177     MidiInputDevice* pDevice = devices[MIDIDeviceId];
1178     if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1179     pSamplerChannel->SetMidiInputDevice(pDevice);
1180 schoenebeck 123 }
1181     catch (LinuxSamplerException e) {
1182     result.Error(e);
1183     }
1184     return result.Produce();
1185     }
1186    
1187 capela 159 String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
1188     dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
1189     LSCPResultSet result;
1190     try {
1191     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1192     if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));
1193     // Driver type name aliasing...
1194     if (MidiInputDriver == "ALSA") MidiInputDriver = "Alsa";
1195     // Check if there's one MIDI input device already created
1196     // for the intended MIDI driver type (MidiInputDriver)...
1197     MidiInputDevice *pDevice = NULL;
1198     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1199     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1200     for (; iter != devices.end(); iter++) {
1201     if ((iter->second)->Driver() == MidiInputDriver) {
1202     pDevice = iter->second;
1203     break;
1204     }
1205     }
1206     // If it doesn't exist, create a new one with default parameters...
1207     if (pDevice == NULL) {
1208     std::map<String,String> params;
1209     pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1210     // Make it with at least one initial port.
1211     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1212     parameters["ports"]->SetValue("1");
1213     }
1214     // Must have a device...
1215     if (pDevice == NULL)
1216     throw LinuxSamplerException("Internal error: could not create MIDI input device.");
1217     // Set it as the current channel device...
1218     pSamplerChannel->SetMidiInputDevice(pDevice);
1219     }
1220     catch (LinuxSamplerException e) {
1221     result.Error(e);
1222     }
1223     return result.Produce();
1224     }
1225    
1226 schoenebeck 35 /**
1227 capela 159 * Will be called by the parser to change the MIDI input device, port and channel on which
1228     * engine of a particular sampler channel should listen to.
1229     */
1230     String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
1231     dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
1232     LSCPResultSet result;
1233     try {
1234     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1235     if (!pSamplerChannel) throw LinuxSamplerException("Invalid channel number " + ToString(uiSamplerChannel));
1236     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1237     MidiInputDevice* pDevice = devices[MIDIDeviceId];
1238     if (!pDevice) throw LinuxSamplerException("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1239     pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (MidiInputDevice::MidiInputPort::midi_chan_t) MIDIChannel);
1240     }
1241     catch (LinuxSamplerException e) {
1242     result.Error(e);
1243     }
1244     return result.Produce();
1245     }
1246    
1247     /**
1248 schoenebeck 35 * Will be called by the parser to change the global volume factor on a
1249     * particular sampler channel.
1250     */
1251 schoenebeck 53 String LSCPServer::SetVolume(double Volume, uint uiSamplerChannel) {
1252     dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", Volume, uiSamplerChannel));
1253 senkov 120 LSCPResultSet result;
1254 schoenebeck 53 try {
1255     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1256     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
1257     Engine* pEngine = pSamplerChannel->GetEngine();
1258     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
1259     pEngine->Volume(Volume);
1260     }
1261     catch (LinuxSamplerException e) {
1262 senkov 120 result.Error(e);
1263 schoenebeck 53 }
1264 senkov 120 return result.Produce();
1265 schoenebeck 35 }
1266    
1267     /**
1268     * Will be called by the parser to reset a particular sampler channel.
1269     */
1270 schoenebeck 53 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
1271     dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
1272 senkov 120 LSCPResultSet result;
1273 schoenebeck 53 try {
1274     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1275     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
1276     Engine* pEngine = pSamplerChannel->GetEngine();
1277     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
1278     pEngine->Reset();
1279     }
1280     catch (LinuxSamplerException e) {
1281 senkov 120 result.Error(e);
1282 schoenebeck 53 }
1283 senkov 120 return result.Produce();
1284 schoenebeck 35 }
1285    
1286     /**
1287 schoenebeck 212 * Will be called by the parser to reset the whole sampler.
1288     */
1289     String LSCPServer::ResetSampler() {
1290     dmsg(2,("LSCPServer: ResetSampler()\n"));
1291     pSampler->Reset();
1292     LSCPResultSet result;
1293     return result.Produce();
1294     }
1295    
1296     /**
1297 schoenebeck 35 * Will be called by the parser to subscribe a client (frontend) on the
1298     * server for receiving event messages.
1299     */
1300 senkov 170 String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
1301     dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
1302     LSCPResultSet result;
1303     SubscriptionMutex.Lock();
1304     eventSubscriptions[type].push_back(currentSocket);
1305     SubscriptionMutex.Unlock();
1306     return result.Produce();
1307 schoenebeck 35 }
1308    
1309     /**
1310     * Will be called by the parser to unsubscribe a client on the server
1311     * for not receiving further event messages.
1312     */
1313 senkov 170 String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
1314     dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
1315     LSCPResultSet result;
1316     SubscriptionMutex.Lock();
1317     eventSubscriptions[type].remove(currentSocket);
1318     SubscriptionMutex.Unlock();
1319     return result.Produce();
1320 schoenebeck 35 }
1321 capela 133
1322 schoenebeck 210 /**
1323     * Will be called by the parser to enable or disable echo mode; if echo
1324     * mode is enabled, all commands from the client will (immediately) be
1325     * echoed back to the client.
1326     */
1327     String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
1328     dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
1329     LSCPResultSet result;
1330     try {
1331     if (boolean_value == 0) pSession->bVerbose = false;
1332     else if (boolean_value == 1) pSession->bVerbose = true;
1333     else throw LinuxSamplerException("Not a boolean value, must either be 0 or 1");
1334     }
1335     catch (LinuxSamplerException e) {
1336     result.Error(e);
1337     }
1338     return result.Produce();
1339     }
1340 capela 133
1341     // Instrument loader constructor.
1342     LSCPLoadInstrument::LSCPLoadInstrument(Engine* pEngine, String Filename, uint uiInstrument)
1343     : Thread(false, 0, -4)
1344     {
1345     this->pEngine = pEngine;
1346     this->Filename = Filename;
1347     this->uiInstrument = uiInstrument;
1348     }
1349    
1350     // Instrument loader process.
1351     int LSCPLoadInstrument::Main()
1352     {
1353     try {
1354     pEngine->LoadInstrument(Filename.c_str(), uiInstrument);
1355     }
1356    
1357     catch (LinuxSamplerException e) {
1358     e.PrintMessage();
1359     }
1360    
1361     // Always re-enable the engine.
1362     pEngine->Enable();
1363    
1364     // FIXME: Shoot ourselves on the foot?
1365     delete this;
1366     }

  ViewVC Help
Powered by ViewVC