source: roaraudio/libroar/stream.c @ 6056:8d4468a24909

Last change on this file since 6056:8d4468a24909 was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

File size: 35.8 KB
Line 
1//stream.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2015
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_connect_to_advanced (struct roar_connection * con, struct roar_stream * s,
304                                     int version, int ask_only, uint_least32_t flags,
305                                     int socket_type, ssize_t socket_len, const void * socketaddr,
306                                     int transport_protocol, ssize_t tranport_len, const void * transportsetup,
307                                     uint16_t clientsetup_flags, struct roar_client * clientsetup) {
308 struct roar_message m;
309 char buf[80];
310 int port;
311 uint16_t tmp;
312
313 if ( con == NULL ) {
314  roar_err_set(ROAR_ERROR_FAULT);
315  return -1;
316 }
317
318 if ( transport_protocol == ROAR_PROTO_NONE && (tranport_len != -1 || transportsetup ) ) {
319  roar_err_set(ROAR_ERROR_INVAL);
320  return -1;
321 }
322
323 if ( !((s == NULL) ^ (clientsetup == NULL)) ) {
324  roar_err_set(ROAR_ERROR_INVAL);
325  return -1;
326 }
327
328 switch (version) {
329  case 0:
330    if ( transport_protocol != ROAR_PROTO_NONE || s == NULL) {
331     roar_err_set(ROAR_ERROR_INVAL);
332     return -1;
333    }
334    switch (socket_type) {
335     case ROAR_SOCKET_TYPE_TCP:
336     case ROAR_SOCKET_TYPE_UDP:
337       if ( socket_len != 6 ) {
338        roar_err_set(ROAR_ERROR_FAULT);
339        return -1;
340       }
341       snprintf(buf, sizeof(buf), "%i.%i.%i.%i",
342                ((const unsigned char*)socketaddr)[0], ((const unsigned char*)socketaddr)[1],
343                ((const unsigned char*)socketaddr)[2], ((const unsigned char*)socketaddr)[3]);
344       port = ROAR_NET2HOST16(((const uint16_t*)socketaddr)[3]);
345       if ( roar_stream_connect_to_ask(con, s, socket_type, buf, port) == -1 )
346        return -1;
347      break;
348     case ROAR_SOCKET_TYPE_DECNET:
349       if ( socket_len < 3 ) {
350        roar_err_set(ROAR_ERROR_FAULT);
351        return -1;
352       }
353       tmp  = ((const uint16_t*)socketaddr)[0];
354       port = ((const unsigned char*)socketaddr)[2];
355       snprintf(buf, sizeof(buf), "%i.%i::%*s", tmp >> 10, tmp & 0x03FF, (int)socket_len - 3, (const char*)socketaddr + 3);
356       if ( roar_stream_connect_to_ask(con, s, socket_type, buf, port) == -1 )
357        return -1;
358      break;
359     default:
360       if ( ((const char *)socketaddr)[socket_len-1] == 0 ) {
361        if ( socket_len > sizeof(buf) ) {
362         roar_err_set(ROAR_ERROR_MSGSIZE);
363         return -1;
364        }
365        memcpy(buf, socketaddr, socket_len);
366        if ( roar_stream_connect_to_ask(con, s, socket_type, buf, 0) == -1 )
367         return -1;
368       } else {
369        roar_err_set(ROAR_ERROR_FAULT);
370        return -1;
371       }
372      break;
373    }
374   break;
375  default:
376    roar_err_set(ROAR_ERROR_NSVERSION);
377    return -1;
378   break;
379 }
380
381
382 if ( ask_only )
383  return 0;
384
385 if ( roar_recv_message(con, &m, NULL) == -1 )
386  return -1;
387
388 if ( m.cmd == ROAR_CMD_OK )
389  return 0;
390 return -1;
391}
392
393int roar_stream_passfh  (struct roar_connection * con, struct roar_stream * s, int fh) {
394 struct roar_message m;
395 int confh;
396
397 if ( con == NULL || s == NULL ) {
398  roar_err_set(ROAR_ERROR_FAULT);
399  return -1;
400 }
401
402 if ( fh < 0 ) {
403  roar_err_set(ROAR_ERROR_INVAL);
404  return -1;
405 }
406
407 memset(&m,  0, sizeof(m));
408
409 m.cmd     = ROAR_CMD_PASSFH;
410 m.stream  = s->id;
411 m.pos     = 0;
412 m.datalen = 0;
413
414 ROAR_DBG("roar_stream_passfh(con=%p{...}, s={.id=%i,...}, fh=%i) = ?", con, s->id, fh);
415
416 roar_libroar_nowarn();
417 if ( (confh = roar_get_connection_fh(con)) == -1 ) {
418  roar_libroar_warn();
419  return -1;
420 }
421 roar_libroar_warn();
422
423 if ( roar_send_message(con, &m, NULL) == -1 ) {
424  ROAR_DBG("roar_stream_passfh(con=%p{...}, s={.id=%i,...}, fh=%i) = -1 // can not send message", con, s->id, fh);
425  return -1;
426 }
427
428 ROAR_DBG("roar_stream_passfh(*): msg send");
429
430 if ( roar_socket_send_fh(confh, fh, NULL, 0) == -1 )
431  return -1;
432
433 ROAR_DBG("roar_stream_passfh(*): fh send");
434
435 if ( roar_recv_message(con, &m, NULL) == -1 )
436  return -1;
437
438 ROAR_DBG("roar_stream_passfh(*): mes recved");
439
440 if ( m.cmd == ROAR_CMD_OK )
441  return 0;
442
443 return -1;
444}
445
446int roar_stream_attach_simple (struct roar_connection * con, struct roar_stream * s, int client) {
447 struct roar_message m;
448 uint16_t * info = (uint16_t *) m.data;
449 int i;
450
451 if ( con == NULL || s == NULL ) {
452  roar_err_set(ROAR_ERROR_FAULT);
453  return -1;
454 }
455
456 if ( client < 0 ) {
457  roar_err_set(ROAR_ERROR_INVAL);
458  return -1;
459 }
460
461 memset(&m,  0, sizeof(m));
462
463 m.cmd     = ROAR_CMD_ATTACH;
464 m.stream  = s->id;
465 m.pos     = 0;
466 m.datalen = 6;
467
468 info[0] = 0;
469 info[1] = ROAR_ATTACH_SIMPLE;
470 info[2] = client;
471
472 for (i = 0; i < m.datalen/2; i++) {
473  info[i] = ROAR_HOST2NET16(info[i]);
474 }
475
476 if ( roar_req(con, &m, NULL) == -1 )
477  return -1;
478
479 if ( m.cmd != ROAR_CMD_OK )
480  return -1;
481
482 return 0;
483}
484
485int roar_stream_get_info (struct roar_connection * con, struct roar_stream * s, struct roar_stream_info * info) {
486 struct roar_message m;
487 uint16_t * data = (uint16_t *) m.data;
488 int i;
489
490 if ( con == NULL || s == NULL || info == NULL ) {
491  roar_err_set(ROAR_ERROR_FAULT);
492  return -1;
493 }
494
495 memset(&m,  0, sizeof(m));
496
497 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
498 m.stream  = s->id;
499 m.datalen = 4;
500 m.pos     = 0;
501
502 data[0] = 0; // Version and reserved
503 data[1] = ROAR_STREAM_PARA_INFO; // stream
504
505 for (i = 0; i < m.datalen/2; i++) {
506  data[i] = ROAR_HOST2NET16(data[i]);
507 }
508
509 if ( roar_req(con, &m, NULL) == -1 )
510  return -1;
511
512 if ( m.cmd != ROAR_CMD_OK )
513  return -1;
514
515 for (i = 0; i < m.datalen/2; i++) {
516  data[i] = ROAR_NET2HOST16(data[i]);
517 }
518
519 if ( m.datalen < 7*2 ) {
520  roar_err_set(ROAR_ERROR_MSGSIZE);
521  return -1;
522 }
523
524 if ( data[0] != 0 || data[1] != 1 ) {
525  roar_err_set(ROAR_ERROR_NSVERSION);
526  return -1;
527 }
528
529 memset(info, 0, sizeof(struct roar_stream_info));
530 info->mixer = -1;
531 info->role  = ROAR_ROLE_UNKNOWN;
532
533 info->block_size     = data[2];
534 info->pre_underruns  = data[3];
535 info->post_underruns = data[4];
536 info->codec          = data[5];
537 info->flags          = data[6];
538 info->delay          = data[7]*1000;
539
540 if ( m.datalen < 9*2 ) {
541  info->state         = ROAR_STREAMSTATE_UNKNOWN;
542  return 0;
543 } else {
544  info->state         = data[8];
545 }
546
547 if ( m.datalen < 10*2 ) {
548  return 0;
549 } else {
550  info->flags        |= ((uint32_t)data[9]) << 16;
551 }
552
553 if ( m.datalen < 11*2 ) {
554  return 0;
555 } else {
556  info->mixer         = data[10];
557 }
558
559 if ( m.datalen < 12*2 ) {
560  return 0;
561 } else {
562  info->role          = data[11];
563 }
564
565 return 0;
566}
567
568int roar_stream_get_name (struct roar_connection * con, struct roar_stream * s, char * name, size_t len) {
569 struct roar_message m;
570 uint16_t * data = (uint16_t *) m.data;
571
572 if ( con == NULL || s == NULL || name == NULL || len == 0 ) {
573  roar_err_set(ROAR_ERROR_FAULT);
574  return -1;
575 }
576
577 name[0] = 0; // just in case...
578
579 memset(&m,  0, sizeof(m));
580
581 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
582 m.stream  = s->id;
583 m.datalen = 4;
584 m.pos     = 0;
585
586 data[0] = 0; // Version and reserved
587 data[1] = ROAR_STREAM_PARA_NAME; // stream
588
589 data[0] = ROAR_HOST2NET16(data[0]);
590 data[1] = ROAR_HOST2NET16(data[1]);
591
592 ROAR_DBG("roar_stream_get_name(*) = ?");
593
594 if ( roar_req(con, &m, NULL) == -1 )
595  return -1;
596
597 ROAR_DBG("roar_stream_get_name(*) = ?");
598
599 if ( m.cmd != ROAR_CMD_OK )
600  return -1;
601
602 ROAR_DBG("roar_stream_get_name(*) = ?");
603
604 if ( m.datalen < 4 ) {
605  roar_err_set(ROAR_ERROR_MSGSIZE);
606  return -1;
607 }
608
609 data[0] = ROAR_NET2HOST16(data[0]);
610 data[1] = ROAR_NET2HOST16(data[1]);
611
612 ROAR_DBG("roar_stream_get_name(*) = ?");
613
614 if ( data[0] != 0 ) {
615  roar_err_set(ROAR_ERROR_NSVERSION);
616  return -1;
617 }
618
619 if ( data[1] != (uint16_t)ROAR_STREAM_PARA_NAME ) {
620  roar_err_set(ROAR_ERROR_TYPEMM);
621  return -1;
622 }
623
624 m.datalen -= 4;
625
626 len--;
627
628 if ( len > m.datalen )
629  len = m.datalen;
630
631 strncpy(name, ((char*)m.data)+4, len);
632 name[len] = 0;
633
634 ROAR_DBG("roar_stream_get_name(*) = 0");
635
636 return 0;
637}
638
639int roar_stream_get_chanmap (struct roar_connection * con, struct roar_stream * s, char * map, size_t * len) {
640 struct roar_message m;
641 uint16_t * data = (uint16_t *) m.data;
642
643 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p, map=%p, len=%p) = ?", con, s, map, len);
644
645 if ( con == NULL || s == NULL || map == NULL || len == NULL ) {
646  roar_err_set(ROAR_ERROR_FAULT);
647  return -1;
648 }
649
650 if ( *len == 0 ) {
651  roar_err_set(ROAR_ERROR_INVAL);
652  return -1;
653 }
654
655 memset(&m, 0, sizeof(m));
656
657 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
658 m.stream  = s->id;
659 m.datalen = 2*2;
660
661 data[0] = 0; // Version and reserved
662 data[1] = ROAR_STREAM_PARA_CHANMAP;
663
664 data[0] = ROAR_HOST2NET16(data[0]);
665 data[1] = ROAR_HOST2NET16(data[1]);
666
667 if ( roar_req(con, &m, NULL) == -1 )
668  return -1;
669
670 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
671
672 if ( m.cmd != ROAR_CMD_OK )
673  return -1;
674
675 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
676
677 if ( m.datalen < 4 ) {
678  roar_err_set(ROAR_ERROR_MSGSIZE);
679  return -1;
680 }
681
682 data[0] = ROAR_NET2HOST16(data[0]);
683 data[1] = ROAR_NET2HOST16(data[1]);
684
685 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
686
687 if ( data[0] != 0 ) {
688  roar_err_set(ROAR_ERROR_NSVERSION);
689  return -1;
690 }
691
692 if ( data[1] != ROAR_STREAM_PARA_CHANMAP ) {
693  roar_err_set(ROAR_ERROR_TYPEMM);
694  return -1;
695 }
696
697 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
698
699 m.datalen -= 4;
700
701 if ( m.datalen > *len ) {
702  roar_err_set(ROAR_ERROR_NOMEM);
703  return -1;
704 }
705
706 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = ?", con, s, s->id, map, len);
707
708 memcpy(map, &(m.data[4]), m.datalen);
709
710 *len = m.datalen;
711
712 ROAR_DBG("roar_stream_get_chanmap(con=%p, s=%p{.id=%i}, map=%p, len=%p) = 0", con, s, s->id, map, len);
713 return 0;
714}
715
716int roar_stream_set_chanmap (struct roar_connection * con, struct roar_stream * s, char * map, size_t   len) {
717 struct roar_message m;
718 uint16_t * data = (uint16_t *) m.data;
719
720 if ( con == NULL || s == NULL || map == NULL ) {
721  roar_err_set(ROAR_ERROR_FAULT);
722  return -1;
723 }
724
725 if ( len == 0 ) {
726  roar_err_set(ROAR_ERROR_INVAL);
727  return 0;
728 }
729
730 memset(&m, 0, sizeof(m));
731
732 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
733 m.stream  = s->id;
734 m.datalen = 2*2 + len;
735
736 if ( m.datalen > sizeof(m.data) )
737  return -1;
738
739 data[0] = 0; // Version and reserved
740 data[1] = ROAR_STREAM_PARA_CHANMAP;
741
742 data[0] = ROAR_HOST2NET16(data[0]);
743 data[1] = ROAR_HOST2NET16(data[1]);
744
745 memcpy(&(m.data[4]), map, len);
746
747 if ( roar_req(con, &m, NULL) == -1 )
748  return -1;
749
750 if ( m.cmd != ROAR_CMD_OK )
751  return -1;
752
753 return 0;
754}
755
756
757int roar_stream_set_flags (struct roar_connection * con, struct roar_stream * s, uint32_t flags, int action) {
758 struct roar_message m;
759 uint16_t * data = (uint16_t *) m.data;
760 int i;
761
762 if ( con == NULL || s == NULL ) {
763  roar_err_set(ROAR_ERROR_FAULT);
764  return -1;
765 }
766
767 memset(&m,  0, sizeof(m));
768
769 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
770 m.stream  = s->id;
771 m.pos     = 0;
772
773 if ( flags & 0xFFFF0000 ) {
774  m.datalen = 2*5;
775 } else {
776  m.datalen = 2*4;
777 }
778
779 data[0] = 0; // Version and reserved
780 data[1] = ROAR_STREAM_PARA_FLAGS; // flags
781 data[2] = action;
782 data[3] = flags & 0x0000FFFF;
783
784 if ( flags & 0xFFFF0000 ) {
785  data[4] = (flags & 0xFFFF0000) >> 16;
786 }
787
788 for (i = 0; i < m.datalen/2; i++) {
789  data[i] = ROAR_HOST2NET16(data[i]);
790 }
791
792 if ( roar_req(con, &m, NULL) == -1 )
793  return -1;
794
795 if ( m.cmd != ROAR_CMD_OK )
796  return -1;
797
798 return 0;
799}
800
801int roar_stream_set_role  (struct roar_connection * con, struct roar_stream * s, int role) {
802 struct roar_message m;
803 uint16_t * data = (uint16_t *) m.data;
804 int i;
805
806 if ( con == NULL || s == NULL ) {
807  roar_err_set(ROAR_ERROR_FAULT);
808  return -1;
809 }
810
811 memset(&m,  0, sizeof(m));
812
813 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
814 m.stream  = s->id;
815 m.datalen = 6;
816 m.pos     = 0;
817
818 data[0] = 0; // Version and reserved
819 data[1] = ROAR_STREAM_PARA_ROLE; // flags
820 data[2] = role;
821
822 for (i = 0; i < m.datalen/2; i++) {
823  data[i] = ROAR_HOST2NET16(data[i]);
824 }
825
826 if ( roar_req(con, &m, NULL) == -1 )
827  return -1;
828
829 if ( m.cmd != ROAR_CMD_OK )
830  return -1;
831
832 return 0;
833}
834
835int roar_stream_get_rpg   (struct roar_connection * con, struct roar_stream * s, struct roar_stream_rpg * rpg) {
836 struct roar_message m;
837 uint16_t * data = (uint16_t *) m.data;
838 size_t i;
839
840 memset(&m,  0, sizeof(m));
841
842 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
843 m.stream  = s->id;
844 m.datalen = 2*2;
845 m.pos     = 0;
846
847 data[0] = 0; // Version and reserved
848 data[1] = ROAR_STREAM_PARA_RPG; // flags
849
850 for (i = 0; i < m.datalen/2; i++) {
851  data[i] = ROAR_HOST2NET16(data[i]);
852 }
853
854 if ( roar_req(con, &m, NULL) == -1 )
855  return -1;
856
857 if ( m.cmd != ROAR_CMD_OK )
858  return -1;
859
860 for (i = 0; i < m.datalen/2; i++) {
861  data[i] = ROAR_NET2HOST16(data[i]);
862 }
863
864 if ( m.datalen != 10 ) {
865  roar_err_set(ROAR_ERROR_MSGSIZE);
866  return -1;
867 }
868
869 if ( data[0] != 0 ) {
870  roar_err_set(ROAR_ERROR_NSVERSION);
871  return -1;
872 }
873
874 if ( data[1] != ROAR_STREAM_PARA_RPG ) {
875  roar_err_set(ROAR_ERROR_BADRQC);
876  return -1;
877 }
878
879 memset(rpg, 0, sizeof(struct roar_stream_rpg));
880
881 rpg->mode = data[2];
882 rpg->mul  = data[3];
883 rpg->div  = data[4];
884
885 if ( rpg->mode == 0xFFFF )
886  rpg->mode = -1;
887
888 return 0;
889}
890
891int roar_stream_set_rpg   (struct roar_connection * con, struct roar_stream * s, const struct roar_stream_rpg * rpg) {
892 struct roar_message m;
893 uint16_t * data = (uint16_t *) m.data;
894 size_t i;
895
896 memset(&m,  0, sizeof(m));
897
898 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
899 m.stream  = s->id;
900 m.datalen = (2+3)*2;
901 m.pos     = 0;
902
903 data[0] = 0; // Version and reserved
904 data[1] = ROAR_STREAM_PARA_RPG; // flags
905 data[2] = rpg->mode;
906 data[3] = rpg->mul;
907 data[4] = rpg->div;
908
909 for (i = 0; i < m.datalen/2; i++) {
910  data[i] = ROAR_HOST2NET16(data[i]);
911 }
912
913 if ( roar_req(con, &m, NULL) == -1 )
914  return -1;
915
916 if ( m.cmd != ROAR_CMD_OK )
917  return -1;
918
919 return 0;
920}
921
922#ifdef DEBUG
923static inline void _roar_debug_audio_info_print (struct roar_audio_info * info) {
924 ROAR_DBG("_roar_debug_audio_info_print(*): Rate    : %i", info->rate);
925 ROAR_DBG("_roar_debug_audio_info_print(*): Channels: %i", info->channels);
926 ROAR_DBG("_roar_debug_audio_info_print(*): Bits    : %i", info->bits);
927 ROAR_DBG("_roar_debug_audio_info_print(*): Codec   : %i", info->codec);
928}
929#endif
930
931#define _ROAR_STREAM_MESSAGE_LEN ((5+1)*4)
932
933int roar_stream_s2m     (struct roar_stream * s, struct roar_message * m) {
934 uint32_t * data;
935 int i;
936
937 if ( s == NULL || m == NULL ) {
938  roar_err_set(ROAR_ERROR_FAULT);
939  return -1;
940 }
941
942 m->datalen = _ROAR_STREAM_MESSAGE_LEN;
943 data = (uint32_t*) m->data;
944
945 data[0] = s->dir;
946 data[1] = s->pos_rel_id;
947 data[2] = s->info.rate;
948 data[3] = s->info.bits;
949 data[4] = s->info.channels;
950 data[5] = s->info.codec;
951
952 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
953  data[i] = ROAR_HOST2NET32(data[i]);
954
955#ifdef DEBUG
956 ROAR_DBG("roar_stream_s2m(*): s->info:");
957 _roar_debug_audio_info_print(&(s->info));
958#endif
959
960 m->pos   = s->pos;
961 m->pos64 = s->pos;
962
963 return 0;
964}
965int roar_stream_m2s     (struct roar_stream * s, struct roar_message * m) {
966 uint32_t * data;
967 int i;
968
969 if ( s == NULL || m == NULL ) {
970  roar_err_set(ROAR_ERROR_FAULT);
971  return -1;
972 }
973
974 if ( m->datalen != _ROAR_STREAM_MESSAGE_LEN ) {
975  roar_err_set(ROAR_ERROR_MSGSIZE);
976  return -1;
977 }
978
979 if ( m->flags & ROAR_MF_LSPOS ) {
980  s->pos = m->pos64;
981 } else {
982  s->pos = m->pos;
983 }
984
985 data = (uint32_t*) m->data;
986
987 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
988  data[i] = ROAR_NET2HOST32(data[i]);
989
990 s->id            = m->stream;
991 s->dir           = data[0];
992 s->pos_rel_id    = data[1];
993 s->info.rate     = data[2];
994 s->info.bits     = data[3];
995 s->info.channels = data[4];
996 s->info.codec    = data[5];
997
998#ifdef DEBUG
999 ROAR_DBG("roar_stream_m2s(*): s->info:");
1000 _roar_debug_audio_info_print(&(s->info));
1001#endif
1002
1003 return 0;
1004}
1005
1006// stream direction funcs:
1007static const struct {
1008 const int    dir;
1009 const char * name;
1010} _libroar_dir[] = {
1011 {ROAR_DIR_PLAY,        "play"       },
1012 {ROAR_DIR_RECORD,      "record"     },
1013 {ROAR_DIR_MONITOR,     "monitor"    },
1014 {ROAR_DIR_FILTER,      "filter"     },
1015 {ROAR_DIR_OUTPUT,      "output"     },
1016 {ROAR_DIR_MIXING,      "mixing"     },
1017 {ROAR_DIR_META,        "meta"       },
1018 {ROAR_DIR_BIDIR,       "bidir"      },
1019 {ROAR_DIR_THRU,        "thru"       },
1020 {ROAR_DIR_BRIDGE,      "bridge"     },
1021 {ROAR_DIR_MIDI_IN,     "midi_in"    },
1022 {ROAR_DIR_MIDI_OUT,    "midi_out"   },
1023 {ROAR_DIR_LIGHT_IN,    "light_in"   },
1024 {ROAR_DIR_LIGHT_OUT,   "light_out"  },
1025 {ROAR_DIR_RAW_IN,      "raw_in"     },
1026 {ROAR_DIR_RAW_OUT,     "raw_out"    },
1027 {ROAR_DIR_COMPLEX_IN,  "complex_in" },
1028 {ROAR_DIR_COMPLEX_OUT, "complex_out"},
1029 {ROAR_DIR_RDTCS_IN,    "rdtcs_in"   },
1030 {ROAR_DIR_RDTCS_OUT,   "rdtcs_out"  },
1031 {ROAR_DIR_RECPLAY,     "recplay"    },
1032 {-1,                   "unknown"    }
1033};
1034
1035const char * roar_dir2str (const int dir) {
1036 int i;
1037
1038 for (i = 0; _libroar_dir[i].dir != -1; i++)
1039  if ( _libroar_dir[i].dir == dir )
1040   return _libroar_dir[i].name;
1041
1042 return _libroar_dir[i].name;
1043}
1044
1045int roar_str2dir (const char * name) {
1046 int i;
1047
1048 for (i = 0; _libroar_dir[i].dir != -1; i++)
1049  if ( !strcmp(_libroar_dir[i].name, name) )
1050   return _libroar_dir[i].dir;
1051
1052 return _libroar_dir[i].dir;
1053}
1054
1055// codec funcs:
1056
1057/*
1058#define roar_codec2str(x) ((x) == ROAR_CODEC_PCM_S_LE  ? "pcm_s_le"  : (x) == ROAR_CODEC_PCM_S_BE  ? "pcm_s_be"  : \
1059                           (x) == ROAR_CODEC_PCM_S_PDP ? "pcm_s_pdp" : (x) == ROAR_CODEC_MIDI_FILE ? "midi_file" : \
1060                           "unknown" )
1061*/
1062
1063static const struct {
1064 const uint32_t codec;
1065 const char   * name;
1066 const char   * mime;
1067} _libroar_codec[] = {
1068 // PCM:
1069 {ROAR_CODEC_PCM_S_LE,    "pcm_s_le",    NULL},
1070 {ROAR_CODEC_PCM_S_BE,    "pcm_s_be",    NULL},
1071 {ROAR_CODEC_PCM_S_PDP,   "pcm_s_pdp",   NULL},
1072 {ROAR_CODEC_PCM_U_LE,    "pcm_u_le",    NULL},
1073 {ROAR_CODEC_PCM_U_BE,    "pcm_u_be",    NULL},
1074 {ROAR_CODEC_PCM_U_PDP,   "pcm_u_pdp",   NULL},
1075 {ROAR_CODEC_DEFAULT,     "default",     NULL}, // alias
1076 {ROAR_CODEC_DEFAULT,     "pcm",         NULL}, // alias
1077 {ROAR_CODEC_DEFAULT,     "raw",         NULL}, // alias
1078 {ROAR_CODEC_PCM_S,       "pcm_s",       NULL}, // alias
1079 {ROAR_CODEC_PCM_U,       "pcm_u",       NULL}, // alias
1080
1081 // MIDI:
1082 {ROAR_CODEC_MIDI_FILE,   "midi_file",   NULL},
1083 {ROAR_CODEC_MIDI,        "midi",        NULL},
1084 {ROAR_CODEC_ROARMIDI,    "roarmidi",    NULL},
1085
1086 // XIPH:
1087 {ROAR_CODEC_OGG_VORBIS,  "ogg_vorbis",  "application/ogg"},
1088 {ROAR_CODEC_OGG_VORBIS,  "vorbis",      "application/ogg"}, // alias
1089 {ROAR_CODEC_FLAC,        "flac",        "audio/x-flac"},
1090 {ROAR_CODEC_OGG_SPEEX,   "ogg_speex",   "audio/ogg; codecs=speex"},
1091 {ROAR_CODEC_OGG_SPEEX,   "speex",       "audio/ogg; codecs=speex"}, // alias
1092 {ROAR_CODEC_OGG_FLAC,    "ogg_flac",    "audio/ogg; codecs=flac"},
1093 {ROAR_CODEC_OGG_GENERAL, "ogg_general", "application/ogg"},
1094 {ROAR_CODEC_OGG_CELT,    "ogg_celt",    "audio/ogg; codecs=celt"},
1095 {ROAR_CODEC_OGG,         "ogg",         "application/ogg"},
1096 {ROAR_CODEC_OGG_OPUS,    "ogg_opus",    NULL},
1097 {ROAR_CODEC_ROAR_OPUS,   "roar_opus",   NULL},
1098 {ROAR_CODEC_ROAR_CELT,   "roar_celt",   NULL},
1099 {ROAR_CODEC_ROAR_SPEEX,  "roar_speex",  NULL},
1100
1101 // RAUM:
1102 {ROAR_CODEC_RAUM,        "raum",        NULL},
1103 {ROAR_CODEC_RAUM_VORBIS, "raum_vorbis", NULL},
1104 {ROAR_CODEC_RAUM_FLAC,   "raum_flac",   NULL},
1105
1106 // RIFF/WAVE like:
1107 {ROAR_CODEC_RIFF_WAVE,   "riff_wave",   "audio/x-wav"},
1108 {ROAR_CODEC_RIFF_WAVE,   "wave",        "audio/x-wav"}, // alias
1109 {ROAR_CODEC_RIFF_WAVE,   "wav",         "audio/x-wav"}, // alias
1110 {ROAR_CODEC_RIFX,        "rifx",        NULL},
1111 {ROAR_CODEC_AU,          "au",          "audio/basic"},
1112 {ROAR_CODEC_AIFF,        "aiff",        "audio/aiff"},
1113
1114 //Log codecs:
1115 {ROAR_CODEC_ALAW,        "alaw",        NULL},
1116 {ROAR_CODEC_AUTLAW_LE,   "autlaw_le",   NULL},
1117 {ROAR_CODEC_AUTLAW_BE,   "autlaw_be",   NULL},
1118 {ROAR_CODEC_AUTLAW,      "autlaw",      NULL}, // alias
1119 {ROAR_CODEC_MULAW,       "mulaw",       NULL},
1120 {ROAR_CODEC_MULAW,       "ulaw",        NULL}, // alias
1121 {ROAR_CODEC_MUUTLAW_LE,  "muutlaw_le",  NULL},
1122 {ROAR_CODEC_MUUTLAW_BE,  "muutlaw_be",  NULL},
1123 {ROAR_CODEC_MUUTLAW,     "muutlaw",     NULL}, // alias
1124
1125 //GSM:
1126 {ROAR_CODEC_GSM,         "gsm",         NULL},
1127 {ROAR_CODEC_GSM49,       "gsm49",       NULL},
1128
1129 //SPC-700 Bit Rate Reduction of
1130 //Super Nintendo Entertainment System (SNES)
1131 {ROAR_CODEC_BRR,         "brr",         NULL},
1132
1133 // Meta Codecs:
1134 {ROAR_CODEC_META_VCLT,     "meta_vclt",     NULL},
1135 {ROAR_CODEC_META_RALT,     "meta_ralt",     NULL},
1136 {ROAR_CODEC_META_RALB,     "meta_ralb",     NULL},
1137 {ROAR_CODEC_META_RALB_LE,  "meta_ralb_le",  NULL},
1138 {ROAR_CODEC_META_RALB_BE,  "meta_ralb_be",  NULL},
1139 {ROAR_CODEC_META_RALB_PDP, "meta_ralb_pdp", NULL},
1140
1141 // light control:
1142 {ROAR_CODEC_DMX512,      "dmx512",      NULL},
1143 {ROAR_CODEC_ROARDMX,     "roardmx",     NULL},
1144
1145 // Radio Data and Transmitter Control System:
1146 {ROAR_CODEC_RDS,         "rds",         NULL},
1147
1148 // User specific:
1149 {ROAR_CODEC_USER0,       "user0",       NULL},
1150 {ROAR_CODEC_USER1,       "user1",       NULL},
1151 {ROAR_CODEC_USER2,       "user2",       NULL},
1152 {ROAR_CODEC_USER3,       "user3",       NULL},
1153 {ROAR_CODEC_USER4,       "user4",       NULL},
1154 {ROAR_CODEC_USER5,       "user5",       NULL},
1155 {ROAR_CODEC_USER6,       "user6",       NULL},
1156 {ROAR_CODEC_USER7,       "user7",       NULL},
1157 {ROAR_CODEC_USER8,       "user8",       NULL},
1158 {ROAR_CODEC_USER9,       "user9",       NULL},
1159 {ROAR_CODEC_USER10,      "user10",      NULL},
1160 {ROAR_CODEC_USER11,      "user11",      NULL},
1161 {ROAR_CODEC_USER12,      "user12",      NULL},
1162 {ROAR_CODEC_USER13,      "user13",      NULL},
1163 {ROAR_CODEC_USER14,      "user14",      NULL},
1164 {ROAR_CODEC_USER15,      "user15",      NULL},
1165 {-1, NULL, NULL}
1166};
1167
1168int32_t roar_str2codec(const char * codec) {
1169 size_t i;
1170 int guess;
1171
1172 if ( codec == NULL || *codec == 0 )
1173  return ROAR_CODEC_DEFAULT;
1174
1175 if ( (guess = atoi(codec)) > 0 )
1176  return guess;
1177
1178 for (i = 0; _libroar_codec[i].codec != (uint32_t)-1; i++)
1179  if ( strcasecmp(_libroar_codec[i].name, codec) == 0 )
1180   return _libroar_codec[i].codec;
1181
1182 roar_err_set(ROAR_ERROR_NOENT);
1183 return -1;
1184}
1185
1186
1187const char * roar_codec2str (const uint32_t codec) {
1188 int i;
1189
1190 for (i = 0; _libroar_codec[i].codec != (uint32_t)-1; i++)
1191  if ( _libroar_codec[i].codec == codec )
1192   return _libroar_codec[i].name;
1193
1194 return "unknown";
1195}
1196
1197int32_t  roar_mime2codec (const char * mime) {
1198 size_t i;
1199
1200 if ( mime == NULL ) {
1201  roar_err_set(ROAR_ERROR_FAULT);
1202  return -1;
1203 }
1204
1205 if ( *mime == 0 ) {
1206  roar_err_set(ROAR_ERROR_INVAL);
1207  return -1;
1208 }
1209
1210 for (i = 0; _libroar_codec[i].codec != (uint32_t)-1; i++)
1211  if ( _libroar_codec[i].mime != NULL )
1212   if ( strcasecmp(_libroar_codec[i].mime, mime) == 0 )
1213    return _libroar_codec[i].codec;
1214
1215 roar_err_set(ROAR_ERROR_NOENT);
1216 return -1;
1217}
1218
1219const char * roar_codec2mime (const uint32_t   codec) {
1220 size_t i;
1221
1222 for (i = 0; _libroar_codec[i].codec != (uint32_t)-1; i++)
1223  if ( _libroar_codec[i].codec == codec )
1224   return _libroar_codec[i].mime;
1225
1226 roar_err_set(ROAR_ERROR_NOENT);
1227 return NULL;
1228}
1229
1230int32_t roar_str2rate(const char * rate) {
1231 struct roar_audio_info info;
1232 int ret;
1233
1234 if ( roar_profile2info(&info, rate) != -1 ) {
1235  return info.rate;
1236 }
1237
1238 ret = atoi(rate);
1239
1240 if ( ret == 0 && rate[0] != '0' ) {
1241  roar_err_set(ROAR_ERROR_NOENT);
1242  return -1;
1243 }
1244
1245 return ret;
1246}
1247
1248int32_t roar_str2bits(const char * bits) {
1249 struct roar_audio_info info;
1250 int ret;
1251
1252 if ( roar_profile2info(&info, bits) != -1 ) {
1253  return info.bits;
1254 }
1255
1256 ret = atoi(bits);
1257
1258 if ( ret == 0 && bits[0] != '0' ) {
1259  roar_err_set(ROAR_ERROR_NOENT);
1260  return -1;
1261 }
1262
1263 return ret;
1264}
1265
1266int32_t roar_str2channels(const char * channels) {
1267 struct roar_audio_info info;
1268 int ret;
1269
1270 if ( !strcasecmp(channels, "mono") ) {
1271  return 1;
1272 } else if ( !strcasecmp(channels, "stereo") ) {
1273  return 2;
1274 }
1275
1276 if ( roar_profile2info(&info, channels) != -1 ) {
1277  return info.channels;
1278 }
1279
1280 ret = atoi(channels);
1281
1282 if ( ret == 0 && channels[0] != '0' ) {
1283  roar_err_set(ROAR_ERROR_NOENT);
1284  return -1;
1285 }
1286
1287 return ret;
1288}
1289
1290
1291const char * roar_streamstate2str(int streamstate) {
1292 switch (streamstate) {
1293  case ROAR_STREAMSTATE_UNUSED:  return "unused";  break;
1294  case ROAR_STREAMSTATE_INITING: return "initing"; break;
1295  case ROAR_STREAMSTATE_NEW:     return "new";     break;
1296  case ROAR_STREAMSTATE_OLD:     return "old";     break;
1297  case ROAR_STREAMSTATE_CLOSING: return "closing"; break;
1298 }
1299
1300 return "unknown";
1301}
1302
1303static const struct {
1304 int    role;
1305 const char * name;
1306} _libroar_role[] = {
1307 {ROAR_ROLE_UNKNOWN,          "unknown"         },
1308 {ROAR_ROLE_NONE,             "none"            },
1309 {ROAR_ROLE_MUSIC,            "music"           },
1310 {ROAR_ROLE_VIDEO,            "video"           },
1311 {ROAR_ROLE_GAME,             "game"            },
1312 {ROAR_ROLE_EVENT,            "event"           },
1313 {ROAR_ROLE_BEEP,             "beep"            },
1314 {ROAR_ROLE_PHONE,            "phone"           },
1315 {ROAR_ROLE_BACKGROUND_MUSIC, "background music"},
1316 {ROAR_ROLE_BACKGROUND_MUSIC, "background_music"}, // alias
1317 {ROAR_ROLE_VOICE,            "voice"           },
1318 {ROAR_ROLE_INSTRUMENT,       "instrument"      },
1319 {ROAR_ROLE_RHYTHM,           "rhythm"          },
1320 {ROAR_ROLE_CLICK,            "click",          },
1321 {ROAR_ROLE_MIXED,            "mixed",          },
1322 {-1, NULL}
1323};
1324
1325int    roar_str2role  (const char * role) {
1326 int i;
1327
1328 roar_err_clear();
1329
1330 for (i = 0; _libroar_role[i].name != NULL; i++)
1331  if ( !strcasecmp(_libroar_role[i].name, role) )
1332   return _libroar_role[i].role;
1333
1334 roar_err_set(ROAR_ERROR_NOENT);
1335 return ROAR_ROLE_UNKNOWN;
1336}
1337
1338const char * roar_role2str  (const int    role) {
1339 int i;
1340
1341 for (i = 0; _libroar_role[i].name != NULL; i++)
1342  if ( _libroar_role[i].role == role )
1343   return _libroar_role[i].name;
1344
1345 return "unknown";
1346}
1347
1348const char * roar_rpgmode2str(const int rpgmode) {
1349 switch (rpgmode) {
1350  case ROAR_RPGMODE_DEFAULT:    return "default"; break;
1351  case ROAR_RPGMODE_NONE:       return "none"; break;
1352  case ROAR_RPGMODE_USER:       return "user"; break;
1353  case ROAR_RPGMODE_ALBUM:      return "album"; break;
1354  case ROAR_RPGMODE_TRACK:      return "track"; break;
1355  case ROAR_RPGMODE_ALBUMTRACK: return "albumtrack"; break;
1356  case ROAR_RPGMODE_TRACKALBUM: return "trackalbum"; break;
1357  default:
1358    roar_err_set(ROAR_ERROR_NOENT);
1359    return NULL;
1360   break;
1361 }
1362}
1363
1364ssize_t roar_info2samplesize (struct roar_audio_info * info) {
1365 if ( info == NULL ) {
1366  roar_err_set(ROAR_ERROR_FAULT);
1367  return -1;
1368 }
1369
1370 switch (info->codec) {
1371  case ROAR_CODEC_PCM_S_LE:
1372  case ROAR_CODEC_PCM_S_BE:
1373  case ROAR_CODEC_PCM_S_PDP:
1374  case ROAR_CODEC_PCM_U_LE:
1375  case ROAR_CODEC_PCM_U_BE:
1376  case ROAR_CODEC_PCM_U_PDP:
1377    return info->bits;
1378   break;
1379  case ROAR_CODEC_ALAW:
1380  case ROAR_CODEC_MULAW:
1381    return 8;
1382   break;
1383  case ROAR_CODEC_DMX512:
1384    return 8;
1385   break;
1386  case ROAR_CODEC_RDS:
1387    return 26;
1388   break;
1389  default:
1390    roar_err_set(ROAR_ERROR_INVAL);
1391    return -1;
1392   break;
1393 }
1394}
1395
1396ssize_t roar_info2framesize  (struct roar_audio_info * info) {
1397 ssize_t ret = roar_info2samplesize(info);
1398
1399 if ( ret == -1 )
1400  return -1;
1401
1402 ret *= info->channels;
1403
1404 return ret;
1405}
1406
1407ssize_t roar_info2bitspersec(struct roar_audio_info * info) {
1408 ssize_t ret = roar_info2samplesize(info);
1409
1410 if ( ret == -1 )
1411  return -1;
1412
1413 ret *= info->channels * info->rate;
1414
1415 return ret;
1416}
1417
1418static const struct {
1419 const char * name;
1420 struct roar_audio_info info;
1421} _libroar_aiprofiles[] = {
1422 {"default",   {.rate     = ROAR_RATE_DEFAULT,
1423                .bits     = ROAR_BITS_DEFAULT,
1424                .channels = ROAR_CHANNELS_DEFAULT,
1425                .codec    = ROAR_CODEC_DEFAULT}},
1426 {"default-server",
1427               {.rate     = ROAR_RATE_DEFAULT,
1428                .bits     = ROAR_ROARD_BITS,
1429                .channels = ROAR_CHANNELS_DEFAULT,
1430                .codec    = ROAR_CODEC_DEFAULT}},
1431 {"wav",       {.rate     = ROAR_RATE_DEFAULT,
1432                .bits     = ROAR_BITS_DEFAULT,
1433                .channels = ROAR_CHANNELS_DEFAULT,
1434                .codec    = ROAR_CODEC_RIFF_WAVE}},
1435 {"au",        {.rate     = ROAR_RATE_DEFAULT,
1436                .bits     = ROAR_BITS_DEFAULT,
1437                .channels = ROAR_CHANNELS_DEFAULT,
1438                .codec    = ROAR_CODEC_AU}},
1439 {"cd",        {.rate =  44100, .bits = 16, .channels =  2, .codec = ROAR_CODEC_DEFAULT}},
1440 {"cdr",       {.rate =  44100, .bits = 16, .channels =  2, .codec = ROAR_CODEC_PCM_S_BE}},
1441 {"dat",       {.rate =  48000, .bits = 16, .channels =  2, .codec = ROAR_CODEC_PCM_S_LE}},
1442 {"isdn-eu",   {.rate =   8000, .bits =  8, .channels =  1, .codec = ROAR_CODEC_ALAW}},
1443 {"isdn-na",   {.rate =   8000, .bits =  8, .channels =  1, .codec = ROAR_CODEC_MULAW}},
1444 {"speex-nb",  {.rate =   8000, .bits = 16, .channels =  2, .codec = ROAR_CODEC_ROAR_SPEEX}},
1445 {"speex-wb",  {.rate =  16000, .bits = 16, .channels =  2, .codec = ROAR_CODEC_ROAR_SPEEX}},
1446 {"speex-uwb", {.rate =  32000, .bits = 16, .channels =  2, .codec = ROAR_CODEC_ROAR_SPEEX}},
1447 {"ogg-vorbis",{.rate =  44100, .bits = 16, .channels =  2, .codec = ROAR_CODEC_OGG_VORBIS}},
1448 {"gsm",       {.rate =   8000, .bits = 16, .channels =  1, .codec = ROAR_CODEC_GSM}},
1449 {"brr",       {.rate =   8000, .bits = 32, .channels =  1, .codec = ROAR_CODEC_BRR}},
1450 {"brr6k",     {.rate =   6000, .bits = 32, .channels =  1, .codec = ROAR_CODEC_BRR}},
1451 {"rds",       {.rate =      0, .bits =  0, .channels =  0, .codec = ROAR_CODEC_RDS}},
1452 {"midi",      {.rate =      0, .bits =  8, .channels = 16, .codec = ROAR_CODEC_MIDI}},
1453 {"dmx512",    {.rate =      0, .bits =  8, .channels =  0, .codec = ROAR_CODEC_DMX512}},
1454 {NULL,        {.rate =      0, .bits =  0, .channels =  0, .codec = 0}}
1455};
1456
1457int     roar_profile2info    (struct roar_audio_info * info, const char * profile) {
1458 int i;
1459
1460 if ( info == NULL || profile == NULL ) {
1461  roar_err_set(ROAR_ERROR_FAULT);
1462  return -1;
1463 }
1464
1465 for (i = 0; _libroar_aiprofiles[i].name != NULL; i++) {
1466  if ( !strcasecmp(_libroar_aiprofiles[i].name, profile) ) {
1467   memcpy(info, &(_libroar_aiprofiles[i].info), sizeof(struct roar_audio_info));
1468   return 0;
1469  }
1470 }
1471
1472 roar_err_set(ROAR_ERROR_NOENT);
1473 return -1;
1474}
1475
1476ssize_t   roar_profiles_list   (const char ** list, size_t len, size_t offset) {
1477 size_t i;
1478 ssize_t idx = 0;
1479
1480 if ( list == NULL ) {
1481  roar_err_set(ROAR_ERROR_FAULT);
1482  return -1;
1483 }
1484
1485 if ( len == 0 )
1486  return 0;
1487
1488 if ( offset >= (sizeof(_libroar_aiprofiles)/sizeof(*_libroar_aiprofiles)) )
1489  return 0;
1490
1491 for (i = offset; idx < len && _libroar_aiprofiles[i].name != NULL; i++) {
1492  list[idx++] = _libroar_aiprofiles[i].name;
1493 }
1494
1495 return idx;
1496}
1497
1498//ll
Note: See TracBrowser for help on using the repository browser.