source: roaraudio/roarclients/roarctl.c @ 577:4c82e13a6b3e

Last change on this file since 577:4c82e13a6b3e was 577:4c82e13a6b3e, checked in by phi, 16 years ago

added command terminate

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