source: roaraudio/roarclients/roarmonhttp.c @ 4139:e9d2fcb0ac6c

Last change on this file since 4139:e9d2fcb0ac6c was 4139:e9d2fcb0ac6c, checked in by phi, 14 years ago

added more mime-types

File size: 8.7 KB
Line 
1//roarmonhttp.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
5 *
6 *  This file is part of roarclients a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include <roaraudio.h>
27
28#if defined(ROAR_HAVE_SETENV) || defined(ROAR_HAVE_PUTENV)
29#define _CAN_SET_ENV
30#endif
31
32#define BUFSIZE 1024
33
34void usage (void) {
35 printf("roarmonhttp [OPTIONS]...\n");
36
37 printf("\nOptions:\n\n");
38
39 printf("  --server    SERVER    - Set server hostname\n"
40        "  --rate  -R  RATE      - Set sample rate\n"
41        "  --bits  -B  BITS      - Set bits per sample\n"
42        "  --chans -C  CHANNELS  - Set number of channels\n"
43        "  --codec     CODEC     - Set the codec\n"
44        "  --rel-id ID           - Set ID of relative stream\n"
45        "  --inetd               - Start in inetd mode (STDIN and STDOUT connected to socket)\n"
46        "  --help                - Show this help\n"
47       );
48
49}
50
51void print_header (int codec, int rate, int channels) {
52 char * mime = "application/octet-stream";
53
54 switch (codec) {
55  case ROAR_CODEC_OGG:
56  case ROAR_CODEC_OGG_GENERAL:
57  case ROAR_CODEC_OGG_VORBIS:
58    mime = "application/ogg";
59   break;
60  case ROAR_CODEC_OGG_SPEEX:
61    mime = "audio/ogg; codecs=speex";
62   break;
63  case ROAR_CODEC_OGG_FLAC:
64    mime = "audio/ogg; codecs=flac";
65   break;
66  case ROAR_CODEC_OGG_CELT:
67    mime = "audio/ogg; codecs=celt";
68   break;
69  case ROAR_CODEC_FLAC:
70    mime = "audio/x-flac";
71   break;
72  case ROAR_CODEC_RIFF_WAVE:
73    mime = "audio/x-wav";
74   break;
75  case ROAR_CODEC_AU:
76    mime = "audio/basic";
77   break;
78  case ROAR_CODEC_AIFF:
79    mime = "audio/aiff";
80   break;
81 }
82
83 printf("Content-type: %s\r\n", mime);
84 printf("ice-audio-info: ice-samplerate=%i;ice-channels=%i\r\n", rate, channels);
85 printf("icy-pub:0\r\n");
86 printf("Server: RoarAudio (roarmonhttp $Revision$)\r\n");
87 printf("\r\n");
88
89 fflush(stdout);
90}
91
92int stream (int dest, int src) {
93 struct roar_buffer *ring = NULL, *cur;
94 ssize_t len;
95 size_t  todo;
96 fd_set fsi[1], fso[1];
97 struct timeval tv;
98 int alive = 1;
99 int maxfh = (dest > src ? dest : src) + 1;
100 void * data;
101
102 roar_socket_nonblock(src,  ROAR_SOCKET_NONBLOCK);
103 roar_socket_nonblock(dest, ROAR_SOCKET_NONBLOCK);
104
105 while (alive) {
106  FD_ZERO(fsi);
107  FD_ZERO(fso);
108  FD_SET(src, fsi);
109  if ( ring != NULL ) {
110   FD_SET(dest, fso);
111  }
112
113  tv.tv_sec  = 0;
114  tv.tv_usec = 100000; // 100ms
115
116  if (select(maxfh, fsi, fso, NULL, &tv) > 0) {
117   if ( FD_ISSET(src, fsi) ) { // we can read!
118    if ( roar_buffer_new(&cur, BUFSIZE) == -1 )
119     return -1;
120
121    if ( roar_buffer_get_data(cur, &data) == -1 )
122     return -1;
123
124    len = read(src, data, BUFSIZE);
125
126    switch (len) {
127     case  0:
128     case -1:
129       roar_buffer_free(cur);
130
131       if ( ring != NULL )
132        roar_buffer_free(ring);
133
134       return -1;
135      break;
136    }
137
138    if ( roar_buffer_set_len(cur, len) == -1 )
139     return -1;
140
141    if ( ring == NULL ) {
142     ring = cur;
143    } else {
144     roar_buffer_add(ring, cur);
145    }
146   } else if ( FD_ISSET(dest, fso) && ring != NULL ) { // we can write!
147    if ( roar_buffer_get_data(ring, &data) == -1 )
148     return -1;
149
150    if ( roar_buffer_get_len(ring, &todo) == -1 )
151     return -1;
152
153    len = write(dest, data, todo);
154
155    if ( len < 1 ) {
156     if ( errno != EAGAIN ) {
157      roar_buffer_free(ring);
158      return -1;
159     }
160    }
161
162    if ( (ssize_t)todo == len ) { // we wrote all of the pkg
163     if ( roar_buffer_next(&ring) == -1 )
164      return -1;
165    } else {
166     if ( roar_buffer_set_offset(ring, len) == -1 )
167      return -1;
168    }
169
170   }
171  }
172 }
173
174 return 0;
175}
176
177#ifdef _CAN_SET_ENV
178int parse_http (int * gopher) {
179 struct roar_keyval kv;
180 char buf[1024];
181 char * qs = buf, *str;
182 ssize_t len;
183 int dir = ROAR_DIR_MONITOR;
184
185 if ( (len = read(ROAR_STDIN, buf, 1023)) == -1 )
186  return -1;
187
188 buf[len] = 0;
189
190 if ( strncmp(buf, "GET /", 5) ) {
191  if ( strncmp(buf, "SOURCE /", 8) ) {
192   if ( buf[0] != '/' ) {
193    return -1;
194   } else {
195    *gopher = 1;
196   }
197  } else {
198   dir = ROAR_DIR_PLAY;
199   qs += 3;
200  }
201 }
202
203 if ( !*gopher ) {
204  qs += 5;
205
206  if ( (str = strstr(qs, " ")) == NULL )
207   return -1;
208
209  *str = 0;
210 } else {
211  if ( (str = strstr(qs, "\r")) != NULL )
212   *str = 0;
213  if ( (str = strstr(qs, "\n")) != NULL )
214   *str = 0;
215 }
216
217 for (; *qs != '?'; qs++)
218  if ( !*qs )
219   break;
220
221 if ( *qs == '?' )
222  qs++;
223
224 if ( !*gopher )
225  printf("HTTP/1.0 200 OK\r\n");
226// printf("QS: %s\r\n", qs);
227
228 fflush(stdout);
229
230 kv.key   = "QUERY_STRING";
231 kv.value = qs;
232
233 roar_env_set(&kv);
234
235 return dir;
236}
237#endif
238
239int main (int argc, char * argv[]) {
240 int    rate     = 44100;
241 int    bits     = 16;
242 int    channels = 2;
243 int    codec    = ROAR_CODEC_OGG_VORBIS;
244 int    rel_id   = -1;
245 int    sflags   = ROAR_FLAG_NONE;
246// int    codec    = ROAR_CODEC_DEFAULT;
247 char * server   = NULL;
248 int    fh;
249 int    i;
250 char * c, * k, * v;
251#ifdef ROAR_HAVE_STRTOK_R
252 char * sp0 = NULL, * sp1 = NULL;
253#endif
254 int dir = ROAR_DIR_MONITOR;
255 int gopher = 0;
256 struct roar_connection    con;
257 struct roar_stream        s;
258
259#ifdef ROAR_HAVE_ALARM
260 alarm(0); // reset alarm timers from httpd
261#endif
262
263 for (i = 1; i < argc; i++) {
264  k = argv[i];
265  if ( !strcmp(k, "--inetd") ) {
266#ifdef _CAN_SET_ENV
267   if ( (dir = parse_http(&gopher)) == -1 )
268    return 1;
269#else
270   return 1;
271#endif
272  } else if ( !strcmp(k, "--server") ) {
273   roar_libroar_set_server(argv[++i]);
274  } else if ( !strcmp(k, "--codec") ) {
275   codec = roar_str2codec(argv[++i]);
276  } else if ( !strcmp(k, "--rate") || !strcmp(k, "-r") || !strcmp(k, "-R") ) {
277   rate = atoi(argv[++i]);
278  } else if ( !strcmp(k, "--bits") || !strcmp(k, "-B") ) {
279   bits = atoi(argv[++i]);
280  } else if ( !strcmp(k, "--channels") || !strcmp(k, "--chans") || !strcmp(k, "-C") ) {
281   channels = atoi(argv[++i]);
282  } else if ( !strcmp(k, "--rel-id") ) {
283   rel_id = atoi(argv[++i]);
284  } else if ( !strcmp(k, "--help") && !strcmp(k, "-h") ) {
285   usage();
286   return 0;
287  } else {
288   ROAR_ERR("Unknown parameter: %s", k);
289   usage();
290   return 1;
291  }
292 }
293
294 c = getenv("QUERY_STRING");
295 if ( c == NULL )
296  c = "";
297
298#ifdef ROAR_HAVE_STRTOK_R
299 c = strtok_r(c, "&", &sp0);
300#else
301 c = strtok(c, "&");
302#endif
303
304 while (c != NULL) {
305#ifdef ROAR_HAVE_STRTOK_R
306  k = strtok_r(c,    "=", &sp1);
307  v = strtok_r(NULL, "=", &sp1);
308#else
309  k = c;
310  if ( (v = strstr(c, "=")) != NULL ) {
311   *v = 0;
312   v++;
313  }
314#endif
315
316  if ( !strcmp(k, "codec") ) {
317   if ( (codec = roar_str2codec(v)) == -1 )
318    return 1;
319  } else if ( !strcmp(k, "channels") ) {
320   channels = atoi(v);
321  } else if ( !strcmp(k, "rate") ) {
322   rate = atoi(v);
323  } else if ( !strcmp(k, "bits") ) {
324   bits = atoi(v);
325  } else if ( !strcmp(k, "rel-id") || !strcmp(k, "relid") ) {
326   rel_id = atoi(v);
327  } else if ( !strcmp(k, "set-flag") ) {
328   if ( !strcmp(v, "meta") ) {
329    sflags |= ROAR_FLAG_META;
330   } else if ( !strcmp(v, "cleanmeta") ) {
331    sflags |= ROAR_FLAG_CLEANMETA;
332   } else if ( !strcmp(v, "prethru") ) {
333    sflags |= ROAR_FLAG_PRETHRU;
334   } else {
335    return 1;
336   }
337  } else if ( !strcmp(k, "dir") ) {
338   if ( (dir = roar_str2dir(v)) == -1 )
339    return 1;
340  } else {
341   return 1;
342  }
343
344#ifdef ROAR_HAVE_STRTOK_R
345  c = strtok_r(NULL, "&", &sp0);
346#else
347  c = strtok(NULL, "&");
348#endif
349 }
350
351 if ( roar_simple_connect(&con, server, "roarmonhttp") == -1 ) {
352  return 10;
353 }
354
355 if ( roar_stream_new(&s, rate, channels, bits, codec) == -1 ) {
356  roar_disconnect(&con);
357  return 20;
358 }
359
360 if ( rel_id != -1 ) {
361  if ( roar_stream_set_rel_id(&s, rel_id) ) {
362   roar_disconnect(&con);
363   return 21;
364  }
365 }
366
367 if ( roar_stream_connect(&con, &s, dir) == -1 ) {
368  roar_disconnect(&con);
369  return 11;
370 }
371
372 if ( sflags != ROAR_FLAG_NONE ) {
373  if ( roar_stream_set_flags(&con, &s, sflags, 0) == -1 ) {
374   roar_disconnect(&con);
375   return 14;
376  }
377 }
378
379 if ( roar_stream_exec(&con, &s) == -1 ) {
380  roar_disconnect(&con);
381  return 12;
382 }
383
384 if ( (fh = roar_get_connection_fh(&con)) == -1 )
385  return 1;
386
387 if ( !gopher )
388  print_header(codec, rate, channels);
389
390/*
391 while((i = read(fh, buf, BUFSIZE)))
392  if (write(out, buf, i) != i)
393   break;
394*/
395
396 switch (dir) {
397  case ROAR_DIR_PLAY:
398    stream(fh, ROAR_STDIN);
399   break;
400  case ROAR_DIR_MONITOR:
401  case ROAR_DIR_THRU:
402    stream(ROAR_STDOUT, fh);
403   break;
404 }
405
406 roar_simple_close(fh);
407
408 return 0;
409}
410
411//ll
Note: See TracBrowser for help on using the repository browser.