source: roaraudio/libroar/stream.c @ 5535:051e141134da

Last change on this file since 5535:051e141134da was 5535:051e141134da, checked in by phi, 12 years ago

added roar_stream_new_by_info() as well as done some related cleanup

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