source: roaraudio/roard/roard.c @ 2451:e6aedd121ada

Last change on this file since 2451:e6aedd121ada was 2451:e6aedd121ada, checked in by phi, 15 years ago

init/free ssynth

File size: 34.7 KB
Line 
1//roard.c:
2
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
25#include "roard.h"
26
27#ifdef ROAR_SUPPORT_LISTEN
28char * server = ROAR_DEFAULT_SOCK_GLOBAL; // global server address
29#endif
30
31#if defined(ROAR_HAVE_IO_POSIX) && defined(ROAR_HAVE_FS_POSIX)
32#define SUPPORT_PIDFILE
33char * pidfile = NULL;
34#endif
35
36#ifdef ROAR_HAVE_MAIN_ARGS
37void usage (void) {
38 printf("Usage: roard [OPTIONS]...\n\n");
39
40 printf("Misc Options:\n\n");
41 printf(
42        " --daemon              - Bring the server into background after init\n"
43        " --terminate           - Terminate after last client quited\n"
44        " --start               - No op parameter (starting roard is default operation)\n"
45        " --restart             - Trys to stop an old instance and start a new with new settings\n"
46        " --stop                - Stops a running roard (provide --pidfile!)\n"
47        " --shutdown            - Terminates a running roard (provide --pidfile!)\n"
48        " --realtime            - Trys to get realtime priority,\n"
49        "                         give multible times for being more realtime\n"
50        " --chroot DIR          - chroots to the given dir\n"
51        " --setgid              - GroupID to the audio group as specified via -G\n"
52        " --setuid              - UserID to the audio user as specified via -U\n"
53        " --sysclocksync        - calculate exact sample rate using the system clock\n"
54        " --location  LOC       - Set lion readable location of server\n"
55#ifdef SUPPORT_PIDFILE
56        " --pidfile PIDFILE     - Write a pidfile at PIDFILE\n"
57#endif
58       );
59
60 printf("\nAudio Options:\n\n");
61 printf(
62        " -R  --rate   RATE     - Set server rate\n"
63        " -B  --bits   BITS     - Set server bits\n"
64        " -C  --chans  CHANNELS - Set server channels\n"
65       );
66
67 printf("\nStream Options:\n\n");
68 printf(
69        " --stream-flags D=F    - Set default flags for stream directions\n"
70        "                         D is the stream direction and F is a comma seperated\n"
71        "                         list of flags in form +flag or -flag to set or unset\n"
72        "                         a flag as default or remove it from the default\n"
73       );
74
75 printf("\nDriver Options: (obsolete, do not use, Use Ouput Options)\n\n");
76 printf(" -d  --driver DRV      - Set the driver (default: %s)\n", ROAR_DRIVER_DEFAULT);
77 printf(" -D  --device DEV      - Set the device\n");
78 printf(" -dO OPTS              - Set output options\n");
79 printf(" --list-driver         - List all drivers\n");
80
81 printf("\nOutput Options:\n\n");
82 printf(" -o  --odriver DRV     - Set the driver, use '--list-driver' to get a list\n");
83 printf(" -O  --odevice DEV     - Set the device\n");
84 printf(" -oO OPTS              - Set output options\n");
85 printf(" -oN                   - Adds another output\n");
86 printf(" -oP                   - Mark output as primary\n");
87
88 printf("\nSource Options:\n\n");
89 printf(" -s  --source DRV      - Use DRV as input driver\n"
90        " -S           DEV      - Use DEV as input device\n"
91        " -sO          OPTS     - Use OPTS as input options\n"
92        " -sN                   - Adds another source\n"
93        " -sP                   - Make souce as primary\n"
94       );
95 printf(" --list-sources        - List all sources\n");
96
97 printf("\nCodec Filter Options:\n\n");
98 printf(" --list-cf             - List all codec filter\n"
99       );
100
101 printf("\nMIDI Options:\n\n");
102 printf(" --midi-no-console     - Disable console based MIDI synth\n"
103        " --midi-console-enable - Enables the console based MIDI synth\n"
104        " --midi-console DEV    - Set device for MIDI console\n"
105        " --ssynth-enable       - Enable simple software synth\n"
106        " --ssynth-disable      - Disable simple software synth\n"
107       );
108
109 printf("\nLight Control Options:\n\n");
110 printf(" --light-channels NUM  - Sets the number of channels for Light control (default: %i)\n",
111                                  LIGHT_CHANNELS_DEFAULT
112       );
113
114 printf("\nServer Options:\n\n");
115 printf(" -t  --tcp             - Use TCP listen socket\n"
116        " -u  --unix            - Use UNIX Domain listen socket (default)\n"
117#ifdef ROAR_HAVE_LIBDNET
118        " -n  --decnet          - use DECnet listen socket\n"
119#endif
120        " -4                    - Use IPv4 connections (implies -t)\n"
121#ifdef PF_INET6
122        " -6                    - Use IPv6 connections (implies -t)\n"
123#endif
124#ifdef IPV6_ADDRFORM
125        " -64                   - Try to downgrade sockets from IPv6 into IPv4,\n"
126        "                         this is normaly not usefull.\n"
127#endif
128        " -p  --port            - TCP Port to bind to\n"
129        " -b  --bind            - IP/Hostname to bind to\n"
130        "     --sock            - Filename for UNIX Domain Socket\n"
131#ifdef ROAR_HAVE_LIBSLP
132        "     --slp             - Enable OpenSLP support\n"
133#endif
134        " -G  GROUP             - Sets the group for the UNIX Domain Socket, (default: %s)\n"
135        "                         You need the permittions to change the GID\n"
136        " -U  USER              - Sets the user for the UNIX Domain Socket, (default: do not set)\n"
137        "                         You need the permittions to change the UID (normaly only root has)\n"
138        " --no-listen           - Do not listen for new clients\n"
139        "                         (only usefull for relaing, impleys --terminate)\n"
140        " --client-fh           - Comunicate with a client over this handle\n"
141        "                         (only usefull for relaing)\n"
142        " --close-fh            - Closes the given fh\n"
143        " --standby             - Start in standby state\n"
144        " --auto-standby        - Automatical goes into standby if there are no streams\n",
145        ROAR_DEFAULT_SOCKGRP
146       );
147// printf("\n Options:\n\n");
148 printf("\n");
149}
150#endif
151
152int restart_server (char * server, int terminate) {
153 struct roar_connection con;
154#ifdef ROAR_HAVE_KILL
155 char buf[80];
156 ssize_t l;
157 struct roar_vio_calls fh;
158 pid_t pid;
159 int ok;
160
161 if ( pidfile != NULL ) {
162  if ( roar_vio_open_file(&fh, pidfile, O_RDONLY, 0644) == -1 ) {
163   ROAR_WARN("restart_server(*): Can not read pidfile: %s", pidfile);
164  } else {
165   l = roar_vio_read(&fh, buf, 80);
166   roar_vio_close(&fh);
167   if ( l > 0 ) {
168    buf[l-1] = 0;
169    buf[79]  = 0;
170    pid = atoi(buf);
171    if ( terminate ) {
172     ok = kill(pid, SIGUSR1);
173    } else {
174     ok = kill(pid, SIGINT);
175    }
176    if ( ok == 0 ) {
177     return 0;
178    } else {
179     ROAR_WARN("restart_server(*): Can not kill roard by pidfile");
180    }
181   } else {
182    ROAR_WARN("restart_server(*): Can not find a PID in the pidfile");
183   }
184  }
185 }
186#endif
187
188 if ( roar_connect(&con, server) == -1 ) {
189  return -1;
190 }
191
192 if ( roar_terminate(&con, terminate) == -1 ) {
193  return -1;
194 }
195
196 return roar_disconnect(&con);
197}
198
199#define R_SETUID 1
200#define R_SETGID 2
201
202int init_config (void) {
203 int i;
204
205 memset(g_config, 0, sizeof(struct roard_config));
206
207 for (i = 0; i < ROAR_DIR_DIRIDS; i++) {
208  g_config->streams[i].mixer_channels = 1;
209  g_config->streams[i].mixer.rpg_mul  = 1;
210  g_config->streams[i].mixer.rpg_div  = 1;
211  g_config->streams[i].mixer.scale    = 65535;
212  g_config->streams[i].mixer.mixer[0] = g_config->streams[i].mixer.scale;
213 }
214
215 g_config->streams[ROAR_DIR_PLAY    ].flags = ROAR_FLAG_META;
216 g_config->streams[ROAR_DIR_OUTPUT  ].flags = ROAR_FLAG_PASSMIXER;
217 g_config->streams[ROAR_DIR_FILTER  ].flags = ROAR_FLAG_SYNC;
218 g_config->streams[ROAR_DIR_MIDI_OUT].flags = ROAR_FLAG_SYNC;
219 g_config->streams[ROAR_DIR_BIDIR   ].flags = ROAR_FLAG_ANTIECHO;
220
221 g_config->location = "***default***";
222
223 return 0;
224}
225
226int update_stream_flags (char * str) {
227 int    dir;
228 char * flags;
229 char * k;
230 int    op;
231 int    flag;
232
233 if ( (flags = strstr(str, "=")) == NULL )
234  return -1;
235
236 *flags = 0;
237  flags++;
238
239 if ( (dir = roar_str2dir(str)) == -1 )
240  return -1;
241
242 while (flags != NULL) {
243  k = flags;
244  flags = strstr(flags, ",");
245
246  if ( flags != NULL )
247   *(flags++) = 0;
248
249  switch (*k) {
250   case '+': k++; op = ROAR_SET_FLAG;   break;
251   case '-': k++; op = ROAR_RESET_FLAG; break;
252   default:
253     op = ROAR_SET_FLAG;
254  }
255
256  flag = 0;
257
258  if ( !strcmp(k, "sync") ) {
259   flag = ROAR_FLAG_SYNC;
260  } else if ( !strcmp(k, "meta") ) {
261   flag = ROAR_FLAG_META;
262  } else if ( !strcmp(k, "cleanmeta") ) {
263   flag = ROAR_FLAG_CLEANMETA;
264  } else if ( !strcmp(k, "pause") ) {
265   flag = ROAR_FLAG_PAUSE;
266  } else if ( !strcmp(k, "mute") ) {
267   flag = ROAR_FLAG_MUTE;
268  } else if ( !strcmp(k, "antiecho") ) {
269   flag = ROAR_FLAG_ANTIECHO;
270  } else if ( !strcmp(k, "passmixer") ) {
271   flag = ROAR_FLAG_PASSMIXER;
272  } else {
273   return -1;
274  }
275
276  g_config->streams[dir].flags |= flag;
277
278  if ( op == ROAR_RESET_FLAG )
279   g_config->streams[dir].flags -= flag;
280 }
281
282 return 0;
283}
284
285int add_output (char * drv, char * dev, char * opts, int prim, int count) {
286 int stream;
287 struct roar_stream * s;
288 struct roar_stream_server * ss;
289 char * k, * v;
290#ifdef ROAR_DRIVER_CODEC
291 char * to_free = NULL;
292#endif
293 int codec;
294 int sync = 0, f_mmap = 0;
295 int32_t blocks = -1, blocksize = -1;
296 int dir = ROAR_DIR_OUTPUT;
297 int error = 0;
298 // DMX:
299 int32_t channel  = -1;
300 int32_t universe = -1;
301 uint16_t tu16;
302 float q = -32e6;
303
304 ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = ?", drv, dev, opts);
305
306 if ( drv == NULL && count == 0 ) {
307  drv  = ROAR_DRIVER_DEFAULT;
308  prim = 1;
309  sync = 1;
310
311#ifdef ROAR_DRIVER_CODEC
312  if ( opts == NULL ) {
313   opts = to_free = strdup("codec=" ROAR_DRIVER_CODEC);
314  }
315#endif
316 }
317
318 if ( opts == NULL && count == 0 ) {
319  sync = 1;
320  prim = 1; // if ( prim == 0 ) prim = 1; -> prim allways = 1
321 }
322
323 if ( (stream = streams_new()) == -1 ) {
324  ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = -1", drv, dev, opts);
325  if ( prim ) alive = 0;
326  return -1;
327 }
328
329 streams_get(stream, &ss);
330 s = ROAR_STREAM(ss);
331
332 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
333
334 s->pos_rel_id = -1;
335// s->info.codec = codec;
336
337 codec = s->info.codec;
338
339 k = strtok(opts, ",");
340 while (k != NULL) {
341//  ROAR_WARN("add_output(*): opts: %s", k);
342
343  if ( (v = strstr(k, "=")) != NULL ) {
344   *v++ = 0;
345  }
346
347  ROAR_DBG("add_output(*): opts: k='%s', v='%s'", k, v);
348  if ( strcmp(k, "rate") == 0 ) {
349   s->info.rate = atoi(v);
350  } else if ( strcmp(k, "channels") == 0 ) {
351   s->info.channels = atoi(v);
352  } else if ( strcmp(k, "bits") == 0 ) {
353   s->info.bits = atoi(v);
354  } else if ( strcmp(k, "codec") == 0 ) {
355   if ( (codec = roar_str2codec(v)) == -1 ) {
356    ROAR_ERR("add_output(*): unknown codec '%s'", v);
357    error++;
358   }
359  } else if ( strcmp(k, "q") == 0 ) {
360   q = atof(v);
361  } else if ( strcmp(k, "blocks") == 0 ) {
362   blocks = atoi(v);
363  } else if ( strcmp(k, "blocksize") == 0 ) {
364   blocksize = atoi(v);
365  } else if ( strcmp(k, "mmap") == 0 ) {
366   f_mmap = 1;
367  } else if ( strcmp(k, "subsystem") == 0 ) {
368   if ( !strcasecmp(v, "wave") || !strcasecmp(v, "waveform") ) {
369    dir = ROAR_DIR_OUTPUT;
370   } else if ( !strcasecmp(v, "midi") ) {
371    dir = ROAR_DIR_MIDI_OUT;
372   } else if ( !strcasecmp(v, "light") ) {
373    dir = ROAR_DIR_LIGHT_OUT;
374   } else if ( !strcasecmp(v, "raw") ) {
375    dir = ROAR_DIR_RAW_OUT;
376   } else {
377    ROAR_ERR("add_output(*): unknown subsystem '%s'", k);
378    error++;
379   }
380  // DMX:
381  } else if ( strcmp(k, "channel") == 0 ) {
382   channel  = atoi(v);
383   if ( channel < 0 || channel > 65535 ) {
384    ROAR_ERR("add_output(*): Invalide channel (not within 0..65535): %i", channel);
385    channel = -1;
386    error++;
387   }
388  } else if ( strcmp(k, "universe") == 0 ) {
389   universe = atoi(v);
390   if ( universe < 0 || universe > 255 ) {
391    ROAR_ERR("add_output(*): Invalide universe (not within 0..255): %i", universe);
392    universe = -1;
393    error++;
394   }
395
396  } else if ( strcmp(k, "name") == 0 ) {
397   if ( streams_set_name(stream, v) == -1 ) {
398    ROAR_ERR("add_output(*): Can not set Stream name");
399    error++;
400   }
401
402  } else if ( strcmp(k, "meta") == 0 ) {
403   streams_set_flag(stream, ROAR_FLAG_META);
404  } else if ( strcmp(k, "sync") == 0 ) {
405   sync = 1;
406  } else if ( strcmp(k, "primary") == 0 ) {
407   prim = 1;
408
409  } else if ( strcmp(k, "cleanmeta") == 0 ) {
410   streams_set_flag(stream, ROAR_FLAG_CLEANMETA);
411  } else if ( strcmp(k, "autoconf") == 0 ) {
412   streams_set_flag(stream, ROAR_FLAG_AUTOCONF);
413  } else if ( strcmp(k, "recsource") == 0 ) {
414   streams_set_flag(stream, ROAR_FLAG_RECSOURCE);
415  } else if ( strcmp(k, "passmixer") == 0 ) {
416   streams_set_flag(stream, ROAR_FLAG_PASSMIXER);
417  } else {
418   ROAR_ERR("add_output(*): unknown option '%s'", k);
419   error++;
420  }
421
422  if ( error ) {
423   streams_delete(stream);
424   if ( prim ) alive = 0;
425#ifdef ROAR_DRIVER_CODEC
426   if ( to_free != NULL )
427    free(to_free);
428#endif
429   return -1;
430  }
431
432  k = strtok(NULL, ",");
433 }
434
435 if ( streams_set_dir(stream, dir, 1) == -1 ) {
436  streams_delete(stream);
437  return -1;
438 }
439
440#ifdef ROAR_DRIVER_CODEC
441 if ( to_free != NULL )
442  free(to_free);
443#endif
444
445 if ( codec == ROAR_CODEC_ALAW || codec == ROAR_CODEC_MULAW )
446  s->info.bits = 8; // needed to open OSS driver, will be overriden by codecfilter
447
448 s->info.codec = codec;
449 ROAR_STREAM_SERVER(s)->codec_orgi = codec;
450
451 if ( driver_openvio(&(ss->vio), &(ss->driver_id), drv, dev, &(s->info), -1, ss) == -1 ) {
452  ss->driver_id = -1; // don't close a driver not opened...
453  memset(&(ss->vio), 0, sizeof(struct roar_vio_calls));
454  streams_delete(stream);
455  ROAR_DBG("add_output(drv='%s', dev='%s', opts='%s') = -1", drv, dev, opts);
456  if ( prim ) alive = 0;
457  return -1;
458 }
459
460 roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_SSTREAMID, &stream); // ignore errors here
461 roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_SSTREAM,   s); // ignore errors here
462
463 if ( blocks != -1 )
464  roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_DBLOCKS, &blocks);
465
466 if ( blocksize != -1 )
467  roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_DBLKSIZE, &blocksize);
468
469 // TODO: we shoudld *really* check for errors here...
470 if ( channel != -1 ) {
471  tu16 = channel;
472  roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_DMXSCHAN, &tu16);
473 }
474 if ( universe != -1 ) {
475  tu16 = universe;
476  roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_SET_DMXUNIV, &tu16);
477 }
478
479 ROAR_DBG("add_output(*): ss->driver_id=%i", ss->driver_id);
480
481 streams_set_fh(stream, -1); // update some internal structures
482
483 if ( q > -1e6 ) {
484  ROAR_DBG("add_output(*): setting q=%f", q);
485  streams_ctl(stream, ROAR_CODECFILTER_CTL_SET_Q|ROAR_STREAM_CTL_TYPE_FLOAT, &q);
486 }
487
488 client_stream_add(g_source_client, stream);
489
490 if ( prim ) {
491  streams_mark_primary(stream);
492  s->pos_rel_id = stream;
493 }
494
495 if ( sync ) {
496  streams_set_flag(stream, ROAR_FLAG_SYNC);
497 } else {
498  streams_reset_flag(stream, ROAR_FLAG_SYNC);
499 }
500
501 if ( f_mmap )
502  streams_set_flag(stream, ROAR_FLAG_MMAP);
503
504 return 0;
505}
506
507
508// SLP:
509void register_slp_callback(SLPHandle hslp, SLPError errcode, void * cookie) {
510 /* return the error code in the cookie */
511 *(SLPError*)cookie = errcode;
512}
513
514int register_slp (int unreg, char * sockname) {
515#ifdef ROAR_HAVE_LIBSLP
516 static int regged = 0;
517 static char * sn = NULL;
518 SLPError err;
519 SLPError callbackerr;
520 SLPHandle hslp;
521 char addr[1024];
522 char attr[1024] = "";
523 char * location;
524
525 if ( sockname != NULL )
526  sn = sockname;
527
528 snprintf(addr, sizeof(addr), ROAR_SLP_URL_TYPE "://%s", sn);
529
530 err = SLPOpen("en", SLP_FALSE, &hslp);
531
532 if (err != SLP_OK) {
533  ROAR_ERR("Error opening slp handle: Error #%i", err);
534  return -1;
535 }
536
537 if (!unreg) {
538
539  if ( SLPEscape(g_config->location, &location, SLP_FALSE) != SLP_OK ) {
540   ROAR_ERR("Error using SLPEscape() on server location, really bad!");
541   SLPClose(hslp);
542   return -1;
543  }
544
545  snprintf(attr, sizeof(attr), "(wave-rate=%i),(wave-channels=%i),(wave-bits=%i),"
546                               "(light-channels=%i),(location=%s)",
547           g_sa->rate, g_sa->channels, g_sa->bits,
548           g_light_state.channels,
549           location
550          );
551
552  /* Register a service with SLP */
553  err = SLPReg(hslp,
554               addr,
555               SLP_LIFETIME_MAXIMUM,
556               0,
557               attr,
558               SLP_TRUE,
559               register_slp_callback,
560               &callbackerr);
561  regged = 1;
562 } else if ( unreg && regged ) {
563  err = SLPDereg(hslp, addr, register_slp_callback, &callbackerr);
564  regged = 0;
565 } else {
566  SLPClose(hslp);
567  return -1;
568 }
569
570 /* err may contain an error code that occurred as the slp library    */
571 /* _prepared_ to make the call.                                     */
572 if ( err != SLP_OK ) {
573  ROAR_ERR("Error (de)registering service with slp: Error #%i", err);
574  return -1;
575 }
576
577 /* callbackerr may contain an error code (that was assigned through */
578 /* the callback cookie) that occurred as slp packets were sent on    */
579 /* the wire */
580 if (callbackerr != SLP_OK) {
581  ROAR_ERR("Error (de)registering service with slp: Error #%i", callbackerr);
582  return -1;
583 }
584
585 SLPClose(hslp);
586 return 0;
587#else
588 return -1;
589#endif
590}
591
592
593// MAIN:
594
595#ifdef ROAR_HAVE_MAIN_ARGS
596int main (int argc, char * argv[]) {
597#else
598int main (void) {
599#endif
600#ifdef ROAR_HAVE_MAIN_ARGS
601 int i;
602 char * k;
603#endif
604#ifdef ROAR_SUPPORT_LISTEN
605 char user_sock[80]  = {0};
606#endif
607 struct roar_audio_info sa, max_sa;
608 struct roard_config config;
609#ifdef ROAR_HAVE_FORK
610 int    daemon       = 0;
611#endif
612 int    realtime     = 0;
613 int    sysclocksync = 0;
614 char * driver    = NULL;
615 char * device    = NULL;
616#ifdef ROAR_HAVE_MAIN_ARGS
617 char * opts      = NULL;
618#endif
619// char * server = ROAR_DEFAULT_SOCK_GLOBAL;
620#ifdef ROAR_SUPPORT_LISTEN
621 int      port    = ROAR_DEFAULT_PORT;
622#endif
623 int               drvid;
624 char * s_drv     = "cf";
625 char * s_dev     = NULL;
626 char * s_con     = NULL;
627 char * s_opt     = NULL;
628 int    s_prim    = 0;
629 char * o_drv     = getenv("ROAR_DRIVER");
630 char * o_dev     = getenv("ROAR_DEVICE");
631 char * o_opts    = NULL;
632 int    o_prim    = 0;
633 int    o_count   = 0;
634 int    light_channels = LIGHT_CHANNELS_DEFAULT;
635 char * sock_grp  = ROAR_DEFAULT_SOCKGRP;
636 char * sock_user = NULL;
637#ifdef ROAR_SUPPORT_LISTEN
638 int    sock_type = ROAR_SOCKET_TYPE_UNKNOWN;
639#endif
640#ifdef ROAR_HAVE_LIBSLP
641 int    reg_slp   = 0;
642#endif
643#ifdef ROAR_HAVE_CHROOT
644 char * chrootdir = NULL;
645#endif
646#if defined(ROAR_HAVE_SETGID) || defined(ROAR_HAVE_SETUID)
647 int    setids    = 0;
648#endif
649#ifdef ROAR_HAVE_UNIX
650 char * env_roar_proxy_backup;
651#endif
652#if defined(ROAR_HAVE_SETGID) && defined(ROAR_HAVE_IO_POSIX)
653 struct group   * grp  = NULL;
654#endif
655#if defined(ROAR_HAVE_SETUID) && defined(ROAR_HAVE_IO_POSIX)
656 struct passwd  * pwd  = NULL;
657#endif
658#ifdef ROAR_HAVE_GETSERVBYNAME
659 struct servent * serv = NULL;
660#endif
661 DRIVER_USERDATA_T drvinst;
662 struct roar_client * self = NULL;
663#ifdef ROAR_HAVE_LIBDNET
664 char decnethost[80];
665#endif
666#ifdef SUPPORT_PIDFILE
667 struct roar_vio_calls pidfile_vio;
668#endif
669
670 g_standby       =  0;
671 g_autostandby   =  0;
672 alive           =  1;
673#ifdef ROAR_SUPPORT_LISTEN
674 g_no_listen     =  0;
675 g_listen_socket = -1;
676#else
677 g_terminate     =  1;
678#endif
679
680 sa.bits     = ROAR_BITS_DEFAULT;
681 sa.channels = ROAR_CHANNELS_DEFAULT;
682 sa.rate     = ROAR_RATE_DEFAULT;
683 sa.codec    = ROAR_CODEC_DEFAULT;
684
685 g_sa        = &sa;
686 g_max_sa    = &max_sa;
687
688 memcpy(g_max_sa, g_sa, sizeof(max_sa));
689
690 g_config = &config;
691
692 if ( init_config() == -1 ) {
693  ROAR_ERR("Can not init default config!");
694  return 1;
695 }
696
697 if ( midi_init_config() == -1 ) {
698  ROAR_ERR("Can not init MIDI config!");
699  return 1;
700 }
701
702 if ( ssynth_init_config() == -1 ) {
703  ROAR_ERR("Can not init ssynth config!");
704  return 1;
705 }
706
707#ifdef ROAR_SUPPORT_LISTEN
708#ifdef ROAR_HAVE_GETUID
709 if ( getuid() != 0 && getenv("HOME") != NULL ) {
710  snprintf(user_sock, 79, "%s/%s", (char*)getenv("HOME"), ROAR_DEFAULT_SOCK_USER);
711  server = user_sock;
712 }
713#endif
714
715 if ( getenv("ROAR_SERVER") != NULL )
716  server = getenv("ROAR_SERVER");
717#endif
718
719 if ( clients_init() == -1 ) {
720  ROAR_ERR("Can not init clients!");
721  return 1;
722 }
723
724 if ( streams_init() == -1 ) {
725  ROAR_ERR("Can not init streams!");
726  return 1;
727 }
728
729 if ( (g_self_client = clients_new()) == -1 ) {
730  ROAR_ERR("Can not create self client!");
731  return 1;
732 }
733
734 if ( sources_init() == -1 ) {
735  ROAR_ERR("Can not init sources!");
736  return 1;
737 }
738
739 if ( (sources_set_client(g_self_client)) == -1 ) {
740  ROAR_ERR("Can not init set source client!");
741  return 1;
742 }
743
744#ifdef ROAR_HAVE_MAIN_ARGS
745 for (i = 1; i < argc; i++) {
746  k = argv[i];
747
748  if ( strcmp(k, "-h") == 0 || strcmp(k, "--help") == 0 ) {
749   usage();
750   return 0;
751
752  } else if ( strcmp(k, "--start") == 0 ) {
753   // this is a no op
754  } else if ( strcmp(k, "--restart") == 0 ) {
755#ifdef ROAR_SUPPORT_LISTEN
756   if ( restart_server(server, 1) == -1 ) {
757    ROAR_WARN("Can not terminate old server (not running at %s?), tring to continue anyway", server);
758   }
759#else
760   ROAR_ERR("--restart not supported");
761#endif
762  } else if ( strcmp(k, "--shutdown") == 0 ) {
763#ifdef ROAR_SUPPORT_LISTEN
764   if ( restart_server(server, 1) == -1 ) {
765    ROAR_WARN("Can not terminate old server (not running at %s?)", server);
766    return 1;
767   }
768   return 0;
769#else
770   ROAR_ERR("--shutdown not supported");
771   return 1;
772#endif
773  } else if ( strcmp(k, "--stop") == 0 ) {
774#ifdef ROAR_SUPPORT_LISTEN
775   if ( restart_server(server, 0) == -1 ) {
776    ROAR_WARN("Can not stop old server (not running at %s?)", server);
777    return 1;
778   }
779   return 0;
780#else
781   ROAR_ERR("--stop not supported");
782   return 1;
783#endif
784
785
786  } else if ( strcmp(k, "--demon") == 0 || strcmp(k, "--daemon") == 0 ) {
787#ifdef ROAR_HAVE_FORK
788   daemon = 1;
789#else
790   ROAR_ERR("--daemon not supported");
791#endif
792  } else if ( strcmp(k, "--terminate") == 0 ) {
793   g_terminate = 1;
794  } else if ( strcmp(k, "--sysclocksync") == 0 ) {
795   sysclocksync = 1000;
796  } else if ( strcmp(k, "--realtime") == 0 ) {
797   realtime++;
798  } else if ( strcmp(k, "--chroot") == 0 ) {
799#ifdef ROAR_HAVE_CHROOT
800   chrootdir = argv[++i];
801#else
802   ROAR_ERR("--chroot not supported");
803   i++;
804#endif
805  } else if ( strcmp(k, "--setgid") == 0 ) {
806#ifdef ROAR_HAVE_SETGID
807   setids |= R_SETGID;
808#else
809   ROAR_ERR("--setgid not supported");
810#endif
811  } else if ( strcmp(k, "--setuid") == 0 ) {
812#ifdef ROAR_HAVE_SETUID
813   setids |= R_SETUID;
814#else
815   ROAR_ERR("--setuid not supported");
816#endif
817  } else if ( strcmp(k, "--location") == 0 ) {
818   g_config->location = argv[++i];
819  } else if ( strcmp(k, "--pidfile") == 0 ) {
820#ifdef SUPPORT_PIDFILE
821   pidfile = argv[++i];
822#else
823   ROAR_ERR("--pidfile not supported");
824   i++;
825#endif
826
827  } else if ( strcmp(k, "--list-cf") == 0 ) {
828   print_codecfilterlist();
829   return 0;
830
831  } else if ( strcmp(k, "-R") == 0 || strcmp(k, "--rate") == 0 ) {
832   sa.rate = atoi(argv[++i]);
833  } else if ( strcmp(k, "-B") == 0 || strcmp(k, "--bits") == 0 ) {
834   sa.bits = atoi(argv[++i]);
835  } else if ( strcmp(k, "-C") == 0 || strcmp(k, "--chans") == 0 ) {
836   sa.channels = atoi(argv[++i]);
837
838  } else if ( strcmp(k, "--stream-flags") == 0 ) {
839   if ( update_stream_flags(argv[++i]) == -1 ) {
840    ROAR_ERR("Can not set stream flags");
841    return 1;
842   }
843
844  } else if ( strcmp(k, "-d") == 0 || strcmp(k, "--driver") == 0 ) {
845   driver = argv[++i];
846   if ( strcmp(driver, "list") == 0 ) {
847    ROAR_WARN("The option is obsolete, use --list-driver!");
848    print_driverlist();
849    return 0;
850   }
851  } else if ( strcmp(k, "-D") == 0 || strcmp(k, "--device") == 0 ) {
852   device = argv[++i];
853  } else if ( strcmp(k, "-dO") == 0 ) {
854   opts = argv[++i];
855  } else if ( strcmp(k, "--list-driver") == 0 ) {
856   print_driverlist();
857   return 0;
858
859  } else if ( strcmp(k, "-o") == 0 || strcmp(k, "--odriver") == 0 ) {
860   o_drv  = argv[++i];
861  } else if ( strcmp(k, "-O") == 0 || strcmp(k, "--odevice") == 0 ) {
862   o_dev  = argv[++i];
863  } else if ( strcmp(k, "-oO") == 0 ) {
864   o_opts = argv[++i];
865  } else if ( strcmp(k, "-oP") == 0 ) {
866   o_prim = 1;
867  } else if ( strcmp(k, "-oN") == 0 ) {
868   if ( add_output(o_drv, o_dev, o_opts, o_prim, o_count) != -1 )
869    o_count++;
870
871   o_drv  = o_dev = o_opts = NULL;
872   o_prim = 0;
873
874  } else if ( strcmp(k, "-s") == 0 || strcmp(k, "--source") == 0 ) {
875   s_drv = argv[++i];
876  } else if ( strcmp(k, "-S") == 0 ) {
877   s_dev = argv[++i];
878  } else if ( strcmp(k, "-sO") == 0 ) {
879   s_opt = argv[++i];
880  } else if ( strcmp(k, "-sC") == 0 ) {
881   s_con = argv[++i];
882  } else if ( strcmp(k, "-sP") == 0 ) {
883   s_prim = 1;
884  } else if ( strcmp(k, "-sN") == 0 ) {
885   if ( sources_add(s_drv, s_dev, s_con, s_opt, s_prim) == -1 ) {
886    ROAR_ERR("main(*): adding source '%s' via '%s' failed!", s_dev, s_drv);
887   }
888   s_opt = s_dev = s_con = NULL;
889   s_drv = "cf";
890   s_prim = 0;
891  } else if ( strcmp(k, "--list-sources") == 0 ) {
892   print_sourcelist();
893   return 0;
894
895  } else if ( strcmp(k, "--light-channels") == 0 ) {
896   light_channels = atoi(argv[++i]);
897
898  } else if ( strcmp(k, "--midi-no-console") == 0 ) {
899   midi_config.init_cb = 0;
900  } else if ( strcmp(k, "--midi-console-enable") == 0 ) {
901   midi_config.init_cb = 1;
902  } else if ( strcmp(k, "--midi-console") == 0 ) {
903   midi_config.console_dev = argv[++i];
904   midi_config.init_cb = 1;
905
906  } else if ( strcmp(k, "--ssynth-enable") == 0 ) {
907   ssynth_conf.enable = 1;
908  } else if ( strcmp(k, "--ssynth-disable") == 0 ) {
909   ssynth_conf.enable = 0;
910
911  } else if ( strcmp(k, "-p") == 0 || strcmp(k, "--port") == 0 ) {
912   // This is only usefull in INET not UNIX mode.
913#ifdef ROAR_SUPPORT_LISTEN
914   if ( *server == '/' )
915    server = ROAR_DEFAULT_HOST;
916
917   errno = 0;
918   if ( (port = atoi(argv[++i])) < 1 ) {
919#ifdef ROAR_HAVE_GETSERVBYNAME
920    if ( (serv = getservbyname(argv[i], "tcp")) == NULL ) {
921     ROAR_ERR("Unknown service: %s: %s", argv[i], strerror(errno));
922     return 1;
923    }
924    // NOTE: we need to use ROAR_NET2HOST16() here even if s_port is of type int!
925    ROAR_DBG("main(*): serv = {s_name='%s', s_aliases={...}, s_port=%i, s_proto='%s'}",
926            serv->s_name, ROAR_NET2HOST16(serv->s_port), serv->s_proto);
927    port = ROAR_NET2HOST16(serv->s_port);
928#else
929    ROAR_ERR("invalite port number: %s", argv[i]);
930    return 1;
931#endif
932   }
933#endif
934  } else if ( strcmp(k, "-b") == 0 || strcmp(k, "--bind") == 0 || strcmp(k, "--sock") == 0 ) {
935#ifdef ROAR_SUPPORT_LISTEN
936   server = argv[++i];
937#endif
938
939  } else if ( strcmp(k, "-t") == 0 || strcmp(k, "--tcp") == 0 ) {
940#ifdef ROAR_SUPPORT_LISTEN
941   if ( sock_type != ROAR_SOCKET_TYPE_TCP && sock_type != ROAR_SOCKET_TYPE_TCP6 )
942    sock_type = ROAR_SOCKET_TYPE_TCP;
943
944   if ( *server == '/' )
945    server = ROAR_DEFAULT_HOST;
946#endif
947
948  } else if ( strcmp(k, "-4") == 0 ) {
949#ifdef ROAR_SUPPORT_LISTEN
950   sock_type = ROAR_SOCKET_TYPE_TCP;
951   if ( *server == '/' )
952    server = ROAR_DEFAULT_HOST;
953#endif
954  } else if ( strcmp(k, "-6") == 0 ) {
955#ifdef ROAR_SUPPORT_LISTEN
956#ifdef PF_INET6
957   sock_type = ROAR_SOCKET_TYPE_TCP6;
958   if ( *server == '/' )
959    server = ROAR_DEFAULT_HOST;
960#else
961    ROAR_ERR("No IPv6 support compiled in!");
962    return 1;
963#endif
964#endif
965
966  } else if ( strcmp(k, "-u") == 0 || strcmp(k, "--unix") == 0 ) {
967#ifdef ROAR_SUPPORT_LISTEN
968   // ignore this case as it is the default behavor.
969   sock_type = ROAR_SOCKET_TYPE_UNIX;
970#endif
971
972  } else if ( strcmp(k, "-n") == 0 || strcmp(k, "--decnet") == 0 ) {
973#ifdef ROAR_SUPPORT_LISTEN
974#ifdef ROAR_HAVE_LIBDNET
975    port   = ROAR_DEFAULT_NUM;
976    strcpy(decnethost, ROAR_DEFAULT_LISTEN_OBJECT);
977    server = decnethost;
978    sock_type = ROAR_SOCKET_TYPE_DECNET;
979#else
980    ROAR_ERR("No DECnet support compiled in!");
981    return 1;
982#endif
983#endif
984
985  } else if ( strcmp(k, "--slp") == 0 ) {
986#ifdef ROAR_HAVE_LIBSLP
987   reg_slp = 1;
988#else
989    ROAR_ERR("No OpenSLP support compiled in!");
990    return 1;
991#endif
992
993  } else if ( strcmp(k, "-G") == 0 ) {
994   sock_grp  = argv[++i];
995  } else if ( strcmp(k, "-U") == 0 ) {
996   sock_user = argv[++i];
997
998  } else if ( strcmp(k, "--no-listen") == 0 ) {
999#ifdef ROAR_SUPPORT_LISTEN
1000   server      = "";
1001   g_terminate = 1;
1002   g_no_listen = 1;
1003#endif
1004  } else if ( strcmp(k, "--client-fh") == 0 ) {
1005   if ( clients_set_fh(clients_new(), atoi(argv[++i])) == -1 ) {
1006    ROAR_ERR("main(*): Can not set client's fh");
1007    return 1;
1008   }
1009  } else if ( strcmp(k, "--close-fh") == 0 ) {
1010#ifdef ROAR_HAVE_IO_POSIX
1011   close(atoi(argv[++i]));
1012#else
1013   i++;
1014   ROAR_WARN("can not close file handle %s (closing not supported)", argv[i]);
1015#endif
1016
1017  } else if ( strcmp(k, "--standby") == 0 ) {
1018   g_standby = 1;
1019  } else if ( strcmp(k, "--auto-standby") == 0 ) {
1020   g_autostandby = 1;
1021  } else {
1022   usage();
1023   return 1;
1024  }
1025
1026 }
1027#endif
1028
1029 if ( s_dev != NULL ) {
1030  if ( sources_add(s_drv, s_dev, s_con, s_opt, s_prim) == -1 ) {
1031   ROAR_ERR("main(*): adding source '%s' via '%s' failed!", s_dev, s_drv);
1032  }
1033 }
1034
1035 add_output(o_drv, o_dev, o_opts, o_prim, o_count);
1036
1037 ROAR_DBG("Server config: rate=%i, bits=%i, chans=%i", sa.rate, sa.bits, sa.channels);
1038
1039 if ( midi_init() == -1 ) {
1040  ROAR_ERR("Can not initialize MIDI subsystem");
1041 }
1042
1043 if ( ssynth_init() == -1 ) {
1044  ROAR_ERR("Can not initialize ssynth subsystem");
1045 }
1046
1047 if ( light_init(light_channels) == -1 ) {
1048  ROAR_ERR("Can not initialize light control subsystem");
1049 }
1050
1051#ifdef ROAR_SUPPORT_LISTEN
1052 if ( *server != 0 ) {
1053  if ( (g_listen_socket = roar_socket_listen(sock_type, server, port)) == -1 ) {
1054#ifdef ROAR_HAVE_UNIX
1055   if ( *server == '/' ) {
1056    if ( (env_roar_proxy_backup = getenv("ROAR_PROXY")) != NULL ) {
1057     env_roar_proxy_backup = strdup(env_roar_proxy_backup);
1058     unsetenv("ROAR_PROXY");
1059    }
1060    if ( (i = roar_socket_connect(server, port)) != -1 ) {
1061     close(i);
1062     ROAR_ERR("Can not open listen socket!");
1063     return 1;
1064    } else {
1065     unlink(server);
1066     if ( (g_listen_socket = roar_socket_listen(sock_type, server, port)) == -1 ) {
1067      ROAR_ERR("Can not open listen socket!");
1068      return 1;
1069     }
1070    }
1071    if ( env_roar_proxy_backup != NULL ) {
1072     setenv("ROAR_PROXY", env_roar_proxy_backup, 0);
1073     free(env_roar_proxy_backup);
1074    }
1075#else
1076   if (0) { // noop
1077#endif
1078   } else {
1079    ROAR_ERR("Can not open listen socket!");
1080    return 1;
1081   }
1082  }
1083
1084#if defined(ROAR_HAVE_SETGID) && defined(ROAR_HAVE_IO_POSIX)
1085  if ( (grp = getgrnam(sock_grp)) == NULL ) {
1086   ROAR_ERR("Can not get GID for group %s: %s", sock_grp, strerror(errno));
1087  }
1088#endif
1089#if defined(ROAR_HAVE_SETUID) && defined(ROAR_HAVE_IO_POSIX)
1090  if ( sock_user || (setids & R_SETUID) ) {
1091   if ( (pwd = getpwnam(sock_user)) == NULL ) {
1092    ROAR_ERR("Can not get UID for user %s: %s", sock_user, strerror(errno));
1093   }
1094  }
1095#endif
1096
1097#if defined(ROAR_HAVE_IO_POSIX) && defined(ROAR_HAVE_UNIX)
1098  if ( *server == '/' ) {
1099   if ( grp ) {
1100    if ( pwd ) {
1101     if ( chown(server, pwd->pw_uid, grp->gr_gid) == -1 )
1102      return 1;
1103    } else {
1104     if ( chown(server, -1, grp->gr_gid) == -1 )
1105      return 1;
1106    }
1107#ifdef ROAR_HAVE_GETUID
1108    if ( getuid() == 0 )
1109     if ( chmod(server, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1 )
1110      return 1;
1111#endif
1112   }
1113  }
1114#endif
1115 }
1116#endif
1117
1118 if ( output_buffer_init(&sa) == -1 ) {
1119  ROAR_ERR("Can not init output buffer!");
1120  return 1;
1121 }
1122
1123 if ( driver == NULL ) {
1124  driver = "null";
1125 } else {
1126  ROAR_WARN("Usage of old driver interface. use -o not -d!");
1127 }
1128
1129 if ( driver_open(&drvinst, &drvid, driver, device, &sa) == -1 ) {
1130  ROAR_ERR("Can not open output driver!");
1131  return 1;
1132 }
1133
1134 if ( samples_init() == -1 ) {
1135  ROAR_ERR("Can not init samples!");
1136  return 1;
1137 }
1138
1139
1140 // we should handle this on microcontrollers, too.
1141#if !defined(ROAR_TARGET_MICROCONTROLLER) && !defined(ROAR_TARGET_WIN32)
1142 signal(SIGINT,  on_sig_int);
1143 signal(SIGCHLD, on_sig_chld);
1144 signal(SIGUSR1, on_sig_usr1);
1145 signal(SIGPIPE, SIG_IGN);  // ignore broken pipes
1146#endif
1147
1148 if ( realtime ) {
1149#ifdef DEBUG
1150  ROAR_WARN("compiled with -DDEBUG but realtime is enabled: for real realtime support compiel without -DDEBUG");
1151#endif
1152
1153#ifdef ROAR_HAVE_NICE
1154  errno = 0;
1155  nice(-5*realtime); // -5 for each --realtime
1156  if ( errno ) {
1157   ROAR_WARN("Can not decrease nice value by %i: %s", 5*realtime, strerror(errno));
1158  }
1159#else
1160  ROAR_WARN("Can not decrease nice value by %i: %s", 5*realtime, strerror(errno));
1161#endif
1162/*
1163#ifdef __linux__
1164  if ( ioprio_set(IOPRIO_WHO_PROCESS, getpid(), IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0)) == -1 )
1165   ROAR_WARN("Can not set io priority: %s", strerror(errno));
1166#endif
1167*/
1168 }
1169
1170#ifdef ROAR_HAVE_SETGID
1171 if ( setids & R_SETGID ) {
1172  if ( setgroups(0, (const gid_t *) NULL) == -1 ) {
1173   ROAR_ERR("Can not clear supplementary group IDs: %s", strerror(errno));
1174  }
1175  if ( !grp || setgid(grp->gr_gid) == -1 ) {
1176   ROAR_ERR("Can not set GroupID: %s", strerror(errno));
1177  }
1178 }
1179#endif
1180
1181
1182 clients_set_pid(g_self_client, getpid());
1183#ifdef ROAR_HAVE_GETUID
1184 clients_set_uid(g_self_client, getuid());
1185#endif
1186#ifdef ROAR_HAVE_GETGID
1187 clients_set_gid(g_self_client, getgid());
1188#endif
1189 clients_get(g_self_client, &self);
1190
1191 if ( self == NULL ) {
1192  ROAR_ERR("Can not get self client!");
1193  return 1;
1194 }
1195
1196 strcpy(self->name, "RoarAudio daemon internal");
1197
1198#ifdef ROAR_HAVE_FORK
1199 if ( daemon ) {
1200  close(ROAR_STDIN );
1201  close(ROAR_STDOUT);
1202  close(ROAR_STDERR);
1203
1204  if ( fork() )
1205   ROAR_U_EXIT(0);
1206
1207#ifdef ROAR_HAVE_SETSID
1208  setsid();
1209#endif
1210  clients_set_pid(g_self_client, getpid()); // reset pid as it changed
1211 }
1212#endif
1213
1214#ifdef SUPPORT_PIDFILE
1215 if ( pidfile != NULL ) {
1216  if ( roar_vio_open_file(&pidfile_vio, pidfile, O_WRONLY|O_CREAT, 0644) == -1 ) {
1217   ROAR_ERR("Can not write pidfile: %s", pidfile);
1218  } else {
1219   roar_vio_printf(&pidfile_vio, "%i\n", getpid());
1220   roar_vio_close(&pidfile_vio);
1221  }
1222 }
1223#endif
1224
1225#ifdef ROAR_HAVE_CHROOT
1226 if (chrootdir) {
1227  if ( chroot(chrootdir) == -1 ) {
1228   ROAR_ERR("Can not chroot to %s: %s", chrootdir, strerror(errno));
1229   return 2;
1230  }
1231  if ( chdir("/") == -1 ) {
1232   ROAR_ERR("Can not chdir to /: %s", strerror(errno));
1233   return 2;
1234  }
1235 }
1236#endif
1237
1238#ifdef ROAR_HAVE_SETUID
1239 if ( setids & R_SETUID ) {
1240  if ( !pwd || setuid(pwd->pw_uid) == -1 ) {
1241   ROAR_ERR("Can not set UserID: %s", strerror(errno));
1242   return 3;
1243  }
1244#ifdef ROAR_HAVE_GETUID
1245  clients_set_uid(g_self_client, getuid());
1246#endif
1247 }
1248#endif
1249
1250 // Register with OpenSLP:
1251#ifdef ROAR_HAVE_LIBSLP
1252 if ( reg_slp ) {
1253  register_slp(0, server);
1254 }
1255#endif
1256
1257 // start main loop...
1258 main_loop(drvid, drvinst, &sa, sysclocksync);
1259
1260 // clean up.
1261 clean_quit_prep();
1262 driver_close(drvinst, drvid);
1263 output_buffer_free();
1264
1265 return 0;
1266}
1267
1268void cleanup_listen_socket (int terminate) {
1269 // Deregister from SLP:
1270#ifdef ROAR_HAVE_LIBSLP
1271 register_slp(1, NULL);
1272#endif
1273
1274#ifdef ROAR_SUPPORT_LISTEN
1275 if ( g_listen_socket != -1 ) {
1276#ifdef ROAR_HAVE_IO_POSIX
1277  close(g_listen_socket);
1278#endif // #else is useless because we are in void context.
1279
1280  g_listen_socket = -1;
1281
1282#ifdef ROAR_HAVE_UNIX
1283  if ( *server == '/' )
1284   unlink(server);
1285#endif
1286 }
1287
1288#endif
1289
1290 if ( terminate )
1291  g_terminate = 1;
1292}
1293
1294void clean_quit_prep (void) {
1295 cleanup_listen_socket(0);
1296
1297 sources_free();
1298 streams_free();
1299 clients_free();
1300 ssynth_free();
1301 midi_cb_stop(); // stop console beep
1302 midi_free();
1303 light_free();
1304
1305#ifdef SUPPORT_PIDFILE
1306 if ( pidfile != NULL )
1307  unlink(pidfile);
1308#endif
1309}
1310
1311void clean_quit (void) {
1312 clean_quit_prep();
1313// driver_close(drvinst, drvid);
1314// output_buffer_free();
1315 exit(0);
1316}
1317
1318//ll
Note: See TracBrowser for help on using the repository browser.