source: roaraudio/roarclients/roarinterconnect.c @ 3807:ba31470e6d4d

Last change on this file since 3807:ba31470e6d4d was 3807:ba31470e6d4d, checked in by phi, 14 years ago

only build OSS support if we have OSS support

File size: 10.0 KB
Line 
1//roarinterconnect.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009
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// configure ROAR_INFO()
27int g_verbose = 0;
28#define ROAR_DBG_INFOVAR g_verbose
29
30#include <roaraudio.h>
31#include <libroareio/libroareio.h>
32
33#ifdef ROAR_HAVE_ESD
34#include <esd.h>
35#endif
36
37#if defined(ROAR_HAVE_OSS_BSD) || defined(ROAR_HAVE_OSS)
38#define _HAVE_OSS
39#endif
40
41#define MT_NONE     0x00
42#define MT_MASK     0xF0
43#define MT_ROAR     0x10
44#define MT_ESD      0x20
45#define MT_SIMPLE   0x30
46#define MT_OSS      0x40
47#define MT_DEFAULT  MT_ROAR
48
49#define ST_NONE     0x00
50#define ST_MASK     0x0F
51#define ST_BIDIR    0x01
52#define ST_FILTER   0x02
53#define ST_TRANSMIT 0x03
54#define ST_RECEIVE  0x04
55// no default here as the default depend on the server type
56
57void usage (void) {
58 printf("roarinterconnect [OPTIONS]...\n");
59
60 printf("\nOptions:\n\n");
61
62 printf("  --server SERVER    - Set server hostname\n"
63        "  --remote SERVER    - Set remote server\n"
64        "  --type   TYPE      - Set type of remote server\n"
65        "  --rate   RATE      - Set sample rate\n"
66        "  --bits   BITS      - Set bits per sample\n"
67        "  --chans  CHANNELS  - Set number of channels\n"
68        "  --codec  CODEC     - Set the codec\n"
69        "  --help             - Show this help\n"
70        "  --verbose -v       - Be verbose\n"
71       );
72
73 printf("\nPossible Types:\n\n");
74 printf("  roar               - RoarAudio Server\n"
75#ifdef ROAR_HAVE_ESD
76        "  esd                - EsounD Server\n"
77#endif
78        "  simple             - PulseAudio using simple protocol\n"
79#ifdef _HAVE_OSS
80        "  oss                - Open Sound System (OSS) device\n"
81#endif
82        "\n"
83        "  bidir              - Connect bidirectional\n"
84        "  filter             - Use local server as filter for remote server\n"
85        "  transmit           - Transmit data from local server to remote server\n"
86        "  receive            - Receive data from remote server\n"
87       );
88
89}
90
91int parse_type (char * type) {
92 int ret = MT_NONE|ST_NONE;
93 char * colon;
94
95 if ( type != NULL ) {
96  while (type != NULL && *type) {
97   if ( (colon = strstr(type, ":")) != NULL ) {
98    *colon = 0;
99     colon++;
100   }
101
102   if ( !strcmp(type, "roar") ) {
103    ret -= ret & MT_MASK;
104    ret += MT_ROAR;
105   } else if ( !strcmp(type, "esd") ) {
106    ret -= ret & MT_MASK;
107    ret += MT_ESD;
108   } else if ( !strcmp(type, "simple") ) {
109    ret -= ret & MT_MASK;
110    ret += MT_SIMPLE;
111   } else if ( !strcmp(type, "oss") ) {
112    ret -= ret & MT_MASK;
113    ret += MT_OSS;
114   } else if ( !strcmp(type, "bidir") ) {
115    ret -= ret & ST_MASK;
116    ret += ST_BIDIR;
117   } else if ( !strcmp(type, "filter") ) {
118    ret -= ret & ST_MASK;
119    ret += ST_FILTER;
120   } else if ( !strcmp(type, "transmit") ) {
121    ret -= ret & ST_MASK;
122    ret += ST_TRANSMIT;
123   } else if ( !strcmp(type, "receive") ) {
124    ret -= ret & ST_MASK;
125    ret += ST_RECEIVE;
126   } else {
127    return MT_NONE|ST_NONE;
128   }
129
130   type = colon;
131  }
132 }
133
134 if ( (ret & MT_MASK) == MT_NONE )
135  ret |= MT_DEFAULT;
136
137 if ( (ret & ST_MASK) == ST_NONE ) {
138  switch (ret & MT_MASK) {
139   case MT_ROAR:   ret |= ST_BIDIR;    break;
140   case MT_ESD:    ret |= ST_FILTER;   break;
141   case MT_SIMPLE: ret |= ST_TRANSMIT; break; // we use ST_TRANSMIT because ST_BIDIR is
142                                              // very unlike to be configured at the server side.
143   case MT_OSS:    ret |= ST_BIDIR;    break;
144   default:
145     return MT_NONE|ST_NONE; // error case
146    break;
147  }
148 }
149
150 return ret;
151}
152
153int main (int argc, char * argv[]) {
154 struct roar_connection con[1];
155 struct roar_stream     stream[1];
156 struct roar_vio_calls  vio;
157 struct roar_audio_info info;
158 int    rate     = 44100;
159 int    bits     = 16;
160 int    channels = 2;
161 int    codec    = ROAR_CODEC_DEFAULT;
162 int    type     = parse_type(NULL);
163 int    tmp;
164 char * server   = NULL;
165 char * remote   = "+slp"; // we hope SLP located server is not local one
166 char * k;
167 int    rfh;
168 int    i;
169 int    localdir = ROAR_DIR_BIDIR;
170 int    rport;
171
172 for (i = 1; i < argc; i++) {
173  k = argv[i];
174
175  if ( strcmp(k, "--server") == 0 ) {
176   server = argv[++i];
177  } else if ( strcmp(k, "--remote") == 0 ) {
178   remote = argv[++i];
179  } else if ( strcmp(k, "--type") == 0 ) {
180   type = parse_type(argv[++i]);
181  } else if ( strcmp(k, "--rate") == 0 ) {
182   rate = atoi(argv[++i]);
183  } else if ( strcmp(k, "--bits") == 0 ) {
184   bits = atoi(argv[++i]);
185  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 ) {
186   channels = atoi(argv[++i]);
187  } else if ( strcmp(k, "--codec") == 0 ) {
188   codec = roar_str2codec(argv[++i]);
189  } else if ( strcmp(k, "--verbose") == 0 || strcmp(k, "-v") == 0 ) {
190   g_verbose++;
191  } else if ( strcmp(k, "--help") == 0 ) {
192   usage();
193   return 0;
194  } else {
195   fprintf(stderr, "Error: unknown argument: %s\n", k);
196   usage();
197   return 1;
198  }
199 }
200
201 switch (type & MT_MASK) {
202  case MT_ROAR:
203    switch (type & ST_MASK) {
204     case ST_BIDIR:
205       tmp      = ROAR_DIR_BIDIR;
206      break;
207     case ST_FILTER:
208       tmp      = ROAR_DIR_FILTER;
209      break;
210     case ST_TRANSMIT:
211       tmp      = ROAR_DIR_PLAY;
212       localdir = ROAR_DIR_MONITOR;
213      break;
214     case ST_RECEIVE:
215       tmp      = ROAR_DIR_MONITOR;
216       localdir = ROAR_DIR_PLAY;
217      break;
218     default:
219       fprintf(stderr, "Error: unknown stream type\n");
220       return 2;
221    }
222    rfh = roar_simple_stream(rate, channels, bits, codec, remote, tmp, "roarinterconnect");
223   break;
224#ifdef _HAVE_OSS
225  case MT_OSS:
226    switch (type & ST_MASK) {
227     case ST_BIDIR:
228       tmp      = ROAR_DIR_BIDIR;
229      break;
230     case ST_TRANSMIT:
231       tmp      = ROAR_DIR_PLAY;
232       localdir = ROAR_DIR_MONITOR;
233      break;
234     case ST_RECEIVE:
235       tmp      = ROAR_DIR_RECORD;
236       localdir = ROAR_DIR_PLAY;
237      break;
238     default:
239       fprintf(stderr, "Error: unknown stream type\n");
240       return 2;
241    }
242    info.rate     = rate;
243    info.channels = channels;
244    info.bits     = bits;
245    info.codec    = codec;
246    if ( roar_cdriver_oss(&vio, "OSS", remote, &info, tmp) == -1 ) {
247     fprintf(stderr, "Error: can not open OSS device %s\n", remote);
248     return 2;
249    }
250    if ( roar_vio_ctl(&vio, ROAR_VIO_CTL_GET_FH, &rfh) == -1 ) {
251     roar_vio_close(&vio);
252     fprintf(stderr, "Error: can not get filehandle for OSS device %s\n", remote);
253     return 2;
254    }
255   break;
256#endif
257#ifdef ROAR_HAVE_ESD
258  case MT_ESD:
259    tmp = ESD_STREAM|ESD_PLAY;
260
261    switch (bits) {
262     case  8: tmp |= ESD_BITS8;  break;
263     case 16: tmp |= ESD_BITS16; break;
264     default:
265       fprintf(stderr, "Error: EsounD only supports 8 and 16 bit streams\n");
266       return 2;
267    }
268
269    switch (channels) {
270     case 1: tmp |= ESD_MONO;   break;
271     case 2: tmp |= ESD_STEREO; break;
272     default:
273       fprintf(stderr, "Error: EsounD only supports mono and stereo streams\n");
274       return 2;
275    }
276
277    // this is only true if the esd runs on a LE system,...
278    if ( bits == 8 && codec != ROAR_CODEC_PCM_U_LE ) {
279     fprintf(stderr, "Error: EsounD only supports unsigned PCM in 8 bit mode\n");
280     return 2;
281    } else if ( bits == 16 && codec != ROAR_CODEC_DEFAULT ) {
282     fprintf(stderr, "Error: EsounD only supports signed PCM in 16 bit mode\n");
283     return 2;
284    }
285
286    switch (type & ST_MASK) {
287     case ST_FILTER:
288       rfh = esd_filter_stream(tmp, rate, remote, "roarinterconnect");
289      break;
290     case ST_TRANSMIT:
291       rfh = esd_play_stream(tmp, rate, remote, "roarinterconnect");
292      break;
293     case ST_RECEIVE:
294       rfh = esd_monitor_stream(tmp, rate, remote, "roarinterconnect");
295      break;
296     default:
297       fprintf(stderr, "Error: this type is not supported by EsounD\n");
298       return 2;
299      break;
300    }
301   break;
302#endif
303  case MT_SIMPLE:
304    switch (type & ST_MASK) {
305     case ST_BIDIR:
306       tmp = -1;
307       localdir = ROAR_DIR_BIDIR;
308      break;
309     case ST_TRANSMIT:
310       tmp = SHUT_RD;
311       localdir = ROAR_DIR_MONITOR;
312      break;
313     case ST_RECEIVE:
314       tmp = SHUT_WR;
315       localdir = ROAR_DIR_PLAY;
316      break;
317     default:
318       fprintf(stderr, "Error: this type is not supported by PulseAudio\n");
319       return 2;
320    }
321    // we guess INET here...
322    if ( strstr(remote, "/") == NULL && (k = strstr(remote, ":")) != NULL ) {
323     *k = 0;
324     k++;
325     rport = atoi(k);
326    } else {
327     rport = 4712;
328    }
329    rfh = roar_socket_connect(remote, rport);
330    if ( tmp != -1 ) {
331     ROAR_SHUTDOWN(rfh, tmp);
332    }
333   break;
334  default:
335    fprintf(stderr, "Error: unknown/not supported server type\n");
336    return 2;
337 }
338
339 if ( rfh == -1 ) {
340  fprintf(stderr, "Error: can not connect to remote server\n");
341  return 10;
342 }
343
344 if ( roar_simple_connect(con, server, "roarinterconnect") == -1 ) {
345  fprintf(stderr, "Can not connect to local server\n");
346  return 20;
347 }
348
349 if ( roar_stream_new(stream, rate, channels, bits, codec) == -1 ) {
350  roar_disconnect(con);
351  return 21;
352 }
353
354 if ( roar_stream_connect(con, stream, localdir) == -1 ) {
355  roar_disconnect(con);
356  return 22;
357 }
358
359 if ( roar_stream_passfh(con, stream, rfh) == -1 ) {
360  roar_disconnect(con);
361  return 23;
362 }
363
364 roar_simple_close(rfh);
365
366 if ( roar_stream_attach_simple(con, stream, 0) == -1 ) {
367  fprintf(stderr, "Can not attach remote stream to local server\n");
368 }
369
370 roar_disconnect(con);
371
372 ROAR_INFO("Stream ID: %i", 1, stream->id);
373
374 return 0;
375}
376
377//ll
Note: See TracBrowser for help on using the repository browser.