source: roaraudio/libroar/stream.c @ 4538:b809f0dcd86a

Last change on this file since 4538:b809f0dcd86a was 4538:b809f0dcd86a, checked in by phi, 14 years ago

implemented support for sending extended flags over the network

File size: 26.0 KB
RevLine 
[0]1//stream.c:
2
[690]3/*
[3811]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
[690]5 *
6 *  This file is part of libroar 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 *  libroar 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.
[690]23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
[0]36#include "libroar.h"
37
38int roar_stream_connect (struct roar_connection * con, struct roar_stream * s, int dir) {
[3136]39 struct roar_libroar_config * config = roar_libroar_get_config();
40 struct roar_stream  ms;
[0]41 struct roar_message m;
42
43 s->dir = dir;
44
[3875]45 memset(&m,  0, sizeof(m));
[3136]46 memcpy(&ms, s, sizeof(ms));
47
[0]48 m.cmd     = ROAR_CMD_NEW_STREAM;
49 m.stream  = -1;
50 m.pos     = 0;
51
[3136]52 if ( config != NULL ) {
53  if ( config->info.rate )
54   ms.info.rate = config->info.rate;
55  if ( config->info.bits )
56   ms.info.bits = config->info.bits;
57  if ( config->info.channels )
58   ms.info.channels = config->info.channels;
59  if ( config->info.codec )
60   ms.info.codec = config->info.codec;
61 }
62
63 roar_stream_s2m(&ms, &m);
[0]64
65 if ( roar_req(con, &m, NULL) != 0 )
66  return -1;
67
68 if ( m.cmd == ROAR_CMD_OK ) {
69  s->id = m.stream;
70
71  ROAR_DBG("roar_stream_connect(*) = 0");
72  return 0;
73 }
74
75 ROAR_ERR("roar_stream_connect(*): Connecting new stream faild!");
76 ROAR_DBG("roar_stream_connect(*) = -1");
77 return -1;
78}
79
80int roar_stream_new (struct roar_stream * s, unsigned int rate,
81                     unsigned int channels, unsigned int bits, unsigned int codec) {
82
[1813]83 if ( s == NULL )
84  return -1;
[0]85
86 s->fh         = -1;
87 s->id         = -1;
[1813]88 s->pos        =  0;
[0]89 s->pos_rel_id = -1;
90
91 s->dir        = ROAR_DIR_DEFAULT;
92
[1804]93/*
[0]94 s->datalen    = 0;
95 s->offset     = 0;
96
97 s->database   = NULL;
98 s->dataoff    = NULL;
[1804]99*/
[0]100
101 s->info.rate     = rate;
102 s->info.channels = channels;
103 s->info.bits     = bits;
104 s->info.codec    = codec;
105
106 if ( bits > ROAR_BITS_MAX )
107  return -1;
108
109 return 0;
110}
111
[1813]112int roar_stream_set_rel_id(struct roar_stream * s, int id) {
113 if ( s == NULL )
114  return -1;
115
116 s->pos_rel_id = id;
117
118 return 0;
119}
120
121int roar_stream_get_rel_id(struct roar_stream * s) {
122 if ( s == NULL )
123  return -1;
124
125 return s->pos_rel_id;
126}
127
[1167]128int roar_stream_new_by_id(struct roar_stream * s, int id) {
129 if ( s == NULL )
130  return -1;
131
132 if ( roar_stream_new_empty(s) == -1 )
133  return -1;
134
135 return roar_stream_set_id(s, id);
136}
137
138int roar_stream_new_empty(struct roar_stream * s) {
139 if ( s == NULL )
140  return -1;
141
142 return roar_stream_new(s, 0, 0, 0, 0);
143}
144
145int roar_stream_set_id (struct roar_stream * s, int id) {
146 if ( s == NULL )
147  return -1;
148
149 s->id = id;
150
151 return 0;
152}
153
154int roar_stream_get_id (struct roar_stream * s) {
155 if ( s == NULL )
156  return -1;
157
158 return s->id;
159}
160
161int roar_stream_set_fh (struct roar_stream * s, int fh) {
162 if ( s == NULL )
163  return -1;
164
165 s->fh = fh;
166
167 return 0;
168}
169
170int roar_stream_get_fh (struct roar_stream * s) {
171 if ( s == NULL )
172  return -1;
173
174 return s->fh;
175}
176
[2588]177int roar_stream_set_dir (struct roar_stream * s, int dir) {
178 if ( s == NULL )
179  return -1;
180
181 s->dir = dir;
182
183 return 0;
184}
185
186int roar_stream_get_dir (struct roar_stream * s) {
187 if ( s == NULL )
188  return -1;
189
190 return s->dir;
191}
192
[1167]193
[0]194int roar_stream_exec    (struct roar_connection * con, struct roar_stream * s) {
195 struct roar_message m;
196
[3875]197 memset(&m,  0, sizeof(m));
198
[0]199 m.cmd     = ROAR_CMD_EXEC_STREAM;
200 m.stream  = s->id;
201 m.datalen = 0;
202 m.pos     = 0;
203
204 if ( roar_req(con, &m, NULL) == -1 )
205  return -1;
206
207 if ( m.cmd == ROAR_CMD_OK )
208  return 0;
209 return -1;
210}
211
[81]212int roar_stream_connect_to (struct roar_connection * con, struct roar_stream * s, int type, char * host, int port) {
213 struct roar_message m;
[82]214
215 if ( roar_stream_connect_to_ask(con, s, type, host, port) == -1 )
216  return -1;
217
218 if ( roar_recv_message(con, &m, NULL) == -1 )
219  return -1;
220
221 if ( m.cmd == ROAR_CMD_OK )
222  return 0;
223 return -1;
224}
225
226int roar_stream_connect_to_ask (struct roar_connection * con, struct roar_stream * s, int type, char * host, int port) {
227 struct roar_message m;
[81]228 int len = 0;
229
230 if ( host == NULL )
231  return -1;
232
[487]233 ROAR_DBG("roar_stream_connect_to_ask(*): Ask the server to connect to: %s:%i", host, port);
234
[3875]235 memset(&m,  0, sizeof(m));
236
[81]237 m.cmd     = ROAR_CMD_CON_STREAM;
238 m.stream  = s->id;
239 m.pos     = 0;
240
241 m.data[0] = 0;
242 m.data[1] = type;
243 ((uint16_t*)&(m.data))[1] = ROAR_HOST2NET16(port);
244
245 len = strlen(host);
246
247 if ( len > 76 )
248  return -1;
249
250 strncpy(&(m.data[4]), host, len);
251
252 m.datalen = len + 4;
253
[82]254 if ( roar_send_message(con, &m, NULL) == -1 )
[81]255  return -1;
256
[82]257 return 0;
[81]258}
[0]259
[758]260int roar_stream_passfh  (struct roar_connection * con, struct roar_stream * s, int fh) {
261 struct roar_message m;
[1660]262 int confh;
[758]263
[3875]264 memset(&m,  0, sizeof(m));
265
[758]266 m.cmd     = ROAR_CMD_PASSFH;
267 m.stream  = s->id;
268 m.pos     = 0;
[759]269 m.datalen = 0;
[758]270
[2038]271 ROAR_DBG("roar_stream_passfh(con=%p{...}, s={.id=%i,...}, fh=%i) = ?", con, s->id, fh);
[759]272
[3857]273 roar_libroar_nowarn();
274 if ( (confh = roar_get_connection_fh(con)) == -1 ) {
275  roar_libroar_warn();
[1660]276  return -1;
[3857]277 }
278 roar_libroar_warn();
[1660]279
[759]280 if ( roar_send_message(con, &m, NULL) == -1 ) {
[2038]281  ROAR_DBG("roar_stream_passfh(con=%p{...}, s={.id=%i,...}, fh=%i) = -1 // can not send message", con, s->id, fh);
[758]282  return -1;
[759]283 }
284
285 ROAR_DBG("roar_stream_passfh(*): msg send");
[758]286
[1660]287 if ( roar_socket_send_fh(confh, fh, NULL, 0) == -1 )
[758]288  return -1;
289
[759]290 ROAR_DBG("roar_stream_passfh(*): fh send");
291
[758]292 if ( roar_recv_message(con, &m, NULL) == -1 )
293  return -1;
294
[759]295 ROAR_DBG("roar_stream_passfh(*): mes recved");
296
[761]297 if ( m.cmd == ROAR_CMD_OK )
298  return 0;
299
300 return -1;
[758]301}
302
[773]303int roar_stream_attach_simple (struct roar_connection * con, struct roar_stream * s, int client) {
304 struct roar_message m;
305 uint16_t * info = (uint16_t *) m.data;
306 int i;
307
[3875]308 memset(&m,  0, sizeof(m));
309
[773]310 m.cmd     = ROAR_CMD_ATTACH;
311 m.stream  = s->id;
312 m.pos     = 0;
313 m.datalen = 6;
314
315 info[0] = 0;
316 info[1] = ROAR_ATTACH_SIMPLE;
317 info[2] = client;
318
319 for (i = 0; i < m.datalen/2; i++) {
320  info[i] = ROAR_HOST2NET16(info[i]);
321 }
322
323 if ( roar_req(con, &m, NULL) == -1 )
324  return -1;
325
326 if ( m.cmd != ROAR_CMD_OK )
327  return -1;
328
329 return 0;
330}
331
[0]332int roar_stream_add_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
333 struct roar_message m;
334
[3875]335 memset(&m,  0, sizeof(m));
336
[0]337 m.cmd     = ROAR_CMD_ADD_DATA;
338 m.stream  = s->id;
[134]339 m.pos     = 0;
[0]340 m.datalen = len;
341
342// if ( roar_req(con, &m, (void**)&data) == -1 )
343//  return -1;
344 if ( roar_send_message(con, &m, data) != 0 )
345  return -1;
346
347 if ( roar_recv_message(con, &m, NULL) == -1 )
348  return -1;
349
350 if ( m.cmd == ROAR_CMD_OK )
351  return 0;
352 return -1;
353}
354
[506]355int roar_stream_send_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
[3857]356
357 roar_debug_warn_obsolete("roar_stream_send_data", "roar_vio_write", NULL);
358
359 if ( s == NULL )
[506]360  return -1;
361
362 if ( s->fh == -1 ) {
[3857]363  if ( con == NULL )
[506]364   return -1;
365
366  if ( roar_stream_add_data(con, s, data, len) == -1 )
367   return -1;
368
369  return len;
370 }
371
[1475]372#ifdef ROAR_HAVE_IO_POSIX
[506]373 return write(s->fh, data, len);
[1475]374#endif
375
376 return -1;
[506]377}
378
[465]379int roar_stream_get_info (struct roar_connection * con, struct roar_stream * s, struct roar_stream_info * info) {
380 struct roar_message m;
381 uint16_t * data = (uint16_t *) m.data;
382 int i;
383
[3875]384 memset(&m,  0, sizeof(m));
385
[465]386 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
387 m.stream  = s->id;
388 m.datalen = 4;
389 m.pos     = 0;
390
391 data[0] = 0; // Version and reserved
[1842]392 data[1] = ROAR_STREAM_PARA_INFO; // stream
[465]393
394 for (i = 0; i < m.datalen/2; i++) {
395  data[i] = ROAR_HOST2NET16(data[i]);
396 }
397
398 if ( roar_req(con, &m, NULL) == -1 )
399  return -1;
400
401 if ( m.cmd != ROAR_CMD_OK )
402  return -1;
403
404 for (i = 0; i < m.datalen/2; i++) {
405  data[i] = ROAR_NET2HOST16(data[i]);
406 }
407
[1137]408 if ( m.datalen < 7*2 )
[465]409  return -1;
410
411 if ( data[0] != 0 || data[1] != 1 )
412  return -1;
413
[963]414 memset(info, 0, sizeof(struct roar_stream_info));
[3213]415 info->mixer = -1;
[3630]416 info->role  = ROAR_ROLE_UNKNOWN;
[963]417
[496]418 info->block_size     = data[2];
419 info->pre_underruns  = data[3];
420 info->post_underruns = data[4];
[540]421 info->codec          = data[5];
[963]422 info->flags          = data[6];
[1137]423 info->delay          = data[7]*1000;
[465]424
[2951]425 if ( m.datalen < 9*2 ) {
[2632]426  info->state         = ROAR_STREAMSTATE_UNKNOWN;
427  return 0;
428 } else {
429  info->state         = data[8];
430 }
431
[2951]432 if ( m.datalen < 10*2 ) {
433  return 0;
434 } else {
435  info->flags        |= ((uint32_t)data[9]) << 16;
436 }
437
[3213]438 if ( m.datalen < 11*2 ) {
439  return 0;
440 } else {
441  info->mixer         = data[10];
442 }
443
[3630]444 if ( m.datalen < 12*2 ) {
445  return 0;
446 } else {
447  info->role          = data[11];
448 }
449
[465]450 return 0;
451}
[0]452
[1842]453int roar_stream_get_name (struct roar_connection * con, struct roar_stream * s, char * name, size_t len) {
454 struct roar_message m;
455 uint16_t * data = (uint16_t *) m.data;
456
457 if ( con == NULL || s == NULL || name == NULL || len == 0 )
458  return -1;
459
460 name[0] = 0; // just in case...
461
[3875]462 memset(&m,  0, sizeof(m));
463
[1842]464 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
465 m.stream  = s->id;
466 m.datalen = 4;
467 m.pos     = 0;
468
469 data[0] = 0; // Version and reserved
470 data[1] = ROAR_STREAM_PARA_NAME; // stream
471
472 data[0] = ROAR_HOST2NET16(data[0]);
473 data[1] = ROAR_HOST2NET16(data[1]);
474
475 ROAR_DBG("roar_stream_get_name(*) = ?");
476
477 if ( roar_req(con, &m, NULL) == -1 )
478  return -1;
479
480 ROAR_DBG("roar_stream_get_name(*) = ?");
481
482 if ( m.cmd != ROAR_CMD_OK )
483  return -1;
484
485 ROAR_DBG("roar_stream_get_name(*) = ?");
486
487 if ( m.datalen < 4 )
488  return -1;
489
490 data[0] = ROAR_NET2HOST16(data[0]);
491 data[1] = ROAR_NET2HOST16(data[1]);
492
493 ROAR_DBG("roar_stream_get_name(*) = ?");
494
495 if ( data[0] != 0 || data[1] != ROAR_STREAM_PARA_NAME )
496  return -1;
497
498 m.datalen -= 4;
499
500 len--;
501
502 if ( len > m.datalen )
503  len = m.datalen;
504
505 strncpy(name, ((char*)m.data)+4, len);
506 name[len] = 0;
507
508 ROAR_DBG("roar_stream_get_name(*) = 0");
509
510 return 0;
511}
512
[3539]513int roar_stream_get_chanmap (struct roar_connection * con, struct roar_stream * s, char * map, size_t * len) {
514 struct roar_message m;
515 uint16_t * data = (uint16_t *) m.data;
516
517 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p, map=%p, len=%p) = ?", con, s, map, len);
518
519 if ( con == NULL || s == NULL || map == NULL || len == NULL )
520  return -1;
521
522 if ( *len == 0 )
523  return -1;
524
525 memset(&m, 0, sizeof(m));
526
527 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
528 m.stream  = s->id;
529 m.datalen = 2*2;
530
531 data[0] = 0; // Version and reserved
532 data[1] = ROAR_STREAM_PARA_CHANMAP;
533
534 data[0] = ROAR_HOST2NET16(data[0]);
535 data[1] = ROAR_HOST2NET16(data[1]);
536
537 if ( roar_req(con, &m, NULL) == -1 )
538  return -1;
539
540 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
541
542 if ( m.cmd != ROAR_CMD_OK )
543  return -1;
544
545 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
546
547 if ( m.datalen < 4 )
548  return -1;
549
550 data[0] = ROAR_NET2HOST16(data[0]);
551 data[1] = ROAR_NET2HOST16(data[1]);
552
553 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
554
555 if ( data[0] != 0 || data[1] != ROAR_STREAM_PARA_CHANMAP )
556  return -1;
557
558 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
559
560 m.datalen -= 4;
561
562 if ( m.datalen > *len )
563  return -1;
564
565 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
566
567 memcpy(map, &(m.data[4]), m.datalen);
568
569 *len = m.datalen;
570
571 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = 0", con, s, s->id, map, len);
572 return 0;
573}
574
[3540]575int roar_stream_set_chanmap (struct roar_connection * con, struct roar_stream * s, char * map, size_t   len) {
576 struct roar_message m;
577 uint16_t * data = (uint16_t *) m.data;
578
579 if ( con == NULL || s == NULL || map == NULL )
580  return -1;
581
582 if ( len == 0 )
583  return 0;
584
585 memset(&m, 0, sizeof(m));
586
587 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
588 m.stream  = s->id;
589 m.datalen = 2*2 + len;
590
591 if ( m.datalen > sizeof(m.data) )
592  return -1;
593
594 data[0] = 0; // Version and reserved
595 data[1] = ROAR_STREAM_PARA_CHANMAP;
596
597 data[0] = ROAR_HOST2NET16(data[0]);
598 data[1] = ROAR_HOST2NET16(data[1]);
599
600 memcpy(&(m.data[4]), map, len);
601
602 if ( roar_req(con, &m, NULL) == -1 )
603  return -1;
604
605 if ( m.cmd != ROAR_CMD_OK )
606  return -1;
607
608 return 0;
609}
[3539]610
611
[1043]612int roar_stream_set_flags (struct roar_connection * con, struct roar_stream * s, int flags, int reset) {
[4538]613 return roar_stream_set_flags2(con, s, flags, reset == ROAR_RESET_FLAG ? ROAR_RESET_FLAG : ROAR_SET_FLAG);
614}
615
616int roar_stream_set_flags2 (struct roar_connection * con, struct roar_stream * s, uint32_t flags, int action) {
[1043]617 struct roar_message m;
618 uint16_t * data = (uint16_t *) m.data;
619 int i;
620
[3875]621 memset(&m,  0, sizeof(m));
622
[1043]623 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
624 m.stream  = s->id;
625 m.pos     = 0;
626
[4538]627 if ( flags & 0xFFFF0000 ) {
628  m.datalen = 2*5;
629 } else {
630  m.datalen = 2*4;
631 }
632
[1043]633 data[0] = 0; // Version and reserved
[3696]634 data[1] = ROAR_STREAM_PARA_FLAGS; // flags
[4538]635 data[2] = action;
636 data[3] = flags & 0x0000FFFF;
637
638 if ( flags & 0xFFFF0000 ) {
639  data[4] = (flags & 0xFFFF0000) >> 16;
640 }
[1043]641
642 for (i = 0; i < m.datalen/2; i++) {
643  data[i] = ROAR_HOST2NET16(data[i]);
644 }
645
646 if ( roar_req(con, &m, NULL) == -1 )
647  return -1;
648
649 if ( m.cmd != ROAR_CMD_OK )
650  return -1;
651
652 return 0;
653}
654
[3696]655int roar_stream_set_role  (struct roar_connection * con, struct roar_stream * s, int role) {
656 struct roar_message m;
657 uint16_t * data = (uint16_t *) m.data;
658 int i;
659
[3875]660 memset(&m,  0, sizeof(m));
661
[3696]662 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
663 m.stream  = s->id;
664 m.datalen = 6;
665 m.pos     = 0;
666
667 data[0] = 0; // Version and reserved
668 data[1] = ROAR_STREAM_PARA_ROLE; // flags
669 data[2] = role;
670
671 for (i = 0; i < m.datalen/2; i++) {
672  data[i] = ROAR_HOST2NET16(data[i]);
673 }
674
675 if ( roar_req(con, &m, NULL) == -1 )
676  return -1;
677
678 if ( m.cmd != ROAR_CMD_OK )
679  return -1;
680
681 return 0;
682}
683
[0]684#define _ROAR_STREAM_MESSAGE_LEN ((5+1)*4)
685
686int roar_stream_s2m     (struct roar_stream * s, struct roar_message * m) {
687 uint32_t * data;
688 int i;
689
690 if ( !(s && m) )
691  return -1;
692
693 m->datalen = _ROAR_STREAM_MESSAGE_LEN;
694 data = (uint32_t*) m->data;
695
696 data[0] = s->dir;
697 data[1] = s->pos_rel_id;
698 data[2] = s->info.rate;
699 data[3] = s->info.bits;
700 data[4] = s->info.channels;
701 data[5] = s->info.codec;
702
703 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
704  data[i] = ROAR_HOST2NET32(data[i]);
705
706 ROAR_DBG("roar_stream_s2m(*): s->info:");
707 roar_debug_audio_info_print(&s->info);
708
[964]709 m->pos = s->pos;
710
[0]711 return 0;
712}
713int roar_stream_m2s     (struct roar_stream * s, struct roar_message * m) {
714 uint32_t * data;
715 int i;
716
717 if ( !(s && m) )
718  return -1;
719
720 if ( m->datalen != _ROAR_STREAM_MESSAGE_LEN )
721  return -1;
722
[964]723 s->pos = m->pos;
724
[0]725 data = (uint32_t*) m->data;
726
727 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
728  data[i] = ROAR_NET2HOST32(data[i]);
729
[465]730 s->id            = m->stream;
[0]731 s->dir           = data[0];
732 s->pos_rel_id    = data[1];
733 s->info.rate     = data[2];
734 s->info.bits     = data[3];
735 s->info.channels = data[4];
736 s->info.codec    = data[5];
737
738 ROAR_DBG("roar_stream_m2s(*): s->info:");
739 roar_debug_audio_info_print(&s->info);
740
741 return 0;
742}
743
[1807]744// stream direction funcs:
745/*
746#define roar_dir2str(x)   ((x) == ROAR_DIR_PLAY   ? "play"   : (x) == ROAR_DIR_MONITOR ? "monitor" : \
747                           (x) == ROAR_DIR_FILTER ? "filter" : (x) == ROAR_DIR_RECORD  ? "record"  : \
748                           (x) == ROAR_DIR_OUTPUT ? "output" : (x) == ROAR_DIR_BIDIR   ? "bidir"   : \
749                           (x) == ROAR_DIR_MIXING ? "mixing" : \
750                           "unknown")
751*/
752
[4296]753static struct {
[2338]754 int    dir;
[4296]755 const char * name;
[2338]756} _libroar_dir[] = {
[2681]757 {ROAR_DIR_PLAY,        "play"       },
758 {ROAR_DIR_RECORD,      "record"     },
759 {ROAR_DIR_MONITOR,     "monitor"    },
760 {ROAR_DIR_FILTER,      "filter"     },
761 {ROAR_DIR_OUTPUT,      "output"     },
762 {ROAR_DIR_MIXING,      "mixing"     },
763 {ROAR_DIR_META,        "meta"       },
764 {ROAR_DIR_BIDIR,       "bidir"      },
765 {ROAR_DIR_THRU,        "thru"       },
766 {ROAR_DIR_BRIDGE,      "bridge"     },
767 {ROAR_DIR_MIDI_IN,     "midi_in"    },
768 {ROAR_DIR_MIDI_OUT,    "midi_out"   },
769 {ROAR_DIR_LIGHT_IN,    "light_in"   },
770 {ROAR_DIR_LIGHT_OUT,   "light_out"  },
771 {ROAR_DIR_RAW_IN,      "raw_in"     },
772 {ROAR_DIR_RAW_OUT,     "raw_out"    },
773 {ROAR_DIR_COMPLEX_IN,  "complex_in" },
774 {ROAR_DIR_COMPLEX_OUT, "complex_out"},
[2711]775 {ROAR_DIR_RDTCS_IN,    "rdtcs_in"   },
776 {ROAR_DIR_RDTCS_OUT,   "rdtcs_out"  },
[2681]777 {-1,                   "unknown"    }
[2338]778};
779
[4296]780const char * roar_dir2str (const int dir) {
[2338]781 int i;
782
783 for (i = 0; _libroar_dir[i].dir != -1; i++)
784  if ( _libroar_dir[i].dir == dir )
785   return _libroar_dir[i].name;
786
787 return _libroar_dir[i].name;
788}
789
[4296]790int roar_str2dir (const char * name) {
[2338]791 int i;
792
793 for (i = 0; _libroar_dir[i].dir != -1; i++)
794  if ( !strcmp(_libroar_dir[i].name, name) )
795   return _libroar_dir[i].dir;
796
797 return _libroar_dir[i].dir;
[1807]798}
[537]799
800// codec funcs:
801
802/*
803#define roar_codec2str(x) ((x) == ROAR_CODEC_PCM_S_LE  ? "pcm_s_le"  : (x) == ROAR_CODEC_PCM_S_BE  ? "pcm_s_be"  : \
804                           (x) == ROAR_CODEC_PCM_S_PDP ? "pcm_s_pdp" : (x) == ROAR_CODEC_MIDI_FILE ? "midi_file" : \
805                           "unknown" )
806*/
807
[4296]808static struct {
[537]809 int    codec;
[4296]810 const char * name;
[537]811} _libroar_codec[] = {
812 // PCM:
813 {ROAR_CODEC_PCM_S_LE,    "pcm_s_le"   },
814 {ROAR_CODEC_PCM_S_BE,    "pcm_s_be"   },
815 {ROAR_CODEC_PCM_S_PDP,   "pcm_s_pdp"  },
816 {ROAR_CODEC_PCM_U_LE,    "pcm_u_le"   },
817 {ROAR_CODEC_PCM_U_BE,    "pcm_u_be"   },
818 {ROAR_CODEC_PCM_U_PDP,   "pcm_u_pdp"  },
819 {ROAR_CODEC_DEFAULT,     "default"    }, // alias
820 {ROAR_CODEC_DEFAULT,     "pcm"        }, // alias
[557]821 {ROAR_CODEC_DEFAULT,     "raw"        }, // alias
[537]822
823 // MIDI:
824 {ROAR_CODEC_MIDI_FILE,   "midi_file"  },
[1820]825 {ROAR_CODEC_MIDI,        "midi"       },
[3996]826 {ROAR_CODEC_ROARMIDI,    "roarmidi"   },
[537]827
828 // XIPH:
829 {ROAR_CODEC_OGG_VORBIS,  "ogg_vorbis" },
830 {ROAR_CODEC_OGG_VORBIS,  "vorbis"     }, // alias
831 {ROAR_CODEC_FLAC,        "flac"       },
832 {ROAR_CODEC_OGG_SPEEX,   "ogg_speex"  },
833 {ROAR_CODEC_OGG_SPEEX,   "speex"      }, // alias
834 {ROAR_CODEC_OGG_FLAC,    "ogg_flac"   },
835 {ROAR_CODEC_OGG_GENERAL, "ogg_general"},
[2681]836 {ROAR_CODEC_OGG_CELT,    "ogg_celt"   },
837 {ROAR_CODEC_OGG,         "ogg"        },
[537]838 {ROAR_CODEC_ROAR_CELT,   "roar_celt"  },
839 {ROAR_CODEC_ROAR_SPEEX,  "roar_speex" },
[560]840
[881]841 // RAUM:
842 {ROAR_CODEC_RAUM,        "raum"       },
843 {ROAR_CODEC_RAUM_VORBIS, "raum_vorbis"},
[2332]844 {ROAR_CODEC_RAUM_FLAC,   "raum_flac"  },
[881]845
[560]846 // RIFF/WAVE like:
847 {ROAR_CODEC_RIFF_WAVE,   "riff_wave"  },
848 {ROAR_CODEC_RIFF_WAVE,   "wave"       }, // alias
849 {ROAR_CODEC_RIFF_WAVE,   "wav"        }, // alias
[4002]850 {ROAR_CODEC_RIFX,        "rifx"       },
851 {ROAR_CODEC_AU,          "au"         },
852 {ROAR_CODEC_AIFF,        "aiff"       },
[560]853
[733]854 //Log codecs:
855 {ROAR_CODEC_ALAW,        "alaw"       },
856 {ROAR_CODEC_MULAW,       "mulaw"      },
857 {ROAR_CODEC_MULAW,       "ulaw"       }, // alias
858
[3996]859 //GSM:
860 {ROAR_CODEC_GSM,         "gsm"        },
861 {ROAR_CODEC_GSM49,       "gsm49"      },
862
[1211]863 // Meta Codecs:
864 {ROAR_CODEC_META_VCLT,     "meta_vclt"    },
865 {ROAR_CODEC_META_RALT,     "meta_ralt"    },
866 {ROAR_CODEC_META_RALB,     "meta_ralb"    },
867 {ROAR_CODEC_META_RALB_LE,  "meta_ralb_le" },
868 {ROAR_CODEC_META_RALB_BE,  "meta_ralb_be" },
869 {ROAR_CODEC_META_RALB_PDP, "meta_ralb_pdp"},
870
[1820]871 // light control:
872 {ROAR_CODEC_DMX512,      "dmx512"     },
[1963]873 {ROAR_CODEC_ROARDMX,     "roardmx"    },
[1820]874
[2709]875 // Radio Data and Transmitter Control System:
876 {ROAR_CODEC_RDS,         "rds"        },
877
878 // User specific:
879 {ROAR_CODEC_USER0,       "user0"      },
880 {ROAR_CODEC_USER1,       "user1"      },
881 {ROAR_CODEC_USER2,       "user2"      },
882 {ROAR_CODEC_USER3,       "user3"      },
883 {ROAR_CODEC_USER4,       "user4"      },
884 {ROAR_CODEC_USER5,       "user5"      },
885 {ROAR_CODEC_USER6,       "user6"      },
886 {ROAR_CODEC_USER7,       "user7"      },
887 {ROAR_CODEC_USER8,       "user8"      },
888 {ROAR_CODEC_USER9,       "user9"      },
889 {ROAR_CODEC_USER10,      "user10"     },
890 {ROAR_CODEC_USER11,      "user11"     },
891 {ROAR_CODEC_USER12,      "user12"     },
892 {ROAR_CODEC_USER13,      "user13"     },
893 {ROAR_CODEC_USER14,      "user14"     },
894 {ROAR_CODEC_USER15,      "user15"     },
[537]895 {-1, NULL}
896};
897
[4296]898int roar_str2codec(const char * codec) {
[537]899 int i;
[549]900 int guess;
[537]901
[549]902 if ( codec == NULL || *codec == 0 )
903  return ROAR_CODEC_DEFAULT;
904
905 if ( (guess = atoi(codec)) > 0 )
[537]906  return guess;
907
908 if ( codec == NULL || *codec == 0 )
909  return ROAR_CODEC_DEFAULT;
910
911 for (i = 0; _libroar_codec[i].codec != -1; i++)
912  if ( strcasecmp(_libroar_codec[i].name, codec) == 0 )
913   return _libroar_codec[i].codec;
914
915 return -1;
916}
917
918
[4296]919const char * roar_codec2str (const int codec) {
[537]920 int i;
921
922 for (i = 0; _libroar_codec[i].codec != -1; i++)
923  if ( _libroar_codec[i].codec == codec )
924   return _libroar_codec[i].name;
925
926 return "unknown";
927}
928
[4296]929const char * roar_streamstate2str(int streamstate) {
[2633]930 switch (streamstate) {
931  case ROAR_STREAMSTATE_UNUSED:  return "unused";  break;
932  case ROAR_STREAMSTATE_INITING: return "initing"; break;
933  case ROAR_STREAMSTATE_NEW:     return "new";     break;
934  case ROAR_STREAMSTATE_OLD:     return "old";     break;
935  case ROAR_STREAMSTATE_CLOSING: return "closing"; break;
936 }
937
938 return "unknown";
939}
940
[4296]941static struct {
[3630]942 int    role;
[4296]943 const char * name;
[3630]944} _libroar_role[] = {
945 {ROAR_ROLE_UNKNOWN,          "unknown"         },
946 {ROAR_ROLE_NONE,             "none"            },
947 {ROAR_ROLE_MUSIC,            "music"           },
948 {ROAR_ROLE_VIDEO,            "video"           },
949 {ROAR_ROLE_GAME,             "game"            },
950 {ROAR_ROLE_EVENT,            "event"           },
951 {ROAR_ROLE_BEEP,             "beep"            },
952 {ROAR_ROLE_PHONE,            "phone"           },
953 {ROAR_ROLE_BACKGROUND_MUSIC, "background music"},
954 {ROAR_ROLE_BACKGROUND_MUSIC, "background_music"}, // alias
[3696]955 {ROAR_ROLE_VOICE,            "voice"           },
956 {ROAR_ROLE_INSTRUMENT,       "instrument"      },
[3724]957 {ROAR_ROLE_RHYTHM,           "rhythm"          },
958 {ROAR_ROLE_CLICK,            "click",          },
959 {ROAR_ROLE_MIXED,            "mixed",          },
[3630]960 {-1, NULL}
961};
962
[4296]963int    roar_str2role  (const char * role) {
[3630]964 int i;
965
966 for (i = 0; _libroar_role[i].name != NULL; i++)
967  if ( !strcasecmp(_libroar_role[i].name, role) )
968   return _libroar_role[i].role;
969
970 return ROAR_ROLE_UNKNOWN;
971}
972
[4296]973const char * roar_role2str  (const int    role) {
[3630]974 int i;
975
976 for (i = 0; _libroar_role[i].name != NULL; i++)
977  if ( _libroar_role[i].role == role )
978   return _libroar_role[i].name;
979
980 return "unknown";
981}
982
[3822]983ssize_t roar_info2samplesize (struct roar_audio_info * info) {
984 if ( info == NULL )
985  return -1;
986
987 switch (info->codec) {
988  case ROAR_CODEC_PCM_S_LE:
989  case ROAR_CODEC_PCM_S_BE:
990  case ROAR_CODEC_PCM_S_PDP:
991  case ROAR_CODEC_PCM_U_LE:
992  case ROAR_CODEC_PCM_U_BE:
993  case ROAR_CODEC_PCM_U_PDP:
994    return info->bits;
995   break;
996  case ROAR_CODEC_ALAW:
997  case ROAR_CODEC_MULAW:
998    return 8;
999   break;
1000  case ROAR_CODEC_DMX512:
1001    return 8;
1002   break;
1003  case ROAR_CODEC_RDS:
1004    return 26;
1005   break;
1006  default:
1007    return -1;
1008   break;
1009 }
1010}
1011
1012ssize_t roar_info2framesize  (struct roar_audio_info * info) {
1013 ssize_t ret = roar_info2samplesize(info);
1014
1015 if ( ret == -1 )
1016  return -1;
1017
1018 ret *= info->channels;
1019
1020 return ret;
1021}
1022
1023ssize_t roar_info2bitspersec(struct roar_audio_info * info) {
1024 ssize_t ret = roar_info2samplesize(info);
1025
1026 if ( ret == -1 )
1027  return -1;
1028
1029 ret *= info->channels * info->rate;
1030
1031 return ret;
1032}
1033
[3942]1034static struct {
1035 const char * name;
1036 struct roar_audio_info info;
1037} _libroar_aiprofiles[] = {
[3943]1038 {"default",   {.rate     = ROAR_RATE_DEFAULT,
1039                .bits     = ROAR_BITS_DEFAULT,
1040                .channels = ROAR_CHANNELS_DEFAULT,
1041                .codec    = ROAR_CODEC_DEFAULT}},
[3955]1042 {"wav",       {.rate     = ROAR_RATE_DEFAULT,
1043                .bits     = ROAR_BITS_DEFAULT,
1044                .channels = ROAR_CHANNELS_DEFAULT,
1045                .codec    = ROAR_CODEC_RIFF_WAVE}},
[4001]1046 {"au",        {.rate     = ROAR_RATE_DEFAULT,
1047                .bits     = ROAR_BITS_DEFAULT,
1048                .channels = ROAR_CHANNELS_DEFAULT,
1049                .codec    = ROAR_CODEC_AU}},
[3943]1050 {"cd",        {.rate =  44100, .bits = 16, .channels =  2, .codec = ROAR_CODEC_DEFAULT}},
1051 {"cdr",       {.rate =  44100, .bits = 16, .channels =  2, .codec = ROAR_CODEC_PCM_S_BE}},
1052 {"dat",       {.rate =  48000, .bits = 16, .channels =  2, .codec = ROAR_CODEC_PCM_S_LE}},
1053 {"isdn-eu",   {.rate =   8000, .bits =  8, .channels =  1, .codec = ROAR_CODEC_ALAW}},
1054 {"isdn-na",   {.rate =   8000, .bits =  8, .channels =  1, .codec = ROAR_CODEC_MULAW}},
1055 {"speex-nb",  {.rate =   8000, .bits = 16, .channels =  2, .codec = ROAR_CODEC_ROAR_SPEEX}},
1056 {"speex-wb",  {.rate =  16000, .bits = 16, .channels =  2, .codec = ROAR_CODEC_ROAR_SPEEX}},
1057 {"speex-uwb", {.rate =  32000, .bits = 16, .channels =  2, .codec = ROAR_CODEC_ROAR_SPEEX}},
[4001]1058 {"gsm",       {.rate =   8000, .bits = 16, .channels =  1, .codec = ROAR_CODEC_GSM}},
[3943]1059 {"rds",       {.rate =      0, .bits =  0, .channels =  0, .codec = ROAR_CODEC_RDS}},
1060 {"midi",      {.rate =      0, .bits =  8, .channels = 16, .codec = ROAR_CODEC_MIDI}},
1061 {"dmx512",    {.rate =      0, .bits =  8, .channels =  0, .codec = ROAR_CODEC_DMX512}},
1062 {NULL,        {.rate =      0, .bits =  0, .channels =  0, .codec = 0}}
[3942]1063};
1064
1065int     roar_profile2info    (struct roar_audio_info * info, const char * profile) {
1066 int i;
1067
1068 for (i = 0; _libroar_aiprofiles[i].name != NULL; i++) {
1069  if ( !strcasecmp(_libroar_aiprofiles[i].name, profile) ) {
1070   memcpy(info, &(_libroar_aiprofiles[i].info), sizeof(struct roar_audio_info));
1071   return 0;
1072  }
1073 }
1074
1075 return -1;
1076}
1077
1078ssize_t   roar_profiles_list   (const char ** list, size_t len, size_t offset) {
1079 size_t i;
1080 int idx = 0;
1081
1082 if ( list == NULL )
1083  return -1;
1084
1085 if ( len == 0 )
1086  return 0;
1087
1088 if ( offset >= (sizeof(_libroar_aiprofiles)/sizeof(*_libroar_aiprofiles)) )
1089  return 0;
1090
1091 for (i = offset; _libroar_aiprofiles[i].name != NULL; i++) {
1092  list[idx++] = _libroar_aiprofiles[i].name;
1093 }
1094
1095 return idx;
1096}
1097
[0]1098//ll
Note: See TracBrowser for help on using the repository browser.