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