/[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 64 - (hide annotations) (download)
Thu May 6 20:06:20 2004 UTC (19 years, 10 months ago) by schoenebeck
File size: 17009 byte(s)
* src/Sampler.cpp: fixed 3 stupid but fatal bugs that left in the rush (in
  method SamplerChannels(), CreateAudioOutputDevice() and
  CreateMidiInputDevice())
* src/network/lscpserver.cpp: implemented LSCP command
  'SET CHANNEL MIDI_INPUT_CHANNEL'
* src/Sampler.h: moved enums 'audio_output_type_t', 'midi_input_type_t'
  and 'engine_type_t' into the respective base classes
  ('AudioOutputDevice', 'MidiInputDevice', 'Engine')

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

  ViewVC Help
Powered by ViewVC