source: roaraudio/roard/sources.c @ 5210:8eb738dee9d4

Last change on this file since 5210:8eb738dee9d4 was 5210:8eb738dee9d4, checked in by phi, 12 years ago

Updated ports to minimal, win32 and avr (pr2)

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