/[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 170 - (hide annotations) (download)
Sat Jul 3 20:08:07 2004 UTC (19 years, 8 months ago) by senkov
File size: 53007 byte(s)
* moved ToString to common
* Implemented handling of multiple connections
* Implemented guts for event subscription/unsubscription
* Illustrated event notification sending by sending MISC events
when connections are established or terminated.

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

  ViewVC Help
Powered by ViewVC