/[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 125 - (show annotations) (download)
Mon Jun 14 21:04:04 2004 UTC (19 years, 10 months ago) by capela
File MIME type: text/plain
File size: 13512 byte(s)
* Added support for the new LIST commands (draft v.08).

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 "AUDIO_OUTPUT_DEVICE: 0\r\n"
72 "AUDIO_OUTPUT_CHANNELS: 2\r\n"
73 "AUDIO_OUTPUT_ROUTING: 0,1\r\n"
74 "MIDI_INPUT_DEVICE: 0\r\n"
75 "MIDI_INPUT_PORT: 0\r\n"
76 "MIDI_INPUT_CHANNEL: ALL\r\n"
77 "VOLUME: 0.5\r\n";
78 }
79 else if (lscp_parser_test(&tok, "VOICE_COUNT")) {
80 // Current number of active voices:
81 // GET CHANNEL VOICE_COUNT <sampler-channel>
82 sprintf(szTemp, "%d", rand() % 100);
83 pszResult = szTemp;
84 }
85 else if (lscp_parser_test(&tok, "STREAM_COUNT")) {
86 // Current number of active disk streams:
87 // GET CHANNEL STREAM_COUNT <sampler-channel>
88 pszResult = "3\r\n";
89 }
90 else if (lscp_parser_test(&tok, "BUFFER_FILL")) {
91 if (lscp_parser_test(&tok, "BYTES")) {
92 // Current fill state of disk stream buffers:
93 // GET CHANNEL BUFFER_FILL BYTES <sampler-channel>
94 sprintf(szTemp, "[1]%d,[2]%d,[3]%d\r\n", rand(), rand(), rand());
95 pszResult = szTemp;
96 }
97 else if (lscp_parser_test(&tok, "PERCENTAGE")) {
98 // Current fill state of disk stream buffers:
99 // GET CHANNEL BUFFER_FILL PERCENTAGE <sampler-channel>
100 sprintf(szTemp, "[1]%d%%,[2]%d%%,[3]%d%%\r\n", rand() % 100, rand() % 100, rand() % 100);
101 pszResult = szTemp;
102 }
103 else ret = LSCP_FAILED;
104 }
105 else ret = LSCP_FAILED;
106 }
107 else if (lscp_parser_test(&tok, "CHANNELS")) {
108 // Current number of sampler channels:
109 // GET CHANNELS
110 sprintf(szTemp, "%d", iChannel);
111 pszResult = szTemp;
112 }
113 else if (lscp_parser_test(&tok, "AVAILABLE_AUDIO_OUTPUT_DRIVERS")) {
114 // Getting all available audio output drivers.
115 // GET AVAILABLE_AUDIO_OUTPUT_DRIVERS
116 pszResult = "ALSA,JACK\r\n";
117 }
118 else if (lscp_parser_test(&tok, "AVAILABLE_MIDI_INPUT_DRIVERS")) {
119 // Getting all available MIDI input drivers.
120 // GET AVAILABLE_MIDI_INPUT_DRIVERS
121 pszResult = "ALSA\r\n";
122 }
123 else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_DRIVER", "INFO")) {
124 // Getting informations about a specific audio output driver.
125 // GET AUDIO_OUTPUT_DRIVER INFO <audio-output-type>
126 if (lscp_parser_test(&tok, "ALSA")) {
127 pszResult = "DESCRIPTION: 'ALSA PCM'\r\n"
128 "VERSION: '1.0'\r\n"
129 "PARAMETERS: CHANNELS,SAMPLERATE,ACTIVE,CARD\r\n";
130 }
131 else if (lscp_parser_test(&tok, "JACK")) {
132 pszResult = "DESCRIPTION: Jack Audio Connection Kit\r\n"
133 "VERSION: 0.98.1\r\n"
134 "PARAMETERS: CHANNELS,SAMPLERATE,ACTIVE\r\n";
135 }
136 else ret = LSCP_FAILED;
137 }
138 else if (lscp_parser_test2(&tok, "MIDI_INPUT_DRIVER", "INFO")) {
139 // Getting informations about a specific MIDI input driver.
140 // GET MIDI_INPUT_DRIVER INFO <midi-input-type>
141 if (lscp_parser_test(&tok, "ALSA")) {
142 pszResult = "DESCRIPTION: ALSA Sequencer\r\n"
143 "VERSION: 1.0\r\n"
144 "PARAMETERS: PORTS,ACTIVE\r\n";
145 }
146 else ret = LSCP_FAILED;
147 }
148 else if (lscp_parser_test(&tok, "AVAILABLE_ENGINES")) {
149 // Getting all available engines:
150 // GET AVAILABLE_ENGINES
151 pszResult = "Engine1,Engine2,Engine3\r\n";
152 }
153 else if (lscp_parser_test2(&tok, "ENGINE", "INFO")) {
154 // Getting information about an engine.
155 // GET ENGINE INFO <engine-name>
156 pszResult = "DESCRIPTION: DummyEngine\r\n"
157 "VERSION: 1.0\r\n";
158 }
159 else ret = LSCP_FAILED;
160 }
161 else if (lscp_parser_test(&tok, "LIST")) {
162 if (lscp_parser_test(&tok, "CHANNELS")) {
163 // Getting all created sampler channel list.
164 // GET CHANNELS
165 if (iChannel > 0) {
166 strcpy(szTemp, "0");
167 for (i = 1; i < iChannel; i++)
168 sprintf(szTemp + strlen(szTemp), ",%d", i);
169 strcat(szTemp, "\r\n");
170 pszResult = szTemp;
171 }
172 else ret = LSCP_FAILED;
173 }
174 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICES")) {
175 // Getting all created audio output device list.
176 // GET AUDIO_OUTPUT_DEVICES
177 pszResult = "0,1\r\n";
178 }
179 else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICES")) {
180 // Getting all created MID input device list.
181 // GET MIDI_INPUT_DEVICES
182 pszResult = "0\r\n";
183 }
184 else ret = LSCP_FAILED;
185 }
186 else if (lscp_parser_test(&tok, "SET")) {
187 if (lscp_parser_test(&tok, "CHANNEL")) {
188 if (lscp_parser_test(&tok, "VOLUME")) {
189 // Setting channel volume:
190 // SET CHANNEL VOLUME <sampler-channel> <volume>
191 }
192 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_TYPE")) {
193 // Setting audio output type:
194 // SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>
195 }
196 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICE")) {
197 // Setting audio output device:
198 // SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
199 }
200 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_CHANNEL")) {
201 // Setting audio output channel:
202 // SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-in> <audio-out>
203 }
204 else if (lscp_parser_test(&tok, "MIDI_INPUT_TYPE")) {
205 // Setting MIDI input type:
206 // SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>
207 }
208 else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICE")) {
209 // Setting MIDI input device:
210 // SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
211 }
212 else if (lscp_parser_test(&tok, "MIDI_INPUT_PORT")) {
213 // Setting MIDI input port:
214 // SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>
215 }
216 else if (lscp_parser_test(&tok, "MIDI_INPUT_CHANNEL")) {
217 // Setting MIDI input channel:
218 // SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>
219 }
220 else ret = LSCP_FAILED;
221 }
222 else ret = LSCP_FAILED;
223 }
224 else if (lscp_parser_test(&tok, "LOAD")) {
225 if (lscp_parser_test(&tok, "ENGINE")) {
226 // Loading a sampler engine:
227 // LOAD ENGINE <engine-name> <sampler-channel>
228 }
229 else if (lscp_parser_test(&tok, "INSTRUMENT")) {
230 // Loading an instrument:
231 // LOAD INSTRUMENT <filename> <instr-index> <sampler-channel>
232 }
233 else ret = LSCP_FAILED;
234 }
235 else if (lscp_parser_test2(&tok, "ADD", "CHANNEL")) {
236 // Adding a new sampler channel:
237 // ADD CHANNEL
238 sprintf(szTemp, "OK[%d]", iChannel++);
239 pszResult = szTemp;
240 }
241 else if (lscp_parser_test2(&tok, "REMOVE", "CHANNEL")) {
242 // Removing a sampler channel:
243 // REMOVE CHANNEL <sampler-channel>
244 }
245 else if (lscp_parser_test2(&tok, "RESET", "CHANNEL")) {
246 // Resetting a sampler channel:
247 // RESET CHANNEL <sampler-channel>
248 }
249 else if (lscp_parser_test2(&tok, "SUBSCRIBE", "NOTIFICATION")) {
250 // Register frontend for receiving UDP event messages:
251 // SUBSCRIBE NOTIFICATION <udp-port>
252 ret = lscp_server_subscribe(pConnect, lscp_parser_nextint(&tok));
253 }
254 else if (lscp_parser_test2(&tok, "UNSUBSCRIBE", "NOTIFICATION")) {
255 // Deregister frontend for not receiving UDP event messages anymore:
256 // UNSUBSCRIBE NOTIFICATION <session-id>
257 ret = lscp_server_unsubscribe(pConnect, lscp_parser_next(&tok));
258 }
259 else if (lscp_parser_test(&tok, "QUIT")) {
260 // Close client connection:
261 // QUIT
262 lscp_parser_free(&tok);
263 return LSCP_FAILED; // Disconnect.
264 }
265 else ret = LSCP_FAILED;
266
267 lscp_parser_free(&tok);
268
269 if (pszResult == NULL)
270 pszResult = (ret == LSCP_OK ? "OK\r\n" : "ERR:1:Failed\r\n");
271
272 fprintf(stderr, "> %s", pszResult);
273
274 return lscp_server_result(pConnect, pszResult, strlen(pszResult));
275 }
276
277 ////////////////////////////////////////////////////////////////////////
278
279 void server_usage (void)
280 {
281 printf("\n %s %s (Build: %s)\n", lscp_server_package(), lscp_server_version(), lscp_server_build());
282
283 fputs("\n Available server commands: help, exit, quit, list", stdout);
284 fputs("\n (all else are broadcast verbatim to subscribers)\n\n", stdout);
285 }
286
287 void server_prompt (void)
288 {
289 fputs("lscp_server> ", stdout);
290 }
291
292 int main (int argc, char *argv[] )
293 {
294 lscp_server_t *pServer;
295 char szLine[200];
296 int cchLine;
297 lscp_connect_t *p;
298
299 #if defined(WIN32)
300 if (WSAStartup(MAKEWORD(1, 1), &_wsaData) != 0) {
301 fprintf(stderr, "lscp_server: WSAStartup failed.\n");
302 return -1;
303 }
304 #endif
305
306 srand(time(NULL));
307
308 pServer = lscp_server_create(SERVER_PORT, server_callback, NULL);
309 if (pServer == NULL)
310 return -1;
311
312 server_usage();
313 server_prompt();
314
315 while (fgets(szLine, sizeof(szLine), stdin)) {
316
317 cchLine = strlen(szLine);
318 while (cchLine > 0 && (szLine[cchLine - 1] == '\n' || szLine[cchLine - 1] == '\r'))
319 cchLine--;
320 szLine[cchLine] = '\0';
321
322 if (strcmp(szLine, "exit") == 0 || strcmp(szLine, "quit") == 0)
323 break;
324 else
325 if (strcmp(szLine, "list") == 0) {
326 for (p = pServer->connects.first; p; p = p->next) {
327 printf("client: sock=%d addr=%s tcp.port=%d udp.port=%d ping=%d sessid=%s.\n",
328 p->client.sock,
329 inet_ntoa(p->client.addr.sin_addr),
330 ntohs(p->client.addr.sin_port),
331 p->port,
332 p->ping,
333 p->sessid
334 );
335 }
336 }
337 else
338 if (cchLine > 0 && strcmp(szLine, "help") != 0)
339 lscp_server_broadcast(pServer, szLine, strlen(szLine));
340 else
341 server_usage();
342
343 server_prompt();
344 }
345
346 lscp_server_destroy(pServer);
347
348 #if defined(WIN32)
349 WSACleanup();
350 #endif
351
352 return 0;
353 }
354
355 // end of example_server.c

  ViewVC Help
Powered by ViewVC