/[svn]/linuxsampler/trunk/src/network/lscpserver.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/network/lscpserver.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 117 - (show annotations) (download)
Tue Jun 8 01:29:08 2004 UTC (19 years, 9 months ago) by senkov
File size: 19218 byte(s)
Updated GET CHANNEL INFO to send uninitialized params with "NONE"/0

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
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 #include "lscpresultset.h"
25
26 #include "../engines/gig/Engine.h"
27
28 LSCPServer::LSCPServer(Sampler* pSampler) : Thread(false, 0, -4) {
29 this->pSampler = pSampler;
30 }
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 //return -1;
37 exit(EXIT_FAILURE);
38 }
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 //return -1;
48 exit(EXIT_FAILURE);
49 }
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 //return -1;
63 exit(EXIT_FAILURE);
64 }
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 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 result_t result;
98 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 result.type = result_type_success;
105 }
106 catch (LinuxSamplerException e) {
107 e.PrintMessage();
108 result.type = result_type_error;
109 result.code = LSCP_ERR_UNKNOWN;
110 result.message = e.Message();
111 }
112 return ConvertResult(result);
113 }
114
115 /**
116 * Will be called by the parser to load and deploy an engine.
117 */
118 String LSCPServer::LoadEngine(String EngineName, uint uiSamplerChannel) {
119 dmsg(2,("LSCPServer: LoadEngine(EngineName=%s,SamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
120 result_t result;
121 try {
122 Engine::type_t type;
123 if (EngineName == "gig") type = Engine::type_gig;
124 else throw LinuxSamplerException("Unknown engine type");
125 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
126 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
127 pSamplerChannel->LoadEngine(type);
128 result.type = result_type_success;
129 }
130 catch (LinuxSamplerException e) {
131 e.PrintMessage();
132 result.type = result_type_error;
133 result.code = LSCP_ERR_UNKNOWN;
134 result.message = e.Message();
135 }
136 return ConvertResult(result);
137 }
138
139 /**
140 * Will be called by the parser to get the amount of sampler channels.
141 */
142 String LSCPServer::GetChannels() {
143 dmsg(2,("LSCPServer: GetChannels()\n"));
144 return ToString(pSampler->SamplerChannels()) + "\r\n";
145 }
146
147 /**
148 * Will be called by the parser to add a sampler channel.
149 */
150 String LSCPServer::AddChannel() {
151 dmsg(2,("LSCPServer: AddChannel()\n"));
152 SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
153 return "OK[" + ToString(pSamplerChannel->Index()) + "]\r\n";
154 }
155
156 /**
157 * Will be called by the parser to remove a sampler channel.
158 */
159 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
160 dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
161 pSampler->RemoveSamplerChannel(uiSamplerChannel);
162 return "OK\r\n";
163 }
164
165 /**
166 * Will be called by the parser to get all available engines.
167 */
168 String LSCPServer::GetAvailableEngines() {
169 dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
170 return "gig\r\n";
171 }
172
173 /**
174 * Will be called by the parser to get descriptions for a particular engine.
175 */
176 String LSCPServer::GetEngineInfo(String EngineName) {
177 dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
178 result_t result;
179 try {
180 if (EngineName == "gig") {
181 Engine* pEngine = new LinuxSampler::gig::Engine;
182 String info = pEngine->Description() + "\r\n";
183 delete pEngine;
184 return info; // success
185 }
186 else throw LinuxSamplerException("Unknown engine type");
187 }
188 catch (LinuxSamplerException e) {
189 e.PrintMessage();
190 result.type = result_type_error;
191 result.code = LSCP_ERR_UNKNOWN;
192 result.message = e.Message();
193 }
194 return ConvertResult(result);
195 }
196
197 /**
198 * Will be called by the parser to get informations about a particular
199 * sampler channel.
200 */
201 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
202 dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
203 try {
204 LSCPResultSet result;
205 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
206 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
207 Engine* pEngine = pSamplerChannel->GetEngine();
208
209 //Defaults values
210 String EngineName = "NONE";
211 float Volume = 0;
212 String InstrumentFileName = "NONE";
213 int InstrumentIndex = 0;
214
215 if (pEngine) {
216 EngineName = pEngine->EngineName();
217 Volume = pEngine->Volume();
218 int iIdx = pEngine->InstrumentIndex();
219 if (iIdx != -1) {
220 InstrumentFileName = pEngine->InstrumentFileName();
221 InstrumentIndex = iIdx;
222 }
223 }
224
225 result.Add("ENGINE_NAME", EngineName);
226 result.Add("VOLUME", Volume);
227
228 //Some hardcoded stuff for now to make GUI look good
229 result.Add("AUDIO_OUTPUT_DEVICE", "0");
230 result.Add("AUDIO_OUTPUT_CHANNELS", "2");
231 result.Add("AUDIO_OUTPUT_ROUTING", "0,1");
232
233 result.Add("INSTRUMENT_FILE", InstrumentFileName);
234 result.Add("INSTRUMENT_NR", InstrumentIndex);
235
236 //Some more hardcoded stuff for now to make GUI look good
237 result.Add("MIDI_INPUT_DEVICE", "0");
238 result.Add("MIDI_INPUT_PORT", "0");
239 result.Add("MIDI_INPUT_CHANNEL", "1");
240
241 return result.Produce();
242 }
243 catch (LinuxSamplerException e) {
244 result_t result;
245 e.PrintMessage();
246 result.type = result_type_error;
247 result.code = LSCP_ERR_UNKNOWN;
248 result.message = e.Message();
249 return ConvertResult(result);
250 }
251 }
252
253 /**
254 * Will be called by the parser to get the amount of active voices on a
255 * particular sampler channel.
256 */
257 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
258 dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
259 result_t result;
260 try {
261 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
262 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
263 Engine* pEngine = pSamplerChannel->GetEngine();
264 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
265 return ToString(pEngine->VoiceCount()) + "\r\n"; // success
266 }
267 catch (LinuxSamplerException e) {
268 e.PrintMessage();
269 result.type = result_type_error;
270 result.code = LSCP_ERR_UNKNOWN;
271 result.message = e.Message();
272 }
273 return ConvertResult(result);
274 }
275
276 /**
277 * Will be called by the parser to get the amount of active disk streams on a
278 * particular sampler channel.
279 */
280 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
281 dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
282 result_t result;
283 try {
284 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
285 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
286 Engine* pEngine = pSamplerChannel->GetEngine();
287 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
288 return ToString(pEngine->DiskStreamCount()) + "\r\n"; // success
289 }
290 catch (LinuxSamplerException e) {
291 e.PrintMessage();
292 result.type = result_type_error;
293 result.code = LSCP_ERR_UNKNOWN;
294 result.message = e.Message();
295 }
296 return ConvertResult(result);
297 }
298
299 /**
300 * Will be called by the parser to get the buffer fill states of all disk
301 * streams on a particular sampler channel.
302 */
303 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
304 dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
305 result_t result;
306 try {
307 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
308 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
309 Engine* pEngine = pSamplerChannel->GetEngine();
310 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
311 if (!pEngine->DiskStreamSupported()) return "NA\r\n";
312 switch (ResponseType) {
313 case fill_response_bytes:
314 return ToString(pEngine->DiskStreamBufferFillBytes()) + "\r\n"; // success
315 case fill_response_percentage:
316 return ToString(pEngine->DiskStreamBufferFillPercentage()) + "\r\n"; // success
317 default:
318 throw LinuxSamplerException("Unknown fill response type");
319 }
320 }
321 catch (LinuxSamplerException e) {
322 e.PrintMessage();
323 result.type = result_type_error;
324 result.code = LSCP_ERR_UNKNOWN;
325 result.message = e.Message();
326 }
327 return ConvertResult(result);
328 }
329
330 /**
331 * Will be called by the parser to change the audio output type on a
332 * particular sampler channel.
333 */
334 String LSCPServer::SetAudioOutputType(AudioOutputDevice::type_t AudioOutputType, uint uiSamplerChannel) {
335 dmsg(2,("LSCPServer: SetAudioOutputType(AudioOutputType=%d, SamplerChannel=%d)\n", AudioOutputType, uiSamplerChannel));
336 result_t result;
337 try {
338 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
339 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
340 pSamplerChannel->SetAudioOutputDevice(AudioOutputType);
341 result.type = result_type_success;
342 }
343 catch (LinuxSamplerException e) {
344 e.PrintMessage();
345 result.type = result_type_error;
346 result.code = LSCP_ERR_UNKNOWN;
347 result.message = e.Message();
348 }
349 return ConvertResult(result);
350 }
351
352 /**
353 * Will be called by the parser to change the audio output channel for
354 * playback on a particular sampler channel.
355 */
356 String LSCPServer::SetAudioOutputChannel(uint AudioOutputChannel, uint uiSamplerChannel) {
357 dmsg(2,("LSCPServer: SetAudioOutputChannel(AudioOutputChannel=%d, SamplerChannel=%d)\n", AudioOutputChannel, uiSamplerChannel));
358 return "ERR:0:Not implemented yet.\r\n";
359 }
360
361 String LSCPServer::SetMIDIInputType(MidiInputDevice::type_t MidiInputType, uint uiSamplerChannel) {
362 dmsg(2,("LSCPServer: SetMIDIInputType(MidiInputType=%d, SamplerChannel=%d)\n", MidiInputType, uiSamplerChannel));
363 result_t result;
364 try {
365 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
366 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
367 pSamplerChannel->SetMidiInputDevice(MidiInputType);
368 result.type = result_type_success;
369 }
370 catch (LinuxSamplerException e) {
371 e.PrintMessage();
372 result.type = result_type_error;
373 result.code = LSCP_ERR_UNKNOWN;
374 result.message = e.Message();
375 }
376 return ConvertResult(result);
377 }
378
379 /**
380 * Will be called by the parser to change the MIDI input port on which the
381 * engine of a particular sampler channel should listen to.
382 */
383 String LSCPServer::SetMIDIInputPort(String MIDIInputPort, uint uiSamplerChannel) {
384 dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIInputPort=%s, Samplerchannel=%d)\n", MIDIInputPort.c_str(), uiSamplerChannel));
385 result_t result;
386 try {
387 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
388 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
389 if (!pSamplerChannel->GetMidiInputDevice()) throw LinuxSamplerException("No MIDI input device connected yet");
390 pSamplerChannel->GetMidiInputDevice()->SetInputPort(MIDIInputPort.c_str());
391 result.type = result_type_success;
392 }
393 catch (LinuxSamplerException e) {
394 e.PrintMessage();
395 result.type = result_type_error;
396 result.code = LSCP_ERR_UNKNOWN;
397 result.message = e.Message();
398 }
399 return ConvertResult(result);
400 }
401
402 /**
403 * Will be called by the parser to change the MIDI input channel on which the
404 * engine of a particular sampler channel should listen to.
405 */
406 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
407 dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n", MIDIChannel, uiSamplerChannel));
408 result_t result;
409 try {
410 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
411 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
412 if (!pSamplerChannel->GetMidiInputDevice()) throw LinuxSamplerException("No MIDI input device connected yet");
413 MidiInputDevice::type_t oldtype = pSamplerChannel->GetMidiInputDevice()->Type();
414 pSamplerChannel->SetMidiInputDevice(oldtype, (MidiInputDevice::midi_chan_t) MIDIChannel);
415
416 result.type = result_type_success;
417 }
418 catch (LinuxSamplerException e) {
419 e.PrintMessage();
420 result.type = result_type_error;
421 result.code = LSCP_ERR_UNKNOWN;
422 result.message = e.Message();
423 }
424 return ConvertResult(result);
425 }
426
427 /**
428 * Will be called by the parser to change the global volume factor on a
429 * particular sampler channel.
430 */
431 String LSCPServer::SetVolume(double Volume, uint uiSamplerChannel) {
432 dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", Volume, uiSamplerChannel));
433 result_t result;
434 try {
435 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
436 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
437 Engine* pEngine = pSamplerChannel->GetEngine();
438 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
439 pEngine->Volume(Volume);
440 result.type = result_type_success;
441 }
442 catch (LinuxSamplerException e) {
443 e.PrintMessage();
444 result.type = result_type_error;
445 result.code = LSCP_ERR_UNKNOWN;
446 result.message = e.Message();
447 }
448 return ConvertResult(result);
449 }
450
451 /**
452 * Will be called by the parser to reset a particular sampler channel.
453 */
454 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
455 dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
456 result_t result;
457 try {
458 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
459 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
460 Engine* pEngine = pSamplerChannel->GetEngine();
461 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
462 pEngine->Reset();
463 result.type = result_type_success;
464 }
465 catch (LinuxSamplerException e) {
466 e.PrintMessage();
467 result.type = result_type_error;
468 result.code = LSCP_ERR_UNKNOWN;
469 result.message = e.Message();
470 }
471 return ConvertResult(result);
472 }
473
474 /**
475 * Will be called by the parser to subscribe a client (frontend) on the
476 * server for receiving event messages.
477 */
478 String LSCPServer::SubscribeNotification(uint UDPPort) {
479 dmsg(2,("LSCPServer: SubscribeNotification(UDPPort=%d)\n", UDPPort));
480 return "ERR:0:Not implemented yet.\r\n";
481 }
482
483 /**
484 * Will be called by the parser to unsubscribe a client on the server
485 * for not receiving further event messages.
486 */
487 String LSCPServer::UnsubscribeNotification(String SessionID) {
488 dmsg(2,("LSCPServer: UnsubscribeNotification(SessionID=%s)\n", SessionID.c_str()));
489 return "ERR:0:Not implemented yet.\r\n";
490 }

  ViewVC Help
Powered by ViewVC