source: roaraudio/roard/sources.c @ 3358:7f9d211148e0

Last change on this file since 3358:7f9d211148e0 was 3061:381084b03fd1, checked in by phi, 14 years ago

fixed NULL dereferencing, set default source to cf

File size: 11.3 KB
Line 
1//sources.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of roard 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, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "roard.h"
26
27#ifndef ROAR_WITHOUT_DCOMP_SOURCES
28
29#define ROAR_SOURCE_DEFAULT "cf"
30
31struct roar_source g_source[] = {
32 {"raw",  "Raw source",                  "/some/file",     SRC_FLAG_FHSEC, ROAR_SUBSYS_WAVEFORM, NULL,  sources_add_raw},
33#ifdef ROAR_HAVE_IO_POSIX
34 {"wav",  "Old RIFF/WAVE source",        "/some/file.wav", SRC_FLAG_NONE,  ROAR_SUBSYS_WAVEFORM, sources_add_wav,  NULL},
35#endif
36 {"cf",   "Old CF source",               "/some/file.ext", SRC_FLAG_NONE,  ROAR_SUBSYS_WAVEFORM, sources_add_cf,   NULL},
37 {"roar", "Old simple RoarAudio source", "some.host",      SRC_FLAG_NONE,  ROAR_SUBSYS_WAVEFORM, sources_add_roar, NULL},
38#ifndef ROAR_WITHOUT_DCOMP_CDRIVER
39 {"oss",  "OSS CDriver",                 "/dev/audio",     SRC_FLAG_NONE,  ROAR_SUBSYS_WAVEFORM, NULL, sources_add_cdriver},
40#endif
41 {NULL, NULL, NULL, SRC_FLAG_NONE, 0, NULL, NULL} // EOL
42};
43
44int sources_init (void) {
45 g_source_client = -1;
46 return 0;
47}
48
49void print_sourcelist (void) {
50 int i;
51 char subsys[7] = "      ";
52
53 printf("  Source   Flag Subsys - Description (devices)\n");
54 printf("------------------------------------------------------\n");
55
56 for (i = 0; g_source[i].name != NULL; i++) {
57  strncpy(subsys, "      ", 6);
58
59  if ( g_source[i].subsystems & ROAR_SUBSYS_WAVEFORM )
60   subsys[0] = 'W';
61  if ( g_source[i].subsystems & ROAR_SUBSYS_MIDI )
62   subsys[1] = 'M';
63  if ( g_source[i].subsystems & ROAR_SUBSYS_CB )
64   subsys[2] = 'C';
65  if ( g_source[i].subsystems & ROAR_SUBSYS_LIGHT )
66   subsys[3] = 'L';
67  if ( g_source[i].subsystems & ROAR_SUBSYS_RAW )
68   subsys[4] = 'R';
69  if ( g_source[i].subsystems & ROAR_SUBSYS_COMPLEX )
70   subsys[5] = 'X';
71
72  printf("  %-9s %c%c%c %6s - %s (devices: %s)\n", g_source[i].name,
73                g_source[i].flags & SRC_FLAG_FHSEC      ? 's' : ' ',
74                g_source[i].old_open != NULL            ? 'S' : ' ',
75                g_source[i].new_open != NULL            ? 'N' : ' ',
76                subsys,
77                g_source[i].desc, g_source[i].devices);
78 }
79}
80
81
82int sources_set_client (int client) {
83 if ( client >= 0 ) {
84  g_source_client = client;
85  return 0;
86 } else {
87  return -1;
88 }
89}
90
91int sources_free (void) {
92 return 0;
93}
94
95int sources_add (char * driver, char * device, char * container, char * options, int primary) {
96 int i;
97
98 if ( driver == NULL )
99  driver = ROAR_SOURCE_DEFAULT;
100
101 for (i = 0; g_source[i].name != NULL; i++) {
102  if ( !strcmp(g_source[i].name, driver) ) {
103   if ( g_source[i].new_open != NULL ) {
104    return sources_add_new(&(g_source[i]), driver, device, container, options, primary);
105   } else if ( g_source[i].old_open != NULL ) {
106    return g_source[i].old_open(driver, device, container, options, primary);
107   } else {
108    ROAR_ERR("sources_add(driver='%s', ...): Found source but did not find any open rutine", driver);
109    return -1;
110   }
111  }
112 }
113
114 ROAR_ERR("sources_add(driver='%s', ...): Source not found", driver);
115 return -1;
116}
117
118int sources_add_new (struct roar_source * source,
119                     char * driver, char * device,
120                     char * container,
121                     char * options, int primary) {
122 int  stream;
123 int  fh = -1;
124 struct roar_stream        *  s;
125 struct roar_stream_server * ss;
126 char * k, * v;
127 int error = 0;
128 int f_sync = 0, f_mmap = 0;
129 int codec;
130
131 if ( source == NULL )
132  return -1;
133
134 if ( (stream = streams_new()) == -1 ) {
135  return -1;
136 }
137
138 streams_get(stream, &ss);
139 s = ROAR_STREAM(ss);
140
141 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
142
143 codec = s->info.codec;
144
145 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
146  streams_delete(stream);
147  return -1;
148 }
149
150 s->pos_rel_id = -1;
151
152 k = strtok(options, ",");
153 while (k != NULL) {
154  if ( (v = strstr(k, "=")) != NULL ) {
155   *v++ = 0;
156  }
157
158  if ( strcmp(k, "rate") == 0 ) {
159   s->info.rate = atoi(v);
160  } else if ( strcmp(k, "channels") == 0 ) {
161   s->info.channels = atoi(v);
162  } else if ( strcmp(k, "bits") == 0 ) {
163   s->info.bits = atoi(v);
164  } else if ( strcmp(k, "codec") == 0 ) {
165   if ( (codec = roar_str2codec(v)) == -1 ) {
166    ROAR_ERR("sources_add_new(*): unknown codec '%s'", v);
167    error++;
168   }
169
170  } else if ( strcmp(k, "name") == 0 ) {
171   if ( streams_set_name(stream, v) == -1 ) {
172    ROAR_ERR("add_output(*): Can not set Stream name");
173    error++;
174   }
175
176  } else if ( strcmp(k, "mmap") == 0 ) {
177   f_mmap = 1;
178  } else if ( strcmp(k, "sync") == 0 ) {
179   f_sync = 1;
180  } else if ( strcmp(k, "primary") == 0 ) {
181   primary = 1;
182  } else if ( strcmp(k, "meta") == 0 ) {
183   streams_set_flag(stream, ROAR_FLAG_META);
184  } else if ( strcmp(k, "cleanmeta") == 0 ) {
185   streams_set_flag(stream, ROAR_FLAG_CLEANMETA);
186  } else if ( strcmp(k, "autoconf") == 0 ) {
187   streams_set_flag(stream, ROAR_FLAG_AUTOCONF);
188
189  } else {
190   ROAR_ERR("sources_add_new(*): unknown option '%s'", k);
191   error++;
192  }
193
194  if ( error ) {
195   streams_delete(stream);
196   if ( primary ) alive = 0;
197   return -1;
198  }
199
200  k = strtok(NULL, ",");
201 }
202
203 if ( primary )
204  streams_mark_primary(stream);
205
206 streams_set_flag(stream, ROAR_FLAG_SOURCE);
207 client_stream_add(g_source_client, stream);
208
209 if ( codec == ROAR_CODEC_ALAW || codec == ROAR_CODEC_MULAW )
210  s->info.bits = 8; // needed to open OSS driver, will be overriden by codecfilter
211
212 s->info.codec = codec;
213 ROAR_STREAM_SERVER(s)->codec_orgi = codec;
214
215 if ( source->new_open(stream, device, fh, driver) == -1 ) {
216  streams_delete(stream);
217  return -1;
218 }
219
220 roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_SSTREAMID, &stream); // ignore errors here
221 roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_SSTREAM,   s); // ignore errors here
222
223 if ( f_sync ) {
224  streams_set_flag(stream, ROAR_FLAG_SYNC);
225 } else {
226  streams_reset_flag(stream, ROAR_FLAG_SYNC);
227 }
228
229 if ( f_mmap )
230  streams_set_flag(stream, ROAR_FLAG_MMAP);
231
232 return 0;
233}
234
235int sources_add_raw  (int stream   , char * device, int fh, char * driver) {
236 struct roar_stream_server * ss;
237
238 if ( fh > -1 )
239  return streams_set_fh(stream, fh);
240
241 streams_get(stream, &ss);
242
243 if ( roar_vio_open_file(&(ss->vio), device, O_RDONLY, 0644) == -1 )
244  return -1;
245
246 return streams_set_fh(stream, -2);
247}
248
249#ifdef ROAR_HAVE_IO_POSIX
250int sources_add_wav (char * driver, char * device, char * container, char * options, int primary) {
251 int stream;
252 int fh;
253 char buf[44];
254 struct roar_stream * s;
255
256 ROAR_WARN("sources_add_raw(*): The wav(e) source is obsolete, use source 'cf' (default)!");
257
258 if ( (fh = open(device, O_RDONLY, 0644)) == -1 ) {
259  return -1;
260 }
261
262 if (read(fh, buf, 44) != 44) {
263  close(fh);
264  return -1;
265 }
266
267 if ( (stream = streams_new()) == -1 ) {
268  close(fh);
269  return -1;
270 }
271
272 streams_get(stream, (struct roar_stream_server **)&s);
273
274 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
275
276 memcpy(&(s->info.rate    ), buf+24, 4);
277 memcpy(&(s->info.channels), buf+22, 2);
278 memcpy(&(s->info.bits    ), buf+34, 2);
279
280 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
281  streams_delete(stream);
282  close(fh);
283  return -1;
284 }
285 s->pos_rel_id = -1;
286
287 streams_set_fh(stream, fh);
288
289 streams_set_flag(stream, ROAR_FLAG_SOURCE);
290 client_stream_add(g_source_client, stream);
291
292 return 0;
293}
294#endif
295
296#define _ret(x) streams_delete(stream); return (x)
297
298int sources_add_cf (char * driver, char * device, char * container, char * options, int primary) {
299 int  stream;
300 int  codec;
301 int  len;
302 char buf[64];
303 struct roar_stream    * s;
304 struct roar_vio_calls * vio;
305 struct roar_vio_defaults def;
306
307 if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, O_RDONLY, 0644) == -1 )
308  return -1;
309
310 if ( (stream = streams_new()) == -1 ) {
311  return -1;
312 }
313
314 streams_get(stream, (struct roar_stream_server **)&s);
315
316 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
317
318 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
319  streams_delete(stream);
320  return -1;
321 }
322
323 s->pos_rel_id = -1;
324
325/*
326 if ( (fh = open(device, O_RDONLY, 0644)) == -1 ) {
327  return -1;
328 }
329*/
330
331 vio = &(ROAR_STREAM_SERVER(s)->vio);
332
333 //if ( roar_vio_open_file(vio, device, O_RDONLY, 0644) == -1 ) {
334 if ( roar_vio_open_dstr(vio, device, &def, 1) == -1 ) {
335  _ret(-1);
336 }
337
338 ROAR_DBG("sources_add_cf(*) = ?");
339
340 // TODO: finy out a better way of doing auto detetion without need for seek!
341 if ( options == NULL ) {
342  if ( (len = roar_vio_read(vio, buf, 64)) < 1 ) {
343   _ret(-1);
344  }
345
346  if ( roar_vio_lseek(vio, -len, SEEK_CUR) == (off_t)-1 ) {
347   _ret(-1);
348  }
349
350  if ( (codec = roar_file_codecdetect(buf, len)) == -1 ) {
351   _ret(-1);
352  }
353 } else {
354  if ( !strncmp(options, "codec=", 6) )
355   options += 6;
356
357  if ( (codec = roar_str2codec(options)) == -1 ) {
358   _ret(-1);
359  }
360 }
361
362 s->info.codec = codec;
363
364 ROAR_STREAM_SERVER(s)->codec_orgi = codec;
365
366 ROAR_DBG("sources_add_cf(*) = ?");
367 streams_set_fh(stream, -2);
368 ROAR_DBG("sources_add_cf(*) = ?");
369 streams_set_socktype(stream, ROAR_SOCKET_TYPE_FILE);
370
371 if ( primary )
372  streams_mark_primary(stream);
373
374 streams_set_flag(stream, ROAR_FLAG_SOURCE);
375 client_stream_add(g_source_client, stream);
376
377 return 0;
378}
379
380#undef _ret
381
382
383int sources_add_roar (char * driver, char * device, char * container, char * options, int primary) {
384 int  stream;
385 int  fh;
386 int  codec = ROAR_CODEC_DEFAULT;
387 struct roar_stream * s;
388
389 if ( options != NULL && *options ) {
390  if ( !strncmp(options, "codec=", 6) )
391   options += 6;
392
393  if ( (codec = roar_str2codec(options)) == -1 ) {
394   return -1;
395  }
396 }
397
398 if ( (fh = roar_simple_monitor(g_sa->rate, g_sa->channels, g_sa->bits, codec, device, "roard")) == -1 ) {
399  return -1;
400 }
401
402 if ( (stream = streams_new()) == -1 ) {
403  close(fh);
404  return -1;
405 }
406
407 streams_get(stream, (struct roar_stream_server **)&s);
408
409 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
410
411 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
412  streams_delete(stream);
413  close(fh);
414  return -1;
415 }
416
417 s->pos_rel_id = -1;
418 s->info.codec = codec;
419
420 ROAR_STREAM_SERVER(s)->codec_orgi = codec;
421
422 streams_set_fh(stream, fh);
423
424 if ( primary )
425  streams_mark_primary(stream);
426
427 streams_set_flag(stream, ROAR_FLAG_SOURCE);
428 client_stream_add(g_source_client, stream);
429
430 return 0;
431}
432
433#ifndef ROAR_WITHOUT_DCOMP_CDRIVER
434int sources_add_cdriver (int stream   , char * device, int fh, char * driver) {
435 int roar_cdriver_open(struct roar_vio_calls * calls, char * name, char * dev, struct roar_audio_info * info, int dir);
436 struct roar_stream_server * ss;
437
438 if ( fh > -1 )
439  return -1;
440
441 streams_get(stream, &ss);
442
443 if ( !strncmp(driver, "cdriver:", 8) )
444  driver += 8;
445
446 ROAR_DBG("sources_add_cdriver(stream=%i, device='%s', fh=%i, driver='%s') = ?", stream, device, fh, driver);
447
448 if ( roar_cdriver_open(&(ss->vio), driver, device, &(ROAR_STREAM(ss)->info), ROAR_DIR_RECORD) == -1 )
449  return -1;
450
451 return streams_set_fh(stream, -2);
452}
453#endif
454
455#endif
456
457//ll
Note: See TracBrowser for help on using the repository browser.