source: roaraudio/roard/sources.c @ 5242:97239101cee9

Last change on this file since 5242:97239101cee9 was 5242:97239101cee9, checked in by phi, 12 years ago

some roard compiler warnings cleanup

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