source: roaraudio/roarclients/roarinterconnect.c @ 3811:49db840fb4f4

Last change on this file since 3811:49db840fb4f4 was 3811:49db840fb4f4, checked in by phi, 14 years ago

fixed some copyright statements

File size: 10.0 KB
Line 
1//roarinterconnect.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2009-2010
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#ifdef _HAVE_OSS
157 struct roar_vio_calls  vio;
158 struct roar_audio_info info;
159#endif
160 int    rate     = 44100;
161 int    bits     = 16;
162 int    channels = 2;
163 int    codec    = ROAR_CODEC_DEFAULT;
164 int    type     = parse_type(NULL);
165 int    tmp;
166 char * server   = NULL;
167 char * remote   = "+slp"; // we hope SLP located server is not local one
168 char * k;
169 int    rfh;
170 int    i;
171 int    localdir = ROAR_DIR_BIDIR;
172 int    rport;
173
174 for (i = 1; i < argc; i++) {
175  k = argv[i];
176
177  if ( strcmp(k, "--server") == 0 ) {
178   server = argv[++i];
179  } else if ( strcmp(k, "--remote") == 0 ) {
180   remote = argv[++i];
181  } else if ( strcmp(k, "--type") == 0 ) {
182   type = parse_type(argv[++i]);
183  } else if ( strcmp(k, "--rate") == 0 ) {
184   rate = atoi(argv[++i]);
185  } else if ( strcmp(k, "--bits") == 0 ) {
186   bits = atoi(argv[++i]);
187  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 ) {
188   channels = atoi(argv[++i]);
189  } else if ( strcmp(k, "--codec") == 0 ) {
190   codec = roar_str2codec(argv[++i]);
191  } else if ( strcmp(k, "--verbose") == 0 || strcmp(k, "-v") == 0 ) {
192   g_verbose++;
193  } else if ( strcmp(k, "--help") == 0 ) {
194   usage();
195   return 0;
196  } else {
197   fprintf(stderr, "Error: unknown argument: %s\n", k);
198   usage();
199   return 1;
200  }
201 }
202
203 switch (type & MT_MASK) {
204  case MT_ROAR:
205    switch (type & ST_MASK) {
206     case ST_BIDIR:
207       tmp      = ROAR_DIR_BIDIR;
208      break;
209     case ST_FILTER:
210       tmp      = ROAR_DIR_FILTER;
211      break;
212     case ST_TRANSMIT:
213       tmp      = ROAR_DIR_PLAY;
214       localdir = ROAR_DIR_MONITOR;
215      break;
216     case ST_RECEIVE:
217       tmp      = ROAR_DIR_MONITOR;
218       localdir = ROAR_DIR_PLAY;
219      break;
220     default:
221       fprintf(stderr, "Error: unknown stream type\n");
222       return 2;
223    }
224    rfh = roar_simple_stream(rate, channels, bits, codec, remote, tmp, "roarinterconnect");
225   break;
226#ifdef _HAVE_OSS
227  case MT_OSS:
228    switch (type & ST_MASK) {
229     case ST_BIDIR:
230       tmp      = ROAR_DIR_BIDIR;
231      break;
232     case ST_TRANSMIT:
233       tmp      = ROAR_DIR_PLAY;
234       localdir = ROAR_DIR_MONITOR;
235      break;
236     case ST_RECEIVE:
237       tmp      = ROAR_DIR_RECORD;
238       localdir = ROAR_DIR_PLAY;
239      break;
240     default:
241       fprintf(stderr, "Error: unknown stream type\n");
242       return 2;
243    }
244    info.rate     = rate;
245    info.channels = channels;
246    info.bits     = bits;
247    info.codec    = codec;
248    if ( roar_cdriver_oss(&vio, "OSS", remote, &info, tmp) == -1 ) {
249     fprintf(stderr, "Error: can not open OSS device %s\n", remote);
250     return 2;
251    }
252    if ( roar_vio_ctl(&vio, ROAR_VIO_CTL_GET_FH, &rfh) == -1 ) {
253     roar_vio_close(&vio);
254     fprintf(stderr, "Error: can not get filehandle for OSS device %s\n", remote);
255     return 2;
256    }
257   break;
258#endif
259#ifdef ROAR_HAVE_ESD
260  case MT_ESD:
261    tmp = ESD_STREAM|ESD_PLAY;
262
263    switch (bits) {
264     case  8: tmp |= ESD_BITS8;  break;
265     case 16: tmp |= ESD_BITS16; break;
266     default:
267       fprintf(stderr, "Error: EsounD only supports 8 and 16 bit streams\n");
268       return 2;
269    }
270
271    switch (channels) {
272     case 1: tmp |= ESD_MONO;   break;
273     case 2: tmp |= ESD_STEREO; break;
274     default:
275       fprintf(stderr, "Error: EsounD only supports mono and stereo streams\n");
276       return 2;
277    }
278
279    // this is only true if the esd runs on a LE system,...
280    if ( bits == 8 && codec != ROAR_CODEC_PCM_U_LE ) {
281     fprintf(stderr, "Error: EsounD only supports unsigned PCM in 8 bit mode\n");
282     return 2;
283    } else if ( bits == 16 && codec != ROAR_CODEC_DEFAULT ) {
284     fprintf(stderr, "Error: EsounD only supports signed PCM in 16 bit mode\n");
285     return 2;
286    }
287
288    switch (type & ST_MASK) {
289     case ST_FILTER:
290       rfh = esd_filter_stream(tmp, rate, remote, "roarinterconnect");
291      break;
292     case ST_TRANSMIT:
293       rfh = esd_play_stream(tmp, rate, remote, "roarinterconnect");
294      break;
295     case ST_RECEIVE:
296       rfh = esd_monitor_stream(tmp, rate, remote, "roarinterconnect");
297      break;
298     default:
299       fprintf(stderr, "Error: this type is not supported by EsounD\n");
300       return 2;
301      break;
302    }
303   break;
304#endif
305  case MT_SIMPLE:
306    switch (type & ST_MASK) {
307     case ST_BIDIR:
308       tmp = -1;
309       localdir = ROAR_DIR_BIDIR;
310      break;
311     case ST_TRANSMIT:
312       tmp = SHUT_RD;
313       localdir = ROAR_DIR_MONITOR;
314      break;
315     case ST_RECEIVE:
316       tmp = SHUT_WR;
317       localdir = ROAR_DIR_PLAY;
318      break;
319     default:
320       fprintf(stderr, "Error: this type is not supported by PulseAudio\n");
321       return 2;
322    }
323    // we guess INET here...
324    if ( strstr(remote, "/") == NULL && (k = strstr(remote, ":")) != NULL ) {
325     *k = 0;
326     k++;
327     rport = atoi(k);
328    } else {
329     rport = 4712;
330    }
331    rfh = roar_socket_connect(remote, rport);
332    if ( tmp != -1 ) {
333     ROAR_SHUTDOWN(rfh, tmp);
334    }
335   break;
336  default:
337    fprintf(stderr, "Error: unknown/not supported server type\n");
338    return 2;
339 }
340
341 if ( rfh == -1 ) {
342  fprintf(stderr, "Error: can not connect to remote server\n");
343  return 10;
344 }
345
346 if ( roar_simple_connect(con, server, "roarinterconnect") == -1 ) {
347  fprintf(stderr, "Can not connect to local server\n");
348  return 20;
349 }
350
351 if ( roar_stream_new(stream, rate, channels, bits, codec) == -1 ) {
352  roar_disconnect(con);
353  return 21;
354 }
355
356 if ( roar_stream_connect(con, stream, localdir) == -1 ) {
357  roar_disconnect(con);
358  return 22;
359 }
360
361 if ( roar_stream_passfh(con, stream, rfh) == -1 ) {
362  roar_disconnect(con);
363  return 23;
364 }
365
366 roar_simple_close(rfh);
367
368 if ( roar_stream_attach_simple(con, stream, 0) == -1 ) {
369  fprintf(stderr, "Can not attach remote stream to local server\n");
370 }
371
372 roar_disconnect(con);
373
374 ROAR_INFO("Stream ID: %i", 1, stream->id);
375
376 return 0;
377}
378
379//ll
Note: See TracBrowser for help on using the repository browser.