/[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 121 - (hide annotations) (download)
Sat Jun 12 07:46:02 2004 UTC (19 years, 9 months ago) by senkov
File size: 17245 byte(s)
typo in case statement (while doing string replace forgot to add breaks)

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 schoenebeck 35
26 schoenebeck 53 #include "../engines/gig/Engine.h"
27    
28     LSCPServer::LSCPServer(Sampler* pSampler) : Thread(false, 0, -4) {
29     this->pSampler = pSampler;
30 schoenebeck 35 }
31    
32     int LSCPServer::Main() {
33     hSocket = socket(AF_INET, SOCK_STREAM, 0);
34     if (hSocket < 0) {
35     std::cerr << "LSCPServer: Could not create server socket." << std::endl;
36 schoenebeck 53 //return -1;
37     exit(EXIT_FAILURE);
38 schoenebeck 35 }
39    
40     SocketAddress.sin_family = AF_INET;
41     SocketAddress.sin_port = htons(LSCP_PORT);
42     SocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
43    
44     if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
45     std::cerr << "LSCPServer: Could not bind server socket." << std::endl;
46     close(hSocket);
47 schoenebeck 53 //return -1;
48     exit(EXIT_FAILURE);
49 schoenebeck 35 }
50    
51     listen(hSocket, 1);
52     dmsg(1,("LSCPServer: Server running.\n")); // server running
53    
54     // now wait for client connections and handle their requests
55     sockaddr_in client;
56     int length = sizeof(client);
57     while (true) {
58     hSession = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
59     if (hSession < 0) {
60     std::cerr << "LSCPServer: Client connection failed." << std::endl;
61     close(hSocket);
62 schoenebeck 53 //return -1;
63     exit(EXIT_FAILURE);
64 schoenebeck 35 }
65    
66     dmsg(1,("LSCPServer: Client connection established.\n"));
67     //send(hSession, "Welcome!\r\n", 10, 0);
68    
69     // Parser invocation
70     yyparse_param_t yyparse_param;
71     yyparse_param.pServer = this;
72     yylex_init(&yyparse_param.pScanner);
73     while (yyparse(&yyparse_param) == LSCP_SYNTAX_ERROR); // recall parser in case of syntax error
74     yylex_destroy(yyparse_param.pScanner);
75    
76     close(hSession);
77     dmsg(1,("LSCPServer: Client connection terminated.\n"));
78     }
79     }
80    
81     /**
82     * Will be called by the parser whenever it wants to send an answer to the
83     * client / frontend.
84     *
85     * @param ReturnMessage - message that will be send to the client
86     */
87     void LSCPServer::AnswerClient(String ReturnMessage) {
88     dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
89     send(hSession, ReturnMessage.c_str(), ReturnMessage.size(), 0);
90     }
91    
92     /**
93     * Will be called by the parser to load an instrument.
94     */
95 schoenebeck 53 String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel) {
96     dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
97 senkov 120 LSCPResultSet result;
98 schoenebeck 53 try {
99     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
100     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
101     Engine* pEngine = pSamplerChannel->GetEngine();
102     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
103     pEngine->LoadInstrument(Filename.c_str(), uiInstrument);
104     }
105     catch (LinuxSamplerException e) {
106 senkov 120 result.Error(e);
107 schoenebeck 53 }
108 senkov 120 return result.Produce();
109 schoenebeck 35 }
110    
111     /**
112     * Will be called by the parser to load and deploy an engine.
113     */
114 schoenebeck 53 String LSCPServer::LoadEngine(String EngineName, uint uiSamplerChannel) {
115     dmsg(2,("LSCPServer: LoadEngine(EngineName=%s,SamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
116 senkov 120 LSCPResultSet result;
117 schoenebeck 53 try {
118 schoenebeck 64 Engine::type_t type;
119 senkov 120 if ((EngineName == "GigEngine") || (EngineName == "gig")) type = Engine::type_gig;
120 schoenebeck 53 else throw LinuxSamplerException("Unknown engine type");
121     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
122     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
123     pSamplerChannel->LoadEngine(type);
124     }
125     catch (LinuxSamplerException e) {
126 senkov 120 result.Error(e);
127 schoenebeck 53 }
128 senkov 120 return result.Produce();
129 schoenebeck 35 }
130    
131     /**
132     * Will be called by the parser to get the amount of sampler channels.
133     */
134     String LSCPServer::GetChannels() {
135     dmsg(2,("LSCPServer: GetChannels()\n"));
136 senkov 120 LSCPResultSet result;
137     result.Add(pSampler->SamplerChannels());
138     return result.Produce();
139 schoenebeck 35 }
140    
141     /**
142     * Will be called by the parser to add a sampler channel.
143     */
144     String LSCPServer::AddChannel() {
145     dmsg(2,("LSCPServer: AddChannel()\n"));
146 schoenebeck 53 SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
147 senkov 120 LSCPResultSet result(pSamplerChannel->Index());
148     return result.Produce();
149 schoenebeck 35 }
150    
151     /**
152     * Will be called by the parser to remove a sampler channel.
153     */
154 schoenebeck 53 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
155     dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
156 senkov 120 LSCPResultSet result;
157 schoenebeck 53 pSampler->RemoveSamplerChannel(uiSamplerChannel);
158 senkov 120 return result.Produce();
159 schoenebeck 35 }
160    
161     /**
162     * Will be called by the parser to get all available engines.
163     */
164     String LSCPServer::GetAvailableEngines() {
165     dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
166 senkov 120 LSCPResultSet result("GigEngine");
167     return result.Produce();
168 schoenebeck 35 }
169    
170     /**
171     * Will be called by the parser to get descriptions for a particular engine.
172     */
173     String LSCPServer::GetEngineInfo(String EngineName) {
174     dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
175 senkov 120 LSCPResultSet result;
176 schoenebeck 53 try {
177 senkov 120 if ((EngineName == "GigEngine") || (EngineName == "gig")) {
178 schoenebeck 53 Engine* pEngine = new LinuxSampler::gig::Engine;
179 senkov 120 result.Add(pEngine->Description());
180 schoenebeck 53 delete pEngine;
181     }
182     else throw LinuxSamplerException("Unknown engine type");
183     }
184     catch (LinuxSamplerException e) {
185 senkov 120 result.Error(e);
186 schoenebeck 53 }
187 senkov 120 return result.Produce();
188 schoenebeck 35 }
189    
190     /**
191     * Will be called by the parser to get informations about a particular
192     * sampler channel.
193     */
194 schoenebeck 53 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
195     dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
196 senkov 120 LSCPResultSet result;
197 senkov 113 try {
198     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
199     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
200     Engine* pEngine = pSamplerChannel->GetEngine();
201 senkov 117
202     //Defaults values
203     String EngineName = "NONE";
204     float Volume = 0;
205     String InstrumentFileName = "NONE";
206     int InstrumentIndex = 0;
207    
208 senkov 113 if (pEngine) {
209 senkov 117 EngineName = pEngine->EngineName();
210     Volume = pEngine->Volume();
211     int iIdx = pEngine->InstrumentIndex();
212     if (iIdx != -1) {
213     InstrumentFileName = pEngine->InstrumentFileName();
214     InstrumentIndex = iIdx;
215     }
216 senkov 113 }
217 senkov 117
218     result.Add("ENGINE_NAME", EngineName);
219     result.Add("VOLUME", Volume);
220    
221 senkov 113 //Some hardcoded stuff for now to make GUI look good
222     result.Add("AUDIO_OUTPUT_DEVICE", "0");
223     result.Add("AUDIO_OUTPUT_CHANNELS", "2");
224     result.Add("AUDIO_OUTPUT_ROUTING", "0,1");
225    
226 senkov 117 result.Add("INSTRUMENT_FILE", InstrumentFileName);
227     result.Add("INSTRUMENT_NR", InstrumentIndex);
228    
229     //Some more hardcoded stuff for now to make GUI look good
230 senkov 113 result.Add("MIDI_INPUT_DEVICE", "0");
231     result.Add("MIDI_INPUT_PORT", "0");
232     result.Add("MIDI_INPUT_CHANNEL", "1");
233     }
234     catch (LinuxSamplerException e) {
235 senkov 120 result.Error(e);
236 senkov 113 }
237 senkov 120 return result.Produce();
238 schoenebeck 35 }
239    
240     /**
241     * Will be called by the parser to get the amount of active voices on a
242     * particular sampler channel.
243     */
244 schoenebeck 53 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
245     dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
246 senkov 120 LSCPResultSet result;
247 schoenebeck 53 try {
248     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
249     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
250     Engine* pEngine = pSamplerChannel->GetEngine();
251     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
252 senkov 120 result.Add(pEngine->VoiceCount());
253 schoenebeck 53 }
254     catch (LinuxSamplerException e) {
255 senkov 120 result.Error(e);
256 schoenebeck 53 }
257 senkov 120 return result.Produce();
258 schoenebeck 35 }
259    
260     /**
261     * Will be called by the parser to get the amount of active disk streams on a
262     * particular sampler channel.
263     */
264 schoenebeck 53 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
265     dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
266 senkov 120 LSCPResultSet result;
267 schoenebeck 53 try {
268     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
269     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
270     Engine* pEngine = pSamplerChannel->GetEngine();
271     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
272 senkov 120 result.Add(pEngine->DiskStreamCount());
273 schoenebeck 53 }
274     catch (LinuxSamplerException e) {
275 senkov 120 result.Error(e);
276 schoenebeck 53 }
277 senkov 120 return result.Produce();
278 schoenebeck 35 }
279    
280     /**
281     * Will be called by the parser to get the buffer fill states of all disk
282     * streams on a particular sampler channel.
283     */
284 schoenebeck 53 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
285     dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
286 senkov 120 LSCPResultSet result;
287 schoenebeck 53 try {
288     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
289     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
290     Engine* pEngine = pSamplerChannel->GetEngine();
291     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
292 senkov 120 if (!pEngine->DiskStreamSupported()) return "NA\r\n"; //FIXME: Update resultset class to support "NA"
293 schoenebeck 53 switch (ResponseType) {
294     case fill_response_bytes:
295 senkov 120 result.Add(pEngine->DiskStreamBufferFillBytes());
296 senkov 121 break;
297 schoenebeck 53 case fill_response_percentage:
298 senkov 120 result.Add(pEngine->DiskStreamBufferFillPercentage());
299 senkov 121 break;
300 schoenebeck 53 default:
301     throw LinuxSamplerException("Unknown fill response type");
302     }
303     }
304     catch (LinuxSamplerException e) {
305 senkov 120 result.Error(e);
306 schoenebeck 53 }
307 senkov 120 return result.Produce();
308 schoenebeck 35 }
309    
310     /**
311     * Will be called by the parser to change the audio output type on a
312     * particular sampler channel.
313     */
314 schoenebeck 64 String LSCPServer::SetAudioOutputType(AudioOutputDevice::type_t AudioOutputType, uint uiSamplerChannel) {
315 schoenebeck 53 dmsg(2,("LSCPServer: SetAudioOutputType(AudioOutputType=%d, SamplerChannel=%d)\n", AudioOutputType, uiSamplerChannel));
316 senkov 120 LSCPResultSet result;
317 schoenebeck 53 try {
318     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
319     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
320     pSamplerChannel->SetAudioOutputDevice(AudioOutputType);
321     }
322     catch (LinuxSamplerException e) {
323 senkov 120 result.Error(e);
324 schoenebeck 53 }
325 senkov 120 return result.Produce();
326 schoenebeck 35 }
327    
328     /**
329     * Will be called by the parser to change the audio output channel for
330     * playback on a particular sampler channel.
331     */
332 schoenebeck 53 String LSCPServer::SetAudioOutputChannel(uint AudioOutputChannel, uint uiSamplerChannel) {
333     dmsg(2,("LSCPServer: SetAudioOutputChannel(AudioOutputChannel=%d, SamplerChannel=%d)\n", AudioOutputChannel, uiSamplerChannel));
334 senkov 120 return "ERR:0:Not implemented yet.\r\n"; //FIXME: Add support for this in resultset class?
335 schoenebeck 35 }
336    
337 schoenebeck 64 String LSCPServer::SetMIDIInputType(MidiInputDevice::type_t MidiInputType, uint uiSamplerChannel) {
338 schoenebeck 53 dmsg(2,("LSCPServer: SetMIDIInputType(MidiInputType=%d, SamplerChannel=%d)\n", MidiInputType, uiSamplerChannel));
339 senkov 120 LSCPResultSet result;
340 schoenebeck 53 try {
341     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
342     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
343     pSamplerChannel->SetMidiInputDevice(MidiInputType);
344     }
345     catch (LinuxSamplerException e) {
346 senkov 120 result.Error(e);
347 schoenebeck 53 }
348 senkov 120 return result.Produce();
349 schoenebeck 53 }
350    
351 schoenebeck 35 /**
352     * Will be called by the parser to change the MIDI input port on which the
353     * engine of a particular sampler channel should listen to.
354     */
355 senkov 68 String LSCPServer::SetMIDIInputPort(String MIDIInputPort, uint uiSamplerChannel) {
356     dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIInputPort=%s, Samplerchannel=%d)\n", MIDIInputPort.c_str(), uiSamplerChannel));
357 senkov 120 LSCPResultSet result;
358 senkov 68 try {
359     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
360     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
361     if (!pSamplerChannel->GetMidiInputDevice()) throw LinuxSamplerException("No MIDI input device connected yet");
362     pSamplerChannel->GetMidiInputDevice()->SetInputPort(MIDIInputPort.c_str());
363     }
364     catch (LinuxSamplerException e) {
365 senkov 120 result.Error(e);
366 senkov 68 }
367 senkov 120 return result.Produce();
368 schoenebeck 35 }
369    
370     /**
371     * Will be called by the parser to change the MIDI input channel on which the
372     * engine of a particular sampler channel should listen to.
373     */
374 schoenebeck 53 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
375     dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n", MIDIChannel, uiSamplerChannel));
376 senkov 120 LSCPResultSet result;
377 schoenebeck 64 try {
378     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
379     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
380     if (!pSamplerChannel->GetMidiInputDevice()) throw LinuxSamplerException("No MIDI input device connected yet");
381     MidiInputDevice::type_t oldtype = pSamplerChannel->GetMidiInputDevice()->Type();
382 senkov 79 pSamplerChannel->SetMidiInputDevice(oldtype, (MidiInputDevice::midi_chan_t) MIDIChannel);
383 schoenebeck 64 }
384     catch (LinuxSamplerException e) {
385 senkov 120 result.Error(e);
386 schoenebeck 64 }
387 senkov 120 return result.Produce();
388 schoenebeck 35 }
389    
390     /**
391     * Will be called by the parser to change the global volume factor on a
392     * particular sampler channel.
393     */
394 schoenebeck 53 String LSCPServer::SetVolume(double Volume, uint uiSamplerChannel) {
395     dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", Volume, uiSamplerChannel));
396 senkov 120 LSCPResultSet result;
397 schoenebeck 53 try {
398     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
399     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
400     Engine* pEngine = pSamplerChannel->GetEngine();
401     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
402     pEngine->Volume(Volume);
403     }
404     catch (LinuxSamplerException e) {
405 senkov 120 result.Error(e);
406 schoenebeck 53 }
407 senkov 120 return result.Produce();
408 schoenebeck 35 }
409    
410     /**
411     * Will be called by the parser to reset a particular sampler channel.
412     */
413 schoenebeck 53 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
414     dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
415 senkov 120 LSCPResultSet result;
416 schoenebeck 53 try {
417     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
418     if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
419     Engine* pEngine = pSamplerChannel->GetEngine();
420     if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
421     pEngine->Reset();
422     }
423     catch (LinuxSamplerException e) {
424 senkov 120 result.Error(e);
425 schoenebeck 53 }
426 senkov 120 return result.Produce();
427 schoenebeck 35 }
428    
429     /**
430     * Will be called by the parser to subscribe a client (frontend) on the
431     * server for receiving event messages.
432     */
433     String LSCPServer::SubscribeNotification(uint UDPPort) {
434     dmsg(2,("LSCPServer: SubscribeNotification(UDPPort=%d)\n", UDPPort));
435     return "ERR:0:Not implemented yet.\r\n";
436     }
437    
438     /**
439     * Will be called by the parser to unsubscribe a client on the server
440     * for not receiving further event messages.
441     */
442     String LSCPServer::UnsubscribeNotification(String SessionID) {
443     dmsg(2,("LSCPServer: UnsubscribeNotification(SessionID=%s)\n", SessionID.c_str()));
444     return "ERR:0:Not implemented yet.\r\n";
445     }

  ViewVC Help
Powered by ViewVC