source: roaraudio/roard/sources.c @ 5192:4237437ca526

Last change on this file since 5192:4237437ca526 was 5162:85c55ccd12a9, checked in by phi, 13 years ago

fixed some compiler warnings

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