source: roaraudio/roard/roard.c @ 3252:5dd53a288c8b

Last change on this file since 3252:5dd53a288c8b was 3252:5dd53a288c8b, checked in by phi, 14 years ago

added support for --proto-* options (no protocol does use it at the moment)

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