source: roaraudio/roard/roard.c @ 3981:0dda28251f72

Last change on this file since 3981:0dda28251f72 was 3981:0dda28251f72, checked in by phi, 14 years ago

activate rplay

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