1 /* 2 * Shairport, an Apple Airplay receiver 3 * Copyright (c) James Laird 2013 4 * All rights reserved. 5 * Modifications and additions (c) Mike Brady 2014--2019 6 * 7 * Permission is hereby granted, free of charge, to any person 8 * obtaining a copy of this software and associated documentation 9 * files (the "Software"), to deal in the Software without 10 * restriction, including without limitation the rights to use, 11 * copy, modify, merge, publish, distribute, sublicense, and/or 12 * sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be 16 * included in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28 #include <errno.h> 29 #include <fcntl.h> 30 #include <getopt.h> 31 #include <libconfig.h> 32 #include <libgen.h> 33 #include <memory.h> 34 #include <net/if.h> 35 #include <popt.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <sys/socket.h> 39 #include <sys/stat.h> 40 #include <sys/types.h> 41 #include <sys/wait.h> 42 #include <unistd.h> 43 44 #include "config.h" 45 46 #ifdef CONFIG_MBEDTLS 47 #include <mbedtls/md5.h> 48 #include <mbedtls/version.h> 49 #endif 50 51 #ifdef CONFIG_POLARSSL 52 #include <polarssl/md5.h> 53 #endif 54 55 #ifdef CONFIG_OPENSSL 56 #include <openssl/md5.h> 57 #endif 58 59 #if defined(CONFIG_DBUS_INTERFACE) 60 #include <glib.h> 61 #endif 62 63 #include "activity_monitor.h" 64 #include "audio.h" 65 #include "common.h" 66 #include "rtp.h" 67 #include "rtsp.h" 68 69 #if defined(CONFIG_DACP_CLIENT) 70 #include "dacp.h" 71 #endif 72 73 #if defined(CONFIG_METADATA_HUB) 74 #include "metadata_hub.h" 75 #endif 76 77 #ifdef CONFIG_DBUS_INTERFACE 78 #include "dbus-service.h" 79 #endif 80 81 #ifdef CONFIG_MQTT 82 #include "mqtt.h" 83 #endif 84 85 #ifdef CONFIG_MPRIS_INTERFACE 86 #include "mpris-service.h" 87 #endif 88 89 #ifdef CONFIG_LIBDAEMON 90 #include <libdaemon/dexec.h> 91 #include <libdaemon/dfork.h> 92 #include <libdaemon/dlog.h> 93 #include <libdaemon/dpid.h> 94 #include <libdaemon/dsignal.h> 95 #else 96 #include <syslog.h> 97 #endif 98 99 #ifdef CONFIG_SOXR 100 #include <math.h> 101 #include <soxr.h> 102 #endif 103 104 #ifdef CONFIG_CONVOLUTION 105 #include <FFTConvolver/convolver.h> 106 #endif 107 108 #ifdef CONFIG_LIBDAEMON 109 pid_t pid; 110 int this_is_the_daemon_process = 0; 111 #endif 112 113 int killOption = 0; 114 int daemonisewith = 0; 115 int daemonisewithout = 0; 116 117 // static int shutting_down = 0; 118 char configuration_file_path[4096 + 1]; 119 char actual_configuration_file_path[4096 + 1]; 120 121 char first_backend_name[256]; 122 123 void print_version(void) { 124 char *version_string = get_version_string(); 125 if (version_string) { 126 printf("%s\n", version_string); 127 free(version_string); 128 } else { 129 debug(1, "Can't print version string!"); 130 } 131 } 132 #ifdef CONFIG_SOXR 133 pthread_t soxr_time_check_thread; 134 void *soxr_time_check(__attribute__((unused)) void *arg) { 135 const int buffer_length = 352; 136 int32_t inbuffer[buffer_length * 2]; 137 int32_t outbuffer[(buffer_length + 1) * 2]; 138 139 // int32_t *outbuffer = (int32_t*)malloc((buffer_length+1)*2*sizeof(int32_t)); 140 // int32_t *inbuffer = (int32_t*)malloc((buffer_length)*2*sizeof(int32_t)); 141 142 // generate a sample signal 143 const double frequency = 440; // 144 145 int i; 146 147 int number_of_iterations = 0; 148 uint64_t soxr_start_time = get_absolute_time_in_ns(); 149 uint64_t loop_until_time = 150 (uint64_t)1500000000 + soxr_start_time; // loop for a second and a half, max -- no need to be 151 // able to cancel it, do _don't even try_! 152 while (get_absolute_time_in_ns() < loop_until_time) { 153 154 number_of_iterations++; 155 for (i = 0; i < buffer_length; i++) { 156 double w = sin(i * (frequency + number_of_iterations * 2) * 2 * M_PI / 44100); 157 int32_t wint = (int32_t)(w * INT32_MAX); 158 inbuffer[i * 2] = wint; 159 inbuffer[i * 2 + 1] = wint; 160 } 161 162 soxr_io_spec_t io_spec; 163 io_spec.itype = SOXR_INT32_I; 164 io_spec.otype = SOXR_INT32_I; 165 io_spec.scale = 1.0; // this seems to crash if not = 1.0 166 io_spec.e = NULL; 167 io_spec.flags = 0; 168 169 size_t odone; 170 171 soxr_oneshot(buffer_length, buffer_length + 1, 2, // Rates and # of chans. 172 inbuffer, buffer_length, NULL, // Input. 173 outbuffer, buffer_length + 1, &odone, // Output. 174 &io_spec, // Input, output and transfer spec. 175 NULL, NULL); // Default configuration. 176 177 io_spec.itype = SOXR_INT32_I; 178 io_spec.otype = SOXR_INT32_I; 179 io_spec.scale = 1.0; // this seems to crash if not = 1.0 180 io_spec.e = NULL; 181 io_spec.flags = 0; 182 183 soxr_oneshot(buffer_length, buffer_length - 1, 2, // Rates and # of chans. 184 inbuffer, buffer_length, NULL, // Input. 185 outbuffer, buffer_length - 1, &odone, // Output. 186 &io_spec, // Input, output and transfer spec. 187 NULL, NULL); // Default configuration. 188 } 189 190 double soxr_execution_time_ns = (get_absolute_time_in_ns() - soxr_start_time) * 1.0; 191 // free(outbuffer); 192 // free(inbuffer); 193 config.soxr_delay_index = (int)(0.9 + soxr_execution_time_ns / (number_of_iterations * 1000000)); 194 debug(2, "soxr_delay_index: %d.", config.soxr_delay_index); 195 if ((config.packet_stuffing == ST_soxr) && 196 (config.soxr_delay_index > config.soxr_delay_threshold)) 197 inform("Note: this device may be too slow for \"soxr\" interpolation. Consider choosing the " 198 "\"basic\" or \"auto\" interpolation setting."); 199 if (config.packet_stuffing == ST_auto) 200 debug(1, "\"%s\" interpolation has been chosen.", 201 config.soxr_delay_index <= config.soxr_delay_threshold ? "soxr" : "basic"); 202 pthread_exit(NULL); 203 } 204 205 #endif 206 207 void usage(char *progname) { 208 printf("Usage: %s [options...]\n", progname); 209 printf(" or: %s [options...] -- [audio output-specific options]\n", progname); 210 printf("\n"); 211 printf("Options:\n"); 212 printf(" -h, --help show this help.\n"); 213 #ifdef CONFIG_LIBDAEMON 214 printf(" -d, --daemon daemonise.\n"); 215 printf(" -j, --justDaemoniseNoPIDFile daemonise without a PID file.\n"); 216 printf(" -k, --kill kill the existing shairport daemon.\n"); 217 #endif 218 printf(" -V, --version show version information.\n"); 219 printf(" -c, --configfile=FILE read configuration settings from FILE. Default is " 220 "/etc/shairport-sync.conf.\n"); 221 222 printf("\n"); 223 printf("The following general options are for backward compatibility. These and all new options " 224 "have settings in the configuration file, by default /etc/shairport-sync.conf:\n"); 225 printf(" -v, --verbose -v print debug information; -vv more; -vvv lots.\n"); 226 printf(" -p, --port=PORT set RTSP listening port.\n"); 227 printf(" -a, --name=NAME set advertised name.\n"); 228 printf(" -L, --latency=FRAMES [Deprecated] Set the latency for audio sent from an unknown " 229 "device.\n"); 230 printf(" The default is to set it automatically.\n"); 231 printf(" -S, --stuffing=MODE set how to adjust current latency to match desired latency, " 232 "where \n"); 233 printf(" \"basic\" inserts or deletes audio frames from " 234 "packet frames with low processor overhead, and \n"); 235 printf(" \"soxr\" uses libsoxr to minimally resample packet frames -- " 236 "moderate processor overhead.\n"); 237 printf( 238 " \"soxr\" option only available if built with soxr support.\n"); 239 printf(" -B, --on-start=PROGRAM run PROGRAM when playback is about to begin.\n"); 240 printf(" -E, --on-stop=PROGRAM run PROGRAM when playback has ended.\n"); 241 printf(" For -B and -E options, specify the full path to the program, " 242 "e.g. /usr/bin/logger.\n"); 243 printf( 244 " Executable scripts work, but must have the appropriate shebang " 245 "(#!/bin/sh) in the headline.\n"); 246 printf( 247 " -w, --wait-cmd wait until the -B or -E programs finish before continuing.\n"); 248 printf(" -o, --output=BACKEND select audio output method.\n"); 249 printf(" -m, --mdns=BACKEND force the use of BACKEND to advertize the service.\n"); 250 printf(" if no mdns provider is specified,\n"); 251 printf(" shairport tries them all until one works.\n"); 252 printf(" -r, --resync=THRESHOLD [Deprecated] resync if error exceeds this number of frames. " 253 "Set to 0 to " 254 "stop resyncing.\n"); 255 printf(" -t, --timeout=SECONDS go back to idle mode from play mode after a break in " 256 "communications of this many seconds (default 120). Set to 0 never to exit play mode.\n"); 257 printf(" --statistics print some interesting statistics -- output to the logfile " 258 "if running as a daemon.\n"); 259 printf(" --tolerance=TOLERANCE [Deprecated] allow a synchronization error of TOLERANCE " 260 "frames (default " 261 "88) before trying to correct it.\n"); 262 printf(" --password=PASSWORD require PASSWORD to connect. Default is not to require a " 263 "password.\n"); 264 printf(" --logOutputLevel log the output level setting -- useful for setting maximum " 265 "volume.\n"); 266 #ifdef CONFIG_METADATA 267 printf(" -M, --metadata-enable ask for metadata from the source and process it.\n"); 268 printf(" --metadata-pipename=PIPE send metadata to PIPE, e.g. " 269 "--metadata-pipename=/tmp/shairport-sync-metadata.\n"); 270 printf(" The default is /tmp/shairport-sync-metadata.\n"); 271 printf(" -g, --get-coverart send cover art through the metadata pipe.\n"); 272 #endif 273 printf(" -u, --use-stderr log messages through STDERR rather than the system log.\n"); 274 printf("\n"); 275 mdns_ls_backends(); 276 printf("\n"); 277 audio_ls_outputs(); 278 } 279 280 int parse_options(int argc, char **argv) { 281 // there are potential memory leaks here -- it's called a second time, previously allocated 282 // strings will dangle. 283 char *raw_service_name = NULL; /* Used to pick up the service name before possibly expanding it */ 284 char *stuffing = NULL; /* used for picking up the stuffing option */ 285 signed char c; /* used for argument parsing */ 286 // int i = 0; /* used for tracking options */ 287 int fResyncthreshold = (int)(config.resyncthreshold * 44100); 288 int fTolerance = (int)(config.tolerance * 44100); 289 poptContext optCon; /* context for parsing command-line options */ 290 struct poptOption optionsTable[] = { 291 {"verbose", 'v', POPT_ARG_NONE, NULL, 'v', NULL, NULL}, 292 {"kill", 'k', POPT_ARG_NONE, &killOption, 0, NULL, NULL}, 293 {"daemon", 'd', POPT_ARG_NONE, &daemonisewith, 0, NULL, NULL}, 294 {"justDaemoniseNoPIDFile", 'j', POPT_ARG_NONE, &daemonisewithout, 0, NULL, NULL}, 295 {"configfile", 'c', POPT_ARG_STRING, &config.configfile, 0, NULL, NULL}, 296 {"statistics", 0, POPT_ARG_NONE, &config.statistics_requested, 0, NULL, NULL}, 297 {"logOutputLevel", 0, POPT_ARG_NONE, &config.logOutputLevel, 0, NULL, NULL}, 298 {"version", 'V', POPT_ARG_NONE, NULL, 0, NULL, NULL}, 299 {"port", 'p', POPT_ARG_INT, &config.port, 0, NULL, NULL}, 300 {"name", 'a', POPT_ARG_STRING, &raw_service_name, 0, NULL, NULL}, 301 {"output", 'o', POPT_ARG_STRING, &config.output_name, 0, NULL, NULL}, 302 {"on-start", 'B', POPT_ARG_STRING, &config.cmd_start, 0, NULL, NULL}, 303 {"on-stop", 'E', POPT_ARG_STRING, &config.cmd_stop, 0, NULL, NULL}, 304 {"wait-cmd", 'w', POPT_ARG_NONE, &config.cmd_blocking, 0, NULL, NULL}, 305 {"mdns", 'm', POPT_ARG_STRING, &config.mdns_name, 0, NULL, NULL}, 306 {"latency", 'L', POPT_ARG_INT, &config.userSuppliedLatency, 0, NULL, NULL}, 307 {"stuffing", 'S', POPT_ARG_STRING, &stuffing, 'S', NULL, NULL}, 308 {"resync", 'r', POPT_ARG_INT, &fResyncthreshold, 0, NULL, NULL}, 309 {"timeout", 't', POPT_ARG_INT, &config.timeout, 't', NULL, NULL}, 310 {"password", 0, POPT_ARG_STRING, &config.password, 0, NULL, NULL}, 311 {"tolerance", 'z', POPT_ARG_INT, &fTolerance, 0, NULL, NULL}, 312 {"use-stderr", 'u', POPT_ARG_NONE, NULL, 'u', NULL, NULL}, 313 #ifdef CONFIG_METADATA 314 {"metadata-enable", 'M', POPT_ARG_NONE, &config.metadata_enabled, 'M', NULL, NULL}, 315 {"metadata-pipename", 0, POPT_ARG_STRING, &config.metadata_pipename, 0, NULL, NULL}, 316 {"get-coverart", 'g', POPT_ARG_NONE, &config.get_coverart, 'g', NULL, NULL}, 317 #endif 318 POPT_AUTOHELP{NULL, 0, 0, NULL, 0, NULL, NULL}}; 319 320 // we have to parse the command line arguments to look for a config file 321 int optind; 322 optind = argc; 323 int j; 324 for (j = 0; j < argc; j++) 325 if (strcmp(argv[j], "--") == 0) 326 optind = j; 327 328 optCon = poptGetContext(NULL, optind, (const char **)argv, optionsTable, 0); 329 if (optCon == NULL) 330 die("Can not get a secondary popt context."); 331 poptSetOtherOptionHelp(optCon, "[OPTIONS]* "); 332 333 /* Now do options processing just to get a debug level */ 334 debuglev = 0; 335 while ((c = poptGetNextOpt(optCon)) >= 0) { 336 switch (c) { 337 case 'v': 338 debuglev++; 339 break; 340 case 'u': 341 log_to_stderr(); 342 break; 343 case 'D': 344 inform("Warning: the option -D or --disconnectFromOutput is deprecated."); 345 break; 346 case 'R': 347 inform("Warning: the option -R or --reconnectToOutput is deprecated."); 348 break; 349 case 'A': 350 inform("Warning: the option -A or --AirPlayLatency is deprecated and ignored. This setting " 351 "is now " 352 "automatically received from the AirPlay device."); 353 break; 354 case 'i': 355 inform("Warning: the option -i or --iTunesLatency is deprecated and ignored. This setting is " 356 "now " 357 "automatically received from iTunes"); 358 break; 359 case 'f': 360 inform( 361 "Warning: the option --forkedDaapdLatency is deprecated and ignored. This setting is now " 362 "automatically received from forkedDaapd"); 363 break; 364 case 'r': 365 inform("Warning: the option -r or --resync is deprecated. Please use the " 366 "\"resync_threshold_in_seconds\" setting in the config file instead."); 367 break; 368 case 'z': 369 inform("Warning: the option --tolerance is deprecated. Please use the " 370 "\"drift_tolerance_in_seconds\" setting in the config file instead."); 371 break; 372 } 373 } 374 if (c < -1) { 375 die("%s: %s", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(c)); 376 } 377 378 poptFreeContext(optCon); 379 380 #ifdef CONFIG_LIBDAEMON 381 if ((daemonisewith) && (daemonisewithout)) 382 die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have selected " 383 "both!"); 384 if ((daemonisewith) || (daemonisewithout)) { 385 config.daemonise = 1; 386 if (daemonisewith) 387 config.daemonise_store_pid = 1; 388 }; 389 #endif 390 391 config.resyncthreshold = 1.0 * fResyncthreshold / 44100; 392 config.tolerance = 1.0 * fTolerance / 44100; 393 config.audio_backend_silent_lead_in_time_auto = 394 1; // start outputting silence as soon as packets start arriving 395 config.airplay_volume = -18.0; // if no volume is ever set, default to initial default value if 396 // nothing else comes in first. 397 config.fixedLatencyOffset = 11025; // this sounds like it works properly. 398 config.diagnostic_drop_packet_fraction = 0.0; 399 config.active_state_timeout = 10.0; 400 config.soxr_delay_threshold = 30; // the soxr measurement time (milliseconds) of two oneshots must 401 // not exceed this if soxr interpolation is to be chosen 402 // automatically. 403 config.volume_range_hw_priority = 404 0; // if combining software and hardware volume control, give the software priority 405 // i.e. when reducing volume, reduce the sw first before reducing the software. 406 // this is because some hw mixers mute at the bottom of their range, and they don't always 407 // advertise this fact 408 config.resend_control_first_check_time = 409 0.10; // wait this many seconds before requesting the resending of a missing packet 410 config.resend_control_check_interval_time = 411 0.25; // wait this many seconds before again requesting the resending of a missing packet 412 config.resend_control_last_check_time = 413 0.10; // give up if the packet is still missing this close to when it's needed 414 config.missing_port_dacp_scan_interval_seconds = 415 2.0; // check at this interval if no DACP port number is known 416 417 config.minimum_free_buffer_headroom = 125; // leave approximately one second's worth of buffers 418 // free after calculating the effective latency. 419 // e.g. if we have 1024 buffers or 352 frames = 8.17 seconds and we have a nominal latency of 2.0 420 // seconds then we can add an offset of 5.17 seconds and still leave a second's worth of buffers 421 // for unexpected circumstances 422 423 #ifdef CONFIG_METADATA 424 /* Get the metadata setting. */ 425 config.metadata_enabled = 1; // if metadata support is included, then enable it by default 426 config.get_coverart = 1; // if metadata support is included, then enable it by default 427 #endif 428 429 #ifdef CONFIG_CONVOLUTION 430 config.convolution_max_length = 8192; 431 #endif 432 config.loudness_reference_volume_db = -20; 433 434 #ifdef CONFIG_METADATA_HUB 435 config.cover_art_cache_dir = "/tmp/shairport-sync/.cache/coverart"; 436 config.scan_interval_when_active = 437 1; // number of seconds between DACP server scans when playing something 438 config.scan_interval_when_inactive = 439 1; // number of seconds between DACP server scans when playing nothing 440 config.scan_max_bad_response_count = 441 5; // number of successive bad results to ignore before giving up 442 // config.scan_max_inactive_count = 443 // (365 * 24 * 60 * 60) / config.scan_interval_when_inactive; // number of scans to do before 444 // stopping if 445 // not made active again (not used) 446 #endif 447 448 // config_setting_t *setting; 449 const char *str = 0; 450 int value = 0; 451 double dvalue = 0.0; 452 453 // debug(1, "Looking for the configuration file \"%s\".", config.configfile); 454 455 config_init(&config_file_stuff); 456 457 char *config_file_real_path = realpath(config.configfile, NULL); 458 if (config_file_real_path == NULL) { 459 debug(2, "can't resolve the configuration file \"%s\".", config.configfile); 460 } else { 461 debug(2, "looking for configuration file at full path \"%s\"", config_file_real_path); 462 /* Read the file. If there is an error, report it and exit. */ 463 if (config_read_file(&config_file_stuff, config_file_real_path)) { 464 free(config_file_real_path); 465 config_set_auto_convert(&config_file_stuff, 466 1); // allow autoconversion from int/float to int/float 467 // make config.cfg point to it 468 config.cfg = &config_file_stuff; 469 /* Get the Service Name. */ 470 if (config_lookup_string(config.cfg, "general.name", &str)) { 471 raw_service_name = (char *)str; 472 } 473 #ifdef CONFIG_LIBDAEMON 474 /* Get the Daemonize setting. */ 475 config_set_lookup_bool(config.cfg, "sessioncontrol.daemonize_with_pid_file", &daemonisewith); 476 477 /* Get the Just_Daemonize setting. */ 478 config_set_lookup_bool(config.cfg, "sessioncontrol.daemonize_without_pid_file", 479 &daemonisewithout); 480 481 /* Get the directory path for the pid file created when the program is daemonised. */ 482 if (config_lookup_string(config.cfg, "sessioncontrol.daemon_pid_dir", &str)) 483 config.piddir = (char *)str; 484 #endif 485 486 /* Get the mdns_backend setting. */ 487 if (config_lookup_string(config.cfg, "general.mdns_backend", &str)) 488 config.mdns_name = (char *)str; 489 490 /* Get the output_backend setting. */ 491 if (config_lookup_string(config.cfg, "general.output_backend", &str)) 492 config.output_name = (char *)str; 493 494 /* Get the port setting. */ 495 if (config_lookup_int(config.cfg, "general.port", &value)) { 496 if ((value < 0) || (value > 65535)) 497 die("Invalid port number \"%sd\". It should be between 0 and 65535, default is 5000", 498 value); 499 else 500 config.port = value; 501 } 502 503 /* Get the udp port base setting. */ 504 if (config_lookup_int(config.cfg, "general.udp_port_base", &value)) { 505 if ((value < 0) || (value > 65535)) 506 die("Invalid port number \"%sd\". It should be between 0 and 65535, default is 6001", 507 value); 508 else 509 config.udp_port_base = value; 510 } 511 512 /* Get the udp port range setting. This is number of ports that will be tried for free ports , 513 * starting at the port base. Only three ports are needed. */ 514 if (config_lookup_int(config.cfg, "general.udp_port_range", &value)) { 515 if ((value < 3) || (value > 65535)) 516 die("Invalid port range \"%sd\". It should be between 3 and 65535, default is 10", 517 value); 518 else 519 config.udp_port_range = value; 520 } 521 522 /* Get the password setting. */ 523 if (config_lookup_string(config.cfg, "general.password", &str)) 524 config.password = (char *)str; 525 526 if (config_lookup_string(config.cfg, "general.interpolation", &str)) { 527 if (strcasecmp(str, "basic") == 0) 528 config.packet_stuffing = ST_basic; 529 else if (strcasecmp(str, "auto") == 0) 530 config.packet_stuffing = ST_auto; 531 else if (strcasecmp(str, "soxr") == 0) 532 #ifdef CONFIG_SOXR 533 config.packet_stuffing = ST_soxr; 534 #else 535 warn("The soxr option not available because this version of shairport-sync was built " 536 "without libsoxr " 537 "support. Change the \"general/interpolation\" setting in the configuration file."); 538 #endif 539 else 540 die("Invalid interpolation option choice. It should be \"auto\", \"basic\" or \"soxr\""); 541 } 542 543 #ifdef CONFIG_SOXR 544 /* Get the soxr_delay_threshold setting. */ 545 if (config_lookup_int(config.cfg, "general.soxr_delay_threshold", &value)) { 546 if ((value >= 0) && (value <= 100)) 547 config.soxr_delay_threshold = value; 548 else 549 warn("Invalid general soxr_delay_threshold setting option choice \"%d\". It should be " 550 "between 0 and 100, " 551 "inclusive. Default is %d (milliseconds).", 552 value, config.soxr_delay_threshold); 553 } 554 #endif 555 556 /* Get the statistics setting. */ 557 if (config_set_lookup_bool(config.cfg, "general.statistics", 558 &(config.statistics_requested))) { 559 warn("The \"general\" \"statistics\" setting is deprecated. Please use the \"diagnostics\" " 560 "\"statistics\" setting instead."); 561 } 562 563 /* The old drift tolerance setting. */ 564 if (config_lookup_int(config.cfg, "general.drift", &value)) { 565 inform("The drift setting is deprecated. Use " 566 "drift_tolerance_in_seconds instead"); 567 config.tolerance = 1.0 * value / 44100; 568 } 569 570 /* The old resync setting. */ 571 if (config_lookup_int(config.cfg, "general.resync_threshold", &value)) { 572 inform("The resync_threshold setting is deprecated. Use " 573 "resync_threshold_in_seconds instead"); 574 config.resyncthreshold = 1.0 * value / 44100; 575 } 576 577 /* Get the drift tolerance setting. */ 578 if (config_lookup_float(config.cfg, "general.drift_tolerance_in_seconds", &dvalue)) 579 config.tolerance = dvalue; 580 581 /* Get the resync setting. */ 582 if (config_lookup_float(config.cfg, "general.resync_threshold_in_seconds", &dvalue)) 583 config.resyncthreshold = dvalue; 584 585 /* Get the verbosity setting. */ 586 if (config_lookup_int(config.cfg, "general.log_verbosity", &value)) { 587 warn("The \"general\" \"log_verbosity\" setting is deprecated. Please use the " 588 "\"diagnostics\" \"log_verbosity\" setting instead."); 589 if ((value >= 0) && (value <= 3)) 590 debuglev = value; 591 else 592 die("Invalid log verbosity setting option choice \"%d\". It should be between 0 and 3, " 593 "inclusive.", 594 value); 595 } 596 597 /* Get the verbosity setting. */ 598 if (config_lookup_int(config.cfg, "diagnostics.log_verbosity", &value)) { 599 if ((value >= 0) && (value <= 3)) 600 debuglev = value; 601 else 602 die("Invalid diagnostics log_verbosity setting option choice \"%d\". It should be " 603 "between 0 and 3, " 604 "inclusive.", 605 value); 606 } 607 608 /* Get the config.debugger_show_file_and_line in debug messages setting. */ 609 if (config_lookup_string(config.cfg, "diagnostics.log_show_file_and_line", &str)) { 610 if (strcasecmp(str, "no") == 0) 611 config.debugger_show_file_and_line = 0; 612 else if (strcasecmp(str, "yes") == 0) 613 config.debugger_show_file_and_line = 1; 614 else 615 die("Invalid diagnostics log_show_file_and_line option choice \"%s\". It should be " 616 "\"yes\" or \"no\""); 617 } 618 619 /* Get the show elapsed time in debug messages setting. */ 620 if (config_lookup_string(config.cfg, "diagnostics.log_show_time_since_startup", &str)) { 621 if (strcasecmp(str, "no") == 0) 622 config.debugger_show_elapsed_time = 0; 623 else if (strcasecmp(str, "yes") == 0) 624 config.debugger_show_elapsed_time = 1; 625 else 626 die("Invalid diagnostics log_show_time_since_startup option choice \"%s\". It should be " 627 "\"yes\" or \"no\""); 628 } 629 630 /* Get the show relative time in debug messages setting. */ 631 if (config_lookup_string(config.cfg, "diagnostics.log_show_time_since_last_message", &str)) { 632 if (strcasecmp(str, "no") == 0) 633 config.debugger_show_relative_time = 0; 634 else if (strcasecmp(str, "yes") == 0) 635 config.debugger_show_relative_time = 1; 636 else 637 die("Invalid diagnostics log_show_time_since_last_message option choice \"%s\". It " 638 "should be \"yes\" or \"no\""); 639 } 640 641 /* Get the statistics setting. */ 642 if (config_lookup_string(config.cfg, "diagnostics.statistics", &str)) { 643 if (strcasecmp(str, "no") == 0) 644 config.statistics_requested = 0; 645 else if (strcasecmp(str, "yes") == 0) 646 config.statistics_requested = 1; 647 else 648 die("Invalid diagnostics statistics option choice \"%s\". It should be \"yes\" or " 649 "\"no\""); 650 } 651 652 /* Get the disable_resend_requests setting. */ 653 if (config_lookup_string(config.cfg, "diagnostics.disable_resend_requests", &str)) { 654 config.disable_resend_requests = 0; // this is for legacy -- only set by -t 0 655 if (strcasecmp(str, "no") == 0) 656 config.disable_resend_requests = 0; 657 else if (strcasecmp(str, "yes") == 0) 658 config.disable_resend_requests = 1; 659 else 660 die("Invalid diagnostic disable_resend_requests option choice \"%s\". It should be " 661 "\"yes\" " 662 "or \"no\""); 663 } 664 665 /* Get the drop packets setting. */ 666 if (config_lookup_float(config.cfg, "diagnostics.drop_this_fraction_of_audio_packets", 667 &dvalue)) { 668 if ((dvalue >= 0.0) && (dvalue <= 3.0)) 669 config.diagnostic_drop_packet_fraction = dvalue; 670 else 671 die("Invalid diagnostics drop_this_fraction_of_audio_packets setting \"%d\". It should " 672 "be " 673 "between 0.0 and 1.0, " 674 "inclusive.", 675 dvalue); 676 } 677 678 /* Get the diagnostics output default. */ 679 if (config_lookup_string(config.cfg, "diagnostics.log_output_to", &str)) { 680 if (strcasecmp(str, "syslog") == 0) 681 log_to_syslog(); 682 else if (strcasecmp(str, "stdout") == 0) { 683 log_to_stdout(); 684 } else if (strcasecmp(str, "stderr") == 0) { 685 log_to_stderr(); 686 } else { 687 config.log_file_path = (char *)str; 688 config.log_fd = -1; 689 log_to_file(); 690 } 691 } 692 /* Get the ignore_volume_control setting. */ 693 if (config_lookup_string(config.cfg, "general.ignore_volume_control", &str)) { 694 if (strcasecmp(str, "no") == 0) 695 config.ignore_volume_control = 0; 696 else if (strcasecmp(str, "yes") == 0) 697 config.ignore_volume_control = 1; 698 else 699 die("Invalid ignore_volume_control option choice \"%s\". It should be \"yes\" or \"no\""); 700 } 701 702 /* Get the optional volume_max_db setting. */ 703 if (config_lookup_float(config.cfg, "general.volume_max_db", &dvalue)) { 704 // debug(1, "Max volume setting of %f dB", dvalue); 705 config.volume_max_db = dvalue; 706 config.volume_max_db_set = 1; 707 } 708 709 if (config_lookup_string(config.cfg, "general.run_this_when_volume_is_set", &str)) { 710 config.cmd_set_volume = (char *)str; 711 } 712 713 /* Get the playback_mode setting */ 714 if (config_lookup_string(config.cfg, "general.playback_mode", &str)) { 715 if (strcasecmp(str, "stereo") == 0) 716 config.playback_mode = ST_stereo; 717 else if (strcasecmp(str, "mono") == 0) 718 config.playback_mode = ST_mono; 719 else if (strcasecmp(str, "reverse stereo") == 0) 720 config.playback_mode = ST_reverse_stereo; 721 else if (strcasecmp(str, "both left") == 0) 722 config.playback_mode = ST_left_only; 723 else if (strcasecmp(str, "both right") == 0) 724 config.playback_mode = ST_right_only; 725 else 726 die("Invalid playback_mode choice \"%s\". It should be \"stereo\" (default), \"mono\", " 727 "\"reverse stereo\", \"both left\", \"both right\""); 728 } 729 730 /* Get the volume control profile setting -- "standard" or "flat" */ 731 if (config_lookup_string(config.cfg, "general.volume_control_profile", &str)) { 732 if (strcasecmp(str, "standard") == 0) 733 config.volume_control_profile = VCP_standard; 734 else if (strcasecmp(str, "flat") == 0) 735 config.volume_control_profile = VCP_flat; 736 else 737 die("Invalid volume_control_profile choice \"%s\". It should be \"standard\" (default) " 738 "or \"flat\""); 739 } 740 741 config_set_lookup_bool(config.cfg, "general.volume_control_combined_hardware_priority", 742 &config.volume_range_hw_priority); 743 744 /* Get the interface to listen on, if specified Default is all interfaces */ 745 /* we keep the interface name and the index */ 746 747 if (config_lookup_string(config.cfg, "general.interface", &str)) 748 config.interface = strdup(str); 749 750 if (config_lookup_string(config.cfg, "general.interface", &str)) { 751 int specified_interface_found = 0; 752 753 struct if_nameindex *if_ni, *i; 754 755 if_ni = if_nameindex(); 756 if (if_ni == NULL) { 757 debug(1, "Can't get a list of interface names."); 758 } else { 759 for (i = if_ni; !(i->if_index == 0 && i->if_name == NULL); i++) { 760 // printf("%u: %s\n", i->if_index, i->if_name); 761 if (strcmp(i->if_name, str) == 0) { 762 config.interface_index = i->if_index; 763 specified_interface_found = 1; 764 } 765 } 766 } 767 768 if_freenameindex(if_ni); 769 770 if (specified_interface_found == 0) { 771 inform( 772 "The mdns service interface \"%s\" was not found, so the setting has been ignored.", 773 config.interface); 774 free(config.interface); 775 config.interface = NULL; 776 config.interface_index = 0; 777 } 778 } 779 780 /* Get the regtype -- the service type and protocol, separated by a dot. Default is 781 * "_raop._tcp" */ 782 if (config_lookup_string(config.cfg, "general.regtype", &str)) 783 config.regtype = strdup(str); 784 785 /* Get the volume range, in dB, that should be used If not set, it means you just use the 786 * range set by the mixer. */ 787 if (config_lookup_int(config.cfg, "general.volume_range_db", &value)) { 788 if ((value < 30) || (value > 150)) 789 die("Invalid volume range %d dB. It should be between 30 and 150 dB. Zero means use " 790 "the mixer's native range. The setting reamins at %d.", 791 value, config.volume_range_db); 792 else 793 config.volume_range_db = value; 794 } 795 796 /* Get the alac_decoder setting. */ 797 if (config_lookup_string(config.cfg, "general.alac_decoder", &str)) { 798 if (strcasecmp(str, "hammerton") == 0) 799 config.use_apple_decoder = 0; 800 else if (strcasecmp(str, "apple") == 0) { 801 if ((config.decoders_supported & 1 << decoder_apple_alac) != 0) 802 config.use_apple_decoder = 1; 803 else 804 inform("Support for the Apple ALAC decoder has not been compiled into this version of " 805 "Shairport Sync. The default decoder will be used."); 806 } else 807 die("Invalid alac_decoder option choice \"%s\". It should be \"hammerton\" or \"apple\""); 808 } 809 810 /* Get the resend control settings. */ 811 if (config_lookup_float(config.cfg, "general.resend_control_first_check_time", &dvalue)) { 812 if ((dvalue >= 0.0) && (dvalue <= 3.0)) 813 config.resend_control_first_check_time = dvalue; 814 else 815 warn("Invalid general resend_control_first_check_time setting \"%f\". It should " 816 "be " 817 "between 0.0 and 3.0, " 818 "inclusive. The setting remains at %f seconds.", 819 dvalue, config.resend_control_first_check_time); 820 } 821 822 if (config_lookup_float(config.cfg, "general.resend_control_check_interval_time", &dvalue)) { 823 if ((dvalue >= 0.0) && (dvalue <= 3.0)) 824 config.resend_control_check_interval_time = dvalue; 825 else 826 warn("Invalid general resend_control_check_interval_time setting \"%f\". It should " 827 "be " 828 "between 0.0 and 3.0, " 829 "inclusive. The setting remains at %f seconds.", 830 dvalue, config.resend_control_check_interval_time); 831 } 832 833 if (config_lookup_float(config.cfg, "general.resend_control_last_check_time", &dvalue)) { 834 if ((dvalue >= 0.0) && (dvalue <= 3.0)) 835 config.resend_control_last_check_time = dvalue; 836 else 837 warn("Invalid general resend_control_last_check_time setting \"%f\". It should " 838 "be " 839 "between 0.0 and 3.0, " 840 "inclusive. The setting remains at %f seconds.", 841 dvalue, config.resend_control_last_check_time); 842 } 843 844 if (config_lookup_float(config.cfg, "general.missing_port_dacp_scan_interval_seconds", 845 &dvalue)) { 846 if ((dvalue >= 0.0) && (dvalue <= 300.0)) 847 config.missing_port_dacp_scan_interval_seconds = dvalue; 848 else 849 warn("Invalid general missing_port_dacp_scan_interval_seconds setting \"%f\". It should " 850 "be " 851 "between 0.0 and 300.0, " 852 "inclusive. The setting remains at %f seconds.", 853 dvalue, config.missing_port_dacp_scan_interval_seconds); 854 } 855 856 /* Get the default latency. Deprecated! */ 857 if (config_lookup_int(config.cfg, "latencies.default", &value)) 858 config.userSuppliedLatency = value; 859 860 #ifdef CONFIG_METADATA 861 /* Get the metadata setting. */ 862 if (config_lookup_string(config.cfg, "metadata.enabled", &str)) { 863 if (strcasecmp(str, "no") == 0) 864 config.metadata_enabled = 0; 865 else if (strcasecmp(str, "yes") == 0) 866 config.metadata_enabled = 1; 867 else 868 die("Invalid metadata enabled option choice \"%s\". It should be \"yes\" or \"no\""); 869 } 870 871 if (config_lookup_string(config.cfg, "metadata.include_cover_art", &str)) { 872 if (strcasecmp(str, "no") == 0) 873 config.get_coverart = 0; 874 else if (strcasecmp(str, "yes") == 0) 875 config.get_coverart = 1; 876 else 877 die("Invalid metadata include_cover_art option choice \"%s\". It should be \"yes\" or " 878 "\"no\""); 879 } 880 881 if (config_lookup_string(config.cfg, "metadata.pipe_name", &str)) { 882 config.metadata_pipename = (char *)str; 883 } 884 885 if (config_lookup_string(config.cfg, "metadata.socket_address", &str)) { 886 config.metadata_sockaddr = (char *)str; 887 } 888 if (config_lookup_int(config.cfg, "metadata.socket_port", &value)) { 889 config.metadata_sockport = value; 890 } 891 config.metadata_sockmsglength = 500; 892 if (config_lookup_int(config.cfg, "metadata.socket_msglength", &value)) { 893 config.metadata_sockmsglength = value < 500 ? 500 : value > 65000 ? 65000 : value; 894 } 895 896 #endif 897 898 #ifdef CONFIG_METADATA_HUB 899 if (config_lookup_string(config.cfg, "metadata.cover_art_cache_directory", &str)) { 900 config.cover_art_cache_dir = (char *)str; 901 } 902 903 if (config_lookup_string(config.cfg, "diagnostics.retain_cover_art", &str)) { 904 if (strcasecmp(str, "no") == 0) 905 config.retain_coverart = 0; 906 else if (strcasecmp(str, "yes") == 0) 907 config.retain_coverart = 1; 908 else 909 die("Invalid metadata retain_cover_art option choice \"%s\". It should be \"yes\" or " 910 "\"no\""); 911 } 912 #endif 913 914 if (config_lookup_string(config.cfg, "sessioncontrol.run_this_before_play_begins", &str)) { 915 config.cmd_start = (char *)str; 916 } 917 918 if (config_lookup_string(config.cfg, "sessioncontrol.run_this_after_play_ends", &str)) { 919 config.cmd_stop = (char *)str; 920 } 921 922 if (config_lookup_string(config.cfg, "sessioncontrol.run_this_before_entering_active_state", 923 &str)) { 924 config.cmd_active_start = (char *)str; 925 } 926 927 if (config_lookup_string(config.cfg, "sessioncontrol.run_this_after_exiting_active_state", 928 &str)) { 929 config.cmd_active_stop = (char *)str; 930 } 931 932 if (config_lookup_float(config.cfg, "sessioncontrol.active_state_timeout", &dvalue)) { 933 if (dvalue < 0.0) 934 warn("Invalid value \"%f\" for sessioncontrol.active_state_timeout. It must be positive. " 935 "The default of %f will be used instead.", 936 dvalue, config.active_state_timeout); 937 else 938 config.active_state_timeout = dvalue; 939 } 940 941 if (config_lookup_string(config.cfg, 942 "sessioncontrol.run_this_if_an_unfixable_error_is_detected", &str)) { 943 config.cmd_unfixable = (char *)str; 944 } 945 946 if (config_lookup_string(config.cfg, "sessioncontrol.wait_for_completion", &str)) { 947 if (strcasecmp(str, "no") == 0) 948 config.cmd_blocking = 0; 949 else if (strcasecmp(str, "yes") == 0) 950 config.cmd_blocking = 1; 951 else 952 die("Invalid session control wait_for_completion option choice \"%s\". It should be " 953 "\"yes\" or \"no\""); 954 } 955 956 if (config_lookup_string(config.cfg, "sessioncontrol.before_play_begins_returns_output", 957 &str)) { 958 if (strcasecmp(str, "no") == 0) 959 config.cmd_start_returns_output = 0; 960 else if (strcasecmp(str, "yes") == 0) 961 config.cmd_start_returns_output = 1; 962 else 963 die("Invalid session control before_play_begins_returns_output option choice \"%s\". It " 964 "should be " 965 "\"yes\" or \"no\""); 966 } 967 968 if (config_lookup_string(config.cfg, "sessioncontrol.allow_session_interruption", &str)) { 969 config.dont_check_timeout = 0; // this is for legacy -- only set by -t 0 970 if (strcasecmp(str, "no") == 0) 971 config.allow_session_interruption = 0; 972 else if (strcasecmp(str, "yes") == 0) 973 config.allow_session_interruption = 1; 974 else 975 die("Invalid session control allow_interruption option choice \"%s\". It should be " 976 "\"yes\" " 977 "or \"no\""); 978 } 979 980 if (config_lookup_int(config.cfg, "sessioncontrol.session_timeout", &value)) { 981 config.timeout = value; 982 config.dont_check_timeout = 0; // this is for legacy -- only set by -t 0 983 } 984 985 #ifdef CONFIG_CONVOLUTION 986 if (config_lookup_string(config.cfg, "dsp.convolution", &str)) { 987 if (strcasecmp(str, "no") == 0) 988 config.convolution = 0; 989 else if (strcasecmp(str, "yes") == 0) 990 config.convolution = 1; 991 else 992 die("Invalid dsp.convolution. It should be \"yes\" or \"no\""); 993 } 994 995 if (config_lookup_float(config.cfg, "dsp.convolution_gain", &dvalue)) { 996 config.convolution_gain = dvalue; 997 if (dvalue > 10 || dvalue < -50) 998 die("Invalid value \"%f\" for dsp.convolution_gain. It should be between -50 and +10 dB", 999 dvalue); 1000 } 1001 1002 if (config_lookup_int(config.cfg, "dsp.convolution_max_length", &value)) { 1003 config.convolution_max_length = value; 1004 1005 if (value < 1 || value > 200000) 1006 die("dsp.convolution_max_length must be within 1 and 200000"); 1007 } 1008 1009 if (config_lookup_string(config.cfg, "dsp.convolution_ir_file", &str)) { 1010 config.convolution_ir_file = strdup(str); 1011 config.convolver_valid = 1012 convolver_init(config.convolution_ir_file, config.convolution_max_length); 1013 } 1014 1015 if (config.convolution && config.convolution_ir_file == NULL) { 1016 warn("Convolution enabled but no convolution_ir_file provided"); 1017 } 1018 #endif 1019 if (config_lookup_string(config.cfg, "dsp.loudness", &str)) { 1020 if (strcasecmp(str, "no") == 0) 1021 config.loudness = 0; 1022 else if (strcasecmp(str, "yes") == 0) 1023 config.loudness = 1; 1024 else 1025 die("Invalid dsp.convolution. It should be \"yes\" or \"no\""); 1026 } 1027 1028 if (config_lookup_float(config.cfg, "dsp.loudness_reference_volume_db", &dvalue)) { 1029 config.loudness_reference_volume_db = dvalue; 1030 if (dvalue > 0 || dvalue < -100) 1031 die("Invalid value \"%f\" for dsp.loudness_reference_volume_db. It should be between " 1032 "-100 and 0", 1033 dvalue); 1034 } 1035 1036 if (config.loudness == 1 && config_lookup_string(config.cfg, "alsa.mixer_control_name", &str)) 1037 die("Loudness activated but hardware volume is active. You must remove " 1038 "\"alsa.mixer_control_name\" to use the loudness filter."); 1039 1040 } else { 1041 if (config_error_type(&config_file_stuff) == CONFIG_ERR_FILE_IO) 1042 debug(2, "Error reading configuration file \"%s\": \"%s\".", 1043 config_error_file(&config_file_stuff), config_error_text(&config_file_stuff)); 1044 else { 1045 die("Line %d of the configuration file \"%s\":\n%s", config_error_line(&config_file_stuff), 1046 config_error_file(&config_file_stuff), config_error_text(&config_file_stuff)); 1047 } 1048 } 1049 #if defined(CONFIG_DBUS_INTERFACE) 1050 /* Get the dbus service sbus setting. */ 1051 if (config_lookup_string(config.cfg, "general.dbus_service_bus", &str)) { 1052 if (strcasecmp(str, "system") == 0) 1053 config.dbus_service_bus_type = DBT_system; 1054 else if (strcasecmp(str, "session") == 0) 1055 config.dbus_service_bus_type = DBT_session; 1056 else 1057 die("Invalid dbus_service_bus option choice \"%s\". It should be \"system\" (default) or " 1058 "\"session\""); 1059 } 1060 #endif 1061 1062 #if defined(CONFIG_MPRIS_INTERFACE) 1063 /* Get the mpris service sbus setting. */ 1064 if (config_lookup_string(config.cfg, "general.mpris_service_bus", &str)) { 1065 if (strcasecmp(str, "system") == 0) 1066 config.mpris_service_bus_type = DBT_system; 1067 else if (strcasecmp(str, "session") == 0) 1068 config.mpris_service_bus_type = DBT_session; 1069 else 1070 die("Invalid mpris_service_bus option choice \"%s\". It should be \"system\" (default) or " 1071 "\"session\""); 1072 } 1073 #endif 1074 1075 #ifdef CONFIG_MQTT 1076 config_set_lookup_bool(config.cfg, "mqtt.enabled", &config.mqtt_enabled); 1077 if (config.mqtt_enabled && !config.metadata_enabled) { 1078 die("You need to have metadata enabled in order to use mqtt"); 1079 } 1080 if (config_lookup_string(config.cfg, "mqtt.hostname", &str)) { 1081 config.mqtt_hostname = (char *)str; 1082 // TODO: Document that, if this is false, whole mqtt func is disabled 1083 } 1084 config.mqtt_port = 1883; 1085 if (config_lookup_int(config.cfg, "mqtt.port", &value)) { 1086 if ((value < 0) || (value > 65535)) 1087 die("Invalid mqtt port number \"%sd\". It should be between 0 and 65535, default is 1883", 1088 value); 1089 else 1090 config.mqtt_port = value; 1091 } 1092 1093 if (config_lookup_string(config.cfg, "mqtt.username", &str)) { 1094 config.mqtt_username = (char *)str; 1095 } 1096 if (config_lookup_string(config.cfg, "mqtt.password", &str)) { 1097 config.mqtt_password = (char *)str; 1098 } 1099 int capath = 0; 1100 if (config_lookup_string(config.cfg, "mqtt.capath", &str)) { 1101 config.mqtt_capath = (char *)str; 1102 capath = 1; 1103 } 1104 if (config_lookup_string(config.cfg, "mqtt.cafile", &str)) { 1105 if (capath) 1106 die("Supply either mqtt cafile or mqtt capath -- you have supplied both!"); 1107 config.mqtt_cafile = (char *)str; 1108 } 1109 int certkeynum = 0; 1110 if (config_lookup_string(config.cfg, "mqtt.certfile", &str)) { 1111 config.mqtt_certfile = (char *)str; 1112 certkeynum++; 1113 } 1114 if (config_lookup_string(config.cfg, "mqtt.keyfile", &str)) { 1115 config.mqtt_keyfile = (char *)str; 1116 certkeynum++; 1117 } 1118 if (certkeynum != 0 && certkeynum != 2) { 1119 die("If you want to use TLS Client Authentication, you have to specify " 1120 "mqtt.certfile AND mqtt.keyfile.\nYou have supplied only one of them.\n" 1121 "If you do not want to use TLS Client Authentication, leave both empty."); 1122 } 1123 1124 if (config_lookup_string(config.cfg, "mqtt.topic", &str)) { 1125 config.mqtt_topic = (char *)str; 1126 } 1127 config_set_lookup_bool(config.cfg, "mqtt.publish_raw", &config.mqtt_publish_raw); 1128 config_set_lookup_bool(config.cfg, "mqtt.publish_parsed", &config.mqtt_publish_parsed); 1129 config_set_lookup_bool(config.cfg, "mqtt.publish_cover", &config.mqtt_publish_cover); 1130 if (config.mqtt_publish_cover && !config.get_coverart) { 1131 die("You need to have metadata.include_cover_art enabled in order to use mqtt.publish_cover"); 1132 } 1133 config_set_lookup_bool(config.cfg, "mqtt.enable_remote", &config.mqtt_enable_remote); 1134 #ifndef CONFIG_AVAHI 1135 if (config.mqtt_enable_remote) { 1136 die("You have enabled MQTT remote control which requires shairport-sync to be built with " 1137 "Avahi, but your installation is not using avahi. Please reinstall/recompile with " 1138 "avahi enabled, or disable remote control."); 1139 } 1140 #endif 1141 #endif 1142 } 1143 1144 // now, do the command line options again, but this time do them fully -- it's a unix convention 1145 // that command line 1146 // arguments have precedence over configuration file settings. 1147 1148 optind = argc; 1149 for (j = 0; j < argc; j++) 1150 if (strcmp(argv[j], "--") == 0) 1151 optind = j; 1152 1153 optCon = poptGetContext(NULL, optind, (const char **)argv, optionsTable, 0); 1154 if (optCon == NULL) 1155 die("Can not get a popt context."); 1156 poptSetOtherOptionHelp(optCon, "[OPTIONS]* "); 1157 1158 /* Now do options processing, get portname */ 1159 int tdebuglev = 0; 1160 while ((c = poptGetNextOpt(optCon)) >= 0) { 1161 switch (c) { 1162 case 'v': 1163 tdebuglev++; 1164 break; 1165 case 't': 1166 if (config.timeout == 0) { 1167 config.dont_check_timeout = 1; 1168 config.allow_session_interruption = 1; 1169 } else { 1170 config.dont_check_timeout = 0; 1171 config.allow_session_interruption = 0; 1172 } 1173 break; 1174 #ifdef CONFIG_METADATA 1175 case 'M': 1176 config.metadata_enabled = 1; 1177 break; 1178 case 'g': 1179 if (config.metadata_enabled == 0) 1180 die("If you want to get cover art, ensure metadata_enabled is true."); 1181 break; 1182 #endif 1183 case 'S': 1184 if (strcmp(stuffing, "basic") == 0) 1185 config.packet_stuffing = ST_basic; 1186 else if (strcmp(stuffing, "auto") == 0) 1187 config.packet_stuffing = ST_auto; 1188 else if (strcmp(stuffing, "soxr") == 0) 1189 #ifdef CONFIG_SOXR 1190 config.packet_stuffing = ST_soxr; 1191 #else 1192 die("The soxr option not available because this version of shairport-sync was built " 1193 "without libsoxr " 1194 "support. Change the -S option setting."); 1195 #endif 1196 else 1197 die("Illegal stuffing option \"%s\" -- must be \"basic\" or \"soxr\"", stuffing); 1198 break; 1199 } 1200 } 1201 if (c < -1) { 1202 die("%s: %s", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(c)); 1203 } 1204 1205 poptFreeContext(optCon); 1206 1207 // here, we are finally finished reading the options 1208 1209 #ifdef CONFIG_LIBDAEMON 1210 if ((daemonisewith) && (daemonisewithout)) 1211 die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have selected " 1212 "both!"); 1213 if ((daemonisewith) || (daemonisewithout)) { 1214 config.daemonise = 1; 1215 if (daemonisewith) 1216 config.daemonise_store_pid = 1; 1217 }; 1218 #else 1219 /* Check if we are called with -d or --daemon or -j or justDaemoniseNoPIDFile options*/ 1220 if ((daemonisewith != 0) || (daemonisewithout != 0)) { 1221 fprintf(stderr, 1222 "%s was built without libdaemon, so does not support daemonisation using the " 1223 "-d, --daemon, -j or --justDaemoniseNoPIDFile options\n", 1224 config.appName); 1225 exit(EXIT_FAILURE); 1226 } 1227 1228 #endif 1229 1230 #ifdef CONFIG_METADATA 1231 if ((config.metadata_enabled == 1) && (config.metadata_pipename == NULL)) 1232 config.metadata_pipename = strdup("/tmp/shairport-sync-metadata"); 1233 #endif 1234 1235 /* if the regtype hasn't been set, do it now */ 1236 if (config.regtype == NULL) 1237 config.regtype = strdup("_raop._tcp"); 1238 1239 if (tdebuglev != 0) 1240 debuglev = tdebuglev; 1241 1242 // now, do the substitutions in the service name 1243 char hostname[100]; 1244 gethostname(hostname, 100); 1245 1246 char *i0; 1247 if (raw_service_name == NULL) 1248 i0 = strdup("%H"); // this is the default it the Service Name wasn't specified 1249 else 1250 i0 = strdup(raw_service_name); 1251 1252 // here, do the substitutions for %h, %H, %v and %V 1253 char *i1 = str_replace(i0, "%h", hostname); 1254 if ((hostname[0] >= 'a') && (hostname[0] <= 'z')) 1255 hostname[0] = hostname[0] - 0x20; // convert a lowercase first letter into a capital letter 1256 char *i2 = str_replace(i1, "%H", hostname); 1257 char *i3 = str_replace(i2, "%v", PACKAGE_VERSION); 1258 char *vs = get_version_string(); 1259 config.service_name = str_replace(i3, "%V", vs); // service name complete 1260 free(i0); 1261 free(i1); 1262 free(i2); 1263 free(i3); 1264 free(vs); 1265 1266 #ifdef CONFIG_MQTT 1267 // mqtt topic was not set. As we have the service name just now, set it 1268 if (config.mqtt_topic == NULL) { 1269 int topic_length = 1 + strlen(config.service_name) + 1; 1270 char *topic = malloc(topic_length + 1); 1271 snprintf(topic, topic_length, "/%s/", config.service_name); 1272 config.mqtt_topic = topic; 1273 } 1274 #endif 1275 1276 #ifdef CONFIG_LIBDAEMON 1277 1278 // now, check and calculate the pid directory 1279 #ifdef DEFINED_CUSTOM_PID_DIR 1280 char *use_this_pid_dir = PIDDIR; 1281 #else 1282 char *use_this_pid_dir = "/var/run/shairport-sync"; 1283 #endif 1284 // debug(1,"config.piddir \"%s\".",config.piddir); 1285 if (config.piddir) 1286 use_this_pid_dir = config.piddir; 1287 if (use_this_pid_dir) 1288 config.computed_piddir = strdup(use_this_pid_dir); 1289 #endif 1290 return optind + 1; 1291 } 1292 1293 #if defined(CONFIG_DBUS_INTERFACE) || defined(CONFIG_MPRIS_INTERFACE) 1294 static GMainLoop *g_main_loop = NULL; 1295 1296 pthread_t dbus_thread; 1297 void *dbus_thread_func(__attribute__((unused)) void *arg) { 1298 g_main_loop = g_main_loop_new(NULL, FALSE); 1299 g_main_loop_run(g_main_loop); 1300 debug(2, "g_main_loop thread exit"); 1301 pthread_exit(NULL); 1302 } 1303 #endif 1304 1305 #ifdef CONFIG_LIBDAEMON 1306 char pid_file_path_string[4096] = "\0"; 1307 1308 const char *pid_file_proc(void) { 1309 snprintf(pid_file_path_string, sizeof(pid_file_path_string), "%s/%s.pid", config.computed_piddir, 1310 daemon_pid_file_ident ? daemon_pid_file_ident : "unknown"); 1311 // debug(1,"pid_file_path_string \"%s\".",pid_file_path_string); 1312 return pid_file_path_string; 1313 } 1314 #endif 1315 1316 void exit_function() { 1317 1318 if (emergency_exit == 0) { 1319 // the following is to ensure that if libdaemon has been included 1320 // that most of this code will be skipped when the parent process is exiting 1321 // exec 1322 #ifdef CONFIG_LIBDAEMON 1323 if ((this_is_the_daemon_process) || 1324 (config.daemonise == 0)) { // if this is the daemon process that is exiting or it's not 1325 // actually daemonised at all 1326 #endif 1327 debug(2, "exit function called..."); 1328 /* 1329 Actually, there is no terminate_mqtt() function. 1330 #ifdef CONFIG_MQTT 1331 if (config.mqtt_enabled) { 1332 terminate_mqtt(); 1333 } 1334 #endif 1335 */ 1336 1337 #if defined(CONFIG_DBUS_INTERFACE) || defined(CONFIG_MPRIS_INTERFACE) 1338 /* 1339 Actually, there is no stop_mpris_service() function. 1340 #ifdef CONFIG_MPRIS_INTERFACE 1341 stop_mpris_service(); 1342 #endif 1343 */ 1344 #ifdef CONFIG_DBUS_INTERFACE 1345 stop_dbus_service(); 1346 #endif 1347 if (g_main_loop) { 1348 debug(2, "Stopping DBUS Loop Thread"); 1349 g_main_loop_quit(g_main_loop); 1350 pthread_join(dbus_thread, NULL); 1351 } 1352 #endif 1353 1354 #ifdef CONFIG_DACP_CLIENT 1355 debug(2, "Stopping DACP Monitor"); 1356 dacp_monitor_stop(); 1357 #endif 1358 1359 #ifdef CONFIG_METADATA_HUB 1360 debug(2, "Stopping metadata hub"); 1361 metadata_hub_stop(); 1362 #endif 1363 1364 #ifdef CONFIG_METADATA 1365 metadata_stop(); // close down the metadata pipe 1366 #endif 1367 1368 activity_monitor_stop(0); 1369 1370 if ((config.output) && (config.output->deinit)) { 1371 debug(2, "Deinitialise the audio backend."); 1372 config.output->deinit(); 1373 } 1374 1375 #ifdef CONFIG_SOXR 1376 // be careful -- not sure if the thread can be cancelled cleanly, so wait for it to shut down 1377 pthread_join(soxr_time_check_thread, NULL); 1378 #endif 1379 1380 if (conns) 1381 free(conns); // make sure the connections have been deleted first 1382 1383 if (config.service_name) 1384 free(config.service_name); 1385 1386 #ifdef CONFIG_CONVOLUTION 1387 if (config.convolution_ir_file) 1388 free(config.convolution_ir_file); 1389 #endif 1390 1391 if (config.regtype) 1392 free(config.regtype); 1393 1394 #ifdef CONFIG_LIBDAEMON 1395 if (this_is_the_daemon_process) { 1396 daemon_retval_send(0); 1397 daemon_pid_file_remove(); 1398 daemon_signal_done(); 1399 if (config.computed_piddir) 1400 free(config.computed_piddir); 1401 } 1402 } 1403 #endif 1404 1405 if (config.cfg) 1406 config_destroy(config.cfg); 1407 if (config.appName) 1408 free(config.appName); 1409 // probably should be freeing malloc'ed memory here, including strdup-created strings... 1410 1411 #ifdef CONFIG_LIBDAEMON 1412 if (this_is_the_daemon_process) { // this is the daemon that is exiting 1413 debug(1, "libdaemon daemon exit"); 1414 } else { 1415 if (config.daemonise) 1416 debug(1, "libdaemon parent exit"); 1417 else 1418 debug(1, "exit"); 1419 } 1420 #else 1421 debug(1, "exit"); 1422 #endif 1423 } else { 1424 debug(1, "emergency exit"); 1425 } 1426 } 1427 1428 // for removing zombie script processes 1429 // see: http://www.microhowto.info/howto/reap_zombie_processes_using_a_sigchld_handler.html 1430 // used with thanks. 1431 1432 void handle_sigchld(__attribute__((unused)) int sig) { 1433 int saved_errno = errno; 1434 while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) { 1435 } 1436 errno = saved_errno; 1437 } 1438 1439 void main_thread_cleanup_handler(__attribute__((unused)) void *arg) { 1440 debug(2, "main thread cleanup handler called"); 1441 exit(EXIT_SUCCESS); 1442 } 1443 1444 int main(int argc, char **argv) { 1445 /* Check if we are called with -V or --version parameter */ 1446 if (argc >= 2 && ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0))) { 1447 print_version(); 1448 exit(EXIT_SUCCESS); 1449 } 1450 1451 /* Check if we are called with -h or --help parameter */ 1452 if (argc >= 2 && ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0))) { 1453 usage(argv[0]); 1454 exit(EXIT_SUCCESS); 1455 } 1456 1457 #ifdef CONFIG_LIBDAEMON 1458 pid = getpid(); 1459 #endif 1460 config.log_fd = -1; 1461 conns = NULL; // no connections active 1462 memset((void *)&main_thread_id, 0, sizeof(main_thread_id)); 1463 memset(&config, 0, sizeof(config)); // also clears all strings, BTW 1464 ns_time_at_startup = get_absolute_time_in_ns(); 1465 ns_time_at_last_debug_message = ns_time_at_startup; 1466 // this is a bit weird, but necessary -- basename() may modify the argument passed in 1467 char *basec = strdup(argv[0]); 1468 char *bname = basename(basec); 1469 config.appName = strdup(bname); 1470 if (config.appName == NULL) 1471 die("can not allocate memory for the app name!"); 1472 free(basec); 1473 1474 // debug(1,"startup"); 1475 #ifdef CONFIG_LIBDAEMON 1476 daemon_set_verbosity(LOG_DEBUG); 1477 #else 1478 setlogmask(LOG_UPTO(LOG_DEBUG)); 1479 openlog(NULL, 0, LOG_DAEMON); 1480 #endif 1481 emergency_exit = 0; // what to do or skip in the exit_function 1482 atexit(exit_function); 1483 1484 // set defaults 1485 1486 // get the endianness 1487 union { 1488 uint32_t u32; 1489 uint8_t arr[4]; 1490 } xn; 1491 1492 xn.arr[0] = 0x44; /* Lowest-address byte */ 1493 xn.arr[1] = 0x33; 1494 xn.arr[2] = 0x22; 1495 xn.arr[3] = 0x11; /* Highest-address byte */ 1496 1497 if (xn.u32 == 0x11223344) 1498 config.endianness = SS_LITTLE_ENDIAN; 1499 else if (xn.u32 == 0x33441122) 1500 config.endianness = SS_PDP_ENDIAN; 1501 else if (xn.u32 == 0x44332211) 1502 config.endianness = SS_BIG_ENDIAN; 1503 else 1504 die("Can not recognise the endianness of the processor."); 1505 1506 // set non-zero / non-NULL default values here 1507 // but note that audio back ends also have a chance to set defaults 1508 1509 // get the first output backend in the list and make it the default 1510 audio_output *first_backend = audio_get_output(NULL); 1511 if (first_backend == NULL) { 1512 die("No audio backend found! Check your build of Shairport Sync."); 1513 } else { 1514 strncpy(first_backend_name, first_backend->name, sizeof(first_backend_name) - 1); 1515 config.output_name = first_backend_name; 1516 } 1517 1518 strcpy(configuration_file_path, SYSCONFDIR); 1519 // strcat(configuration_file_path, "/shairport-sync"); // thinking about adding a special 1520 // shairport-sync directory 1521 strcat(configuration_file_path, "/"); 1522 strcat(configuration_file_path, config.appName); 1523 strcat(configuration_file_path, ".conf"); 1524 config.configfile = configuration_file_path; 1525 1526 // config.statistics_requested = 0; // don't print stats in the log 1527 // config.userSuppliedLatency = 0; // zero means none supplied 1528 1529 config.debugger_show_file_and_line = 1530 1; // by default, log the file and line of the originating message 1531 config.debugger_show_relative_time = 1532 1; // by default, log the time back to the previous debug message 1533 config.resyncthreshold = 0.05; // 50 ms 1534 config.timeout = 120; // this number of seconds to wait for [more] audio before switching to idle. 1535 config.tolerance = 1536 0.002; // this number of seconds of timing error before attempting to correct it. 1537 config.buffer_start_fill = 220; 1538 config.port = 5000; 1539 1540 #ifdef CONFIG_SOXR 1541 config.packet_stuffing = ST_auto; // use soxr interpolation by default if support has been 1542 // included and if the CPU is fast enough 1543 #else 1544 config.packet_stuffing = ST_basic; // simple interpolation or deletion 1545 #endif 1546 1547 // char hostname[100]; 1548 // gethostname(hostname, 100); 1549 // config.service_name = malloc(20 + 100); 1550 // snprintf(config.service_name, 20 + 100, "Shairport Sync on %s", hostname); 1551 set_requested_connection_state_to_output( 1552 1); // we expect to be able to connect to the output device 1553 config.audio_backend_buffer_desired_length = 0.15; // seconds 1554 config.udp_port_base = 6001; 1555 config.udp_port_range = 10; 1556 config.output_format = SPS_FORMAT_S16_LE; // default 1557 config.output_format_auto_requested = 1; // default auto select format 1558 config.output_rate = 44100; // default 1559 config.output_rate_auto_requested = 1; // default auto select format 1560 config.decoders_supported = 1561 1 << decoder_hammerton; // David Hammerton's decoder supported by default 1562 #ifdef CONFIG_APPLE_ALAC 1563 config.decoders_supported += 1 << decoder_apple_alac; 1564 config.use_apple_decoder = 1; // use the ALAC decoder by default if support has been included 1565 #endif 1566 1567 // initialise random number generator 1568 1569 r64init(0); 1570 1571 #ifdef CONFIG_LIBDAEMON 1572 1573 /* Reset signal handlers */ 1574 if (daemon_reset_sigs(-1) < 0) { 1575 daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno)); 1576 return 1; 1577 } 1578 1579 /* Unblock signals */ 1580 if (daemon_unblock_sigs(-1) < 0) { 1581 daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno)); 1582 return 1; 1583 } 1584 1585 /* Set identification string for the daemon for both syslog and PID file */ 1586 daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); 1587 1588 daemon_pid_file_proc = pid_file_proc; 1589 1590 #endif 1591 1592 // parse arguments into config -- needed to locate pid_dir 1593 int audio_arg = parse_options(argc, argv); 1594 1595 // mDNS supports maximum of 63-character names (we append 13). 1596 if (strlen(config.service_name) > 50) { 1597 warn("Supplied name too long (max 50 characters)"); 1598 config.service_name[50] = '\0'; // truncate it and carry on... 1599 } 1600 1601 /* Check if we are called with -k or --kill option */ 1602 if (killOption != 0) { 1603 #ifdef CONFIG_LIBDAEMON 1604 int ret; 1605 1606 /* Kill daemon with SIGTERM */ 1607 /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ 1608 if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) { 1609 if (errno == ENOENT) 1610 daemon_log(LOG_WARNING, "Failed to kill %s daemon: PID file not found.", config.appName); 1611 else 1612 daemon_log(LOG_WARNING, "Failed to kill %s daemon: \"%s\", errno %u.", config.appName, 1613 strerror(errno), errno); 1614 } else { 1615 // debug(1,"Successfully killed the %s daemon.", config.appName); 1616 if (daemon_pid_file_remove() == 0) 1617 debug(2, "killed the %s daemon.", config.appName); 1618 else 1619 daemon_log(LOG_WARNING, 1620 "killed the %s daemon, but cannot remove old PID file: \"%s\", errno %u.", 1621 config.appName, strerror(errno), errno); 1622 } 1623 return ret < 0 ? 1 : 0; 1624 #else 1625 fprintf(stderr, "%s was built without libdaemon, so does not support the -k or --kill option\n", 1626 config.appName); 1627 return 1; 1628 #endif 1629 } 1630 1631 #ifdef CONFIG_LIBDAEMON 1632 /* If we are going to daemonise, check that the daemon is not running already.*/ 1633 if ((config.daemonise) && ((pid = daemon_pid_file_is_running()) >= 0)) { 1634 daemon_log(LOG_ERR, "The %s daemon is already running as PID %u", config.appName, pid); 1635 return 1; 1636 } 1637 1638 /* here, daemonise with libdaemon */ 1639 1640 if (config.daemonise) { 1641 /* Prepare for return value passing from the initialization procedure of the daemon process */ 1642 if (daemon_retval_init() < 0) { 1643 daemon_log(LOG_ERR, "Failed to create pipe."); 1644 return 1; 1645 } 1646 1647 /* Do the fork */ 1648 if ((pid = daemon_fork()) < 0) { 1649 1650 /* Exit on error */ 1651 daemon_retval_done(); 1652 return 1; 1653 1654 } else if (pid) { /* The parent */ 1655 int ret; 1656 1657 /* Wait for 20 seconds for the return value passed from the daemon process */ 1658 if ((ret = daemon_retval_wait(20)) < 0) { 1659 daemon_log(LOG_ERR, "Could not receive return value from daemon process: %s", 1660 strerror(errno)); 1661 return 255; 1662 } 1663 1664 switch (ret) { 1665 case 0: 1666 break; 1667 case 1: 1668 daemon_log( 1669 LOG_ERR, 1670 "the %s daemon failed to launch: could not close open file descriptors after forking.", 1671 config.appName); 1672 break; 1673 case 2: 1674 daemon_log(LOG_ERR, "the %s daemon failed to launch: could not create PID file.", 1675 config.appName); 1676 break; 1677 case 3: 1678 daemon_log(LOG_ERR, 1679 "the %s daemon failed to launch: could not create or access PID directory.", 1680 config.appName); 1681 break; 1682 default: 1683 daemon_log(LOG_ERR, "the %s daemon failed to launch, error %i.", config.appName, ret); 1684 } 1685 return ret; 1686 } else { /* pid == 0 means we are the daemon */ 1687 1688 this_is_the_daemon_process = 1; // 1689 1690 /* Close FDs */ 1691 if (daemon_close_all(-1) < 0) { 1692 daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); 1693 /* Send the error condition to the parent process */ 1694 daemon_retval_send(1); 1695 1696 daemon_signal_done(); 1697 return 0; 1698 } 1699 1700 /* Create the PID file if required */ 1701 if (config.daemonise_store_pid) { 1702 /* Create the PID directory if required -- we don't really care about the result */ 1703 printf("PID directory is \"%s\".", config.computed_piddir); 1704 int result = mkpath(config.computed_piddir, 0700); 1705 if ((result != 0) && (result != -EEXIST)) { 1706 // error creating or accessing the PID file directory 1707 daemon_retval_send(3); 1708 1709 daemon_signal_done(); 1710 return 0; 1711 } 1712 1713 if (daemon_pid_file_create() < 0) { 1714 daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); 1715 1716 daemon_retval_send(2); 1717 daemon_signal_done(); 1718 return 0; 1719 } 1720 } 1721 1722 /* Send OK to parent process */ 1723 daemon_retval_send(0); 1724 } 1725 /* end libdaemon stuff */ 1726 } 1727 1728 #endif 1729 debug(1, "Started!"); 1730 1731 // stop a pipe signal from killing the program 1732 signal(SIGPIPE, SIG_IGN); 1733 1734 // install a zombie process reaper 1735 // see: http://www.microhowto.info/howto/reap_zombie_processes_using_a_sigchld_handler.html 1736 struct sigaction sa; 1737 sa.sa_handler = &handle_sigchld; 1738 sigemptyset(&sa.sa_mask); 1739 sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; 1740 if (sigaction(SIGCHLD, &sa, 0) == -1) { 1741 perror(0); 1742 exit(1); 1743 } 1744 1745 main_thread_id = pthread_self(); 1746 if (!main_thread_id) 1747 debug(1, "Main thread is set up to be NULL!"); 1748 1749 // make sure the program can create files that group and world can read 1750 umask(S_IWGRP | S_IWOTH); 1751 1752 /* print out version */ 1753 1754 char *version_dbs = get_version_string(); 1755 if (version_dbs) { 1756 debug(1, "software version: \"%s\"", version_dbs); 1757 free(version_dbs); 1758 } else { 1759 debug(1, "can't print the version information!"); 1760 } 1761 1762 debug(1, "log verbosity is %d.", debuglev); 1763 1764 config.output = audio_get_output(config.output_name); 1765 if (!config.output) { 1766 die("Invalid audio backend \"%s\" selected!", 1767 config.output_name == NULL ? "<unspecified>" : config.output_name); 1768 } 1769 config.output->init(argc - audio_arg, argv + audio_arg); 1770 1771 pthread_cleanup_push(main_thread_cleanup_handler, NULL); 1772 1773 // daemon_log(LOG_NOTICE, "startup"); 1774 1775 switch (config.endianness) { 1776 case SS_LITTLE_ENDIAN: 1777 debug(2, "The processor is running little-endian."); 1778 break; 1779 case SS_BIG_ENDIAN: 1780 debug(2, "The processor is running big-endian."); 1781 break; 1782 case SS_PDP_ENDIAN: 1783 debug(2, "The processor is running pdp-endian."); 1784 break; 1785 } 1786 1787 /* Mess around with the latency options */ 1788 // Basically, we expect the source to set the latency and add a fixed offset of 11025 frames to 1789 // it, which sounds right 1790 // If this latency is outside the max and min latensies that may be set by the source, clamp it to 1791 // fit. 1792 1793 // If they specify a non-standard latency, we suggest the user to use the 1794 // audio_backend_latency_offset instead. 1795 1796 if (config.userSuppliedLatency) { 1797 inform("The fixed latency setting is deprecated, as Shairport Sync gets the correct " 1798 "latency automatically from the source."); 1799 inform("Use the audio_backend_latency_offset_in_seconds setting " 1800 "instead to compensate for timing issues."); 1801 if ((config.userSuppliedLatency != 0) && 1802 ((config.userSuppliedLatency < 4410) || 1803 (config.userSuppliedLatency > BUFFER_FRAMES * 352 - 22050))) 1804 die("An out-of-range fixed latency has been specified. It must be between 4410 and %d (at " 1805 "44100 frames per second).", 1806 BUFFER_FRAMES * 352 - 22050); 1807 } 1808 1809 /* Print out options */ 1810 debug(1, "disable resend requests is %s.", config.disable_resend_requests ? "on" : "off"); 1811 debug(1, 1812 "diagnostic_drop_packet_fraction is %f. A value of 0.0 means no packets will be dropped " 1813 "deliberately.", 1814 config.diagnostic_drop_packet_fraction); 1815 debug(1, "statistics_requester status is %d.", config.statistics_requested); 1816 #if CONFIG_LIBDAEMON 1817 debug(1, "daemon status is %d.", config.daemonise); 1818 debug(1, "daemon pid file path is \"%s\".", pid_file_proc()); 1819 #endif 1820 debug(1, "rtsp listening port is %d.", config.port); 1821 debug(1, "udp base port is %d.", config.udp_port_base); 1822 debug(1, "udp port range is %d.", config.udp_port_range); 1823 debug(1, "player name is \"%s\".", config.service_name); 1824 debug(1, "backend is \"%s\".", config.output_name); 1825 debug(1, "run_this_before_play_begins action is \"%s\".", config.cmd_start); 1826 debug(1, "run_this_after_play_ends action is \"%s\".", config.cmd_stop); 1827 debug(1, "wait-cmd status is %d.", config.cmd_blocking); 1828 debug(1, "run_this_before_play_begins may return output is %d.", config.cmd_start_returns_output); 1829 debug(1, "run_this_if_an_unfixable_error_is_detected action is \"%s\".", config.cmd_unfixable); 1830 debug(1, "run_this_before_entering_active_state action is \"%s\".", config.cmd_active_start); 1831 debug(1, "run_this_after_exiting_active_state action is \"%s\".", config.cmd_active_stop); 1832 debug(1, "active_state_timeout is %f seconds.", config.active_state_timeout); 1833 debug(1, "mdns backend \"%s\".", config.mdns_name); 1834 debug(2, "userSuppliedLatency is %d.", config.userSuppliedLatency); 1835 debug(1, "interpolation setting is \"%s\".", 1836 config.packet_stuffing == ST_basic ? "basic" 1837 : config.packet_stuffing == ST_soxr ? "soxr" : "auto"); 1838 debug(1, "interpolation soxr_delay_threshold is %d.", config.soxr_delay_threshold); 1839 debug(1, "resync time is %f seconds.", config.resyncthreshold); 1840 debug(1, "allow a session to be interrupted: %d.", config.allow_session_interruption); 1841 debug(1, "busy timeout time is %d.", config.timeout); 1842 debug(1, "drift tolerance is %f seconds.", config.tolerance); 1843 debug(1, "password is \"%s\".", config.password); 1844 debug(1, "ignore_volume_control is %d.", config.ignore_volume_control); 1845 if (config.volume_max_db_set) 1846 debug(1, "volume_max_db is %d.", config.volume_max_db); 1847 else 1848 debug(1, "volume_max_db is not set"); 1849 debug(1, "volume range in dB (zero means use the range specified by the mixer): %u.", 1850 config.volume_range_db); 1851 debug(1, 1852 "volume_range_combined_hardware_priority (1 means hardware mixer attenuation is used " 1853 "first) is %d.", 1854 config.volume_range_hw_priority); 1855 debug(1, "playback_mode is %d (0-stereo, 1-mono, 1-reverse_stereo, 2-both_left, 3-both_right).", 1856 config.playback_mode); 1857 debug(1, "disable_synchronization is %d.", config.no_sync); 1858 debug(1, "use_mmap_if_available is %d.", config.no_mmap ? 0 : 1); 1859 debug(1, "output_format automatic selection is %sabled.", 1860 config.output_format_auto_requested ? "en" : "dis"); 1861 if (config.output_format_auto_requested == 0) 1862 debug(1, "output_format is \"%s\".", sps_format_description_string(config.output_format)); 1863 debug(1, "output_rate automatic selection is %sabled.", 1864 config.output_rate_auto_requested ? "en" : "dis"); 1865 if (config.output_rate_auto_requested == 0) 1866 debug(1, "output_rate is %d.", config.output_rate); 1867 debug(1, "audio backend desired buffer length is %f seconds.", 1868 config.audio_backend_buffer_desired_length); 1869 debug(1, "audio_backend_buffer_interpolation_threshold_in_seconds is %f seconds.", 1870 config.audio_backend_buffer_interpolation_threshold_in_seconds); 1871 debug(1, "audio backend latency offset is %f seconds.", config.audio_backend_latency_offset); 1872 if (config.audio_backend_silent_lead_in_time_auto == 1) 1873 debug(1, "audio backend silence lead-in time is \"auto\"."); 1874 else 1875 debug(1, "audio backend silence lead-in time is %f seconds.", 1876 config.audio_backend_silent_lead_in_time); 1877 debug(1, "zeroconf regtype is \"%s\".", config.regtype); 1878 debug(1, "decoders_supported field is %d.", config.decoders_supported); 1879 debug(1, "use_apple_decoder is %d.", config.use_apple_decoder); 1880 debug(1, "alsa_use_hardware_mute is %d.", config.alsa_use_hardware_mute); 1881 if (config.interface) 1882 debug(1, "mdns service interface \"%s\" requested.", config.interface); 1883 else 1884 debug(1, "no special mdns service interface was requested."); 1885 char *realConfigPath = realpath(config.configfile, NULL); 1886 if (realConfigPath) { 1887 debug(1, "configuration file name \"%s\" resolves to \"%s\".", config.configfile, 1888 realConfigPath); 1889 free(realConfigPath); 1890 } else { 1891 debug(1, "configuration file name \"%s\" can not be resolved.", config.configfile); 1892 } 1893 #ifdef CONFIG_METADATA 1894 debug(1, "metadata enabled is %d.", config.metadata_enabled); 1895 debug(1, "metadata pipename is \"%s\".", config.metadata_pipename); 1896 debug(1, "metadata socket address is \"%s\" port %d.", config.metadata_sockaddr, 1897 config.metadata_sockport); 1898 debug(1, "metadata socket packet size is \"%d\".", config.metadata_sockmsglength); 1899 debug(1, "get-coverart is %d.", config.get_coverart); 1900 #endif 1901 #ifdef CONFIG_MQTT 1902 debug(1, "mqtt is %sabled.", config.mqtt_enabled ? "en" : "dis"); 1903 debug(1, "mqtt hostname is %s, port is %d.", config.mqtt_hostname, config.mqtt_port); 1904 debug(1, "mqtt topic is %s.", config.mqtt_topic); 1905 debug(1, "mqtt will%s publish raw metadata.", config.mqtt_publish_raw ? "" : " not"); 1906 debug(1, "mqtt will%s publish parsed metadata.", config.mqtt_publish_parsed ? "" : " not"); 1907 debug(1, "mqtt will%s publish cover Art.", config.mqtt_publish_cover ? "" : " not"); 1908 debug(1, "mqtt remote control is %sabled.", config.mqtt_enable_remote ? "en" : "dis"); 1909 #endif 1910 1911 #ifdef CONFIG_CONVOLUTION 1912 debug(1, "convolution is %d.", config.convolution); 1913 debug(1, "convolution IR file is \"%s\"", config.convolution_ir_file); 1914 debug(1, "convolution max length %d", config.convolution_max_length); 1915 debug(1, "convolution gain is %f", config.convolution_gain); 1916 #endif 1917 debug(1, "loudness is %d.", config.loudness); 1918 debug(1, "loudness reference level is %f", config.loudness_reference_volume_db); 1919 1920 uint8_t ap_md5[16]; 1921 1922 #ifdef CONFIG_SOXR 1923 pthread_create(&soxr_time_check_thread, NULL, &soxr_time_check, NULL); 1924 #endif 1925 1926 #ifdef CONFIG_OPENSSL 1927 MD5_CTX ctx; 1928 MD5_Init(&ctx); 1929 MD5_Update(&ctx, config.service_name, strlen(config.service_name)); 1930 MD5_Final(ap_md5, &ctx); 1931 #endif 1932 1933 #ifdef CONFIG_MBEDTLS 1934 #if MBEDTLS_VERSION_MINOR >= 7 1935 mbedtls_md5_context tctx; 1936 mbedtls_md5_starts_ret(&tctx); 1937 mbedtls_md5_update_ret(&tctx, (unsigned char *)config.service_name, strlen(config.service_name)); 1938 mbedtls_md5_finish_ret(&tctx, ap_md5); 1939 #else 1940 mbedtls_md5_context tctx; 1941 mbedtls_md5_starts(&tctx); 1942 mbedtls_md5_update(&tctx, (unsigned char *)config.service_name, strlen(config.service_name)); 1943 mbedtls_md5_finish(&tctx, ap_md5); 1944 #endif 1945 #endif 1946 1947 #ifdef CONFIG_POLARSSL 1948 md5_context tctx; 1949 md5_starts(&tctx); 1950 md5_update(&tctx, (unsigned char *)config.service_name, strlen(config.service_name)); 1951 md5_finish(&tctx, ap_md5); 1952 #endif 1953 memcpy(config.hw_addr, ap_md5, sizeof(config.hw_addr)); 1954 #ifdef CONFIG_METADATA 1955 metadata_init(); // create the metadata pipe if necessary 1956 #endif 1957 1958 #ifdef CONFIG_METADATA_HUB 1959 // debug(1, "Initialising metadata hub"); 1960 metadata_hub_init(); 1961 #endif 1962 1963 #ifdef CONFIG_DACP_CLIENT 1964 // debug(1, "Requesting DACP Monitor"); 1965 dacp_monitor_start(); 1966 #endif 1967 1968 #if defined(CONFIG_DBUS_INTERFACE) || defined(CONFIG_MPRIS_INTERFACE) 1969 // Start up DBUS services after initial settings are all made 1970 // debug(1, "Starting up D-Bus services"); 1971 pthread_create(&dbus_thread, NULL, &dbus_thread_func, NULL); 1972 #ifdef CONFIG_DBUS_INTERFACE 1973 start_dbus_service(); 1974 #endif 1975 #ifdef CONFIG_MPRIS_INTERFACE 1976 start_mpris_service(); 1977 #endif 1978 #endif 1979 1980 #ifdef CONFIG_MQTT 1981 if (config.mqtt_enabled) { 1982 initialise_mqtt(); 1983 } 1984 #endif 1985 1986 activity_monitor_start(); 1987 rtsp_listen_loop(); 1988 pthread_cleanup_pop(1); 1989 return 0; 1990 } 1991