source: roaraudio/roarclients/roarinterconnect.c @ 3271:36616a17a9d0

Last change on this file since 3271:36616a17a9d0 was 3271:36616a17a9d0, checked in by phi, 14 years ago

support bidir with PA simple

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