source: roaraudio/roarclients/roarinterconnect.c @ 5238:5117fb0e7ed4

Last change on this file since 5238:5117fb0e7ed4 was 5238:5117fb0e7ed4, checked in by phi, 12 years ago

Removed roar_stream_connect(), roar_stream_add_data(), roar_stream_send_data() and roar_stream_set_flags().

File size: 13.8 KB
Line 
1//roarinterconnect.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2011
5 *
6 *  This file is part of roarclients 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 *  RoarAudio 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 */
25
26/* ckport options:
27 * ckport: ignore-symbol: roar_cdriver_oss of target libroareio0 -- For OSS streams
28 */
29
30// configure ROAR_INFO()
31int g_verbose = 0;
32#define ROAR_DBG_INFOVAR g_verbose
33
34#include <roaraudio.h>
35#include <libroareio/libroareio.h>
36
37#ifdef ROAR_HAVE_ESD
38#include <esd.h>
39#endif
40
41#ifdef ROAR_HAVE_LIBRSOUND
42#include <rsound.h>
43#ifdef RSD_EXEC
44#define _HAVE_RSOUND
45#endif
46#endif
47
48#if defined(ROAR_HAVE_OSS_BSD) || defined(ROAR_HAVE_OSS)
49#define _HAVE_OSS
50#endif
51
52#define CLIENT_NAME "roarinterconnect"
53
54#define MT_NONE     0x00
55#define MT_MASK     0xF0
56#define MT_ROAR     0x10
57#define MT_ESD      0x20
58#define MT_SIMPLE   0x30
59#define MT_OSS      0x40
60#define MT_RSOUND   0x50
61#define MT_DEFAULT  MT_ROAR
62
63#define ST_NONE     0x00
64#define ST_MASK     0x0F
65#define ST_BIDIR    0x01
66#define ST_FILTER   0x02
67#define ST_TRANSMIT 0x03
68#define ST_RECEIVE  0x04
69// no default here as the default depend on the server type
70
71void usage (void) {
72 printf("roarinterconnect [OPTIONS]...\n");
73
74 printf("\nOptions:\n\n");
75
76 printf("  --server SERVER    - Set server hostname\n"
77        "  --remote SERVER    - Set remote server\n"
78        "  --type   TYPE      - Set type of remote server\n"
79        "  --rate   RATE      - Set sample rate\n"
80        "  --bits   BITS      - Set bits per sample\n"
81        "  --chans  CHANNELS  - Set number of channels\n"
82        "  --codec  CODEC     - Set the codec\n"
83        "  --help             - Show this help\n"
84        "  --verbose -v       - Be verbose\n"
85       );
86
87 printf("\nPossible Types:\n\n");
88 printf("  roar               - RoarAudio Server\n"
89#ifdef ROAR_HAVE_ESD
90        "  esd                - EsounD Server\n"
91#endif
92        "  simple             - PulseAudio using simple protocol\n"
93#ifdef _HAVE_OSS
94        "  oss                - Open Sound System (OSS) device\n"
95#endif
96#ifdef _HAVE_RSOUND
97        "  rsound             - RSound server\n"
98#endif
99        "\n"
100        "  bidir              - Connect bidirectional\n"
101        "  filter             - Use local server as filter for remote server\n"
102        "  transmit           - Transmit data from local server to remote server\n"
103        "  receive            - Receive data from remote server\n"
104       );
105
106}
107
108int parse_type (char * type) {
109 int ret = MT_NONE|ST_NONE;
110 char * colon;
111
112 if ( type != NULL ) {
113  while (type != NULL && *type) {
114   if ( (colon = strstr(type, ":")) != NULL ) {
115    *colon = 0;
116     colon++;
117   }
118
119   if ( !strcmp(type, "roar") ) {
120    ret -= ret & MT_MASK;
121    ret += MT_ROAR;
122   } else if ( !strcmp(type, "esd") ) {
123    ret -= ret & MT_MASK;
124    ret += MT_ESD;
125   } else if ( !strcmp(type, "simple") ) {
126    ret -= ret & MT_MASK;
127    ret += MT_SIMPLE;
128   } else if ( !strcmp(type, "oss") ) {
129    ret -= ret & MT_MASK;
130    ret += MT_OSS;
131   } else if ( !strcmp(type, "rsound") ) {
132    ret -= ret & MT_MASK;
133    ret += MT_RSOUND;
134   } else if ( !strcmp(type, "bidir") ) {
135    ret -= ret & ST_MASK;
136    ret += ST_BIDIR;
137   } else if ( !strcmp(type, "filter") ) {
138    ret -= ret & ST_MASK;
139    ret += ST_FILTER;
140   } else if ( !strcmp(type, "transmit") ) {
141    ret -= ret & ST_MASK;
142    ret += ST_TRANSMIT;
143   } else if ( !strcmp(type, "receive") ) {
144    ret -= ret & ST_MASK;
145    ret += ST_RECEIVE;
146   } else {
147    return MT_NONE|ST_NONE;
148   }
149
150   type = colon;
151  }
152 }
153
154 if ( (ret & MT_MASK) == MT_NONE )
155  ret |= MT_DEFAULT;
156
157 if ( (ret & ST_MASK) == ST_NONE ) {
158  switch (ret & MT_MASK) {
159   case MT_ROAR:   ret |= ST_BIDIR;    break;
160   case MT_ESD:    ret |= ST_FILTER;   break;
161   case MT_SIMPLE: ret |= ST_TRANSMIT; break; // we use ST_TRANSMIT because ST_BIDIR is
162                                              // very unlike to be configured at the server side.
163   case MT_OSS:    ret |= ST_BIDIR;    break;
164   case MT_RSOUND: ret |= ST_TRANSMIT; break; // RSound does only handle playback streams.
165   default:
166     return MT_NONE|ST_NONE; // error case
167    break;
168  }
169 }
170
171 return ret;
172}
173
174#ifdef _HAVE_RSOUND
175// RSound format helper function:
176enum rsd_format para2rsdfmt (int bits, int codec) {
177 switch (codec) {
178  case ROAR_CODEC_PCM_S_LE:
179    switch (bits) {
180#ifdef RSD_S8
181     case  8: return RSD_S8;     break;
182#endif
183#ifdef RSD_S16_LE
184     case 16: return RSD_S16_LE; break;
185#endif
186#ifdef RSD_S32_LE
187     case 32: return RSD_S32_LE; break;
188#endif
189    }
190   break;
191  case ROAR_CODEC_PCM_S_BE:
192    switch (bits) {
193#ifdef RSD_S8
194     case  8: return RSD_S8;     break;
195#endif
196#ifdef RSD_S16_BE
197     case 16: return RSD_S16_BE; break;
198#endif
199#ifdef RSD_S32_BE
200     case 32: return RSD_S32_BE; break;
201#endif
202    }
203   break;
204  case ROAR_CODEC_PCM_U_LE:
205    switch (bits) {
206#ifdef RSD_U8
207     case  8: return RSD_U8;     break;
208#endif
209#ifdef RSD_U16_LE
210     case 16: return RSD_U16_LE; break;
211#endif
212#ifdef RSD_U32_LE
213     case 32: return RSD_U32_LE; break;
214#endif
215    }
216   break;
217  case ROAR_CODEC_PCM_U_BE:
218    switch (bits) {
219#ifdef RSD_U8
220     case  8: return RSD_U8;     break;
221#endif
222#ifdef RSD_U16_BE
223     case 16: return RSD_U16_BE; break;
224#endif
225#ifdef RSD_U32_BE
226     case 32: return RSD_U32_BE; break;
227#endif
228    }
229   break;
230#ifdef RSD_ALAW
231  case ROAR_CODEC_ALAW:
232    return RSD_ALAW;
233   break;
234#endif
235#ifdef RSD_MULAW
236  case ROAR_CODEC_MULAW:
237    return RSD_MULAW;
238   break;
239#endif
240 }
241 return 0;
242}
243#endif
244
245int main (int argc, char * argv[]) {
246 struct roar_connection con[1];
247 struct roar_stream     stream[1];
248 struct roar_vio_calls  vio;
249#ifdef _HAVE_OSS
250 struct roar_audio_info info;
251#endif
252#ifdef _HAVE_RSOUND
253 rsound_t *rd;
254 enum rsd_format fmt = 0;
255#endif
256 int    rate     = 44100;
257 int    bits     = 16;
258 int    channels = 2;
259 int    codec    = ROAR_CODEC_DEFAULT;
260 int    type     = parse_type(NULL);
261 int    tmp;
262 char * server   = NULL;
263 char * remote   = "+slp"; // we hope SLP located server is not local one
264 char * k;
265 int    rfh;
266 int    i;
267 int    localdir = ROAR_DIR_BIDIR;
268 int    rport;
269
270 for (i = 1; i < argc; i++) {
271  k = argv[i];
272
273  if ( strcmp(k, "--server") == 0 ) {
274   server = argv[++i];
275  } else if ( strcmp(k, "--remote") == 0 ) {
276   remote = argv[++i];
277  } else if ( strcmp(k, "--type") == 0 ) {
278   type = parse_type(argv[++i]);
279  } else if ( strcmp(k, "--rate") == 0 ) {
280   rate = roar_str2rate(argv[++i]);
281  } else if ( strcmp(k, "--bits") == 0 ) {
282   bits = roar_str2bits(argv[++i]);
283  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 ) {
284   channels = roar_str2channels(argv[++i]);
285  } else if ( strcmp(k, "--codec") == 0 ) {
286   codec = roar_str2codec(argv[++i]);
287  } else if ( strcmp(k, "--verbose") == 0 || strcmp(k, "-v") == 0 ) {
288   g_verbose++;
289  } else if ( strcmp(k, "--help") == 0 ) {
290   usage();
291   return 0;
292  } else {
293   fprintf(stderr, "Error: unknown argument: %s\n", k);
294   usage();
295   return 1;
296  }
297 }
298
299 if ( server != NULL && !strcmp(server, "+invalid") ) {
300  return 0;
301 }
302
303 switch (type & MT_MASK) {
304  case MT_ROAR:
305    switch (type & ST_MASK) {
306     case ST_BIDIR:
307       tmp      = ROAR_DIR_BIDIR;
308      break;
309     case ST_FILTER:
310       tmp      = ROAR_DIR_FILTER;
311      break;
312     case ST_TRANSMIT:
313       tmp      = ROAR_DIR_PLAY;
314       localdir = ROAR_DIR_MONITOR;
315      break;
316     case ST_RECEIVE:
317       tmp      = ROAR_DIR_MONITOR;
318       localdir = ROAR_DIR_PLAY;
319      break;
320     default:
321       fprintf(stderr, "Error: unknown stream type\n");
322       return 2;
323    }
324    if ( roar_vio_simple_stream(&vio, rate, channels, bits, codec, remote, tmp, CLIENT_NAME) == -1 ) {
325     fprintf(stderr, "Error: can not open RoarAudio stream to %s: %s\n", remote, roar_error2str(roar_error));
326     return 2;
327    }
328    if ( roar_vio_ctl(&vio, ROAR_VIO_CTL_GET_FH, &rfh) == -1 ) {
329     fprintf(stderr, "Error: can not get filehandle for RoarAudio stream: %s\n", roar_error2str(roar_error));
330     roar_vio_close(&vio);
331     return 2;
332    }
333   break;
334#ifdef _HAVE_OSS
335  case MT_OSS:
336    switch (type & ST_MASK) {
337     case ST_BIDIR:
338       tmp      = ROAR_DIR_BIDIR;
339      break;
340     case ST_TRANSMIT:
341       tmp      = ROAR_DIR_PLAY;
342       localdir = ROAR_DIR_MONITOR;
343      break;
344     case ST_RECEIVE:
345       tmp      = ROAR_DIR_RECORD;
346       localdir = ROAR_DIR_PLAY;
347      break;
348     default:
349       fprintf(stderr, "Error: unknown stream type\n");
350       return 2;
351    }
352    info.rate     = rate;
353    info.channels = channels;
354    info.bits     = bits;
355    info.codec    = codec;
356    if ( roar_cdriver_oss(&vio, "OSS", remote, &info, tmp) == -1 ) {
357     fprintf(stderr, "Error: can not open OSS device %s: %s\n", remote, roar_error2str(roar_error));
358     return 2;
359    }
360    if ( roar_vio_ctl(&vio, ROAR_VIO_CTL_GET_FH, &rfh) == -1 ) {
361     fprintf(stderr, "Error: can not get filehandle for OSS device %s: %s\n", remote, roar_error2str(roar_error));
362     roar_vio_close(&vio);
363     return 2;
364    }
365   break;
366#endif
367#ifdef ROAR_HAVE_ESD
368  case MT_ESD:
369    tmp = ESD_STREAM|ESD_PLAY;
370
371    switch (bits) {
372     case  8: tmp |= ESD_BITS8;  break;
373     case 16: tmp |= ESD_BITS16; break;
374     default:
375       fprintf(stderr, "Error: EsounD only supports 8 and 16 bit streams\n");
376       return 2;
377    }
378
379    switch (channels) {
380     case 1: tmp |= ESD_MONO;   break;
381     case 2: tmp |= ESD_STEREO; break;
382     default:
383       fprintf(stderr, "Error: EsounD only supports mono and stereo streams\n");
384       return 2;
385    }
386
387    // TODO: FIXME: this is only true if the esd runs on a LE system,...
388    if ( bits == 8 && codec != ROAR_CODEC_PCM_U_LE ) {
389     fprintf(stderr, "Error: EsounD only supports unsigned PCM in 8 bit mode\n");
390     return 2;
391    } else if ( bits == 16 && codec != ROAR_CODEC_DEFAULT ) {
392     fprintf(stderr, "Error: EsounD only supports signed PCM in 16 bit mode\n");
393     return 2;
394    }
395
396    switch (type & ST_MASK) {
397     case ST_FILTER:
398       rfh = esd_filter_stream(tmp, rate, remote, CLIENT_NAME);
399      break;
400     case ST_TRANSMIT:
401       rfh = esd_play_stream(tmp, rate, remote, CLIENT_NAME);
402      break;
403     case ST_RECEIVE:
404       rfh = esd_monitor_stream(tmp, rate, remote, CLIENT_NAME);
405      break;
406     default:
407       fprintf(stderr, "Error: this type is not supported by EsounD\n");
408       return 2;
409      break;
410    }
411   break;
412#endif
413#ifdef _HAVE_RSOUND
414  case MT_RSOUND:
415    fmt = para2rsdfmt(bits, codec);
416
417    if ( fmt == 0 ) {
418     fprintf(stderr, "Error: Bits/Codec not supported by RSound\n");
419     return 2;
420    }
421
422    switch (type & ST_MASK) {
423     case ST_TRANSMIT:
424       localdir = ROAR_DIR_MONITOR;
425
426       rsd_init(&rd);
427       rsd_set_param(rd, RSD_HOST,       remote);
428       rsd_set_param(rd, RSD_CHANNELS,   &channels);
429       rsd_set_param(rd, RSD_SAMPLERATE, &rate);
430       rsd_set_param(rd, RSD_FORMAT,     &fmt);
431#ifdef RSD_IDENTITY
432       rsd_set_param(rd, RSD_IDENTITY,   CLIENT_NAME);
433#endif
434       rfh = rsd_exec(rd);
435       if ( rfh == -1 ) {
436        rsd_stop(rd);
437        rsd_free(rd);
438       }
439      break;
440     default:
441       fprintf(stderr, "Error: this type is not supported by RSound\n");
442       return 2;
443      break;
444    }
445   break;
446#endif
447  case MT_SIMPLE:
448    switch (type & ST_MASK) {
449     case ST_BIDIR:
450       tmp = -1;
451       localdir = ROAR_DIR_BIDIR;
452      break;
453     case ST_TRANSMIT:
454       tmp = SHUT_RD;
455       localdir = ROAR_DIR_MONITOR;
456      break;
457     case ST_RECEIVE:
458       tmp = SHUT_WR;
459       localdir = ROAR_DIR_PLAY;
460      break;
461     default:
462       fprintf(stderr, "Error: this type is not supported by PulseAudio\n");
463       return 2;
464    }
465    // we guess INET here...
466    if ( strstr(remote, "/") == NULL && (k = strstr(remote, ":")) != NULL ) {
467     *k = 0;
468     k++;
469     rport = atoi(k);
470    } else {
471     rport = ROAR_DEFAULT_PA_PORT;
472    }
473
474    if ( roar_vio_open_socket(&vio, remote, rport) == -1 ) {
475     fprintf(stderr, "Error: can not open socket for Simple stream: %s\n", roar_error2str(roar_error));
476     return 2;
477    }
478
479    roar_vio_shutdown(&vio, tmp);
480
481    if ( roar_vio_ctl(&vio, ROAR_VIO_CTL_GET_FH, &rfh) == -1 ) {
482     fprintf(stderr, "Error: can not get filehandle for Simple stream: %s\n", roar_error2str(roar_error));
483     roar_vio_close(&vio);
484     return 2;
485    }
486   break;
487  default:
488    fprintf(stderr, "Error: unknown/not supported server type\n");
489    return 2;
490 }
491
492 if ( rfh == -1 ) {
493  fprintf(stderr, "Error: can not connect to remote server\n");
494  return 10;
495 }
496
497 if ( roar_simple_connect(con, server, CLIENT_NAME) == -1 ) {
498  fprintf(stderr, "Can not connect to local server\n");
499  return 20;
500 }
501
502 if ( roar_stream_new(stream, rate, channels, bits, codec) == -1 ) {
503  roar_disconnect(con);
504  return 21;
505 }
506
507 if ( roar_stream_connect(con, stream, localdir, -1) == -1 ) {
508  roar_disconnect(con);
509  return 22;
510 }
511
512 if ( roar_stream_passfh(con, stream, rfh) == -1 ) {
513  roar_disconnect(con);
514  return 23;
515 }
516
517 switch (type & MT_MASK) {
518  case MT_ESD:
519    close(rfh);
520   break;
521  case MT_RSOUND:
522    roar_vio_open_fh_socket(&vio, rfh);
523  case MT_ROAR:
524  case MT_OSS:
525  case MT_SIMPLE:
526    roar_vio_close(&vio);
527   break;
528  default:
529    close(rfh);
530 }
531
532 if ( roar_stream_attach_simple(con, stream, 0) == -1 ) {
533  fprintf(stderr, "Can not attach remote stream to local server\n");
534 }
535
536 roar_disconnect(con);
537
538 ROAR_INFO("Stream ID: %i", 1, stream->id);
539
540 return 0;
541}
542
543//ll
Note: See TracBrowser for help on using the repository browser.