source: roaraudio/roarclients/roarvorbis.c @ 4656:5a99c25bbb0d

Last change on this file since 4656:5a99c25bbb0d was 4656:5a99c25bbb0d, checked in by phi, 13 years ago

do no longer use wget for HTTP streams, first part of a set of patches.

File size: 8.1 KB
Line 
1//roarvorbis.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#include <stdio.h>
29#include <stdlib.h>
30#include <math.h>
31#ifdef ROAR_HAVE_LIBVORBISFILE
32#include <vorbis/codec.h>
33#include <vorbis/vorbisfile.h>
34#endif
35
36#ifdef _WIN32
37#include <io.h>
38#include <fcntl.h>
39#endif
40
41#define BUFSIZE 1024
42
43void usage (void) {
44 printf("roarvorbis [OPTIONS]... FILE\n");
45
46 printf("\nOptions:\n\n");
47
48 printf("  --server SERVER    - Set server hostname\n"
49        "  --help             - Show this help\n"
50        "  --vclt-out FILE    - Writes VCLT file\n"
51       );
52
53}
54
55
56#ifdef ROAR_HAVE_LIBVORBISFILE
57int _g_cf_vorbis_vfvio_return_err (void) {
58 return -1;
59}
60
61size_t cf_vorbis_vfvio_read (void *ptr, size_t size, size_t nmemb, void *datasource) {
62 ssize_t r;
63
64 r = roar_vio_read(datasource, ptr, size*nmemb);
65
66 ROAR_DBG("cf_vorbis_vfvio_read(ptr=%p, size=%lu, nmemb=%lu, datasource=%p): r=%i", ptr, size, nmemb, datasource, r);
67
68 if ( r == -1 )
69  return 0;
70
71 if ( r > 0 )
72  errno = 0;
73
74 r /= size;
75
76 ROAR_DBG("cf_vorbis_vfvio_read(ptr=%p, size=%lu, nmemb=%lu, datasource=%p) = %i", ptr, size, nmemb, datasource, r);
77 return r;
78}
79
80
81ov_callbacks _g_cf_vorbis_vfvio = {
82  .read_func  = cf_vorbis_vfvio_read,
83  .seek_func  = (int    (*)(void *, ogg_int64_t, int      )) _g_cf_vorbis_vfvio_return_err,
84  .close_func = (int    (*)(void *                        )) _g_cf_vorbis_vfvio_return_err,
85  .tell_func  = (long   (*)(void *                        )) _g_cf_vorbis_vfvio_return_err
86};
87
88
89int update_stream (struct roar_connection * con,
90                   struct roar_stream     * s,
91                   struct roar_vio_calls  * vio,
92                   OggVorbis_File         * vf,
93                   char                   * file,
94                   struct roar_audio_info * info,
95                   struct roar_vio_calls  * vclt) {
96 vorbis_info *vi = ov_info(vf, -1);
97 int    bits     = 16;
98 int    codec    = ROAR_CODEC_DEFAULT;
99 char **ptr = ov_comment(vf, -1)->user_comments;
100 char key[ROAR_META_MAX_NAMELEN], value[LIBROAR_BUFFER_MSGDATA] = {0};
101 int j, h = 0;
102 struct roar_meta   meta;
103 static int need_new_stream = 1;
104 int need_close = 0;
105 int meta_ok;
106
107 fprintf(stderr, "\n");
108
109 if ( vclt != NULL ) {
110  roar_vio_printf(vclt, "AUDIOINFO=rate:%iHz, channels:%i\n", vi->rate, vi->channels);
111 }
112
113 if ( !need_new_stream ) {
114  if ( info->rate != (uint16_t)vi->rate || info->channels != (uint16_t)vi->channels ) {
115   need_close      = 1;
116   need_new_stream = 1;
117  }
118 }
119
120 if ( need_new_stream ) {
121  if ( need_close )
122   roar_vio_close(vio);
123
124  fprintf(stderr, "Audio: %i channel, %liHz\n\n", vi->channels, vi->rate);
125
126  info->rate     = vi->rate;
127  info->channels = vi->channels;
128
129  if ( roar_vio_simple_new_stream_obj(vio, con, s, vi->rate, vi->channels, bits, codec, ROAR_DIR_PLAY) == -1 ) {
130   roar_disconnect(con);
131   return -1;
132  }
133  need_new_stream = 0;
134 }
135
136
137 meta.value = value;
138 meta.key[0] = 0;
139 meta.type = ROAR_META_TYPE_NONE;
140
141 roar_stream_meta_set(con, s, ROAR_META_MODE_CLEAR, &meta);
142
143 if ( strncmp(file, "http:", 5) == 0 )
144  meta.type = ROAR_META_TYPE_FILEURL;
145 else
146  meta.type = ROAR_META_TYPE_FILENAME;
147
148
149 strncpy(value, file, LIBROAR_BUFFER_MSGDATA-1);
150 value[LIBROAR_BUFFER_MSGDATA-1] = 0;
151 roar_stream_meta_set(con, s, ROAR_META_MODE_SET, &meta);
152
153 while(*ptr){
154  meta_ok = 1;
155
156   for (j = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++) {
157    if ( j == ROAR_META_MAX_NAMELEN ) {
158     ROAR_ERR("update_stream(*): invalid meta data: meta data key too long");
159     meta_ok = 0;
160     j = 0;
161     break;
162    }
163    key[j] = (*ptr)[j];
164   }
165   key[j] = 0;
166
167   if ( meta_ok ) {
168    for (j++, h = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++) {
169     if ( h == LIBROAR_BUFFER_MSGDATA ) {
170      ROAR_ERR("update_stream(*): invalid meta data: meta data value for key '%s' too long", key);
171      meta_ok = 0;
172      h = 0;
173      break;
174     }
175     value[h++] = (*ptr)[j];
176    }
177    value[h]   = 0;
178   }
179
180   if ( meta_ok ) {
181    fprintf(stderr, "Meta %-16s: %s\n", key, value);
182
183    if ( vclt != NULL ) {
184     roar_vio_printf(vclt, "%s=%s\n", key, value);
185    }
186
187    meta.type = roar_meta_inttype(key);
188    if ( meta.type != -1 )
189     roar_stream_meta_set(con, s, ROAR_META_MODE_SET, &meta);
190   }
191
192   ptr++;
193 }
194
195 *value      = 0;
196 meta.key[0] = 0;
197 meta.type   = ROAR_META_TYPE_NONE;
198 roar_stream_meta_set(con, s, ROAR_META_MODE_FINALIZE, &meta);
199
200 if ( vclt != NULL ) {
201  roar_vio_printf(vclt, "==\n");
202 }
203
204 return 0;
205}
206
207#endif
208
209int main (int argc, char * argv[]) {
210#ifndef ROAR_HAVE_LIBVORBISFILE
211 (void)argc, (void)argv;
212 fprintf(stderr, "Error: no Vorbis support!\n");
213 return 1;
214#else
215 struct roar_vio_calls vclt, in;
216 struct roar_vio_defaults def;
217 char * server   = NULL;
218 char * file     = NULL;
219 char * vcltfile = NULL;
220 char * k;
221 int    i;
222 struct roar_connection con;
223 struct roar_stream     s;
224 struct roar_vio_calls  vio;
225 OggVorbis_File vf;
226 int eof=0;
227 int current_section = -1;
228 int last_section = -1;
229 struct roar_audio_info info;
230 char pcmout[4096];
231
232
233 for (i = 1; i < argc; i++) {
234  k = argv[i];
235
236  if ( strcmp(k, "--server") == 0 ) {
237   server = argv[++i];
238  } else if ( strcmp(k, "--vclt-out") == 0 ) {
239   vcltfile = argv[++i];
240  } else if ( strcmp(k, "--help") == 0 ) {
241   usage();
242   return 0;
243  } else if ( file == NULL ) {
244   file = k;
245  } else {
246   fprintf(stderr, "Error: unknown argument: %s\n", k);
247   usage();
248   return 1;
249  }
250 }
251
252 roar_libroar_set_server(server);
253
254 if ( file == NULL ) {
255  ROAR_ERR("No filename given.");
256  return 1;
257 }
258
259 if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, O_RDONLY, 0644) == -1 )
260  return 1;
261
262 if ( roar_vio_open_dstr(&in, file, &def, 1) == -1 ) {
263  fprintf(stderr, "Error: can not open file: %s: %s\n", file, strerror(errno));
264  return 1;
265 }
266
267 if ( roar_simple_connect(&con, server, "roarvorbis") == -1 ) {
268  ROAR_DBG("roar_simple_play(*): roar_simple_connect() faild!");
269  roar_vio_close(&in);
270  return 1;
271 }
272
273 if ( ov_open_callbacks((void*)&in, &vf, NULL, 0, _g_cf_vorbis_vfvio) < 0 ) {
274// if( ov_open(in, &vf, NULL, 0) < 0 ) {
275  fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
276  roar_disconnect(&con);
277  roar_vio_close(&in);
278  return 1;
279 }
280
281 if ( vcltfile != NULL ) {
282  if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, O_WRONLY|O_CREAT|O_APPEND, 0644) == -1 )
283   return 1;
284  if ( roar_vio_open_dstr(&vclt, vcltfile, &def, 1) == -1 ) {
285   fprintf(stderr, "Error: can not open file: %s: %s\n", k, strerror(errno));
286   roar_disconnect(&con);
287   roar_vio_close(&in);
288   return 1;
289  }
290 }
291
292// if ( update_stream(&con, &s, &out, &vf, file) == -1 )
293//  return 1;
294
295 while (!eof) {
296  long ret = ov_read(&vf, pcmout, sizeof(pcmout), 0, 2, 1, &current_section);
297
298  if ( last_section != current_section )
299   if ( update_stream(&con, &s, &vio, &vf, file, &info, vcltfile == NULL ? NULL : &vclt) == -1 ) {
300    roar_vio_close(&in);
301    if ( vcltfile != NULL )
302     roar_vio_close(&vclt);
303    return 1;
304   }
305
306  last_section = current_section;
307
308  if (ret == 0) {
309   /* EOF */
310   eof = 1;
311  } else if (ret < 0) {
312   /* error in the stream.  Not a problem, just reporting it in
313      case we (the app) cares.  In this case, we don't. */
314  } else {
315   roar_vio_write(&vio, pcmout, ret);
316  }
317 }
318
319 ov_clear(&vf);
320
321// fclose(in);
322 roar_vio_close(&vio);
323 roar_disconnect(&con);
324
325 if ( vcltfile != NULL )
326  roar_vio_close(&vclt);
327
328 roar_vio_close(&in);
329
330 return 0;
331#endif
332}
333
334//ll
Note: See TracBrowser for help on using the repository browser.