source: roaraudio/libroar/stream.c @ 4907:7ce748f993d8

Last change on this file since 4907:7ce748f993d8 was 4907:7ce748f993d8, checked in by phi, 13 years ago

assigned codec IDs for opus

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