source: roaraudio/roard/sources.c @ 5826:edb28d83ca21

Last change on this file since 5826:edb28d83ca21 was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

File size: 12.3 KB
RevLine 
[0]1//sources.c:
2
[668]3/*
[5823]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
[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
[5194]30static int g_source_client = -1;
31
[3061]32#define ROAR_SOURCE_DEFAULT "cf"
33
[2270]34struct roar_source g_source[] = {
[5242]35 {"raw",  "DSTR source",                 "/some/file",     SRC_FLAG_FHSEC, ROAR_SUBSYS_WAVEFORM, NULL,  sources_add_dstr},
[2275]36 {"cf",   "Old CF source",               "/some/file.ext", SRC_FLAG_NONE,  ROAR_SUBSYS_WAVEFORM, sources_add_cf,   NULL},
[4919]37 {"roar", "New simple RoarAudio source", "some.host",      SRC_FLAG_NONE,  ROAR_SUBSYS_WAVEFORM, NULL, sources_add_roar},
[2507]38#ifndef ROAR_WITHOUT_DCOMP_CDRIVER
[2286]39 {"oss",  "OSS CDriver",                 "/dev/audio",     SRC_FLAG_NONE,  ROAR_SUBSYS_WAVEFORM, NULL, sources_add_cdriver},
[2507]40#endif
[4807]41 {"radionoise", "Noise source at -102dB", NULL,            SRC_FLAG_NONE, ROAR_SUBSYS_WAVEFORM, NULL, sources_add_radionoise},
[2269]42 {NULL, NULL, NULL, SRC_FLAG_NONE, 0, NULL, NULL} // EOL
43};
44
[0]45int sources_init (void) {
46 return 0;
47}
48
[2270]49void print_sourcelist (void) {
50 int i;
51 char subsys[7] = "      ";
52
[4807]53 printf("  Source    Flag Subsys - Description (devices)\n");
54 printf("-------------------------------------------------------\n");
[2270]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';
[2681]69  if ( g_source[i].subsystems & ROAR_SUBSYS_COMPLEX )
70   subsys[5] = 'X';
[2270]71
[4807]72  if ( g_source[i].devices != NULL ) {
73   printf("  %-10s %c%c%c %6s - %s (devices: %s)\n", g_source[i].name,
74                 g_source[i].flags & SRC_FLAG_FHSEC      ? 's' : ' ',
75                 g_source[i].old_open != NULL            ? 'S' : ' ',
76                 g_source[i].new_open != NULL            ? 'N' : ' ',
77                 subsys,
78                 g_source[i].desc, g_source[i].devices);
79  } else {
80   printf("  %-9s %c%c%c %6s - %s\n", g_source[i].name,
81                 g_source[i].flags & SRC_FLAG_FHSEC      ? 's' : ' ',
82                 g_source[i].old_open != NULL            ? 'S' : ' ',
83                 g_source[i].new_open != NULL            ? 'N' : ' ',
84                 subsys,
85                 g_source[i].desc);
86  }
[2270]87 }
88}
89
90
[64]91int sources_set_client (int client) {
92 if ( client >= 0 ) {
93  g_source_client = client;
94  return 0;
95 } else {
96  return -1;
97 }
98}
[0]99
100int sources_free (void) {
101 return 0;
102}
103
[65]104int sources_add (char * driver, char * device, char * container, char * options, int primary) {
[2272]105 int i;
106
[3061]107 if ( driver == NULL )
108  driver = ROAR_SOURCE_DEFAULT;
109
[2272]110 for (i = 0; g_source[i].name != NULL; i++) {
111  if ( !strcmp(g_source[i].name, driver) ) {
112   if ( g_source[i].new_open != NULL ) {
[5586]113    return sources_add_new(&(g_source[i]), driver, device, options, primary);
[2272]114   } else if ( g_source[i].old_open != NULL ) {
115    return g_source[i].old_open(driver, device, container, options, primary);
116   } else {
117    ROAR_ERR("sources_add(driver='%s', ...): Found source but did not find any open rutine", driver);
118    return -1;
119   }
120  }
[67]121 }
[65]122
[2272]123 ROAR_ERR("sources_add(driver='%s', ...): Source not found", driver);
[0]124 return -1;
125}
126
[2273]127int sources_add_new (struct roar_source * source,
128                     char * driver, char * device,
129                     char * options, int primary) {
[2274]130 int  stream;
131 int  fh = -1;
132 struct roar_stream        *  s;
133 struct roar_stream_server * ss;
134 char * k, * v;
135 int error = 0;
136 int f_sync = 0, f_mmap = 0;
137 int codec;
[5210]138 char * strtok_store;
[2274]139
140 if ( source == NULL )
141  return -1;
142
143 if ( (stream = streams_new()) == -1 ) {
144  return -1;
145 }
146
[4807]147 if ( streams_get(stream, &ss) == -1 ) {
148  streams_delete(stream);
149  return -1;
150 }
151
[2274]152 s = ROAR_STREAM(ss);
153
154 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
155
[2275]156 codec = s->info.codec;
157
[2274]158 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
159  streams_delete(stream);
160  return -1;
161 }
162
163 s->pos_rel_id = -1;
164
[5246]165 if ( options == NULL ) {
166  k = NULL;
167 } else {
168  k = roar_mm_strtok_r(options, ",", &strtok_store);
169 }
[2274]170 while (k != NULL) {
171  if ( (v = strstr(k, "=")) != NULL ) {
172   *v++ = 0;
173  }
174
175  if ( strcmp(k, "rate") == 0 ) {
[4920]176   s->info.rate = roar_str2rate(v);
[2274]177  } else if ( strcmp(k, "channels") == 0 ) {
[4920]178   s->info.channels = roar_str2channels(v);
[2274]179  } else if ( strcmp(k, "bits") == 0 ) {
[4920]180   s->info.bits = roar_str2bits(v);
[2274]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
[5210]217  k = roar_mm_strtok_r(NULL, ",", &strtok_store);
[2274]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
[2275]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
[2285]232 if ( source->new_open(stream, device, fh, driver) == -1 ) {
[2274]233  streams_delete(stream);
234  return -1;
235 }
236
[5162]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
[2274]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;
[2273]250}
251
[5242]252int sources_add_dstr  (int stream   , const char * device, int fh, const char * driver) {
[2275]253 struct roar_stream_server * ss;
[5242]254 struct roar_vio_defaults def;
255
[5586]256 (void)driver;
257
[5242]258 if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, O_RDONLY, 0644) == -1 )
259  return -1;
[566]260
[2275]261 streams_get(stream, &ss);
[1609]262
[5162]263 if ( fh > -1 ) {
264  if ( roar_vio_open_fh(&(ss->vio), fh) == -1 )
265   return -1;
266 } else {
[5242]267  if ( roar_vio_open_dstr(&(ss->vio), device, &def, 1) == -1 )
[5162]268   return -1;
269 }
[65]270
[2275]271 return streams_set_fh(stream, -2);
[65]272}
273
[1614]274#define _ret(x) streams_delete(stream); return (x)
[542]275
[5242]276int sources_add_cf (const char * driver, const char * device, const char * container, const char * options, int primary) {
[555]277 int  stream;
278 int  codec;
279 int  len;
280 char buf[64];
[1499]281 struct roar_stream    * s;
282 struct roar_vio_calls * vio;
[1614]283 struct roar_vio_defaults def;
284
[5586]285 (void)driver, (void)container;
286
[1614]287 if ( roar_vio_dstr_init_defaults(&def, ROAR_VIO_DEF_TYPE_NONE, O_RDONLY, 0644) == -1 )
288  return -1;
[555]289
[542]290 if ( (stream = streams_new()) == -1 ) {
291  return -1;
292 }
293
[4521]294 streams_get_clientobj(stream, &s);
[542]295
296 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
297
[1609]298 if ( streams_set_dir(stream, ROAR_DIR_PLAY, 1) == -1 ) {
299  streams_delete(stream);
300  return -1;
301 }
302
[542]303 s->pos_rel_id = -1;
[1499]304
305/*
306 if ( (fh = open(device, O_RDONLY, 0644)) == -1 ) {
307  return -1;
308 }
309*/
310
311 vio = &(ROAR_STREAM_SERVER(s)->vio);
312
[1614]313 if ( roar_vio_open_dstr(vio, device, &def, 1) == -1 ) {
[4964]314  roar_vio_clear_calls(vio); // clear the VIO object again
[4419]315                            // from things roar_vio_open_dstr() left.
[1499]316  _ret(-1);
317 }
318
[1614]319 ROAR_DBG("sources_add_cf(*) = ?");
320
[5242]321 // TODO: find out a better way of doing auto detetion without need for seek!
[1499]322 if ( options == NULL ) {
323  if ( (len = roar_vio_read(vio, buf, 64)) < 1 ) {
324   _ret(-1);
325  }
326
[5278]327  if ( roar_vio_lseek(vio, -len, SEEK_CUR) == (roar_off_t)-1 ) {
[1499]328   _ret(-1);
329  }
330
331  if ( (codec = roar_file_codecdetect(buf, len)) == -1 ) {
332   _ret(-1);
333  }
334 } else {
335  if ( !strncmp(options, "codec=", 6) )
336   options += 6;
337
338  if ( (codec = roar_str2codec(options)) == -1 ) {
339   _ret(-1);
340  }
341 }
342
[542]343 s->info.codec = codec;
344
[566]345 ROAR_STREAM_SERVER(s)->codec_orgi = codec;
346
[1614]347 ROAR_DBG("sources_add_cf(*) = ?");
[1504]348 streams_set_fh(stream, -2);
[1614]349 ROAR_DBG("sources_add_cf(*) = ?");
[644]350 streams_set_socktype(stream, ROAR_SOCKET_TYPE_FILE);
351
352 if ( primary )
353  streams_mark_primary(stream);
[542]354
[1031]355 streams_set_flag(stream, ROAR_FLAG_SOURCE);
[542]356 client_stream_add(g_source_client, stream);
357
358 return 0;
359}
360
[1499]361#undef _ret
362
[2507]363#ifndef ROAR_WITHOUT_DCOMP_CDRIVER
[5242]364int sources_add_cdriver (int stream   , const char * device, int fh, const char * driver) {
[2286]365 struct roar_stream_server * ss;
366
367 if ( fh > -1 )
368  return -1;
369
[4807]370 if ( streams_get(stream, &ss) == -1 )
371  return -1;
[2286]372
373 if ( !strncmp(driver, "cdriver:", 8) )
374  driver += 8;
375
[2290]376 ROAR_DBG("sources_add_cdriver(stream=%i, device='%s', fh=%i, driver='%s') = ?", stream, device, fh, driver);
377
[2286]378 if ( roar_cdriver_open(&(ss->vio), driver, device, &(ROAR_STREAM(ss)->info), ROAR_DIR_RECORD) == -1 )
379  return -1;
380
381 return streams_set_fh(stream, -2);
382}
[2507]383#endif
[2286]384
[4807]385static ssize_t sources_radionoise_read (struct roar_vio_calls * vio, void *buf, size_t count) {
386 int32_t * pcm = buf;
387 int16_t noise;
388 size_t len, i;
389
[5586]390 (void)vio;
391
[4807]392 ROAR_DBG("sources_radionoise_read(vio=%p, buf=%p, count=%llu) = 0", vio, buf, (long long unsigned int)count);
393
394 // ensure size is a multiple of 4.
395 count -= count & 0x03LLU;
396
397 if ( count == 0 )
398  return 0;
399
400 if ( buf == NULL )
401  return -1;
402
403 roar_random_gen_nonce(buf, count);
404
405 len = count / 4;
406
407 for (i = 0; i < len; i++) {
408  noise  = pcm[i] & 0xFFFF;
409  pcm[i] = ((int32_t)noise << 16) >> 17;
410 }
411
412 ROAR_DBG("sources_radionoise_read(vio=%p, buf=%p, count=?) = %llu", vio, buf, (long long unsigned int)count);
413 return count;
414}
415
416static int     sources_radionoise_return_zero (struct roar_vio_calls * vio) {
417 (void)vio;
418
419 ROAR_DBG("sources_radionoise_return_zero(vio=%p) = 0", vio);
420
421 return 0;
422}
423
[5278]424static int  sources_radionoise_ctl(struct roar_vio_calls * vio, roar_vio_ctl_t cmd, void * data) {
[5586]425 (void)vio, (void)data;
426
[5276]427 if ( cmd == ROAR_VIO_CTL_NONBLOCK )
428  return 0;
429
430 roar_err_set(ROAR_ERROR_BADRQC);
431 return -1;
432}
433
[5242]434int sources_add_radionoise (int stream, const char * device, int fh, const char * driver) {
[4807]435 struct roar_stream_server * ss;
436 struct roar_audio_info    * info;
437
[5586]438 (void)device, (void)driver;
439
[4807]440 if ( fh > -1 )
441  return -1;
442
443 if ( streams_get(stream, &ss) == -1 )
444  return -1;
445
446 info = &(ROAR_STREAM(ss)->info);
447
448 info->codec = ROAR_CODEC_DEFAULT;
449 info->bits  = 32;
450
451 memset(&(ss->vio), 0, sizeof(struct roar_vio_calls));
[5388]452 ss->vio.flags    = ROAR_VIO_FLAGS_NONE;
453 ss->vio.refc     = 1;
[4807]454 ss->vio.read     = sources_radionoise_read;
455 ss->vio.close    = sources_radionoise_return_zero;
456 ss->vio.sync     = sources_radionoise_return_zero;
[5276]457 ss->vio.ctl      = sources_radionoise_ctl;
[4807]458
459 return streams_set_fh(stream, -2);
460}
461
[5242]462int sources_add_roar (int stream, const char * device, int fh, const char * driver) {
[4919]463 struct roar_stream_server * ss;
464 struct roar_stream        * s;
465
[5586]466 (void)driver;
467
[4919]468 if ( fh > -1 )
469  return -1;
470
471 if ( streams_get(stream, &ss) == -1 )
472  return -1;
473
474 s = ROAR_STREAM(ss);
475
476 if ( roar_vio_simple_stream(&(ss->vio), s->info.rate, s->info.channels, s->info.bits, s->info.codec,
[5289]477                             device, ROAR_DIR_MONITOR, "roard", -1) == -1 )
[4919]478  return -1;
479
480 return streams_set_fh(stream, -2);
481}
482
[2485]483#endif
484
[0]485//ll
Note: See TracBrowser for help on using the repository browser.