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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 125 - (hide 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 capela 105 // 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 capela 125 int i;
42 capela 105 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 capela 125 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 capela 105 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 capela 125 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 capela 105 else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_CHANNEL")) {
201     // Setting audio output channel:
202 capela 125 // SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-in> <audio-out>
203 capela 105 }
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 capela 125 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 capela 105 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