source: roaraudio/libroar/stream.c @ 5373:8da157c10483

Last change on this file since 5373:8da157c10483 was 5270:e25346c13638, checked in by phi, 12 years ago

fixed some gcc -Wextra warnings

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