source: roaraudio/roarclients/roarinterconnect.c @ 3266:40be2c179060

Last change on this file since 3266:40be2c179060 was 3266:40be2c179060, checked in by phi, 14 years ago

support for PulseAudio? Simple protocol

File size: 8.1 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;
122   default:
123     return MT_NONE|ST_NONE; // error case
124    break;
125  }
126 }
127
128 return ret;
129}
130
131int main (int argc, char * argv[]) {
132 struct roar_connection con[1];
133 struct roar_stream     stream[1];
134 int    rate     = 44100;
135 int    bits     = 16;
136 int    channels = 2;
137 int    codec    = ROAR_CODEC_DEFAULT;
138 int    type     = parse_type(NULL);
139 int    tmp;
140 char * server   = NULL;
141 char * remote   = "+slp"; // we hope SLP located server is not local one
142 char * k;
143 int    rfh;
144 int    i;
145 int    localdir = ROAR_DIR_BIDIR;
146 int    rport;
147
148 for (i = 1; i < argc; i++) {
149  k = argv[i];
150
151  if ( strcmp(k, "--server") == 0 ) {
152   server = argv[++i];
153  } else if ( strcmp(k, "--remote") == 0 ) {
154   remote = argv[++i];
155  } else if ( strcmp(k, "--type") == 0 ) {
156   type = parse_type(argv[++i]);
157  } else if ( strcmp(k, "--rate") == 0 ) {
158   rate = atoi(argv[++i]);
159  } else if ( strcmp(k, "--bits") == 0 ) {
160   bits = atoi(argv[++i]);
161  } else if ( strcmp(k, "--channels") == 0 || strcmp(k, "--chans") == 0 ) {
162   channels = atoi(argv[++i]);
163  } else if ( strcmp(k, "--codec") == 0 ) {
164   codec = roar_str2codec(argv[++i]);
165  } else if ( strcmp(k, "--help") == 0 ) {
166   usage();
167   return 0;
168  } else {
169   fprintf(stderr, "Error: unknown argument: %s\n", k);
170   usage();
171   return 1;
172  }
173 }
174
175 switch (type & MT_MASK) {
176  case MT_ROAR:
177    switch (type & ST_MASK) {
178     case ST_BIDIR:
179       tmp      = ROAR_DIR_BIDIR;
180      break;
181     case ST_FILTER:
182       tmp      = ROAR_DIR_FILTER;
183      break;
184     case ST_TRANSMIT:
185       tmp      = ROAR_DIR_PLAY;
186       localdir = ROAR_DIR_MONITOR;
187      break;
188     case ST_RECEIVE:
189       tmp      = ROAR_DIR_MONITOR;
190       localdir = ROAR_DIR_PLAY;
191      break;
192     default:
193       fprintf(stderr, "Error: unknown stream type\n");
194       return 2;
195    }
196    rfh = roar_simple_stream(rate, channels, bits, codec, remote, tmp, "roarinterconnect");
197   break;
198#ifdef ROAR_HAVE_ESD
199  case MT_ESD:
200    tmp = ESD_STREAM|ESD_PLAY;
201
202    switch (bits) {
203     case  8: tmp |= ESD_BITS8;  break;
204     case 16: tmp |= ESD_BITS16; break;
205     default:
206       fprintf(stderr, "Error: EsounD only supports 8 and 16 bit streams\n");
207       return 2;
208    }
209
210    switch (channels) {
211     case 1: tmp |= ESD_MONO;   break;
212     case 2: tmp |= ESD_STEREO; break;
213     default:
214       fprintf(stderr, "Error: EsounD only supports mono and stereo streams\n");
215       return 2;
216    }
217
218    // this is only true if the esd runs on a LE system,...
219    if ( bits == 8 && codec != ROAR_CODEC_PCM_U_LE ) {
220     fprintf(stderr, "Error: EsounD only supports unsigned PCM in 8 bit mode\n");
221     return 2;
222    } else if ( bits == 16 && codec != ROAR_CODEC_DEFAULT ) {
223     fprintf(stderr, "Error: EsounD only supports signed PCM in 16 bit mode\n");
224     return 2;
225    }
226
227    switch (type & ST_MASK) {
228     case ST_FILTER:
229       rfh = esd_filter_stream(tmp, rate, remote, "roarinterconnect");
230      break;
231     case ST_TRANSMIT:
232       rfh = esd_play_stream(tmp, rate, remote, "roarinterconnect");
233      break;
234     case ST_RECEIVE:
235       rfh = esd_monitor_stream(tmp, rate, remote, "roarinterconnect");
236      break;
237     default:
238       fprintf(stderr, "Error: this type is not supported by EsounD\n");
239       return 2;
240      break;
241    }
242   break;
243#endif
244  case MT_SIMPLE:
245    switch (type & ST_MASK) {
246     case ST_TRANSMIT:
247       tmp = SHUT_RD;
248       localdir = ROAR_DIR_MONITOR;
249      break;
250     case ST_RECEIVE:
251       tmp = SHUT_WR;
252       localdir = ROAR_DIR_PLAY;
253      break;
254     default:
255       fprintf(stderr, "Error: this type is not supported by PulseAudio\n");
256       return 2;
257    }
258    // we guess INET here...
259    if ( strstr(remote, "/") == NULL && (k = strstr(remote, ":")) != NULL ) {
260     *k = 0;
261     k++;
262     rport = atoi(k);
263    } else {
264     rport = 4712;
265    }
266    rfh = roar_socket_connect(remote, rport);
267    ROAR_SHUTDOWN(rfh, tmp);
268   break;
269  default:
270    fprintf(stderr, "Error: unknown/not supported server type\n");
271    return 2;
272 }
273
274 if ( rfh == -1 ) {
275  fprintf(stderr, "Error: can not connect to remote server\n");
276  return 10;
277 }
278
279 if ( roar_simple_connect(con, server, "roarinterconnect") == -1 ) {
280  fprintf(stderr, "Can not connect to local server\n");
281  return 20;
282 }
283
284 if ( roar_stream_new(stream, rate, channels, bits, codec) == -1 ) {
285  roar_disconnect(con);
286  return 21;
287 }
288
289 if ( roar_stream_connect(con, stream, localdir) == -1 ) {
290  roar_disconnect(con);
291  return 22;
292 }
293
294 if ( roar_stream_passfh(con, stream, rfh) == -1 ) {
295  roar_disconnect(con);
296  return 23;
297 }
298
299 roar_simple_close(rfh);
300
301 if ( roar_stream_attach_simple(con, stream, 0) == -1 ) {
302  fprintf(stderr, "Can not attach remote stream to local server\n");
303 }
304
305 roar_disconnect(con);
306
307 return 0;
308}
309
310//ll
Note: See TracBrowser for help on using the repository browser.