/[svn]/liblscp/trunk/examples/example_server.c
ViewVC logotype

Contents of /liblscp/trunk/examples/example_server.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 163 - (show annotations) (download)
Wed Jun 30 15:16:03 2004 UTC (19 years, 9 months ago) by capela
File MIME type: text/plain
File size: 16512 byte(s)
Driver parameter info wrapper implementation.

1 // example_server.c
2 //
3 /****************************************************************************
4 Copyright (C) 2004, rncbc aka Rui Nuno Capela. All rights reserved.
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 *****************************************************************************/
21
22 #include "server.h"
23 #include "parser.h"
24
25 #include <time.h>
26
27 #define SERVER_PORT 8888
28
29 #if defined(WIN32)
30 static WSADATA _wsaData;
31 #endif
32
33 ////////////////////////////////////////////////////////////////////////
34
35 lscp_status_t server_callback ( lscp_connect_t *pConnect, const char *pchBuffer, int cchBuffer, void *pvData )
36 {
37 lscp_status_t ret = LSCP_OK;
38 lscp_parser_t tok;
39 const char *pszResult = NULL;
40 char szTemp[256];
41 int i;
42 static int iChannel = 0;
43
44 if (pchBuffer == NULL) {
45 fprintf(stderr, "server_callback: addr=%s port=%d: ",
46 inet_ntoa(pConnect->client.addr.sin_addr),
47 htons(pConnect->client.addr.sin_port));
48 switch (cchBuffer) {
49 case LSCP_CONNECT_OPEN:
50 fprintf(stderr, "New client connection.\n");
51 break;
52 case LSCP_CONNECT_CLOSE:
53 fprintf(stderr, "Connection closed.\n");
54 break;
55 }
56 return ret;
57 }
58
59 lscp_socket_trace("server_callback", &(pConnect->client.addr), pchBuffer, cchBuffer);
60
61 lscp_parser_init(&tok, pchBuffer, cchBuffer);
62
63 if (lscp_parser_test(&tok, "GET")) {
64 if (lscp_parser_test(&tok, "CHANNEL")) {
65 if (lscp_parser_test(&tok, "INFO")) {
66 // Getting sampler channel informations:
67 // GET CHANNEL INFO <sampler-channel>
68 pszResult = "ENGINE_NAME: DummyEngine\r\n"
69 "INSTRUMENT_FILE: DummyInstrument.gig\r\n"
70 "INSTRUMENT_NR: 0\r\n"
71 "INSTRUMENT_STATUS: 100\r\n"
72 "AUDIO_OUTPUT_DEVICE: 0\r\n"
73 "AUDIO_OUTPUT_CHANNELS: 2\r\n"
74 "AUDIO_OUTPUT_ROUTING: 0,1\r\n"
75 "MIDI_INPUT_DEVICE: 0\r\n"
76 "MIDI_INPUT_PORT: 0\r\n"
77 "MIDI_INPUT_CHANNEL: ALL\r\n"
78 "VOLUME: 0.5\r\n";
79 }
80 else if (lscp_parser_test(&tok, "VOICE_COUNT")) {
81 // Current number of active voices:
82 // GET CHANNEL VOICE_COUNT <sampler-channel>
83 sprintf(szTemp, "%d", rand() % 100);
84 pszResult = szTemp;
85 }
86 else if (lscp_parser_test(&tok, "STREAM_COUNT")) {
87 // Current number of active disk streams:
88 // GET CHANNEL STREAM_COUNT <sampler-channel>
89 pszResult = "3\r\n";
90 }
91 else if (lscp_parser_test(&tok, "BUFFER_FILL")) {
92 if (lscp_parser_test(&tok, "BYTES")) {
93 // Current fill state of disk stream buffers:
94 // GET CHANNEL BUFFER_FILL BYTES <sampler-channel>
95 sprintf(szTemp, "[1]%d,[2]%d,[3]%d\r\n", rand(), rand(), rand());
96 pszResult = szTemp;
97 }
98 else if (lscp_parser_test(&tok, "PERCENTAGE")) {
99 // Current fill state of disk stream buffers:
100 // GET CHANNEL BUFFER_FILL PERCENTAGE <sampler-channel>
101 sprintf(szTemp, "[1]%d%%,[2]%d%%,[3]%d%%\r\n", rand() % 100, rand() % 100, rand() % 100);
102 pszResult = szTemp;
103 }
104 else ret = LSCP_FAILED;
105 }
106 else ret = LSCP_FAILED;
107 }
108 else if (lscp_parser_test(&tok, "CHANNELS")) {
109 // Current number of sampler channels:
110 // GET CHANNELS
111 sprintf(szTemp, "%d", iChannel);
112 pszResult = szTemp;
113 }
114 else if (lscp_parser_test(&tok, "AVAILABLE_AUDIO_OUTPUT_DRIVERS")) {
115 // Getting all available audio output drivers.
116 // GET AVAILABLE_AUDIO_OUTPUT_DRIVERS
117 pszResult = "Alsa,Jack,CoreAudio\r\n";
118 }
119 else if (lscp_parser_test(&tok, "AVAILABLE_MIDI_INPUT_DRIVERS")) {
120 // Getting all available MIDI input drivers.
121 // GET AVAILABLE_MIDI_INPUT_DRIVERS
122 pszResult = "Alsa,MidiShare,CoreMidi\r\n";
123 }
124 else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_DRIVER", "INFO")) {
125 // Getting informations about a specific audio output driver.
126 // GET AUDIO_OUTPUT_DRIVER INFO <audio-output-type>
127 if (lscp_parser_test(&tok, "Alsa")) {
128 pszResult = "DESCRIPTION: 'ALSA PCM'\r\n"
129 "VERSION: '1.0'\r\n"
130 "PARAMETERS: channels,samplerate,active,card\r\n";
131 }
132 else if (lscp_parser_test(&tok, "Jack")) {
133 pszResult = "DESCRIPTION: JACK Audio Connection Kit\r\n"
134 "VERSION: 0.98.1\r\n"
135 "PARAMETERS: channels,samplerate,active\r\n";
136 }
137 else ret = LSCP_FAILED;
138 }
139 else if (lscp_parser_test2(&tok, "MIDI_INPUT_DRIVER", "INFO")) {
140 // Getting informations about a specific MIDI input driver.
141 // GET MIDI_INPUT_DRIVER INFO <midi-input-type>
142 if (lscp_parser_test(&tok, "Alsa")) {
143 pszResult = "DESCRIPTION: ALSA Sequencer\r\n"
144 "VERSION: 1.0\r\n"
145 "PARAMETERS: ports,active\r\n";
146 }
147 else ret = LSCP_FAILED;
148 }
149 else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_DRIVER_PARAMETER", "INFO")) {
150 // Getting informations about a specific audio output driver parameter.
151 // GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO <audio-output-type> <param>
152 if (lscp_parser_test2(&tok, "Alsa", "active")) {
153 pszResult = "DESCRIPTION: 'ALSA PCM device active state'\r\n"
154 "TYPE: BOOL\r\n"
155 "MANDATORY: TRUE\r\n"
156 "FIX: TRUE\r\n"
157 "MULTIPLICITY: FALSE\r\n"
158 "DEPENDS: channels,samplerate,card\r\n"
159 "DEFAULT: TRUE\r\n"
160 "RANGE_MIN: FALSE\r\n"
161 "RANGE_MIN: TRUE\r\n"
162 "POSSIBILITIES: FALSE,TRUE\r\n";
163 }
164 else if (lscp_parser_test2(&tok, "Jack", "active")) {
165 pszResult = "DESCRIPTION: 'JACK device active state'\r\n"
166 "TYPE: BOOL\r\n"
167 "MANDATORY: TRUE\r\n"
168 "FIX: TRUE\r\n"
169 "MULTIPLICITY: FALSE\r\n"
170 "DEPENDS: channels,samplerate\r\n"
171 "DEFAULT: TRUE\r\n"
172 "RANGE_MIN: FALSE\r\n"
173 "RANGE_MIN: TRUE\r\n"
174 "POSSIBILITIES: FALSE,TRUE\r\n";
175 }
176 else ret = LSCP_FAILED;
177 }
178 else if (lscp_parser_test2(&tok, "MIDI_INPUT_DRIVER_PARAMETER", "INFO")) {
179 // Getting informations about a specific MIDI input driver parameter.
180 // GET MIDI_INPUT_DRIVER_PARAMETER INFO <midi-input-type> <param>
181 if (lscp_parser_test2(&tok, "Alsa", "active")) {
182 pszResult = "DESCRIPTION: 'ALSA Sequencer device active state'\r\n"
183 "TYPE: BOOL\r\n"
184 "MANDATORY: TRUE\r\n"
185 "FIX: TRUE\r\n"
186 "MULTIPLICITY: FALSE\r\n"
187 "DEPENDS: channels,ports\r\n"
188 "DEFAULT: TRUE\r\n"
189 "RANGE_MIN: FALSE\r\n"
190 "RANGE_MIN: TRUE\r\n"
191 "POSSIBILITIES: FALSE,TRUE\r\n";
192 }
193 else ret = LSCP_FAILED;
194 }
195 else if (lscp_parser_test(&tok, "AVAILABLE_ENGINES")) {
196 // Getting all available engines:
197 // GET AVAILABLE_ENGINES
198 pszResult = "GigEngine,DLSEngine,AkaiEngine\r\n";
199 }
200 else if (lscp_parser_test2(&tok, "ENGINE", "INFO")) {
201 // Getting information about an engine.
202 // GET ENGINE INFO <engine-name>
203 if (lscp_parser_test(&tok, "GigEngine")) {
204 pszResult = "DESCRIPTION: GigaSampler Engine\r\n"
205 "VERSION: 0.3\r\n";
206 }
207 else if (lscp_parser_test(&tok, "DLSEngine")) {
208 pszResult = "DESCRIPTION: 'DLS Generic Engine'\r\n"
209 "VERSION: 0.2\r\n";
210 }
211 else if (lscp_parser_test(&tok, "AkaiEngine")) {
212 pszResult = "DESCRIPTION: Akai Sampler Engine\r\n"
213 "VERSION: 0.1\r\n";
214 }
215 else ret = LSCP_FAILED;
216 }
217 else ret = LSCP_FAILED;
218 }
219 else if (lscp_parser_test(&tok, "LIST")) {
220 if (lscp_parser_test(&tok, "CHANNELS")) {
221 // Getting all created sampler channel list.
222 // GET CHANNELS
223 if (iChannel > 0) {
224 strcpy(szTemp, "0");
225 for (i = 1; i < iChannel; i++)
226 sprintf(szTemp + strlen(szTemp), ",%d", i);
227 strcat(szTemp, "\r\n");
228 pszResult = szTemp;
229 }
230 else ret = LSCP_FAILED;
231 }
232 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICES")) {
233 // Getting all created audio output device list.
234 // GET AUDIO_OUTPUT_DEVICES
235 pszResult = "0,1\r\n";
236 }
237 else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICES")) {
238 // Getting all created MID input device list.
239 // GET MIDI_INPUT_DEVICES
240 pszResult = "0\r\n";
241 }
242 else ret = LSCP_FAILED;
243 }
244 else if (lscp_parser_test(&tok, "SET")) {
245 if (lscp_parser_test(&tok, "CHANNEL")) {
246 if (lscp_parser_test(&tok, "VOLUME")) {
247 // Setting channel volume:
248 // SET CHANNEL VOLUME <sampler-channel> <volume>
249 }
250 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_TYPE")) {
251 // Setting audio output type:
252 // SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>
253 }
254 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICE")) {
255 // Setting audio output device:
256 // SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
257 }
258 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_CHANNEL")) {
259 // Setting audio output channel:
260 // SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-in> <audio-out>
261 }
262 else if (lscp_parser_test(&tok, "MIDI_INPUT_TYPE")) {
263 // Setting MIDI input type:
264 // SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>
265 }
266 else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICE")) {
267 // Setting MIDI input device:
268 // SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
269 }
270 else if (lscp_parser_test(&tok, "MIDI_INPUT_PORT")) {
271 // Setting MIDI input port:
272 // SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>
273 }
274 else if (lscp_parser_test(&tok, "MIDI_INPUT_CHANNEL")) {
275 // Setting MIDI input channel:
276 // SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>
277 }
278 else ret = LSCP_FAILED;
279 }
280 else ret = LSCP_FAILED;
281 }
282 else if (lscp_parser_test(&tok, "LOAD")) {
283 if (lscp_parser_test(&tok, "ENGINE")) {
284 // Loading a sampler engine:
285 // LOAD ENGINE <engine-name> <sampler-channel>
286 }
287 else if (lscp_parser_test(&tok, "INSTRUMENT")) {
288 // Loading an instrument:
289 // LOAD INSTRUMENT [NON_MODAL] <filename> <instr-index> <sampler-channel>
290 }
291 else ret = LSCP_FAILED;
292 }
293 else if (lscp_parser_test2(&tok, "ADD", "CHANNEL")) {
294 // Adding a new sampler channel:
295 // ADD CHANNEL
296 sprintf(szTemp, "OK[%d]", iChannel++);
297 pszResult = szTemp;
298 }
299 else if (lscp_parser_test2(&tok, "REMOVE", "CHANNEL")) {
300 // Removing a sampler channel:
301 // REMOVE CHANNEL <sampler-channel>
302 }
303 else if (lscp_parser_test2(&tok, "RESET", "CHANNEL")) {
304 // Resetting a sampler channel:
305 // RESET CHANNEL <sampler-channel>
306 }
307 else if (lscp_parser_test(&tok, "SUBSCRIBE")) {
308 // Register frontend for receiving event notification messages:
309 // SUBSCRIBE <event>
310 ret = lscp_server_subscribe(pConnect, lscp_event_from_text(lscp_parser_next(&tok)));
311 }
312 else if (lscp_parser_test(&tok, "UNSUBSCRIBE")) {
313 // Deregister frontend for not receiving event notification messages anymore:
314 // UNSUBSCRIBE <event>
315 ret = lscp_server_unsubscribe(pConnect, lscp_event_from_text(lscp_parser_next(&tok)));
316 }
317 else if (lscp_parser_test(&tok, "QUIT")) {
318 // Close client connection:
319 // QUIT
320 lscp_parser_free(&tok);
321 return LSCP_FAILED; // Disconnect.
322 }
323 else ret = LSCP_FAILED;
324
325 lscp_parser_free(&tok);
326
327 if (pszResult == NULL)
328 pszResult = (ret == LSCP_OK ? "OK\r\n" : "ERR:1:Failed\r\n");
329
330 fprintf(stderr, "> %s", pszResult);
331
332 return lscp_server_result(pConnect, pszResult, strlen(pszResult));
333 }
334
335 ////////////////////////////////////////////////////////////////////////
336
337 void server_usage (void)
338 {
339 printf("\n %s %s (Build: %s)\n", lscp_server_package(), lscp_server_version(), lscp_server_build());
340
341 fputs("\n Available server commands: help, exit, quit, list", stdout);
342 fputs("\n (all else are broadcast verbatim to subscribers)\n\n", stdout);
343 }
344
345 void server_prompt (void)
346 {
347 fputs("lscp_server> ", stdout);
348 }
349
350 int main (int argc, char *argv[] )
351 {
352 lscp_server_t *pServer;
353 char szLine[200];
354 int cchLine;
355 lscp_connect_t *p;
356
357 #if defined(WIN32)
358 if (WSAStartup(MAKEWORD(1, 1), &_wsaData) != 0) {
359 fprintf(stderr, "lscp_server: WSAStartup failed.\n");
360 return -1;
361 }
362 #endif
363
364 srand(time(NULL));
365
366 pServer = lscp_server_create(SERVER_PORT, server_callback, NULL);
367 if (pServer == NULL)
368 return -1;
369
370 server_usage();
371 server_prompt();
372
373 while (fgets(szLine, sizeof(szLine), stdin)) {
374
375 cchLine = strlen(szLine);
376 while (cchLine > 0 && (szLine[cchLine - 1] == '\n' || szLine[cchLine - 1] == '\r'))
377 cchLine--;
378 szLine[cchLine] = '\0';
379
380 if (strcmp(szLine, "exit") == 0 || strcmp(szLine, "quit") == 0)
381 break;
382 else
383 if (strcmp(szLine, "list") == 0) {
384 for (p = pServer->connects.first; p; p = p->next) {
385 printf("client: sock=%d addr=%s port=%d events=0x%04x.\n",
386 p->client.sock,
387 inet_ntoa(p->client.addr.sin_addr),
388 ntohs(p->client.addr.sin_port),
389 (int) p->events
390 );
391 }
392 }
393 else
394 if (cchLine > 0 && strcmp(szLine, "help") != 0)
395 lscp_server_broadcast(pServer, LSCP_EVENT_MISCELLANEOUS, szLine, strlen(szLine));
396 else
397 server_usage();
398
399 server_prompt();
400 }
401
402 lscp_server_destroy(pServer);
403
404 #if defined(WIN32)
405 WSACleanup();
406 #endif
407
408 return 0;
409 }
410
411 // end of example_server.c

  ViewVC Help
Powered by ViewVC