source: roaraudio/roarclients/roarctl.c @ 669:90348e6a785f

Last change on this file since 669:90348e6a785f was 669:90348e6a785f, checked in by phi, 16 years ago

added license statements

File size: 13.7 KB
Line 
1//roarctl.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
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#include <pwd.h>
27#include <grp.h>
28
29
30int display_mixer (struct roar_connection * con, int stream);
31int show_meta_all (struct roar_connection * con, int id);
32
33void usage (void) {
34 printf("roarctl [OPTIONS]... COMMAND [OPTS] [COMMAND [OPTS] [COMMAND [OPTS] [...]]]\n");
35
36 printf("\nOptions:\n\n");
37
38 printf("  --server SERVER         - Set server hostname\n"
39        "  --help                  - Show this help\n"
40       );
41
42 printf("\nCommands:\n\n");
43 printf(
44        "  help                    - Show this help\n"
45        "\n"
46        "  standby, off            - Go into standby mode\n"
47        "  resume, on              - Go into active mode\n"
48        "  standbymode             - Show current standby mode\n"
49        "  exit                    - Quits the roard (must be used as last command)\n"
50        "  terminate               - Like exit but let the server up to serve still connected clients,\n"
51        "                            new clients cann't connect and the server terminates after the last\n"
52        "                            client disconnected\n"
53        "\n"
54        "  volume ID CHAN V0 V1... - Sets volume for stream ID\n"
55        "                            CHAN is the number of channels or 'mono' or 'stereo'\n"
56        "                            if mono or stereo is chosen roarctl trys to set\n"
57        "                            sensfull values for all channels even if the output\n"
58        "                            is has more channels.\n"
59        "                            all other args are the volumes of the channels\n"
60        "                            you may use integer or percent values.\n"
61        "                            percent values can flooding points.\n"
62        "\n"
63        "  kick TYPE ID            - Kicks object of TYPE with id ID\n"
64        "                            Types: client stream sample source\n"
65        "\n"
66        "  serveroinfo             - Gets Informations about server output\n"
67        "  listclients             - Gets Informations about clients\n"
68        "  liststreams             - Gets Informations about streams\n"
69        "  allinfo                 - Get all infos\n"
70       );
71}
72
73void server_oinfo (struct roar_connection * con) {
74 struct roar_stream s;
75
76 if ( roar_server_oinfo(con, &s) == -1 ) {
77  fprintf(stderr, "Error: can not get server output info\n");
78  return;
79 }
80
81 printf("Stream direction      : %s\n", roar_dir2str(s.dir));
82 printf("Server Output rate    : %i\n", s.info.rate);
83 printf("Server Output bits    : %i\n", s.info.bits);
84 printf("Server Output channels: %i\n", s.info.channels);
85 printf("Server Output codec   : %i (%s%s)\n", s.info.codec, roar_codec2str(s.info.codec),
86                                     s.info.codec == ROAR_CODEC_DEFAULT ? " native" : "");
87// printf("Server Output rate: %i", s.info.rate);
88}
89
90const char * proc_name (pid_t pid) {
91 static char ret[80] = "?";
92#ifdef __linux__
93 char file[80], buf[80], *r;
94 int  i;
95
96 snprintf(file, 79, "/proc/%i/exe", pid);
97 file[79] = 0;
98
99 ret[0] = '?';
100 ret[1] = 0;
101
102 if ( (i = readlink(file, buf, 79)) != -1 ) {
103  buf[i] = 0;
104  if ( (r = strrchr(buf, '/')) != NULL ) {
105   r++;
106   if ( *r != 0 )
107    strcpy(ret, r);
108  }
109 }
110#endif
111
112 return ret;
113}
114
115void list_clients (struct roar_connection * con) {
116 int i;
117 int num;
118 int h;
119 int id[ROAR_CLIENTS_MAX];
120 struct roar_client c;
121 struct group  * grp = NULL;
122 struct passwd * pwd = NULL;
123
124 if ( (num = roar_list_clients(con, id, ROAR_CLIENTS_MAX)) == -1 ) {
125  fprintf(stderr, "Error: can not get client list\n");
126  return;
127 }
128
129 for (i = 0; i < num; i++) {
130  printf("client %i:\n", id[i]);
131  if ( roar_get_client(con, &c, id[i]) == -1 ) {
132   fprintf(stderr, "Error: can not get client info\n");
133   continue;
134  }
135  printf("Player name           : %s\n", c.name);
136  printf("Player PID            : %i(%s)\n", c.pid, proc_name(c.pid));
137  if ( c.uid != -1 ) {
138   pwd = getpwuid(c.uid);
139   grp = getgrgid(c.gid);
140   printf("Player UID/GID        : %i(%s)/%i(%s)\n", c.uid, pwd ? pwd->pw_name : "?", c.gid, grp ? grp->gr_name : "?");
141  }
142  if ( c.execed != -1 )
143   printf("Execed stream         : %i\n", c.execed);
144
145  for (h = 0; h < ROAR_CLIENTS_MAX_STREAMS_PER_CLIENT; h++)
146   if ( c.streams[h] != -1 )
147    printf("stream                : %i\n", c.streams[h]);
148 }
149
150}
151
152void list_streams (struct roar_connection * con) {
153 int i;
154 int num;
155 int id[ROAR_STREAMS_MAX];
156 struct roar_stream s;
157 struct roar_stream_info info;
158
159
160 if ( (num = roar_list_streams(con, id, ROAR_STREAMS_MAX)) == -1 ) {
161  fprintf(stderr, "Error: can not get stream list\n");
162  return;
163 }
164
165 for (i = 0; i < num; i++) {
166  printf("stream %i:\n", id[i]);
167  if ( roar_get_stream(con, &s, id[i]) == -1 ) {
168   fprintf(stderr, "Error: can not get stream info\n");
169   continue;
170  }
171  printf("Stream direction      : %s\n", roar_dir2str(s.dir));
172  if ( s.pos_rel_id == -1 )
173   printf("Relativ position id   : none (stream not synchronized)\n");
174  else
175   printf("Relativ position id   : %i\n", s.pos_rel_id);
176  printf("Input rate            : %i\n", s.info.rate);
177  printf("Input bits            : %i\n", s.info.bits);
178  printf("Input channels        : %i\n", s.info.channels);
179  printf("Input codec           : %2i (%s%s)\n", s.info.codec, roar_codec2str(s.info.codec),
180                                       s.info.codec == ROAR_CODEC_DEFAULT ? " native" : "");
181  if ( roar_stream_get_info(con, &s, &info) != -1 ) {
182   printf("Input codec (streamed): %2i (%s%s)\n", info.codec, roar_codec2str(info.codec),
183                                      info.codec == ROAR_CODEC_DEFAULT ? " native" : "");
184   printf("Input block size      : %i Byte\n", info.block_size);
185   printf("Underruns pre/post    : %i/%i\n",   info.pre_underruns, info.post_underruns);
186  }
187  display_mixer(con, id[i]);
188  show_meta_all(con, id[i]);
189 }
190
191}
192
193int display_mixer (struct roar_connection * con, int stream) {
194 int channels;
195 struct roar_mixer_settings mixer;
196 int i;
197
198 if ( roar_get_vol(con, stream, &mixer, &channels) == -1 ) {
199  fprintf(stderr, "Error: can not get stream mixer info\n");
200  return -1;
201 }
202
203 for (i = 0; i < channels; i++)
204  printf("Mixer volume chan %2i  : %i (%.2f%%)\n", i, mixer.mixer[i], (float)mixer.mixer[i]/655.35);
205
206 return 0;
207}
208
209int set_mixer (struct roar_connection * con, int * cur, int max, char * arg[]) {
210 int chans = 0;
211 int id;
212 int i;
213 int len;
214 int old_chans;
215 int vol_l, vol_r;
216 char * k;
217 struct roar_mixer_settings mixer;
218 struct roar_mixer_settings old_mixer;
219
220 if (*cur + 2 > max)
221  return -1;
222
223 id = atoi(arg[++(*cur)]);
224
225 k = arg[++(*cur)];
226
227 if ( roar_get_vol(con, id, &old_mixer, &old_chans) == -1 ) {
228  fprintf(stderr, "Error: can not get stream mixer info\n");
229  return -1;
230 }
231
232
233 if ( strcmp(k, "mono") == 0 && old_chans != 1 ) {
234  chans = 1;
235
236  if ( *cur + 1 > max )
237   return -1;
238
239  k   = arg[++(*cur)];
240  len = strlen(k);
241
242  if ( k[len - 1] == '%' ) {
243   k[len - 1] = 0;
244   vol_l = (atof(k)*65535)/100;
245  } else {
246   vol_l = atoi(k);
247  }
248
249  for (i = 0; i < old_chans; i++)
250   mixer.mixer[i] = vol_l;
251
252  chans = old_chans;
253
254 } else if ( strcmp(k, "stereo") == 0 && old_chans != 2 ) {
255  chans = 2;
256//  printf("mode: stereo; chans=%i, old_chans=%i\n", chans, old_chans);
257  ROAR_ERR("mode stereo not supported");
258  return -1;
259 } else {
260  if ( strcmp(k, "mono") == 0 ) {
261   chans = 1;
262  } else if ( strcmp(k, "stereo") == 0 ) {
263   chans = 2;
264  } else {
265   chans = atoi(k);
266  }
267
268//  printf("mode: int; chans=%i, old_chans=%i\n", chans, old_chans);
269
270  if ( *cur + chans > max )
271   return -1;
272
273  for (i = 0; i < chans; i++) {
274   k   = arg[++(*cur)];
275   len = strlen(k);
276
277   if ( k[len - 1] == '%' ) {
278    k[len - 1] = 0;
279    mixer.mixer[i] = (atof(k)*(int)65535)/100;
280   } else {
281    mixer.mixer[i] = atoi(k);
282   }
283  }
284 }
285
286 mixer.scale = 65535;
287
288 return roar_set_vol(con, id, &mixer, chans);
289}
290
291int set_meta (struct roar_connection * con, int id, char * mode, char * type, char * val) {
292 struct roar_meta   meta;
293 struct roar_stream s;
294 int mode_i = ROAR_META_MODE_SET;
295
296 s.id = id;
297
298// printf("set_meta(*): mode='%s', type='%s', val='%s'\n", mode, type, val);
299
300 if ( strcmp(mode, "add") == 0 ) {
301  mode_i = ROAR_META_MODE_ADD;
302 }
303
304 meta.type   = roar_meta_inttype(type);
305 meta.value  = val;
306 meta.key[0] = 0;
307
308 if ( meta.type == -1 ) {
309  fprintf(stderr, "Error: unknown type: %s\n", type);
310  return -1;
311 }
312
313// printf("D: type=%i, mode=%i\n", meta.type, mode_i);
314
315 return roar_stream_meta_set(con, &s, mode_i, &meta);
316}
317
318int show_meta_type (struct roar_connection * con, int id, char * type) {
319 struct roar_meta   meta;
320 struct roar_stream s;
321
322 s.id = id;
323
324 meta.type  = roar_meta_inttype(type);
325
326 if ( meta.type == -1 ) {
327  fprintf(stderr, "Error: unknown type: %s\n", type);
328  return -1;
329 }
330
331 if ( roar_stream_meta_get(con, &s, &meta) == -1 )
332  return -1;
333
334 printf("Meta %-17s: %s\n", roar_meta_strtype(meta.type), meta.value);
335
336 roar_meta_free(&meta);
337
338 return 0;
339}
340
341int show_meta_all (struct roar_connection * con, int id) {
342 struct roar_stream s;
343 int types[ROAR_META_MAX_PER_STREAM];
344 int i;
345 int len;
346
347 s.id = id;
348
349 if ( (len = roar_stream_meta_list(con, &s, types, ROAR_META_MAX_PER_STREAM)) == -1 )
350  return -1;
351
352 for (i = 0; i < len; i++)
353  show_meta_type(con, id, roar_meta_strtype(types[i]));
354
355 return 0;
356}
357
358int main (int argc, char * argv[]) {
359 struct roar_connection con;
360 char * server   = NULL;
361 char * k = NULL;
362 int    i;
363 int    t = 0;
364
365 for (i = 1; i < argc; i++) {
366  k = argv[i];
367
368  if ( strcmp(k, "--server") == 0 ) {
369   server = argv[++i];
370  } else if ( strcmp(k, "--help") == 0 ) {
371   usage();
372   return 0;
373  } else if ( *k == '-' ) {
374   fprintf(stderr, "Error: unknown argument: %s\n", k);
375   usage();
376   return 1;
377  } else {
378   break;
379  }
380 }
381
382 // connect
383
384 if ( roar_connect(&con, server) == -1 ) {
385  fprintf(stderr, "Error: Can not connect to server\n");
386  return 1;
387 }
388
389 if ( roar_identify(&con, "roarctl") == -1 ) {
390  fprintf(stderr, "Error: Can not identify to server\n");
391  return 1;
392 }
393
394 if ( i == argc ) {
395  fprintf(stderr, "Error: No Commands given\n");
396  return 0; // this is not a fatal error...
397 }
398
399 for (; i < argc; i++) {
400  k = argv[i];
401  // cmd is in k
402
403  printf("--- [ %s ] ---\n", k);
404
405  if ( !strcmp(k, "help") ) {
406   usage();
407
408
409  } else if ( !strcmp(k, "standby") || !strcmp(k, "off") ) {
410   if ( roar_set_standby(&con, ROAR_STANDBY_ACTIVE) == -1 ) {
411    fprintf(stderr, "Error: can not set mode to standby\n");
412   } else {
413    printf("going into standby\n");
414   }
415  } else if ( !strcmp(k, "resume") || !strcmp(k, "on") ) {
416   if ( roar_set_standby(&con, ROAR_STANDBY_INACTIVE) == -1 ) {
417    fprintf(stderr, "Error: can not set mode to active\n");
418   } else {
419    printf("going into active mode\n");
420   }
421
422  } else if ( !strcmp(k, "exit") ) {
423   if ( roar_exit(&con) == -1 ) {
424    fprintf(stderr, "Error: can not quit server\n");
425   } else {
426    printf("Server quited\n");
427    break;
428   }
429  } else if ( !strcmp(k, "terminate") ) {
430   if ( roar_terminate(&con, 1) == -1 ) {
431    fprintf(stderr, "Error: can not terminate server\n");
432   } else {
433    printf("Server got asked to quited\n");
434    break;
435   }
436
437  } else if ( !strcmp(k, "standbymode") ) {
438   t = roar_get_standby(&con);
439   if ( t == -1 ) {
440    fprintf(stderr, "Error: can not get stanby mode\n");
441   } else if ( t == ROAR_STANDBY_ACTIVE ) {
442    printf("Server is in standby\n");
443   } else if ( t == ROAR_STANDBY_INACTIVE ) {
444    printf("Server is active\n");
445   } else {
446    fprintf(stderr, "Error: unknown standby mode: %i\n", t);
447   }
448
449  } else if ( !strcmp(k, "serveroinfo") ) {
450   server_oinfo(&con);
451  } else if ( !strcmp(k, "listclients") ) {
452   list_clients(&con);
453  } else if ( !strcmp(k, "liststreams") ) {
454   list_streams(&con);
455  } else if ( !strcmp(k, "allinfo") ) {
456   server_oinfo(&con);
457   printf("\n");
458   list_clients(&con);
459   printf("\n");
460   list_streams(&con);
461
462  } else if ( !strcmp(k, "kick") ) {
463   k = argv[++i];
464   if ( !strcmp(k, "client") ) {
465    t = ROAR_OT_CLIENT;
466   } else if ( !strcmp(k, "stream") ) {
467    t = ROAR_OT_STREAM;
468   } else if ( !strcmp(k, "sample") ) {
469    t = ROAR_OT_SAMPLE;
470   } else if ( !strcmp(k, "source") ) {
471    t = ROAR_OT_SOURCE;
472   } else {
473    fprintf(stderr, "Error: unknown type: %s\n", k);
474    continue;
475   }
476   //t = atoi(argv[i++]);
477   if ( roar_kick(&con, t, atoi(argv[++i])) == -1 ) {
478    fprintf(stderr, "Error: can not kick %s\n", k);
479   } else {
480    printf("%s kicked\n", k);
481   }
482
483  } else if ( !strcmp(k, "volume") ) {
484   if ( set_mixer(&con, &i, argc, argv) == -1 ) {
485    fprintf(stderr, "Error: can not set volume\n");
486   } else {
487    printf("volume changed\n");
488   }
489
490  } else if ( !strcmp(k, "metaset") ) {
491   i++;
492   if ( set_meta(&con, atoi(argv[i]), argv[i+1], argv[i+2], argv[i+3]) == -1 ) {
493    fprintf(stderr, "Error: can not set meta data\n");
494   } else {
495    printf("meta data changed\n");
496   }
497   i += 3;
498  } else if ( !strcmp(k, "metaget") ) {
499   i++;
500   if ( show_meta_type(&con, atoi(argv[i]), argv[i+1]) == -1 ) {
501    fprintf(stderr, "Error: can not get meta data\n");
502   }
503   i++;
504
505  } else {
506   fprintf(stderr, "Error: invalid command: %s\n", k);
507  }
508
509 }
510
511 roar_disconnect(&con);
512
513 return 0;
514}
515
516//ll
Note: See TracBrowser for help on using the repository browser.