source: roaraudio/roard/roard.c @ 3374:18a9494d6784

Last change on this file since 3374:18a9494d6784 was 3374:18a9494d6784, checked in by phi, 14 years ago

support --{x11-,}display

File size: 49.7 KB
RevLine 
[0]1//roard.c:
2
[668]3/*
[3358]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
[668]5 *
6 *  This file is part of roard 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
[0]25#include "roard.h"
26
[1494]27#ifdef ROAR_SUPPORT_LISTEN
[2530]28char * server[ROAR_MAX_LISTEN_SOCKETS];
[1494]29#endif
[60]30
[2104]31#if defined(ROAR_HAVE_IO_POSIX) && defined(ROAR_HAVE_FS_POSIX)
32#define SUPPORT_PIDFILE
33char * pidfile = NULL;
34#endif
35
[2530]36#if defined(ROAR_HAVE_SETGID) || defined(ROAR_HAVE_SETUID)
[3374]37int    setids    = 0;
38#endif
39
40#ifdef ROAR_HAVE_LIBX11
41char * x11display = NULL;
[2530]42#endif
43
[1503]44#ifdef ROAR_HAVE_MAIN_ARGS
[0]45void usage (void) {
46 printf("Usage: roard [OPTIONS]...\n\n");
47
[68]48 printf("Misc Options:\n\n");
49 printf(
[775]50        " --daemon              - Bring the server into background after init\n"
[2970]51        " --verbose             - Be more verbose, can be used multiple times\n"
[71]52        " --terminate           - Terminate after last client quited\n"
[2109]53        " --start               - No op parameter (starting roard is default operation)\n"
[274]54        " --restart             - Trys to stop an old instance and start a new with new settings\n"
[2109]55        " --stop                - Stops a running roard (provide --pidfile!)\n"
56        " --shutdown            - Terminates a running roard (provide --pidfile!)\n"
[276]57        " --realtime            - Trys to get realtime priority,\n"
58        "                         give multible times for being more realtime\n"
[444]59        " --chroot DIR          - chroots to the given dir\n"
60        " --setgid              - GroupID to the audio group as specified via -G\n"
61        " --setuid              - UserID to the audio user as specified via -U\n"
[905]62        " --sysclocksync        - calculate exact sample rate using the system clock\n"
[2017]63        " --location  LOC       - Set lion readable location of server\n"
[2104]64#ifdef SUPPORT_PIDFILE
65        " --pidfile PIDFILE     - Write a pidfile at PIDFILE\n"
66#endif
[68]67       );
68
[3356]69 printf("\nPlugin Options:\n\n");
70 printf(
71        " --plugin-load FILE    - Load plugin FILE\n"
72       );
73
[68]74 printf("\nAudio Options:\n\n");
[0]75 printf(
76        " -R  --rate   RATE     - Set server rate\n"
77        " -B  --bits   BITS     - Set server bits\n"
78        " -C  --chans  CHANNELS - Set server channels\n"
79       );
80
[2339]81 printf("\nStream Options:\n\n");
82 printf(
83        " --stream-flags D=F    - Set default flags for stream directions\n"
84        "                         D is the stream direction and F is a comma seperated\n"
85        "                         list of flags in form +flag or -flag to set or unset\n"
86        "                         a flag as default or remove it from the default\n"
87       );
88
[1923]89 printf("\nDriver Options: (obsolete, do not use, Use Ouput Options)\n\n");
[974]90 printf(" -d  --driver DRV      - Set the driver (default: %s)\n", ROAR_DRIVER_DEFAULT);
[0]91 printf(" -D  --device DEV      - Set the device\n");
92 printf(" -dO OPTS              - Set output options\n");
[973]93 printf(" --list-driver         - List all drivers\n");
[0]94
[932]95 printf("\nOutput Options:\n\n");
[974]96 printf(" -o  --odriver DRV     - Set the driver, use '--list-driver' to get a list\n");
[932]97 printf(" -O  --odevice DEV     - Set the device\n");
98 printf(" -oO OPTS              - Set output options\n");
99 printf(" -oN                   - Adds another output\n");
[961]100 printf(" -oP                   - Mark output as primary\n");
[932]101
[2485]102#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[0]103 printf("\nSource Options:\n\n");
104 printf(" -s  --source DRV      - Use DRV as input driver\n"
105        " -S           DEV      - Use DEV as input device\n"
106        " -sO          OPTS     - Use OPTS as input options\n"
[1512]107        " -sN                   - Adds another source\n"
[0]108        " -sP                   - Make souce as primary\n"
109       );
[2270]110 printf(" --list-sources        - List all sources\n");
[2485]111#endif
[0]112
[280]113 printf("\nCodec Filter Options:\n\n");
114 printf(" --list-cf             - List all codec filter\n"
115       );
[0]116
[2500]117#ifndef ROAR_WITHOUT_DCOMP_MIDI
[1923]118 printf("\nMIDI Options:\n\n");
[1924]119 printf(" --midi-no-console     - Disable console based MIDI synth\n"
[2444]120        " --midi-console-enable - Enables the console based MIDI synth\n"
[1924]121        " --midi-console DEV    - Set device for MIDI console\n"
[2489]122#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
[2451]123        " --ssynth-enable       - Enable simple software synth\n"
124        " --ssynth-disable      - Disable simple software synth\n"
[2489]125#endif
[1924]126       );
[2500]127#endif
[1923]128
[2494]129#ifndef ROAR_WITHOUT_DCOMP_LIGHT
[1923]130 printf("\nLight Control Options:\n\n");
131 printf(" --light-channels NUM  - Sets the number of channels for Light control (default: %i)\n",
132                                  LIGHT_CHANNELS_DEFAULT
133       );
[2494]134#endif
[1923]135
[2725]136#ifndef ROAR_WITHOUT_DCOMP_RDTCS
[3339]137 printf("\nRadio Data and Transmitter Control System Options:\n\n");
[2725]138 printf(" --rds-pi   PI         - Sets the RDS Programme Identification (PI)\n"
139        " --rds-ps   PS         - Sets the RDS Programme Service Name (PS)\n"
140        " --rds-pty  PTY        - Sets the RDS Programme Type (PTY)\n"
141        " --rds-tp              - Sets the RDS Traffic Programme (TP) flag\n"
142        " --rds-ct              - Enables sending of RDS Clock Time (CT)\n"
143       );
144#endif
145
[3374]146#ifdef ROAR_HAVE_LIBX11
147 printf("\nX11 Options:\n\n");
148 printf(
149        " --x11-display DISPLAY - Set display for X11\n"
150        " --display DISPLAY     - Set display for X11\n"
151       );
152#endif
153
[0]154 printf("\nServer Options:\n\n");
155 printf(" -t  --tcp             - Use TCP listen socket\n"
156        " -u  --unix            - Use UNIX Domain listen socket (default)\n"
[508]157#ifdef ROAR_HAVE_LIBDNET
158        " -n  --decnet          - use DECnet listen socket\n"
159#endif
[518]160        " -4                    - Use IPv4 connections (implies -t)\n"
161#ifdef PF_INET6
162        " -6                    - Use IPv6 connections (implies -t)\n"
163#endif
164#ifdef IPV6_ADDRFORM
165        " -64                   - Try to downgrade sockets from IPv6 into IPv4,\n"
166        "                         this is normaly not usefull.\n"
167#endif
[0]168        " -p  --port            - TCP Port to bind to\n"
169        " -b  --bind            - IP/Hostname to bind to\n"
[1115]170        "     --sock            - Filename for UNIX Domain Socket\n"
[2530]171        "     --proto PROTO     - Use PROTO as protocol on Socket\n"
[3252]172        "     --proto-dir DIR   - Set direction parameter for protocol\n"
173        "     --proto-rate RATE - Set sample rate parameter for protocol\n"
174        "     --proto-bits BITS - Set bits per sample parameter for protocol\n"
175        "     --proto-codec E   - Set codec parameter for protocol\n"
176        "     --proto-chans C   - Set number of channels paramter for protocol\n"
[3127]177        "     --list-proto      - List supported protocols\n"
[2530]178        "     --new-sock        - Parameters for new socket follows\n"
[1993]179#ifdef ROAR_HAVE_LIBSLP
180        "     --slp             - Enable OpenSLP support\n"
181#endif
[3373]182#ifdef ROAR_HAVE_LIBX11
183        "     --x11             - Enable X11 support\n"
184#endif
[3039]185        " --jumbo-mtu MTU       - Sets the MTU for Jumbo Packets\n"
[450]186        " -G  GROUP             - Sets the group for the UNIX Domain Socket, (default: %s)\n"
[2737]187        "                         You need the permissions to change the GID\n"
[444]188        " -U  USER              - Sets the user for the UNIX Domain Socket, (default: do not set)\n"
[2737]189        "                         You need the permissions to change the UID (normaly only root has)\n"
[548]190        " --no-listen           - Do not listen for new clients\n"
191        "                         (only usefull for relaing, impleys --terminate)\n"
[274]192        " --client-fh           - Comunicate with a client over this handle\n"
[501]193        "                         (only usefull for relaing)\n"
[920]194        " --close-fh            - Closes the given fh\n"
195        " --standby             - Start in standby state\n"
196        " --auto-standby        - Automatical goes into standby if there are no streams\n",
[2755]197#ifdef ROAR_DEFAULT_SOCKGRP
[450]198        ROAR_DEFAULT_SOCKGRP
[2755]199#else
200        "(none)"
201#endif
[0]202       );
203// printf("\n Options:\n\n");
204 printf("\n");
205}
[3127]206
207static void list_proto (void) {
208 printf("  Protocol Flag Subsys - Description\n");
209 printf("------------------------------------------------------\n");
210 printf("  roar          WM LRX - RoarAudio native protocol\n");
211#if !defined(ROAR_WITHOUT_DCOMP_EMUL_ESD) && defined(ROAR_HAVE_H_ESD)
212 printf("  esd           W      - EsounD emulation\n");
213#endif
[3257]214 printf("  simple        WM LRX - PulseAudio simple protocol\n");
[3127]215}
216
[1503]217#endif
[0]218
[2109]219int restart_server (char * server, int terminate) {
[579]220 struct roar_connection con;
[2111]221#ifdef ROAR_HAVE_KILL
222 char buf[80];
223 ssize_t l;
224 struct roar_vio_calls fh;
225 pid_t pid;
226 int ok;
227
228 if ( pidfile != NULL ) {
229  if ( roar_vio_open_file(&fh, pidfile, O_RDONLY, 0644) == -1 ) {
230   ROAR_WARN("restart_server(*): Can not read pidfile: %s", pidfile);
231  } else {
232   l = roar_vio_read(&fh, buf, 80);
233   roar_vio_close(&fh);
234   if ( l > 0 ) {
235    buf[l-1] = 0;
236    buf[79]  = 0;
237    pid = atoi(buf);
238    if ( terminate ) {
[2113]239     ok = kill(pid, SIGUSR1);
[2111]240    } else {
241     ok = kill(pid, SIGINT);
242    }
243    if ( ok == 0 ) {
244     return 0;
245    } else {
246     ROAR_WARN("restart_server(*): Can not kill roard by pidfile");
247    }
248   } else {
249    ROAR_WARN("restart_server(*): Can not find a PID in the pidfile");
250   }
251  }
252 }
253#endif
[2109]254
[579]255 if ( roar_connect(&con, server) == -1 ) {
256  return -1;
257 }
258
[2109]259 if ( roar_terminate(&con, terminate) == -1 ) {
[579]260  return -1;
261 }
262
263 return roar_disconnect(&con);
264}
265
[444]266#define R_SETUID 1
267#define R_SETGID 2
268
[1609]269int init_config (void) {
270 int i;
271
272 memset(g_config, 0, sizeof(struct roard_config));
273
274 for (i = 0; i < ROAR_DIR_DIRIDS; i++) {
275  g_config->streams[i].mixer_channels = 1;
276  g_config->streams[i].mixer.rpg_mul  = 1;
277  g_config->streams[i].mixer.rpg_div  = 1;
278  g_config->streams[i].mixer.scale    = 65535;
279  g_config->streams[i].mixer.mixer[0] = g_config->streams[i].mixer.scale;
280 }
281
[2291]282 g_config->streams[ROAR_DIR_PLAY    ].flags = ROAR_FLAG_META;
[2413]283 g_config->streams[ROAR_DIR_OUTPUT  ].flags = ROAR_FLAG_PASSMIXER;
[2264]284 g_config->streams[ROAR_DIR_FILTER  ].flags = ROAR_FLAG_SYNC;
[1899]285 g_config->streams[ROAR_DIR_MIDI_OUT].flags = ROAR_FLAG_SYNC;
[2160]286 g_config->streams[ROAR_DIR_BIDIR   ].flags = ROAR_FLAG_ANTIECHO;
[1899]287
[2017]288 g_config->location = "***default***";
289
[1609]290 return 0;
291}
292
[2530]293#ifdef ROAR_SUPPORT_LISTEN
294int init_listening (void) {
295 int i;
296
[3128]297 memset(g_listen, 0, sizeof(g_listen));
298
[2530]299 for (i = 0; i < ROAR_MAX_LISTEN_SOCKETS; i++) {
[3129]300  g_listen[i].socket = -1;
[3128]301  g_listen[i].proto  = ROAR_PROTO_ROARAUDIO;
[2530]302  server[i]          = NULL;
303 }
304
305 return 0;
306}
307
[3252]308int add_listen (char * addr, int port, int sock_type, char * user, char * group, int proto, int dir, struct roar_audio_info * info) {
[2530]309#if defined(ROAR_HAVE_SETGID) && defined(ROAR_HAVE_IO_POSIX)
310 struct group   * grp  = NULL;
311#endif
312#if defined(ROAR_HAVE_SETUID) && defined(ROAR_HAVE_IO_POSIX)
313 struct passwd  * pwd  = NULL;
314#endif
315#ifdef ROAR_HAVE_UNIX
316 char * env_roar_proxy_backup;
317#endif
318 int    sockid = -1;
319 int    sock;
320 int    i;
321
322 if ( *addr != 0 ) {
323  for (i = 0; i < ROAR_MAX_LISTEN_SOCKETS; i++) {
[3129]324   if ( g_listen[i].socket == -1 ) {
[2530]325    sockid = i;
326    break;
327   }
328  }
329
330  if ( sockid == -1 )
331   return -1;
332
[3128]333  g_listen[sockid].proto = proto;
[2530]334
335  ROAR_DBG("add_listen(*): proto=0x%.4x", proto);
336
[3129]337  if ( (g_listen[sockid].socket = roar_socket_listen(sock_type, addr, port)) == -1 ) {
[2530]338#ifdef ROAR_HAVE_UNIX
339   if ( *addr == '/' ) {
340    if ( (env_roar_proxy_backup = getenv("ROAR_PROXY")) != NULL ) {
341     env_roar_proxy_backup = strdup(env_roar_proxy_backup);
342     unsetenv("ROAR_PROXY");
343    }
344    if ( (sock = roar_socket_connect(addr, port)) != -1 ) {
345     close(sock);
[3040]346     ROAR_ERR("Can not open listen socket: Socket allready in use");
[2530]347     return 1;
348    } else {
349     unlink(addr);
[3129]350     if ( (g_listen[sockid].socket = roar_socket_listen(sock_type, addr, port)) == -1 ) {
[3040]351      ROAR_ERR("Can not open listen socket: %s", strerror(errno));
[2530]352      return 1;
353     }
354    }
355    if ( env_roar_proxy_backup != NULL ) {
356     setenv("ROAR_PROXY", env_roar_proxy_backup, 0);
357     free(env_roar_proxy_backup);
358    }
359#else
360   if (0) { // noop
361#endif
362   } else {
[3041]363    ROAR_ERR("Can not open listen socket: %s", strerror(errno));
[2530]364    return 1;
365   }
366  }
367
368#if defined(ROAR_HAVE_SETGID) && defined(ROAR_HAVE_IO_POSIX)
[2753]369  if ( group != NULL ) {
370   if ( (grp = getgrnam(group)) == NULL ) {
371    ROAR_ERR("Can not get GID for group %s: %s", group, strerror(errno));
372   }
[2530]373  }
374#endif
375#if defined(ROAR_HAVE_SETUID) && defined(ROAR_HAVE_IO_POSIX)
[2752]376  if ( user ) {
[2530]377   if ( (pwd = getpwnam(user)) == NULL ) {
378    ROAR_ERR("Can not get UID for user %s: %s", user, strerror(errno));
379   }
380  }
381#endif
382
383#if defined(ROAR_HAVE_IO_POSIX) && defined(ROAR_HAVE_UNIX)
384  if ( *addr == '/' ) {
[2753]385   if ( grp || pwd ) {
386     if ( chown(addr, pwd ? pwd->pw_uid : -1, grp ? grp->gr_gid : -1) == -1 )
[2530]387      return 1;
[2753]388   }
[2530]389#ifdef ROAR_HAVE_GETUID
[2753]390   if ( grp ) {
[2530]391    if ( getuid() == 0 )
392     if ( chmod(addr, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1 )
393      return 1;
[2753]394   }
[2530]395#endif
396  }
397#endif
398 }
399
[2736]400 // in case we opened the listening socket correctly.
[3256]401 if ( dir == -1 )
402  dir = ROAR_DIR_PLAY;
403
[3252]404 g_listen[sockid].inst.stpl.dir = dir;
405 memcpy(&(g_listen[sockid].inst.stpl.info), info, sizeof(struct roar_audio_info));
[3256]406
407 switch (dir) {
408  case ROAR_DIR_PLAY:
409  case ROAR_DIR_RECORD:
410  case ROAR_DIR_MONITOR:
411  case ROAR_DIR_FILTER:
412  case ROAR_DIR_BIDIR:
413    if ( !g_listen[sockid].inst.stpl.info.rate )
414     g_listen[sockid].inst.stpl.info.rate = g_sa->rate;
415
416    if ( !g_listen[sockid].inst.stpl.info.bits )
417     g_listen[sockid].inst.stpl.info.bits = g_sa->bits;
418
419    if ( !g_listen[sockid].inst.stpl.info.channels )
420     g_listen[sockid].inst.stpl.info.channels = g_sa->channels;
421
422    if ( !g_listen[sockid].inst.stpl.info.codec )
423     g_listen[sockid].inst.stpl.info.codec = g_sa->codec;
424   break;
425 }
426
[2736]427 server[sockid] = addr;
[2530]428 return 0;
429}
430#endif
431
[2339]432int update_stream_flags (char * str) {
433 int    dir;
434 char * flags;
435 char * k;
436 int    op;
437 int    flag;
438
439 if ( (flags = strstr(str, "=")) == NULL )
440  return -1;
441
442 *flags = 0;
443  flags++;
444
445 if ( (dir = roar_str2dir(str)) == -1 )
446  return -1;
447
448 while (flags != NULL) {
449  k = flags;
450  flags = strstr(flags, ",");
451
452  if ( flags != NULL )
453   *(flags++) = 0;
454
455  switch (*k) {
[2340]456   case '+': k++; op = ROAR_SET_FLAG;   break;
457   case '-': k++; op = ROAR_RESET_FLAG; break;
[2339]458   default:
[2340]459     op = ROAR_SET_FLAG;
[2339]460  }
461
462  flag = 0;
463
464  if ( !strcmp(k, "sync") ) {
465   flag = ROAR_FLAG_SYNC;
466  } else if ( !strcmp(k, "meta") ) {
467   flag = ROAR_FLAG_META;
468  } else if ( !strcmp(k, "cleanmeta") ) {
469   flag = ROAR_FLAG_CLEANMETA;
470  } else if ( !strcmp(k, "pause") ) {
471   flag = ROAR_FLAG_PAUSE;
472  } else if ( !strcmp(k, "mute") ) {
473   flag = ROAR_FLAG_MUTE;
474  } else if ( !strcmp(k, "antiecho") ) {
475   flag = ROAR_FLAG_ANTIECHO;
[2413]476  } else if ( !strcmp(k, "passmixer") ) {
477   flag = ROAR_FLAG_PASSMIXER;
[2339]478  } else {
479   return -1;
480  }
481
482  g_config->streams[dir].flags |= flag;
483
[2340]484  if ( op == ROAR_RESET_FLAG )
[2339]485   g_config->streams[dir].flags -= flag;
486 }
487
488 return 0;
489}
490
[1145]491int add_output (char * drv, char * dev, char * opts, int prim, int count) {
[933]492 int stream;
493 struct roar_stream * s;
494 struct roar_stream_server * ss;
[938]495 char * k, * v;
[1208]496#ifdef ROAR_DRIVER_CODEC
497 char * to_free = NULL;
498#endif
[1926]499 int sync = 0, f_mmap = 0;
[1522]500 int32_t blocks = -1, blocksize = -1;
[1920]501 int dir = ROAR_DIR_OUTPUT;
[1991]502 int error = 0;
503 // DMX:
504 int32_t channel  = -1;
505 int32_t universe = -1;
506 uint16_t tu16;
[2085]507 float q = -32e6;
[933]508
[938]509 ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = ?", drv, dev, opts);
[933]510
[1145]511 if ( drv == NULL && count == 0 ) {
512  drv  = ROAR_DRIVER_DEFAULT;
513  prim = 1;
514  sync = 1;
[1208]515
516#ifdef ROAR_DRIVER_CODEC
517  if ( opts == NULL ) {
518   opts = to_free = strdup("codec=" ROAR_DRIVER_CODEC);
519  }
520#endif
[1145]521 }
522
[1227]523 if ( opts == NULL && count == 0 ) {
524  sync = 1;
525  prim = 1; // if ( prim == 0 ) prim = 1; -> prim allways = 1
526 }
527
[2785]528 ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = ?", drv, dev, opts);
529
[933]530 if ( (stream = streams_new()) == -1 ) {
[938]531  ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = -1", drv, dev, opts);
[982]532  if ( prim ) alive = 0;
[933]533  return -1;
534 }
535
[2785]536 ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = ?", drv, dev, opts);
537
[933]538 streams_get(stream, &ss);
539 s = ROAR_STREAM(ss);
540
[2785]541 ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = ?", drv, dev, opts);
542
[2511]543 memset(&(s->info), 0xFF, sizeof(struct roar_audio_info)); // set everything to -1
[933]544
545 s->pos_rel_id = -1;
546// s->info.codec = codec;
547
[2785]548 ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = ?", drv, dev, opts);
549
[2788]550 if ( opts == NULL ) {
551  k = NULL;
552 } else {
553  k = strtok(opts, ",");
554 }
[2786]555
556 ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s'): initial k='%s'(%p)", drv, dev, opts, k, k);
557
[938]558 while (k != NULL) {
559//  ROAR_WARN("add_output(*): opts: %s", k);
560
561  if ( (v = strstr(k, "=")) != NULL ) {
562   *v++ = 0;
563  }
564
565  ROAR_DBG("add_output(*): opts: k='%s', v='%s'", k, v);
566  if ( strcmp(k, "rate") == 0 ) {
567   s->info.rate = atoi(v);
568  } else if ( strcmp(k, "channels") == 0 ) {
569   s->info.channels = atoi(v);
570  } else if ( strcmp(k, "bits") == 0 ) {
571   s->info.bits = atoi(v);
572  } else if ( strcmp(k, "codec") == 0 ) {
[2511]573   if ( (s->info.codec = roar_str2codec(v)) == -1 ) {
[938]574    ROAR_ERR("add_output(*): unknown codec '%s'", v);
[1991]575    error++;
[938]576   }
[2085]577  } else if ( strcmp(k, "q") == 0 ) {
578   q = atof(v);
[1221]579  } else if ( strcmp(k, "blocks") == 0 ) {
580   blocks = atoi(v);
[1522]581  } else if ( strcmp(k, "blocksize") == 0 ) {
582   blocksize = atoi(v);
[1926]583  } else if ( strcmp(k, "mmap") == 0 ) {
584   f_mmap = 1;
[1919]585  } else if ( strcmp(k, "subsystem") == 0 ) {
586   if ( !strcasecmp(v, "wave") || !strcasecmp(v, "waveform") ) {
[1920]587    dir = ROAR_DIR_OUTPUT;
[2494]588#ifndef ROAR_WITHOUT_DCOMP_MIDI
[1919]589   } else if ( !strcasecmp(v, "midi") ) {
590    dir = ROAR_DIR_MIDI_OUT;
[2494]591#endif
592#ifndef ROAR_WITHOUT_DCOMP_LIGHT
[1919]593   } else if ( !strcasecmp(v, "light") ) {
594    dir = ROAR_DIR_LIGHT_OUT;
[2494]595#endif
596#ifndef ROAR_WITHOUT_DCOMP_RAW
[2234]597   } else if ( !strcasecmp(v, "raw") ) {
598    dir = ROAR_DIR_RAW_OUT;
[2494]599#endif
[2681]600   } else if ( !strcasecmp(v, "complex") ) {
601    dir = ROAR_DIR_COMPLEX_OUT;
[1919]602   } else {
[2494]603    ROAR_ERR("add_output(*): unknown/unsupported subsystem '%s'", k);
[1991]604    error++;
605   }
606  // DMX:
607  } else if ( strcmp(k, "channel") == 0 ) {
608   channel  = atoi(v);
609   if ( channel < 0 || channel > 65535 ) {
610    ROAR_ERR("add_output(*): Invalide channel (not within 0..65535): %i", channel);
611    channel = -1;
612    error++;
[1919]613   }
[1991]614  } else if ( strcmp(k, "universe") == 0 ) {
615   universe = atoi(v);
616   if ( universe < 0 || universe > 255 ) {
617    ROAR_ERR("add_output(*): Invalide universe (not within 0..255): %i", universe);
618    universe = -1;
619    error++;
620   }
621
[2115]622  } else if ( strcmp(k, "name") == 0 ) {
623   if ( streams_set_name(stream, v) == -1 ) {
624    ROAR_ERR("add_output(*): Can not set Stream name");
625    error++;
626   }
[1991]627
[1032]628  } else if ( strcmp(k, "meta") == 0 ) {
629   streams_set_flag(stream, ROAR_FLAG_META);
[1117]630  } else if ( strcmp(k, "sync") == 0 ) {
631   sync = 1;
[1221]632  } else if ( strcmp(k, "primary") == 0 ) {
633   prim = 1;
634
635  } else if ( strcmp(k, "cleanmeta") == 0 ) {
636   streams_set_flag(stream, ROAR_FLAG_CLEANMETA);
637  } else if ( strcmp(k, "autoconf") == 0 ) {
[1531]638   streams_set_flag(stream, ROAR_FLAG_AUTOCONF);
[2413]639  } else if ( strcmp(k, "recsource") == 0 ) {
640   streams_set_flag(stream, ROAR_FLAG_RECSOURCE);
641  } else if ( strcmp(k, "passmixer") == 0 ) {
642   streams_set_flag(stream, ROAR_FLAG_PASSMIXER);
[938]643  } else {
644   ROAR_ERR("add_output(*): unknown option '%s'", k);
[1991]645   error++;
646  }
647
648  if ( error ) {
[938]649   streams_delete(stream);
[982]650   if ( prim ) alive = 0;
[1208]651#ifdef ROAR_DRIVER_CODEC
652   if ( to_free != NULL )
653    free(to_free);
654#endif
[938]655   return -1;
656  }
657
658  k = strtok(NULL, ",");
659 }
660
[2785]661 ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = ?", drv, dev, opts);
662
[2511]663 // set audio info...
664 switch (dir) {
665  case ROAR_DIR_LIGHT_OUT:
666    switch (s->info.codec) {
667     case ROAR_CODEC_DMX512:
668     case -1:
669       if ( s->info.rate == -1 )
670        s->info.rate = ROAR_OUTPUT_CFREQ;
671
672       s->info.channels =   0;
673       s->info.bits     =   8;
674       s->info.codec    = ROAR_CODEC_DMX512; // in case codec == -1
675      break;
676    }
677   break;
678  case ROAR_DIR_MIDI_OUT:
679    switch (s->info.codec) {
680     case ROAR_CODEC_MIDI:
681     case -1:
682       if ( s->info.rate == -1 )
683        s->info.rate    = ROAR_MIDI_TICKS_PER_BEAT;
684
685       s->info.channels = ROAR_MIDI_CHANNELS_DEFAULT;
686       s->info.bits     = ROAR_MIDI_BITS;
687       s->info.codec    = ROAR_CODEC_MIDI; // in case codec == -1
688      break;
689    }
690   break;
691  case ROAR_DIR_RAW_OUT:
692    if ( s->info.rate == -1 )
693     s->info.rate = 0;
694    if ( s->info.bits == -1 )
695     s->info.bits = 0;
696    if ( s->info.channels == -1 )
697     s->info.channels = 0;
698    if ( s->info.codec == -1 )
699     s->info.codec = 0;
700   break;
701 }
702
703 if ( s->info.rate == -1 )
704  s->info.rate = g_sa->rate;
705 if ( s->info.bits == -1 )
706  s->info.bits = g_sa->bits;
707 if ( s->info.channels == -1 )
708  s->info.channels = g_sa->channels;
709 if ( s->info.codec == -1 )
710  s->info.codec = g_sa->codec;
711
712 ROAR_DBG("add_output(*): s->info = {.rate=%i, .bits=%i, .channels=%i, .codec=%i}", s->info.rate, s->info.bits, s->info.channels, s->info.codec);
713
[1919]714 if ( streams_set_dir(stream, dir, 1) == -1 ) {
715  streams_delete(stream);
716  return -1;
717 }
718
[1208]719#ifdef ROAR_DRIVER_CODEC
720 if ( to_free != NULL )
721  free(to_free);
722#endif
723
[2511]724 if ( s->info.codec == ROAR_CODEC_ALAW || s->info.codec == ROAR_CODEC_MULAW )
[941]725  s->info.bits = 8; // needed to open OSS driver, will be overriden by codecfilter
726
[2511]727 ROAR_STREAM_SERVER(s)->codec_orgi = s->info.codec;
[933]728
[2364]729 if ( driver_openvio(&(ss->vio), &(ss->driver_id), drv, dev, &(s->info), -1, ss) == -1 ) {
[1581]730  ss->driver_id = -1; // don't close a driver not opened...
731  memset(&(ss->vio), 0, sizeof(struct roar_vio_calls));
[933]732  streams_delete(stream);
[938]733  ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = -1", drv, dev, opts);
[982]734  if ( prim ) alive = 0;
[933]735  return -1;
736 }
737
[1528]738 roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_SSTREAMID, &stream); // ignore errors here
739 roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_SSTREAM,   s); // ignore errors here
740
[1221]741 if ( blocks != -1 )
742  roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_DBLOCKS, &blocks);
743
[1522]744 if ( blocksize != -1 )
745  roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_DBLKSIZE, &blocksize);
746
[1991]747 // TODO: we shoudld *really* check for errors here...
748 if ( channel != -1 ) {
749  tu16 = channel;
750  roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_DMXSCHAN, &tu16);
751 }
752 if ( universe != -1 ) {
753  tu16 = universe;
754  roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_DMXUNIV, &tu16);
755 }
756
[1156]757 ROAR_DBG("add_output(*): ss->driver_id=%i", ss->driver_id);
758
[938]759 streams_set_fh(stream, -1); // update some internal structures
760
[2087]761 if ( q > -1e6 ) {
762  ROAR_DBG("add_output(*): setting q=%f", q);
763  streams_ctl(stream, ROAR_CODECFILTER_CTL_SET_Q|ROAR_STREAM_CTL_TYPE_FLOAT, &q);
764 }
765
[2490]766 client_stream_add(g_self_client, stream);
[933]767
[1200]768 if ( prim ) {
[961]769  streams_mark_primary(stream);
[1200]770  s->pos_rel_id = stream;
771 }
[961]772
[1120]773 if ( sync ) {
[1117]774  streams_set_flag(stream, ROAR_FLAG_SYNC);
[1120]775 } else {
776  streams_reset_flag(stream, ROAR_FLAG_SYNC);
777 }
[1117]778
[1926]779 if ( f_mmap )
780  streams_set_flag(stream, ROAR_FLAG_MMAP);
781
[2511]782 ROAR_DBG("add_output(*): s->info = {.rate=%i, .bits=%i, .channels=%i, .codec=%i}", s->info.rate, s->info.bits, s->info.channels, s->info.codec);
[933]783 return 0;
[932]784}
785
[3373]786// X11:
787#ifdef ROAR_HAVE_LIBX11
788int register_x11 (int unreg, char * sockname) {
789 struct roar_x11_connection * x11con = NULL;
790 int ret = 0;
791
[3374]792 if ( (x11con = roar_x11_connect(x11display)) == NULL )
[3373]793  return -1;
794
795 if ( unreg ) {
796  if ( roar_x11_delete_prop(x11con, "ROAR_SERVER") == -1 )
797   ret = -1;
798 } else {
799  if ( roar_x11_set_prop(x11con, "ROAR_SERVER", sockname) == -1 )
800   ret = -1;
801 }
802
803 roar_x11_disconnect(x11con);
804
805 return ret;
806}
807#endif
[1993]808
809// SLP:
810void register_slp_callback(SLPHandle hslp, SLPError errcode, void * cookie) {
811 /* return the error code in the cookie */
812 *(SLPError*)cookie = errcode;
813}
814
815int register_slp (int unreg, char * sockname) {
816#ifdef ROAR_HAVE_LIBSLP
817 static int regged = 0;
818 static char * sn = NULL;
819 SLPError err;
820 SLPError callbackerr;
821 SLPHandle hslp;
822 char addr[1024];
823 char attr[1024] = "";
[2017]824 char * location;
[1993]825
826 if ( sockname != NULL )
827  sn = sockname;
828
[3076]829 snprintf(addr, sizeof(addr), ROAR_SLP_URL_TYPE_ROAR "://%s", sn);
[1993]830
831 err = SLPOpen("en", SLP_FALSE, &hslp);
832
833 if (err != SLP_OK) {
834  ROAR_ERR("Error opening slp handle: Error #%i", err);
835  return -1;
836 }
837
838 if (!unreg) {
[2017]839
840  if ( SLPEscape(g_config->location, &location, SLP_FALSE) != SLP_OK ) {
841   ROAR_ERR("Error using SLPEscape() on server location, really bad!");
842   SLPClose(hslp);
843   return -1;
844  }
845
[1995]846  snprintf(attr, sizeof(attr), "(wave-rate=%i),(wave-channels=%i),(wave-bits=%i),"
[2494]847#ifndef ROAR_WITHOUT_DCOMP_LIGHT
848                               "(light-channels=%i),"
849#endif
850                               "(location=%s)",
[1995]851           g_sa->rate, g_sa->channels, g_sa->bits,
[2494]852#ifndef ROAR_WITHOUT_DCOMP_LIGHT
[2017]853           g_light_state.channels,
[2494]854#endif
[2017]855           location
[1995]856          );
857
[1993]858  /* Register a service with SLP */
859  err = SLPReg(hslp,
860               addr,
861               SLP_LIFETIME_MAXIMUM,
862               0,
863               attr,
864               SLP_TRUE,
865               register_slp_callback,
866               &callbackerr);
[1994]867  regged = 1;
868 } else if ( unreg && regged ) {
869  err = SLPDereg(hslp, addr, register_slp_callback, &callbackerr);
870  regged = 0;
871 } else {
872  SLPClose(hslp);
873  return -1;
874 }
[1993]875
[1994]876 /* err may contain an error code that occurred as the slp library    */
877 /* _prepared_ to make the call.                                     */
878 if ( err != SLP_OK ) {
879  ROAR_ERR("Error (de)registering service with slp: Error #%i", err);
880  return -1;
881 }
882
883 /* callbackerr may contain an error code (that was assigned through */
884 /* the callback cookie) that occurred as slp packets were sent on    */
885 /* the wire */
886 if (callbackerr != SLP_OK) {
887  ROAR_ERR("Error (de)registering service with slp: Error #%i", callbackerr);
888  return -1;
[1993]889 }
890
891 SLPClose(hslp);
892 return 0;
893#else
894 return -1;
895#endif
896}
897
898
899// MAIN:
900
[1503]901#ifdef ROAR_HAVE_MAIN_ARGS
[0]902int main (int argc, char * argv[]) {
[1503]903#else
904int main (void) {
905#endif
906#ifdef ROAR_HAVE_MAIN_ARGS
[0]907 int i;
908 char * k;
[1503]909#endif
[2787]910#if defined(ROAR_SUPPORT_LISTEN) && defined(ROAR_HAVE_GETUID)
[905]911 char user_sock[80]  = {0};
[1494]912#endif
[1609]913 struct roar_audio_info sa, max_sa;
914 struct roard_config config;
[1486]915#ifdef ROAR_HAVE_FORK
[905]916 int    daemon       = 0;
[1486]917#endif
[905]918 int    realtime     = 0;
919 int    sysclocksync = 0;
[1207]920 char * driver    = NULL;
921 char * device    = NULL;
[1503]922#ifdef ROAR_HAVE_MAIN_ARGS
[1207]923 char * opts      = NULL;
[1503]924#endif
[60]925// char * server = ROAR_DEFAULT_SOCK_GLOBAL;
[1494]926#ifdef ROAR_SUPPORT_LISTEN
[2530]927 int    port       = ROAR_DEFAULT_PORT;
928 char * sock_addr  = NULL;
929 int    sock_proto = ROAR_PROTO_ROARAUDIO;
[3252]930 int    sock_dir   = -1;
931 struct roar_audio_info sock_info = {0, 0, 0, 0};
[1494]932#endif
[0]933 int               drvid;
[2486]934#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[550]935 char * s_drv     = "cf";
[1110]936 char * s_dev     = NULL;
[444]937 char * s_con     = NULL;
938 char * s_opt     = NULL;
939 int    s_prim    = 0;
[2486]940#endif
[1207]941 char * o_drv     = getenv("ROAR_DRIVER");
942 char * o_dev     = getenv("ROAR_DEVICE");
[932]943 char * o_opts    = NULL;
[961]944 int    o_prim    = 0;
[1145]945 int    o_count   = 0;
[2494]946#ifndef ROAR_WITHOUT_DCOMP_LIGHT
[1923]947 int    light_channels = LIGHT_CHANNELS_DEFAULT;
[2494]948#endif
[2751]949#ifdef ROAR_DEFAULT_SOCKGRP
[450]950 char * sock_grp  = ROAR_DEFAULT_SOCKGRP;
[2751]951#else
952 char * sock_grp  = NULL;
953#endif
[444]954 char * sock_user = NULL;
[1494]955#ifdef ROAR_SUPPORT_LISTEN
[517]956 int    sock_type = ROAR_SOCKET_TYPE_UNKNOWN;
[1494]957#endif
[1993]958#ifdef ROAR_HAVE_LIBSLP
959 int    reg_slp   = 0;
960#endif
[3373]961#ifdef ROAR_HAVE_LIBX11
962 int    reg_x11   = 0;
963#endif
[1486]964#ifdef ROAR_HAVE_CHROOT
[444]965 char * chrootdir = NULL;
[1486]966#endif
967#if defined(ROAR_HAVE_SETGID) && defined(ROAR_HAVE_IO_POSIX)
[446]968 struct group   * grp  = NULL;
[1486]969#endif
970#if defined(ROAR_HAVE_SETUID) && defined(ROAR_HAVE_IO_POSIX)
[446]971 struct passwd  * pwd  = NULL;
[1486]972#endif
973#ifdef ROAR_HAVE_GETSERVBYNAME
[446]974 struct servent * serv = NULL;
[1486]975#endif
[0]976 DRIVER_USERDATA_T drvinst;
[39]977 struct roar_client * self = NULL;
[508]978#ifdef ROAR_HAVE_LIBDNET
979 char decnethost[80];
980#endif
[2104]981#ifdef SUPPORT_PIDFILE
982 struct roar_vio_calls pidfile_vio;
983#endif
[0]984
[2784]985 ROAR_DBG("main(*): starting roard...");
986
[0]987 g_standby       =  0;
[920]988 g_autostandby   =  0;
[982]989 alive           =  1;
[1494]990#ifdef ROAR_SUPPORT_LISTEN
[1155]991 g_no_listen     =  0;
[1494]992#else
993 g_terminate     =  1;
994#endif
[0]995
[2970]996 g_verbose       = ROAR_DBG_INFO_NONE;
997
[0]998 sa.bits     = ROAR_BITS_DEFAULT;
999 sa.channels = ROAR_CHANNELS_DEFAULT;
1000 sa.rate     = ROAR_RATE_DEFAULT;
1001 sa.codec    = ROAR_CODEC_DEFAULT;
1002
[1609]1003 g_sa        = &sa;
1004 g_max_sa    = &max_sa;
1005
1006 memcpy(g_max_sa, g_sa, sizeof(max_sa));
1007
1008 g_config = &config;
1009
1010 if ( init_config() == -1 ) {
1011  ROAR_ERR("Can not init default config!");
1012  return 1;
1013 }
[0]1014
[2968]1015 // load config
1016 roar_libroar_get_config();
1017
[2530]1018#ifdef ROAR_SUPPORT_LISTEN
1019 if ( init_listening() == -1 ) {
1020  ROAR_ERR("Can not init listening sockets!");
1021  return 1;
1022 }
1023#endif
1024
[2500]1025#ifndef ROAR_WITHOUT_DCOMP_MIDI
[1924]1026 if ( midi_init_config() == -1 ) {
1027  ROAR_ERR("Can not init MIDI config!");
1028  return 1;
1029 }
[2500]1030#endif
[60]1031
[2489]1032#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
[2451]1033 if ( ssynth_init_config() == -1 ) {
1034  ROAR_ERR("Can not init ssynth config!");
1035  return 1;
1036 }
[2489]1037#endif
[2451]1038
[2718]1039#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1040 if ( rdtcs_init_config() == -1 ) {
1041  ROAR_ERR("Can not init RDTCS config!");
1042  return 1;
1043 }
1044#endif
1045
[3354]1046 if ( plugins_preinit() == -1 ) {
1047  ROAR_ERR("Can not pre-init plugins!");
1048  return 1;
1049 }
1050
[1494]1051#ifdef ROAR_SUPPORT_LISTEN
[2767]1052#ifndef ROAR_TARGET_WIN32
[2530]1053 sock_addr = ROAR_DEFAULT_SOCK_GLOBAL;
[2767]1054#else
1055 sock_addr = ROAR_DEFAULT_HOST;
1056#endif
1057
[1753]1058#ifdef ROAR_HAVE_GETUID
[1486]1059 if ( getuid() != 0 && getenv("HOME") != NULL ) {
1060  snprintf(user_sock, 79, "%s/%s", (char*)getenv("HOME"), ROAR_DEFAULT_SOCK_USER);
[2530]1061  sock_addr = user_sock;
[60]1062 }
[1753]1063#endif
[60]1064
[279]1065 if ( getenv("ROAR_SERVER") != NULL )
[2530]1066  sock_addr = getenv("ROAR_SERVER");
[1494]1067#endif
[279]1068
[63]1069 if ( clients_init() == -1 ) {
1070  ROAR_ERR("Can not init clients!");
1071  return 1;
1072 }
1073
1074 if ( streams_init() == -1 ) {
1075  ROAR_ERR("Can not init streams!");
1076  return 1;
1077 }
1078
[64]1079 if ( (g_self_client = clients_new()) == -1 ) {
1080  ROAR_ERR("Can not create self client!");
1081  return 1;
1082 }
1083
[2485]1084#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[0]1085 if ( sources_init() == -1 ) {
1086  ROAR_ERR("Can not init sources!");
1087  return 1;
1088 }
1089
[64]1090 if ( (sources_set_client(g_self_client)) == -1 ) {
1091  ROAR_ERR("Can not init set source client!");
1092  return 1;
1093 }
[2485]1094#endif
[64]1095
[1503]1096#ifdef ROAR_HAVE_MAIN_ARGS
[0]1097 for (i = 1; i < argc; i++) {
1098  k = argv[i];
1099
1100  if ( strcmp(k, "-h") == 0 || strcmp(k, "--help") == 0 ) {
1101   usage();
1102   return 0;
1103
[2109]1104  } else if ( strcmp(k, "--start") == 0 ) {
1105   // this is a no op
[579]1106  } else if ( strcmp(k, "--restart") == 0 ) {
[1494]1107#ifdef ROAR_SUPPORT_LISTEN
[2530]1108   if ( restart_server(sock_addr, 1) == -1 ) {
1109    ROAR_WARN("Can not terminate old server (not running at %s?), tring to continue anyway", sock_addr);
[579]1110   }
[1494]1111#else
1112   ROAR_ERR("--restart not supported");
1113#endif
[2109]1114  } else if ( strcmp(k, "--shutdown") == 0 ) {
1115#ifdef ROAR_SUPPORT_LISTEN
[2530]1116   if ( restart_server(sock_addr, 1) == -1 ) {
1117    ROAR_WARN("Can not terminate old server (not running at %s?)", sock_addr);
[2109]1118    return 1;
1119   }
1120   return 0;
1121#else
1122   ROAR_ERR("--shutdown not supported");
1123   return 1;
1124#endif
1125  } else if ( strcmp(k, "--stop") == 0 ) {
1126#ifdef ROAR_SUPPORT_LISTEN
[2530]1127   if ( restart_server(sock_addr, 0) == -1 ) {
1128    ROAR_WARN("Can not stop old server (not running at %s?)", sock_addr);
[2109]1129    return 1;
1130   }
1131   return 0;
1132#else
1133   ROAR_ERR("--stop not supported");
1134   return 1;
1135#endif
1136
[579]1137
[775]1138  } else if ( strcmp(k, "--demon") == 0 || strcmp(k, "--daemon") == 0 ) {
[1486]1139#ifdef ROAR_HAVE_FORK
[775]1140   daemon = 1;
[1486]1141#else
1142   ROAR_ERR("--daemon not supported");
1143#endif
[2970]1144  } else if ( strcmp(k, "--verbose") == 0 ) {
1145   g_verbose++;
[71]1146  } else if ( strcmp(k, "--terminate") == 0 ) {
1147   g_terminate = 1;
[905]1148  } else if ( strcmp(k, "--sysclocksync") == 0 ) {
1149   sysclocksync = 1000;
[275]1150  } else if ( strcmp(k, "--realtime") == 0 ) {
[276]1151   realtime++;
[444]1152  } else if ( strcmp(k, "--chroot") == 0 ) {
[1486]1153#ifdef ROAR_HAVE_CHROOT
[444]1154   chrootdir = argv[++i];
[1486]1155#else
1156   ROAR_ERR("--chroot not supported");
1157   i++;
1158#endif
[444]1159  } else if ( strcmp(k, "--setgid") == 0 ) {
[1486]1160#ifdef ROAR_HAVE_SETGID
[444]1161   setids |= R_SETGID;
[1486]1162#else
1163   ROAR_ERR("--setgid not supported");
1164#endif
[444]1165  } else if ( strcmp(k, "--setuid") == 0 ) {
[1486]1166#ifdef ROAR_HAVE_SETUID
[444]1167   setids |= R_SETUID;
[1486]1168#else
1169   ROAR_ERR("--setuid not supported");
1170#endif
[2017]1171  } else if ( strcmp(k, "--location") == 0 ) {
1172   g_config->location = argv[++i];
[2104]1173  } else if ( strcmp(k, "--pidfile") == 0 ) {
1174#ifdef SUPPORT_PIDFILE
1175   pidfile = argv[++i];
1176#else
1177   ROAR_ERR("--pidfile not supported");
1178   i++;
1179#endif
[68]1180
[3356]1181  } else if ( strcmp(k, "--plugin-load") == 0 ) {
1182   if ( plugins_load(argv[++i]) == -1 ) {
1183    ROAR_ERR("Can not load plugin");
1184   }
1185
[280]1186  } else if ( strcmp(k, "--list-cf") == 0 ) {
1187   print_codecfilterlist();
1188   return 0;
1189
[0]1190  } else if ( strcmp(k, "-R") == 0 || strcmp(k, "--rate") == 0 ) {
1191   sa.rate = atoi(argv[++i]);
1192  } else if ( strcmp(k, "-B") == 0 || strcmp(k, "--bits") == 0 ) {
1193   sa.bits = atoi(argv[++i]);
1194  } else if ( strcmp(k, "-C") == 0 || strcmp(k, "--chans") == 0 ) {
1195   sa.channels = atoi(argv[++i]);
1196
[2339]1197  } else if ( strcmp(k, "--stream-flags") == 0 ) {
1198   if ( update_stream_flags(argv[++i]) == -1 ) {
1199    ROAR_ERR("Can not set stream flags");
1200    return 1;
1201   }
1202
[0]1203  } else if ( strcmp(k, "-d") == 0 || strcmp(k, "--driver") == 0 ) {
1204   driver = argv[++i];
1205   if ( strcmp(driver, "list") == 0 ) {
[974]1206    ROAR_WARN("The option is obsolete, use --list-driver!");
[0]1207    print_driverlist();
[973]1208    return 0;
[0]1209   }
1210  } else if ( strcmp(k, "-D") == 0 || strcmp(k, "--device") == 0 ) {
1211   device = argv[++i];
1212  } else if ( strcmp(k, "-dO") == 0 ) {
1213   opts = argv[++i];
[973]1214  } else if ( strcmp(k, "--list-driver") == 0 ) {
1215   print_driverlist();
1216   return 0;
[0]1217
[932]1218  } else if ( strcmp(k, "-o") == 0 || strcmp(k, "--odriver") == 0 ) {
1219   o_drv  = argv[++i];
1220  } else if ( strcmp(k, "-O") == 0 || strcmp(k, "--odevice") == 0 ) {
1221   o_dev  = argv[++i];
1222  } else if ( strcmp(k, "-oO") == 0 ) {
1223   o_opts = argv[++i];
[961]1224  } else if ( strcmp(k, "-oP") == 0 ) {
1225   o_prim = 1;
[932]1226  } else if ( strcmp(k, "-oN") == 0 ) {
[1145]1227   if ( add_output(o_drv, o_dev, o_opts, o_prim, o_count) != -1 )
1228    o_count++;
1229
[961]1230   o_drv  = o_dev = o_opts = NULL;
1231   o_prim = 0;
[932]1232
[0]1233  } else if ( strcmp(k, "-s") == 0 || strcmp(k, "--source") == 0 ) {
[2485]1234#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[550]1235   s_drv = argv[++i];
[2485]1236#else
1237   ROAR_ERR("main(*): No support for sources compiled in");
1238#endif
[550]1239  } else if ( strcmp(k, "-S") == 0 ) {
[2485]1240#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[1110]1241   s_dev = argv[++i];
[2485]1242#else
1243   ROAR_ERR("main(*): No support for sources compiled in");
1244#endif
[0]1245  } else if ( strcmp(k, "-sO") == 0 ) {
[2485]1246#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[0]1247   s_opt = argv[++i];
[2485]1248#else
1249   ROAR_ERR("main(*): No support for sources compiled in");
1250#endif
[0]1251  } else if ( strcmp(k, "-sC") == 0 ) {
[2485]1252#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[0]1253   s_con = argv[++i];
[2485]1254#else
1255   ROAR_ERR("main(*): No support for sources compiled in");
1256#endif
[0]1257  } else if ( strcmp(k, "-sP") == 0 ) {
[2485]1258#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[0]1259   s_prim = 1;
[2485]1260#else
1261   ROAR_ERR("main(*): No support for sources compiled in");
1262#endif
[1110]1263  } else if ( strcmp(k, "-sN") == 0 ) {
[2485]1264#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[1110]1265   if ( sources_add(s_drv, s_dev, s_con, s_opt, s_prim) == -1 ) {
1266    ROAR_ERR("main(*): adding source '%s' via '%s' failed!", s_dev, s_drv);
1267   }
1268   s_opt = s_dev = s_con = NULL;
1269   s_drv = "cf";
1270   s_prim = 0;
[2485]1271#else
1272   ROAR_ERR("main(*): No support for sources compiled in");
1273#endif
[2270]1274  } else if ( strcmp(k, "--list-sources") == 0 ) {
[2485]1275#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[2270]1276   print_sourcelist();
1277   return 0;
[2485]1278#else
1279   ROAR_ERR("main(*): No support for sources compiled in");
[2504]1280   return 1;
[2485]1281#endif
[0]1282
[1923]1283  } else if ( strcmp(k, "--light-channels") == 0 ) {
[2494]1284#ifndef ROAR_WITHOUT_DCOMP_LIGHT
[1923]1285   light_channels = atoi(argv[++i]);
[2494]1286#else
1287   ROAR_WARN("main(*): no light subsystem compiled in");
1288#endif
[1923]1289
[2725]1290  } else if ( strcmp(k, "--rds-pi") == 0 ) {
1291#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1292   g_rdtcs.rds.pi = atoi(argv[++i]);
1293#else
1294   ROAR_WARN("main(*): no RDTCS subsystem compiled in");
1295#endif
[2728]1296  } else if ( strcmp(k, "--rds-ps") == 0 ) {
1297#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1298   if ( rdtcs_rds_set_ps(argv[++i]) == -1 ) {
[2729]1299    ROAR_ERR("Can not set RDS PS to '%s' (longer than 8 chars?)", argv[i]);
[2728]1300    return 1;
1301   }
1302#else
1303   ROAR_WARN("main(*): no RDTCS subsystem compiled in");
1304#endif
1305  } else if ( strcmp(k, "--rds-pty") == 0 ) {
1306#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1307   if ( rdtcs_rds_set_pty(argv[++i]) == -1 ) {
[2729]1308    ROAR_ERR("Can not set RDS PTY to '%s'", argv[i]);
[2728]1309    return 1;
1310   }
1311#else
1312   ROAR_WARN("main(*): no RDTCS subsystem compiled in");
1313#endif
1314  } else if ( strcmp(k, "--rds-tp") == 0 ) {
1315#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1316   if ( rdtcs_rds_set_flag(RDTCS_RDS_FLAG_TP, 0) == -1 ) {
1317    ROAR_ERR("Can not set RDS TP flag");
1318    return 1;
1319   }
1320#else
1321   ROAR_WARN("main(*): no RDTCS subsystem compiled in");
1322#endif
1323  } else if ( strcmp(k, "--rds-ct") == 0 ) {
1324#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1325   if ( rdtcs_rds_set_flag(RDTCS_RDS_FLAG_CT, 0) == -1 ) {
1326    ROAR_ERR("Can not set RDS CT flag");
1327    return 1;
1328   }
1329#else
1330   ROAR_WARN("main(*): no RDTCS subsystem compiled in");
1331#endif
1332
[2725]1333
[1924]1334  } else if ( strcmp(k, "--midi-no-console") == 0 ) {
[2487]1335#ifndef ROAR_WITHOUT_DCOMP_CB
[1924]1336   midi_config.init_cb = 0;
[2487]1337#else
1338   // no warning here as this is the disable option
1339#endif
[2444]1340  } else if ( strcmp(k, "--midi-console-enable") == 0 ) {
[2487]1341#ifndef ROAR_WITHOUT_DCOMP_CB
[2444]1342   midi_config.init_cb = 1;
[2487]1343#else
1344   ROAR_ERR("main(*): No support for MIDI subsystem part CB compiled in");
1345#endif
[1924]1346  } else if ( strcmp(k, "--midi-console") == 0 ) {
[2487]1347#ifndef ROAR_WITHOUT_DCOMP_CB
[1924]1348   midi_config.console_dev = argv[++i];
[2444]1349   midi_config.init_cb = 1;
[2487]1350#else
1351   ROAR_ERR("main(*): No support for MIDI subsystem part CB compiled in");
1352#endif
[1924]1353
[2451]1354  } else if ( strcmp(k, "--ssynth-enable") == 0 ) {
[2489]1355#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
[2451]1356   ssynth_conf.enable = 1;
[2489]1357#else
1358   ROAR_ERR("main(*): No support for ssynth compiled in");
1359#endif
[2451]1360  } else if ( strcmp(k, "--ssynth-disable") == 0 ) {
[2489]1361#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
[2451]1362   ssynth_conf.enable = 0;
[2489]1363#else
1364   // we can safely ignore the disable
1365#endif
[2451]1366
[3374]1367  } else if ( strcmp(k, "--x11-display") == 0 || strcmp(k, "--display") == 0 ) {
1368#ifdef ROAR_HAVE_LIBX11
1369   x11display = argv[++i];
1370#else
1371   ROAR_ERR("No X11 support compiled in!");
1372   return 1;
1373#endif
1374
1375
[0]1376  } else if ( strcmp(k, "-p") == 0 || strcmp(k, "--port") == 0 ) {
[447]1377   // This is only usefull in INET not UNIX mode.
[1494]1378#ifdef ROAR_SUPPORT_LISTEN
[2530]1379   if ( *sock_addr == '/' )
1380    sock_addr = ROAR_DEFAULT_HOST;
[447]1381
[446]1382   errno = 0;
1383   if ( (port = atoi(argv[++i])) < 1 ) {
[1486]1384#ifdef ROAR_HAVE_GETSERVBYNAME
[446]1385    if ( (serv = getservbyname(argv[i], "tcp")) == NULL ) {
1386     ROAR_ERR("Unknown service: %s: %s", argv[i], strerror(errno));
1387     return 1;
1388    }
1389    // NOTE: we need to use ROAR_NET2HOST16() here even if s_port is of type int!
1390    ROAR_DBG("main(*): serv = {s_name='%s', s_aliases={...}, s_port=%i, s_proto='%s'}",
1391            serv->s_name, ROAR_NET2HOST16(serv->s_port), serv->s_proto);
1392    port = ROAR_NET2HOST16(serv->s_port);
[1486]1393#else
1394    ROAR_ERR("invalite port number: %s", argv[i]);
1395    return 1;
1396#endif
[446]1397   }
[1494]1398#endif
[1115]1399  } else if ( strcmp(k, "-b") == 0 || strcmp(k, "--bind") == 0 || strcmp(k, "--sock") == 0 ) {
[1494]1400#ifdef ROAR_SUPPORT_LISTEN
[2530]1401   sock_addr = argv[++i];
1402#endif
1403
1404  } else if ( strcmp(k, "--proto") == 0 ) {
1405#ifdef ROAR_SUPPORT_LISTEN
[2549]1406   if ( (sock_proto = roar_str2proto(argv[++i])) == -1 ) {
[2530]1407    ROAR_ERR("Unknown protocol: %s", argv[i]);
1408    return 1;
1409   }
[1494]1410#endif
[3252]1411  } else if ( strcmp(k, "--proto-dir") == 0 ) {
1412#ifdef ROAR_SUPPORT_LISTEN
1413   if ( (sock_dir = roar_str2dir(argv[++i])) == -1 ) {
1414    ROAR_ERR("Unknown stream direction: %s", argv[i]);
1415    return 1;
1416   }
1417#endif
1418  } else if ( strcmp(k, "--proto-rate") == 0 ) {
1419#ifdef ROAR_SUPPORT_LISTEN
1420   sock_info.rate = atoi(argv[++i]);
1421#endif
1422  } else if ( strcmp(k, "--proto-bits") == 0 ) {
1423#ifdef ROAR_SUPPORT_LISTEN
1424   sock_info.bits = atoi(argv[++i]);
1425#endif
1426  } else if ( strcmp(k, "--proto-chans") == 0 ) {
1427#ifdef ROAR_SUPPORT_LISTEN
1428   sock_info.channels = atoi(argv[++i]);
1429#endif
1430  } else if ( strcmp(k, "--proto-codec") == 0 ) {
1431#ifdef ROAR_SUPPORT_LISTEN
1432   if ( (sock_info.codec = roar_str2codec(argv[++i])) == -1 ) {
1433    ROAR_ERR("Unknown codec: %s", argv[i]);
1434    return 1;
1435   }
1436#endif
1437
1438
[3127]1439  } else if ( strcmp(k, "--list-proto") == 0 ) {
1440   list_proto();
1441   return 0;
[518]1442
[573]1443  } else if ( strcmp(k, "-t") == 0 || strcmp(k, "--tcp") == 0 ) {
[1494]1444#ifdef ROAR_SUPPORT_LISTEN
[518]1445   if ( sock_type != ROAR_SOCKET_TYPE_TCP && sock_type != ROAR_SOCKET_TYPE_TCP6 )
1446    sock_type = ROAR_SOCKET_TYPE_TCP;
1447
[2530]1448   if ( *sock_addr == '/' )
1449    sock_addr = ROAR_DEFAULT_HOST;
[1494]1450#endif
[518]1451
1452  } else if ( strcmp(k, "-4") == 0 ) {
[1494]1453#ifdef ROAR_SUPPORT_LISTEN
[517]1454   sock_type = ROAR_SOCKET_TYPE_TCP;
[2530]1455   if ( *sock_addr == '/' )
1456    sock_addr = ROAR_DEFAULT_HOST;
[1494]1457#endif
[518]1458  } else if ( strcmp(k, "-6") == 0 ) {
[1494]1459#ifdef ROAR_SUPPORT_LISTEN
[519]1460#ifdef PF_INET6
[518]1461   sock_type = ROAR_SOCKET_TYPE_TCP6;
[2530]1462   if ( *sock_addr == '/' )
1463    sock_addr = ROAR_DEFAULT_HOST;
[519]1464#else
1465    ROAR_ERR("No IPv6 support compiled in!");
1466    return 1;
1467#endif
[1494]1468#endif
[518]1469
[573]1470  } else if ( strcmp(k, "-u") == 0 || strcmp(k, "--unix") == 0 ) {
[1494]1471#ifdef ROAR_SUPPORT_LISTEN
[62]1472   // ignore this case as it is the default behavor.
[517]1473   sock_type = ROAR_SOCKET_TYPE_UNIX;
[1494]1474#endif
[518]1475
[573]1476  } else if ( strcmp(k, "-n") == 0 || strcmp(k, "--decnet") == 0 ) {
[1494]1477#ifdef ROAR_SUPPORT_LISTEN
[508]1478#ifdef ROAR_HAVE_LIBDNET
1479    port   = ROAR_DEFAULT_NUM;
1480    strcpy(decnethost, ROAR_DEFAULT_LISTEN_OBJECT);
[2530]1481    sock_addr = decnethost;
[517]1482    sock_type = ROAR_SOCKET_TYPE_DECNET;
[508]1483#else
1484    ROAR_ERR("No DECnet support compiled in!");
1485    return 1;
1486#endif
[1494]1487#endif
[2530]1488  } else if ( strcmp(k, "--new-sock") == 0 ) {
1489#ifdef ROAR_SUPPORT_LISTEN
[3252]1490   if ( add_listen(sock_addr, port, sock_type, sock_user, sock_grp, sock_proto, sock_dir, &sock_info) != 0 ) {
[2530]1491    ROAR_ERR("Can not open listen socket!");
1492    return 1;
1493   }
1494#endif
[518]1495
[1993]1496  } else if ( strcmp(k, "--slp") == 0 ) {
1497#ifdef ROAR_HAVE_LIBSLP
1498   reg_slp = 1;
1499#else
[3373]1500   ROAR_ERR("No OpenSLP support compiled in!");
1501   return 1;
[1993]1502#endif
1503
[3373]1504  } else if ( strcmp(k, "--x11") == 0 ) {
1505#ifdef ROAR_HAVE_LIBX11
1506   reg_x11 = 1;
1507#else
1508   ROAR_ERR("No X11 support compiled in!");
1509   return 1;
1510#endif
1511
1512
[3039]1513  } else if ( strcmp(k, "--jumbo-mtu") == 0 ) {
1514   g_config->jumbo_mtu = atoi(argv[++i]);
1515
[60]1516  } else if ( strcmp(k, "-G") == 0 ) {
[444]1517   sock_grp  = argv[++i];
1518  } else if ( strcmp(k, "-U") == 0 ) {
1519   sock_user = argv[++i];
[0]1520
[68]1521  } else if ( strcmp(k, "--no-listen") == 0 ) {
[1494]1522#ifdef ROAR_SUPPORT_LISTEN
[2530]1523   sock_addr   = "";
[548]1524   g_terminate = 1;
[1155]1525   g_no_listen = 1;
[1494]1526#endif
[68]1527  } else if ( strcmp(k, "--client-fh") == 0 ) {
1528   if ( clients_set_fh(clients_new(), atoi(argv[++i])) == -1 ) {
1529    ROAR_ERR("main(*): Can not set client's fh");
1530    return 1;
1531   }
[501]1532  } else if ( strcmp(k, "--close-fh") == 0 ) {
[1486]1533#ifdef ROAR_HAVE_IO_POSIX
[501]1534   close(atoi(argv[++i]));
[1486]1535#else
1536   i++;
1537   ROAR_WARN("can not close file handle %s (closing not supported)", argv[i]);
1538#endif
[68]1539
[920]1540  } else if ( strcmp(k, "--standby") == 0 ) {
1541   g_standby = 1;
1542  } else if ( strcmp(k, "--auto-standby") == 0 ) {
1543   g_autostandby = 1;
[0]1544  } else {
1545   usage();
1546   return 1;
1547  }
1548
1549 }
[1503]1550#endif
[0]1551
[2485]1552#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[1110]1553 if ( s_dev != NULL ) {
1554  if ( sources_add(s_drv, s_dev, s_con, s_opt, s_prim) == -1 ) {
1555   ROAR_ERR("main(*): adding source '%s' via '%s' failed!", s_dev, s_drv);
1556  }
1557 }
[2485]1558#endif
[1110]1559
[1145]1560 add_output(o_drv, o_dev, o_opts, o_prim, o_count);
[932]1561
[0]1562 ROAR_DBG("Server config: rate=%i, bits=%i, chans=%i", sa.rate, sa.bits, sa.channels);
1563
[2945]1564 if ( waveform_init() == -1 ) {
1565  ROAR_ERR("Can not initialize Waveform subsystem");
1566  return 1;
1567 }
1568
[2500]1569#ifndef ROAR_WITHOUT_DCOMP_MIDI
[1819]1570 if ( midi_init() == -1 ) {
[281]1571  ROAR_ERR("Can not initialize MIDI subsystem");
[1819]1572 }
[2500]1573#endif
[1819]1574
[2489]1575#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
[2451]1576 if ( ssynth_init() == -1 ) {
1577  ROAR_ERR("Can not initialize ssynth subsystem");
1578 }
[2489]1579#endif
[2451]1580
[2494]1581#ifndef ROAR_WITHOUT_DCOMP_LIGHT
[1819]1582 if ( light_init(light_channels) == -1 ) {
1583  ROAR_ERR("Can not initialize light control subsystem");
1584 }
[2494]1585#endif
[281]1586
[2718]1587#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1588 if ( rdtcs_init() == -1 ) {
1589  ROAR_ERR("Can not initialize RDTCS subsystem");
1590 }
1591#endif
1592
[3354]1593 if ( plugins_init() == -1 ) {
1594  ROAR_ERR("Can not initialize plugins");
1595 }
1596
[1494]1597#ifdef ROAR_SUPPORT_LISTEN
[3252]1598 if ( add_listen(sock_addr, port, sock_type, sock_user, sock_grp, sock_proto, sock_dir, &sock_info) != 0 ) {
[2530]1599  ROAR_ERR("Can not open listen socket!");
1600  return 1;
[60]1601 }
[1494]1602#endif
[60]1603
[0]1604 if ( output_buffer_init(&sa) == -1 ) {
1605  ROAR_ERR("Can not init output buffer!");
1606  return 1;
1607 }
1608
[1145]1609 if ( driver == NULL ) {
1610  driver = "null";
1611 } else {
1612  ROAR_WARN("Usage of old driver interface. use -o not -d!");
1613 }
1614
[0]1615 if ( driver_open(&drvinst, &drvid, driver, device, &sa) == -1 ) {
1616  ROAR_ERR("Can not open output driver!");
1617  return 1;
1618 }
1619
[44]1620 if ( samples_init() == -1 ) {
1621  ROAR_ERR("Can not init samples!");
1622  return 1;
1623 }
1624
1625
[1486]1626 // we should handle this on microcontrollers, too.
[1753]1627#if !defined(ROAR_TARGET_MICROCONTROLLER) && !defined(ROAR_TARGET_WIN32)
[0]1628 signal(SIGINT,  on_sig_int);
[2732]1629 signal(SIGTERM, on_sig_term);
[285]1630 signal(SIGCHLD, on_sig_chld);
[2112]1631 signal(SIGUSR1, on_sig_usr1);
[0]1632 signal(SIGPIPE, SIG_IGN);  // ignore broken pipes
[1486]1633#endif
[0]1634
[275]1635 if ( realtime ) {
[278]1636#ifdef DEBUG
1637  ROAR_WARN("compiled with -DDEBUG but realtime is enabled: for real realtime support compiel without -DDEBUG");
1638#endif
1639
[1486]1640#ifdef ROAR_HAVE_NICE
[275]1641  errno = 0;
[276]1642  nice(-5*realtime); // -5 for each --realtime
[1486]1643  if ( errno ) {
1644   ROAR_WARN("Can not decrease nice value by %i: %s", 5*realtime, strerror(errno));
1645  }
1646#else
1647  ROAR_WARN("Can not decrease nice value by %i: %s", 5*realtime, strerror(errno));
1648#endif
[277]1649/*
[276]1650#ifdef __linux__
[277]1651  if ( ioprio_set(IOPRIO_WHO_PROCESS, getpid(), IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0)) == -1 )
1652   ROAR_WARN("Can not set io priority: %s", strerror(errno));
[276]1653#endif
[277]1654*/
[275]1655 }
1656
[2756]1657#if defined(ROAR_HAVE_SETGID) && defined(ROAR_HAVE_IO_POSIX)
[444]1658 if ( setids & R_SETGID ) {
[2754]1659  if ( sock_grp == NULL ) {
1660   ROAR_ERR("Can not set GID if no groupname is supplied");
1661   return 1;
1662  }
[2584]1663  if ( (grp = getgrnam(sock_grp)) == NULL ) {
1664   ROAR_ERR("Can not get GID for group %s: %s", sock_grp, strerror(errno));
1665   return 1;
1666  }
[444]1667  if ( setgroups(0, (const gid_t *) NULL) == -1 ) {
1668   ROAR_ERR("Can not clear supplementary group IDs: %s", strerror(errno));
1669  }
[523]1670  if ( !grp || setgid(grp->gr_gid) == -1 ) {
[444]1671   ROAR_ERR("Can not set GroupID: %s", strerror(errno));
1672  }
1673 }
[1486]1674#endif
[444]1675
[0]1676
[39]1677 clients_set_pid(g_self_client, getpid());
[1753]1678#ifdef ROAR_HAVE_GETUID
[440]1679 clients_set_uid(g_self_client, getuid());
[1753]1680#endif
1681#ifdef ROAR_HAVE_GETGID
[440]1682 clients_set_gid(g_self_client, getgid());
[1753]1683#endif
[39]1684 clients_get(g_self_client, &self);
[37]1685
[39]1686 if ( self == NULL ) {
1687  ROAR_ERR("Can not get self client!");
1688  return 1;
1689 }
1690
[775]1691 strcpy(self->name, "RoarAudio daemon internal");
[68]1692
[2815]1693 if ( roar_nnode_free(&(self->nnode)) == -1 )
1694  return 1;
1695
1696 // not fully correct but ok as workaorund
1697 // so tools assume that roard runs on the same machine as
1698 // they in case they use AF_UNIX:
1699 if ( roar_nnode_new(&(self->nnode), ROAR_SOCKET_TYPE_UNIX) == -1 )
1700  return 1;
1701
[1486]1702#ifdef ROAR_HAVE_FORK
[775]1703 if ( daemon ) {
[68]1704  close(ROAR_STDIN );
1705  close(ROAR_STDOUT);
1706  close(ROAR_STDERR);
[1753]1707
[68]1708  if ( fork() )
[1486]1709   ROAR_U_EXIT(0);
[1753]1710
1711#ifdef ROAR_HAVE_SETSID
1712  setsid();
1713#endif
[1046]1714  clients_set_pid(g_self_client, getpid()); // reset pid as it changed
[68]1715 }
[1486]1716#endif
[68]1717
[2757]1718#if defined(ROAR_HAVE_SETUID) && defined(ROAR_HAVE_IO_POSIX)
1719 // early test for UID as we need this for the pidfile and the setuid()
1720 if ( sock_user != NULL ) {
1721  if ( (pwd = getpwnam(sock_user)) == NULL ) {
1722   ROAR_ERR("Can not get UID for user %s: %s", sock_user, strerror(errno));
1723   return 1;
1724  }
1725 }
1726#endif
1727
[2104]1728#ifdef SUPPORT_PIDFILE
[2106]1729 if ( pidfile != NULL ) {
1730  if ( roar_vio_open_file(&pidfile_vio, pidfile, O_WRONLY|O_CREAT, 0644) == -1 ) {
1731   ROAR_ERR("Can not write pidfile: %s", pidfile);
1732  } else {
1733   roar_vio_printf(&pidfile_vio, "%i\n", getpid());
1734   roar_vio_close(&pidfile_vio);
1735  }
[2765]1736#if defined(ROAR_HAVE_SETGID) && defined(ROAR_HAVE_SETUID) && defined(ROAR_HAVE_IO_POSIX)
[2759]1737  if ( pwd || grp ) {
1738   if ( chown(pidfile, pwd ? pwd->pw_uid : -1, grp ? grp->gr_gid : -1) == -1 ) {
1739    ROAR_WARN("Can not change ownership of pidfile: %s: %s", pidfile, strerror(errno));
1740   }
1741  }
1742  if ( chmod(pidfile, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1 ) {
1743   ROAR_WARN("Can not change permissions of pidfile: %s: %s", pidfile, strerror(errno));
1744  }
[2765]1745#endif
[2104]1746 }
1747#endif
1748
[1486]1749#ifdef ROAR_HAVE_CHROOT
[444]1750 if (chrootdir) {
1751  if ( chroot(chrootdir) == -1 ) {
1752   ROAR_ERR("Can not chroot to %s: %s", chrootdir, strerror(errno));
1753   return 2;
1754  }
1755  if ( chdir("/") == -1 ) {
1756   ROAR_ERR("Can not chdir to /: %s", strerror(errno));
1757   return 2;
1758  }
1759 }
[1486]1760#endif
[444]1761
[2756]1762#if defined(ROAR_HAVE_SETUID) && defined(ROAR_HAVE_IO_POSIX)
[444]1763 if ( setids & R_SETUID ) {
[2752]1764  if ( sock_user == NULL ) {
1765   ROAR_ERR("Can not set UID if no username is supplied");
1766   return 1;
1767  }
[444]1768  if ( !pwd || setuid(pwd->pw_uid) == -1 ) {
1769   ROAR_ERR("Can not set UserID: %s", strerror(errno));
1770   return 3;
1771  }
[1753]1772#ifdef ROAR_HAVE_GETUID
[444]1773  clients_set_uid(g_self_client, getuid());
[1753]1774#endif
[444]1775 }
[1486]1776#endif
[444]1777
[1993]1778 // Register with OpenSLP:
[2028]1779#ifdef ROAR_HAVE_LIBSLP
[1993]1780 if ( reg_slp ) {
[2530]1781  register_slp(0, sock_addr);
[1993]1782 }
[2028]1783#endif
[1993]1784
[3373]1785#ifdef ROAR_HAVE_LIBX11
1786 if ( reg_x11 ) {
1787  register_x11(0, sock_addr);
1788 }
1789#endif
1790
[0]1791 // start main loop...
[905]1792 main_loop(drvid, drvinst, &sa, sysclocksync);
[0]1793
1794 // clean up.
1795 clean_quit_prep();
1796 driver_close(drvinst, drvid);
1797 output_buffer_free();
1798
1799 return 0;
1800}
1801
[574]1802void cleanup_listen_socket (int terminate) {
[2530]1803 int i;
1804
[1993]1805 // Deregister from SLP:
[2028]1806#ifdef ROAR_HAVE_LIBSLP
[1993]1807 register_slp(1, NULL);
[2028]1808#endif
[580]1809
[3373]1810#ifdef ROAR_HAVE_LIBX11
1811 register_x11(1, NULL);
1812#endif
1813
[1494]1814#ifdef ROAR_SUPPORT_LISTEN
[2530]1815 for (i = 0; i < ROAR_MAX_LISTEN_SOCKETS; i++) {
[3129]1816  if ( g_listen[i].socket != -1 ) {
[1486]1817#ifdef ROAR_HAVE_IO_POSIX
[3129]1818   close(g_listen[i].socket);
[1486]1819#endif // #else is useless because we are in void context.
[60]1820
[3129]1821   g_listen[i].socket = -1;
[576]1822
[1486]1823#ifdef ROAR_HAVE_UNIX
[2530]1824   if ( server[i] != NULL )
1825    if ( *(server[i]) == '/' )
1826     unlink(server[i]);
[1486]1827#endif
[2530]1828  }
[580]1829 }
[60]1830
[1494]1831#endif
1832
[574]1833 if ( terminate )
1834  g_terminate = 1;
1835}
1836
1837void clean_quit_prep (void) {
1838 cleanup_listen_socket(0);
[60]1839
[3354]1840 plugins_free();
1841
[2485]1842#ifndef ROAR_WITHOUT_DCOMP_SOURCES
[0]1843 sources_free();
[2485]1844#endif
[0]1845 streams_free();
1846 clients_free();
[2489]1847#ifndef ROAR_WITHOUT_DCOMP_SSYNTH
[2451]1848 ssynth_free();
[2489]1849#endif
[2487]1850#ifndef ROAR_WITHOUT_DCOMP_CB
[282]1851 midi_cb_stop(); // stop console beep
[2487]1852#endif
[2500]1853#ifndef ROAR_WITHOUT_DCOMP_MIDI
[281]1854 midi_free();
[2500]1855#endif
[2494]1856#ifndef ROAR_WITHOUT_DCOMP_LIGHT
[1819]1857 light_free();
[2494]1858#endif
[2718]1859#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1860 rdtcs_free();
1861#endif
[2104]1862
[2945]1863 waveform_free();
1864
[2104]1865#ifdef SUPPORT_PIDFILE
1866 if ( pidfile != NULL )
1867  unlink(pidfile);
1868#endif
[0]1869}
1870
1871void clean_quit (void) {
1872 clean_quit_prep();
1873// driver_close(drvinst, drvid);
1874// output_buffer_free();
1875 exit(0);
1876}
1877
1878//ll
Note: See TracBrowser for help on using the repository browser.