/[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 121 - (show 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 /***************************************************************************
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 LSCPResultSet 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 }
105 catch (LinuxSamplerException e) {
106 result.Error(e);
107 }
108 return result.Produce();
109 }
110
111 /**
112 * Will be called by the parser to load and deploy an engine.
113 */
114 String LSCPServer::LoadEngine(String EngineName, uint uiSamplerChannel) {
115 dmsg(2,("LSCPServer: LoadEngine(EngineName=%s,SamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
116 LSCPResultSet result;
117 try {
118 Engine::type_t type;
119 if ((EngineName == "GigEngine") || (EngineName == "gig")) type = Engine::type_gig;
120 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 result.Error(e);
127 }
128 return result.Produce();
129 }
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 LSCPResultSet result;
137 result.Add(pSampler->SamplerChannels());
138 return result.Produce();
139 }
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 SamplerChannel* pSamplerChannel = pSampler->AddSamplerChannel();
147 LSCPResultSet result(pSamplerChannel->Index());
148 return result.Produce();
149 }
150
151 /**
152 * Will be called by the parser to remove a sampler channel.
153 */
154 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
155 dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
156 LSCPResultSet result;
157 pSampler->RemoveSamplerChannel(uiSamplerChannel);
158 return result.Produce();
159 }
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 LSCPResultSet result("GigEngine");
167 return result.Produce();
168 }
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 LSCPResultSet result;
176 try {
177 if ((EngineName == "GigEngine") || (EngineName == "gig")) {
178 Engine* pEngine = new LinuxSampler::gig::Engine;
179 result.Add(pEngine->Description());
180 delete pEngine;
181 }
182 else throw LinuxSamplerException("Unknown engine type");
183 }
184 catch (LinuxSamplerException e) {
185 result.Error(e);
186 }
187 return result.Produce();
188 }
189
190 /**
191 * Will be called by the parser to get informations about a particular
192 * sampler channel.
193 */
194 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
195 dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
196 LSCPResultSet result;
197 try {
198 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
199 if (!pSamplerChannel) throw LinuxSamplerException("Index out of bounds");
200 Engine* pEngine = pSamplerChannel->GetEngine();
201
202 //Defaults values
203 String EngineName = "NONE";
204 float Volume = 0;
205 String InstrumentFileName = "NONE";
206 int InstrumentIndex = 0;
207
208 if (pEngine) {
209 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 }
217
218 result.Add("ENGINE_NAME", EngineName);
219 result.Add("VOLUME", Volume);
220
221 //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 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 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 result.Error(e);
236 }
237 return result.Produce();
238 }
239
240 /**
241 * Will be called by the parser to get the amount of active voices on a
242 * particular sampler channel.
243 */
244 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
245 dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
246 LSCPResultSet result;
247 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 result.Add(pEngine->VoiceCount());
253 }
254 catch (LinuxSamplerException e) {
255 result.Error(e);
256 }
257 return result.Produce();
258 }
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 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
265 dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
266 LSCPResultSet result;
267 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 result.Add(pEngine->DiskStreamCount());
273 }
274 catch (LinuxSamplerException e) {
275 result.Error(e);
276 }
277 return result.Produce();
278 }
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 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
285 dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
286 LSCPResultSet result;
287 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 if (!pEngine->DiskStreamSupported()) return "NA\r\n"; //FIXME: Update resultset class to support "NA"
293 switch (ResponseType) {
294 case fill_response_bytes:
295 result.Add(pEngine->DiskStreamBufferFillBytes());
296 break;
297 case fill_response_percentage:
298 result.Add(pEngine->DiskStreamBufferFillPercentage());
299 break;
300 default:
301 throw LinuxSamplerException("Unknown fill response type");
302 }
303 }
304 catch (LinuxSamplerException e) {
305 result.Error(e);
306 }
307 return result.Produce();
308 }
309
310 /**
311 * Will be called by the parser to change the audio output type on a
312 * particular sampler channel.
313 */
314 String LSCPServer::SetAudioOutputType(AudioOutputDevice::type_t AudioOutputType, uint uiSamplerChannel) {
315 dmsg(2,("LSCPServer: SetAudioOutputType(AudioOutputType=%d, SamplerChannel=%d)\n", AudioOutputType, uiSamplerChannel));
316 LSCPResultSet result;
317 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 result.Error(e);
324 }
325 return result.Produce();
326 }
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 String LSCPServer::SetAudioOutputChannel(uint AudioOutputChannel, uint uiSamplerChannel) {
333 dmsg(2,("LSCPServer: SetAudioOutputChannel(AudioOutputChannel=%d, SamplerChannel=%d)\n", AudioOutputChannel, uiSamplerChannel));
334 return "ERR:0:Not implemented yet.\r\n"; //FIXME: Add support for this in resultset class?
335 }
336
337 String LSCPServer::SetMIDIInputType(MidiInputDevice::type_t MidiInputType, uint uiSamplerChannel) {
338 dmsg(2,("LSCPServer: SetMIDIInputType(MidiInputType=%d, SamplerChannel=%d)\n", MidiInputType, uiSamplerChannel));
339 LSCPResultSet result;
340 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 result.Error(e);
347 }
348 return result.Produce();
349 }
350
351 /**
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 String LSCPServer::SetMIDIInputPort(String MIDIInputPort, uint uiSamplerChannel) {
356 dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIInputPort=%s, Samplerchannel=%d)\n", MIDIInputPort.c_str(), uiSamplerChannel));
357 LSCPResultSet result;
358 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 result.Error(e);
366 }
367 return result.Produce();
368 }
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 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
375 dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n", MIDIChannel, uiSamplerChannel));
376 LSCPResultSet result;
377 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 pSamplerChannel->SetMidiInputDevice(oldtype, (MidiInputDevice::midi_chan_t) MIDIChannel);
383 }
384 catch (LinuxSamplerException e) {
385 result.Error(e);
386 }
387 return result.Produce();
388 }
389
390 /**
391 * Will be called by the parser to change the global volume factor on a
392 * particular sampler channel.
393 */
394 String LSCPServer::SetVolume(double Volume, uint uiSamplerChannel) {
395 dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", Volume, uiSamplerChannel));
396 LSCPResultSet result;
397 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 result.Error(e);
406 }
407 return result.Produce();
408 }
409
410 /**
411 * Will be called by the parser to reset a particular sampler channel.
412 */
413 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
414 dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
415 LSCPResultSet result;
416 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 result.Error(e);
425 }
426 return result.Produce();
427 }
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