/[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 113 - (show annotations) (download)
Sun Jun 6 20:59:49 2004 UTC (19 years, 9 months ago) by senkov
File size: 18957 byte(s)
* Added LSCP command GET CHANNEL INFO

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 if (pEngine) {
209 result.Add("ENGINE_NAME", pEngine->EngineName());
210 result.Add("VOLUME", pEngine->Volume());
211 }
212 //Some hardcoded stuff for now to make GUI look good
213 result.Add("AUDIO_OUTPUT_DEVICE", "0");
214 result.Add("AUDIO_OUTPUT_CHANNELS", "2");
215 result.Add("AUDIO_OUTPUT_ROUTING", "0,1");
216
217 if (pEngine) {
218 int iIdx = pEngine->InstrumentIndex();
219 if (iIdx != -1) {
220 result.Add("INSTRUMENT_FILE", pEngine->InstrumentFileName());
221 result.Add("INSTRUMENT_NR", iIdx);
222 }
223 }
224 //Some hardcoded stuff for now to make GUI look good
225 result.Add("MIDI_INPUT_DEVICE", "0");
226 result.Add("MIDI_INPUT_PORT", "0");
227 result.Add("MIDI_INPUT_CHANNEL", "1");
228
229 return result.Produce();
230 }
231 catch (LinuxSamplerException e) {
232 result_t result;
233 e.PrintMessage();
234 result.type = result_type_error;
235 result.code = LSCP_ERR_UNKNOWN;
236 result.message = e.Message();
237 return ConvertResult(result);
238 }
239 }
240
241 /**
242 * Will be called by the parser to get the amount of active voices on a
243 * particular sampler channel.
244 */
245 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
246 dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
247 result_t result;
248 try {
249 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
250 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
251 Engine* pEngine = pSamplerChannel->GetEngine();
252 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
253 return ToString(pEngine->VoiceCount()) + "\r\n"; // success
254 }
255 catch (LinuxSamplerException e) {
256 e.PrintMessage();
257 result.type = result_type_error;
258 result.code = LSCP_ERR_UNKNOWN;
259 result.message = e.Message();
260 }
261 return ConvertResult(result);
262 }
263
264 /**
265 * Will be called by the parser to get the amount of active disk streams on a
266 * particular sampler channel.
267 */
268 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
269 dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
270 result_t result;
271 try {
272 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
273 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
274 Engine* pEngine = pSamplerChannel->GetEngine();
275 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
276 return ToString(pEngine->DiskStreamCount()) + "\r\n"; // success
277 }
278 catch (LinuxSamplerException e) {
279 e.PrintMessage();
280 result.type = result_type_error;
281 result.code = LSCP_ERR_UNKNOWN;
282 result.message = e.Message();
283 }
284 return ConvertResult(result);
285 }
286
287 /**
288 * Will be called by the parser to get the buffer fill states of all disk
289 * streams on a particular sampler channel.
290 */
291 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
292 dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
293 result_t result;
294 try {
295 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
296 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
297 Engine* pEngine = pSamplerChannel->GetEngine();
298 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
299 if (!pEngine->DiskStreamSupported()) return "NA\r\n";
300 switch (ResponseType) {
301 case fill_response_bytes:
302 return ToString(pEngine->DiskStreamBufferFillBytes()) + "\r\n"; // success
303 case fill_response_percentage:
304 return ToString(pEngine->DiskStreamBufferFillPercentage()) + "\r\n"; // success
305 default:
306 throw LinuxSamplerException("Unknown fill response type");
307 }
308 }
309 catch (LinuxSamplerException e) {
310 e.PrintMessage();
311 result.type = result_type_error;
312 result.code = LSCP_ERR_UNKNOWN;
313 result.message = e.Message();
314 }
315 return ConvertResult(result);
316 }
317
318 /**
319 * Will be called by the parser to change the audio output type on a
320 * particular sampler channel.
321 */
322 String LSCPServer::SetAudioOutputType(AudioOutputDevice::type_t AudioOutputType, uint uiSamplerChannel) {
323 dmsg(2,("LSCPServer: SetAudioOutputType(AudioOutputType=%d, SamplerChannel=%d)\n", AudioOutputType, uiSamplerChannel));
324 result_t result;
325 try {
326 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
327 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
328 pSamplerChannel->SetAudioOutputDevice(AudioOutputType);
329 result.type = result_type_success;
330 }
331 catch (LinuxSamplerException e) {
332 e.PrintMessage();
333 result.type = result_type_error;
334 result.code = LSCP_ERR_UNKNOWN;
335 result.message = e.Message();
336 }
337 return ConvertResult(result);
338 }
339
340 /**
341 * Will be called by the parser to change the audio output channel for
342 * playback on a particular sampler channel.
343 */
344 String LSCPServer::SetAudioOutputChannel(uint AudioOutputChannel, uint uiSamplerChannel) {
345 dmsg(2,("LSCPServer: SetAudioOutputChannel(AudioOutputChannel=%d, SamplerChannel=%d)\n", AudioOutputChannel, uiSamplerChannel));
346 return "ERR:0:Not implemented yet.\r\n";
347 }
348
349 String LSCPServer::SetMIDIInputType(MidiInputDevice::type_t MidiInputType, uint uiSamplerChannel) {
350 dmsg(2,("LSCPServer: SetMIDIInputType(MidiInputType=%d, SamplerChannel=%d)\n", MidiInputType, uiSamplerChannel));
351 result_t result;
352 try {
353 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
354 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
355 pSamplerChannel->SetMidiInputDevice(MidiInputType);
356 result.type = result_type_success;
357 }
358 catch (LinuxSamplerException e) {
359 e.PrintMessage();
360 result.type = result_type_error;
361 result.code = LSCP_ERR_UNKNOWN;
362 result.message = e.Message();
363 }
364 return ConvertResult(result);
365 }
366
367 /**
368 * Will be called by the parser to change the MIDI input port on which the
369 * engine of a particular sampler channel should listen to.
370 */
371 String LSCPServer::SetMIDIInputPort(String MIDIInputPort, uint uiSamplerChannel) {
372 dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIInputPort=%s, Samplerchannel=%d)\n", MIDIInputPort.c_str(), uiSamplerChannel));
373 result_t result;
374 try {
375 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
376 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
377 if (!pSamplerChannel->GetMidiInputDevice()) throw LinuxSamplerException("No MIDI input device connected yet");
378 pSamplerChannel->GetMidiInputDevice()->SetInputPort(MIDIInputPort.c_str());
379 result.type = result_type_success;
380 }
381 catch (LinuxSamplerException e) {
382 e.PrintMessage();
383 result.type = result_type_error;
384 result.code = LSCP_ERR_UNKNOWN;
385 result.message = e.Message();
386 }
387 return ConvertResult(result);
388 }
389
390 /**
391 * Will be called by the parser to change the MIDI input channel on which the
392 * engine of a particular sampler channel should listen to.
393 */
394 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
395 dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n", MIDIChannel, uiSamplerChannel));
396 result_t result;
397 try {
398 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
399 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
400 if (!pSamplerChannel->GetMidiInputDevice()) throw LinuxSamplerException("No MIDI input device connected yet");
401 MidiInputDevice::type_t oldtype = pSamplerChannel->GetMidiInputDevice()->Type();
402 pSamplerChannel->SetMidiInputDevice(oldtype, (MidiInputDevice::midi_chan_t) MIDIChannel);
403
404 result.type = result_type_success;
405 }
406 catch (LinuxSamplerException e) {
407 e.PrintMessage();
408 result.type = result_type_error;
409 result.code = LSCP_ERR_UNKNOWN;
410 result.message = e.Message();
411 }
412 return ConvertResult(result);
413 }
414
415 /**
416 * Will be called by the parser to change the global volume factor on a
417 * particular sampler channel.
418 */
419 String LSCPServer::SetVolume(double Volume, uint uiSamplerChannel) {
420 dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", Volume, uiSamplerChannel));
421 result_t result;
422 try {
423 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
424 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
425 Engine* pEngine = pSamplerChannel->GetEngine();
426 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
427 pEngine->Volume(Volume);
428 result.type = result_type_success;
429 }
430 catch (LinuxSamplerException e) {
431 e.PrintMessage();
432 result.type = result_type_error;
433 result.code = LSCP_ERR_UNKNOWN;
434 result.message = e.Message();
435 }
436 return ConvertResult(result);
437 }
438
439 /**
440 * Will be called by the parser to reset a particular sampler channel.
441 */
442 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
443 dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
444 result_t result;
445 try {
446 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
447 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
448 Engine* pEngine = pSamplerChannel->GetEngine();
449 if (!pEngine) throw LinuxSamplerException("No engine loaded on channel");
450 pEngine->Reset();
451 result.type = result_type_success;
452 }
453 catch (LinuxSamplerException e) {
454 e.PrintMessage();
455 result.type = result_type_error;
456 result.code = LSCP_ERR_UNKNOWN;
457 result.message = e.Message();
458 }
459 return ConvertResult(result);
460 }
461
462 /**
463 * Will be called by the parser to subscribe a client (frontend) on the
464 * server for receiving event messages.
465 */
466 String LSCPServer::SubscribeNotification(uint UDPPort) {
467 dmsg(2,("LSCPServer: SubscribeNotification(UDPPort=%d)\n", UDPPort));
468 return "ERR:0:Not implemented yet.\r\n";
469 }
470
471 /**
472 * Will be called by the parser to unsubscribe a client on the server
473 * for not receiving further event messages.
474 */
475 String LSCPServer::UnsubscribeNotification(String SessionID) {
476 dmsg(2,("LSCPServer: UnsubscribeNotification(SessionID=%s)\n", SessionID.c_str()));
477 return "ERR:0:Not implemented yet.\r\n";
478 }

  ViewVC Help
Powered by ViewVC