source: roaraudio/roard/sources.c @ 5194:b40015b16ff2

Last change on this file since 5194:b40015b16ff2 was 5194:b40015b16ff2, checked in by phi, 12 years ago

make more use of /extern/

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
143 if ( source == NULL )
144  return -1;
145
146 if ( (stream = streams_new()) == -1 ) {
147  return -1;
148 }
149
150 if ( streams_get(stream, &ss) == -1 ) {
151  streams_delete(stream);
152  return -1;
153 }
154
155 s = ROAR_STREAM(ss);
156
157 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
158
159 codec = s->info.codec;
160
161 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
162  streams_delete(stream);
163  return -1;
164 }
165
166 s->pos_rel_id = -1;
167
168 k = strtok(options, ",");
169 while (k != NULL) {
170  if ( (v = strstr(k, "=")) != NULL ) {
171   *v++ = 0;
172  }
173
174  if ( strcmp(k, "rate") == 0 ) {
175   s->info.rate = roar_str2rate(v);
176  } else if ( strcmp(k, "channels") == 0 ) {
177   s->info.channels = roar_str2channels(v);
178  } else if ( strcmp(k, "bits") == 0 ) {
179   s->info.bits = roar_str2bits(v);
180  } else if ( strcmp(k, "codec") == 0 ) {
181   if ( (codec = roar_str2codec(v)) == -1 ) {
182    ROAR_ERR("sources_add_new(*): unknown codec '%s'", v);
183    error++;
184   }
185
186  } else if ( strcmp(k, "name") == 0 ) {
187   if ( streams_set_name(stream, v) == -1 ) {
188    ROAR_ERR("add_output(*): Can not set Stream name");
189    error++;
190   }
191
192  } else if ( strcmp(k, "mmap") == 0 ) {
193   f_mmap = 1;
194  } else if ( strcmp(k, "sync") == 0 ) {
195   f_sync = 1;
196  } else if ( strcmp(k, "primary") == 0 ) {
197   primary = 1;
198  } else if ( strcmp(k, "meta") == 0 ) {
199   streams_set_flag(stream, ROAR_FLAG_META);
200  } else if ( strcmp(k, "cleanmeta") == 0 ) {
201   streams_set_flag(stream, ROAR_FLAG_CLEANMETA);
202  } else if ( strcmp(k, "autoconf") == 0 ) {
203   streams_set_flag(stream, ROAR_FLAG_AUTOCONF);
204
205  } else {
206   ROAR_ERR("sources_add_new(*): unknown option '%s'", k);
207   error++;
208  }
209
210  if ( error ) {
211   streams_delete(stream);
212   if ( primary ) alive = 0;
213   return -1;
214  }
215
216  k = strtok(NULL, ",");
217 }
218
219 if ( primary )
220  streams_mark_primary(stream);
221
222 streams_set_flag(stream, ROAR_FLAG_SOURCE);
223 client_stream_add(g_source_client, stream);
224
225 if ( codec == ROAR_CODEC_ALAW || codec == ROAR_CODEC_MULAW )
226  s->info.bits = 8; // needed to open OSS driver, will be overriden by codecfilter
227
228 s->info.codec = codec;
229 ROAR_STREAM_SERVER(s)->codec_orgi = codec;
230
231 if ( source->new_open(stream, device, fh, driver) == -1 ) {
232  streams_delete(stream);
233  return -1;
234 }
235
236 _LIBROAR_IGNORE_RET(roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_SSTREAMID, &stream)); // ignore errors here
237 _LIBROAR_IGNORE_RET(roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_SSTREAM,   s)); // ignore errors here
238
239 if ( f_sync ) {
240  streams_set_flag(stream, ROAR_FLAG_SYNC);
241 } else {
242  streams_reset_flag(stream, ROAR_FLAG_SYNC);
243 }
244
245 if ( f_mmap )
246  streams_set_flag(stream, ROAR_FLAG_MMAP);
247
248 return 0;
249}
250
251int sources_add_raw  (int stream   , char * device, int fh, char * driver) {
252 struct roar_stream_server * ss;
253
254 streams_get(stream, &ss);
255
256 if ( fh > -1 ) {
257  if ( roar_vio_open_fh(&(ss->vio), fh) == -1 )
258   return -1;
259 } else {
260  if ( roar_vio_open_file(&(ss->vio), device, O_RDONLY, 0644) == -1 )
261   return -1;
262 }
263
264 return streams_set_fh(stream, -2);
265}
266
267#ifdef ROAR_HAVE_IO_POSIX
268int sources_add_wav (char * driver, char * device, char * container, char * options, int primary) {
269 int stream;
270 int fh;
271 char buf[44];
272 struct roar_stream * s;
273
274 ROAR_WARN("sources_add_raw(*): The wav(e) source is obsolete, use source 'cf' (default)!");
275
276 if ( (fh = open(device, O_RDONLY, 0644)) == -1 ) {
277  return -1;
278 }
279
280 if (read(fh, buf, 44) != 44) {
281  close(fh);
282  return -1;
283 }
284
285 if ( (stream = streams_new()) == -1 ) {
286  close(fh);
287  return -1;
288 }
289
290 streams_get_clientobj(stream, &s);
291
292 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
293
294 memcpy(&(s->info.rate    ), buf+24, 4);
295 memcpy(&(s->info.channels), buf+22, 2);
296 memcpy(&(s->info.bits    ), buf+34, 2);
297
298 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
299  streams_delete(stream);
300  close(fh);
301  return -1;
302 }
303 s->pos_rel_id = -1;
304
305 streams_set_fh(stream, fh);
306
307 streams_set_flag(stream, ROAR_FLAG_SOURCE);
308 client_stream_add(g_source_client, stream);
309
310 return 0;
311}
312#endif
313
314#define _ret(x) streams_delete(stream); return (x)
315
316int sources_add_cf (char * driver, char * device, char * container, char * options, int primary) {
317 int  stream;
318 int  codec;
319 int  len;
320 char buf[64];
321 struct roar_stream    * s;
322 struct roar_vio_calls * vio;
323 struct roar_vio_defaults def;
324
325 if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, O_RDONLY, 0644) == -1 )
326  return -1;
327
328 if ( (stream = streams_new()) == -1 ) {
329  return -1;
330 }
331
332 streams_get_clientobj(stream, &s);
333
334 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
335
336 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
337  streams_delete(stream);
338  return -1;
339 }
340
341 s->pos_rel_id = -1;
342
343/*
344 if ( (fh = open(device, O_RDONLY, 0644)) == -1 ) {
345  return -1;
346 }
347*/
348
349 vio = &(ROAR_STREAM_SERVER(s)->vio);
350
351 //if ( roar_vio_open_file(vio, device, O_RDONLY, 0644) == -1 ) {
352 if ( roar_vio_open_dstr(vio, device, &def, 1) == -1 ) {
353  roar_vio_clear_calls(vio); // clear the VIO object again
354                            // from things roar_vio_open_dstr() left.
355  _ret(-1);
356 }
357
358 ROAR_DBG("sources_add_cf(*) = ?");
359
360 // TODO: finy out a better way of doing auto detetion without need for seek!
361 if ( options == NULL ) {
362  if ( (len = roar_vio_read(vio, buf, 64)) < 1 ) {
363   _ret(-1);
364  }
365
366  if ( roar_vio_lseek(vio, -len, SEEK_CUR) == (off_t)-1 ) {
367   _ret(-1);
368  }
369
370  if ( (codec = roar_file_codecdetect(buf, len)) == -1 ) {
371   _ret(-1);
372  }
373 } else {
374  if ( !strncmp(options, "codec=", 6) )
375   options += 6;
376
377  if ( (codec = roar_str2codec(options)) == -1 ) {
378   _ret(-1);
379  }
380 }
381
382 s->info.codec = codec;
383
384 ROAR_STREAM_SERVER(s)->codec_orgi = codec;
385
386 ROAR_DBG("sources_add_cf(*) = ?");
387 streams_set_fh(stream, -2);
388 ROAR_DBG("sources_add_cf(*) = ?");
389 streams_set_socktype(stream, ROAR_SOCKET_TYPE_FILE);
390
391 if ( primary )
392  streams_mark_primary(stream);
393
394 streams_set_flag(stream, ROAR_FLAG_SOURCE);
395 client_stream_add(g_source_client, stream);
396
397 return 0;
398}
399
400#undef _ret
401
402#ifndef ROAR_WITHOUT_DCOMP_CDRIVER
403int sources_add_cdriver (int stream   , char * device, int fh, char * driver) {
404 struct roar_stream_server * ss;
405
406 if ( fh > -1 )
407  return -1;
408
409 if ( streams_get(stream, &ss) == -1 )
410  return -1;
411
412 if ( !strncmp(driver, "cdriver:", 8) )
413  driver += 8;
414
415 ROAR_DBG("sources_add_cdriver(stream=%i, device='%s', fh=%i, driver='%s') = ?", stream, device, fh, driver);
416
417 if ( roar_cdriver_open(&(ss->vio), driver, device, &(ROAR_STREAM(ss)->info), ROAR_DIR_RECORD) == -1 )
418  return -1;
419
420 return streams_set_fh(stream, -2);
421}
422#endif
423
424static ssize_t sources_radionoise_read (struct roar_vio_calls * vio, void *buf, size_t count) {
425 int32_t * pcm = buf;
426 int16_t noise;
427 size_t len, i;
428
429 ROAR_DBG("sources_radionoise_read(vio=%p, buf=%p, count=%llu) = 0", vio, buf, (long long unsigned int)count);
430
431 // ensure size is a multiple of 4.
432 count -= count & 0x03LLU;
433
434 if ( count == 0 )
435  return 0;
436
437 if ( buf == NULL )
438  return -1;
439
440 roar_random_gen_nonce(buf, count);
441
442 len = count / 4;
443
444 for (i = 0; i < len; i++) {
445  noise  = pcm[i] & 0xFFFF;
446  pcm[i] = ((int32_t)noise << 16) >> 17;
447 }
448
449 ROAR_DBG("sources_radionoise_read(vio=%p, buf=%p, count=?) = %llu", vio, buf, (long long unsigned int)count);
450 return count;
451}
452
453static int     sources_radionoise_return_zero (struct roar_vio_calls * vio) {
454 (void)vio;
455
456 ROAR_DBG("sources_radionoise_return_zero(vio=%p) = 0", vio);
457
458 return 0;
459}
460
461int sources_add_radionoise (int stream, char * device, int fh, char * driver) {
462 struct roar_stream_server * ss;
463 struct roar_audio_info    * info;
464
465 if ( fh > -1 )
466  return -1;
467
468 if ( streams_get(stream, &ss) == -1 )
469  return -1;
470
471 info = &(ROAR_STREAM(ss)->info);
472
473 info->codec = ROAR_CODEC_DEFAULT;
474 info->bits  = 32;
475
476 memset(&(ss->vio), 0, sizeof(struct roar_vio_calls));
477 ss->vio.read     = sources_radionoise_read;
478 ss->vio.close    = sources_radionoise_return_zero;
479 ss->vio.sync     = sources_radionoise_return_zero;
480 ss->vio.nonblock = (int (*)(struct roar_vio_calls * vio, int state))sources_radionoise_return_zero;
481
482 return streams_set_fh(stream, -2);
483}
484
485int sources_add_roar (int stream, char * device, int fh, char * driver) {
486 struct roar_stream_server * ss;
487 struct roar_stream        * s;
488
489 if ( fh > -1 )
490  return -1;
491
492 if ( streams_get(stream, &ss) == -1 )
493  return -1;
494
495 s = ROAR_STREAM(ss);
496
497 if ( roar_vio_simple_stream(&(ss->vio), s->info.rate, s->info.channels, s->info.bits, s->info.codec,
498                             device, ROAR_DIR_MONITOR, "roard") == -1 )
499  return -1;
500
501 return streams_set_fh(stream, -2);
502}
503
504#endif
505
506//ll
Note: See TracBrowser for help on using the repository browser.