BB. Fix a crash that occurred in AP2 mode if no configuration file was present, duh.
This commit is contained in:
+99
-81
@@ -2,7 +2,7 @@
|
||||
* Shairport, an Apple Airplay receiver
|
||||
* Copyright (c) James Laird 2013
|
||||
* All rights reserved.
|
||||
* Modifications and additions (c) Mike Brady 2014--2021
|
||||
* Modifications and additions (c) Mike Brady 2014--2022
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
@@ -469,6 +469,44 @@ int parse_options(int argc, char **argv) {
|
||||
// not made active again (not used)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AIRPLAY_2
|
||||
// the features code is a 64-bit number, but in the mDNS advertisement, the least significant 32
|
||||
// bit are given first for example, if the features number is 0x1C340405F4A00, it will be given as
|
||||
// features=0x405F4A00,0x1C340 in the mDNS string, and in a signed decimal number in the plist:
|
||||
// 496155702020608 this setting here is the source of both the plist features response and the
|
||||
// mDNS string.
|
||||
// note: 0x300401F4A00 works but with weird delays and stuff
|
||||
// config.airplay_features = 0x1C340405FCA00;
|
||||
uint64_t mask =
|
||||
((uint64_t)1 << 17) | ((uint64_t)1 << 16) | ((uint64_t)1 << 15) | ((uint64_t)1 << 50);
|
||||
config.airplay_features =
|
||||
0x1C340405D4A00 & (~mask); // APX + Authentication4 (b14) with no metadata (see below)
|
||||
// Advertised with mDNS and returned with GET /info, see
|
||||
// https://openairplay.github.io/airplay-spec/status_flags.html 0x4: Audio cable attached, no PIN
|
||||
// required (transient pairing), 0x204: Audio cable attached, OneTimePairingRequired 0x604: Audio
|
||||
// cable attached, OneTimePairingRequired, device was setup for Homekit access control
|
||||
config.airplay_statusflags = 0x04;
|
||||
// Set to NULL to work with transient pairing
|
||||
config.airplay_pin = NULL;
|
||||
|
||||
// use the start of the config.hw_addr and the PID to generate the default airplay_device_id
|
||||
uint64_t temporary_airplay_id = nctoh64(config.hw_addr);
|
||||
temporary_airplay_id =
|
||||
temporary_airplay_id >> 16; // we only use the first 6 bytes but have imported 8.
|
||||
|
||||
// now generate a UUID
|
||||
// from https://stackoverflow.com/questions/51053568/generating-a-random-uuid-in-c
|
||||
// with thanks
|
||||
uuid_t binuuid;
|
||||
uuid_generate_random(binuuid);
|
||||
|
||||
char *uuid = malloc(UUID_STR_LEN);
|
||||
// Produces a UUID string at uuid consisting of lower-case letters
|
||||
uuid_unparse_lower(binuuid, uuid);
|
||||
config.airplay_pi = uuid;
|
||||
|
||||
#endif
|
||||
|
||||
// config_setting_t *setting;
|
||||
const char *str = 0;
|
||||
int value = 0;
|
||||
@@ -1150,6 +1188,21 @@ int parse_options(int argc, char **argv) {
|
||||
"avahi enabled, or disable remote control.");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AIRPLAY_2
|
||||
int64_t aid;
|
||||
|
||||
// replace the airplay_device_id with this, if provided
|
||||
if (config_lookup_int64(config.cfg, "general.airplay_device_id", &aid)) {
|
||||
temporary_airplay_id = aid;
|
||||
}
|
||||
|
||||
// add the airplay_device_id_offset if provided
|
||||
if (config_lookup_int64(config.cfg, "general.airplay_device_id_offset", &aid)) {
|
||||
temporary_airplay_id += aid;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1218,6 +1271,44 @@ int parse_options(int argc, char **argv) {
|
||||
|
||||
// here, we are finally finished reading the options
|
||||
|
||||
// finish the Airplay 2 options
|
||||
|
||||
#ifdef CONFIG_AIRPLAY_2
|
||||
|
||||
char shared_memory_interface_name[256] = "";
|
||||
snprintf(shared_memory_interface_name, sizeof(shared_memory_interface_name), "/%s-%" PRIx64 "",
|
||||
config.appName, temporary_airplay_id);
|
||||
// debug(1, "smi name: \"%s\"", shared_memory_interface_name);
|
||||
|
||||
config.nqptp_shared_memory_interface_name = strdup(shared_memory_interface_name);
|
||||
|
||||
char apids[6 * 2 + 5 + 1]; // six pairs of digits, 5 colons and a NUL
|
||||
apids[6 * 2 + 5] = 0; // NUL termination
|
||||
int i;
|
||||
char hexchar[] = "0123456789abcdef";
|
||||
for (i = 5; i >= 0; i--) {
|
||||
apids[i * 3 + 1] = hexchar[temporary_airplay_id & 0xF];
|
||||
temporary_airplay_id = temporary_airplay_id >> 4;
|
||||
apids[i * 3] = hexchar[temporary_airplay_id & 0xF];
|
||||
temporary_airplay_id = temporary_airplay_id >> 4;
|
||||
if (i != 0)
|
||||
apids[i * 3 - 1] = ':';
|
||||
}
|
||||
|
||||
config.airplay_device_id = strdup(apids);
|
||||
|
||||
#ifdef CONFIG_METADATA
|
||||
// If we are asking for metadata, turn on the relevant bits
|
||||
if (config.metadata_enabled != 0) {
|
||||
config.airplay_features |= (1 << 17) | (1 << 16); // 16 is progress, 17 is text
|
||||
// If we are asking for artwork, turn on the relevant bit
|
||||
if (config.get_coverart)
|
||||
config.airplay_features |= (1 << 15); // 15 is artwork
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LIBDAEMON
|
||||
if ((daemonisewith) && (daemonisewithout))
|
||||
die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have selected "
|
||||
@@ -1792,86 +1883,13 @@ int main(int argc, char **argv) {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AIRPLAY_2
|
||||
// the features code is a 64-bit number, but in the mDNS advertisement, the least significant 32
|
||||
// bit are given first for example, if the features number is 0x1C340405F4A00, it will be given as
|
||||
// features=0x405F4A00,0x1C340 in the mDNS string, and in a signed decimal number in the plist:
|
||||
// 496155702020608 this setting here is the source of both the plist features response and the
|
||||
// mDNS string.
|
||||
// note: 0x300401F4A00 works but with weird delays and stuff
|
||||
// config.airplay_features = 0x1C340405FCA00;
|
||||
uint64_t mask =
|
||||
((uint64_t)1 << 17) | ((uint64_t)1 << 16) | ((uint64_t)1 << 15) | ((uint64_t)1 << 50);
|
||||
config.airplay_features =
|
||||
0x1C340405D4A00 & (~mask); // APX + Authentication4 (b14) with no metadata (see below)
|
||||
// Advertised with mDNS and returned with GET /info, see
|
||||
// https://openairplay.github.io/airplay-spec/status_flags.html 0x4: Audio cable attached, no PIN
|
||||
// required (transient pairing), 0x204: Audio cable attached, OneTimePairingRequired 0x604: Audio
|
||||
// cable attached, OneTimePairingRequired, device was setup for Homekit access control
|
||||
|
||||
#ifdef CONFIG_METADATA
|
||||
// If we are asking for metadata, turn on the relevant bits
|
||||
if (config.metadata_enabled != 0) {
|
||||
config.airplay_features |= (1 << 17) | (1 << 16); // 16 is progress, 17 is text
|
||||
// If we are asking for artwork, turn on the relevant bit
|
||||
if (config.get_coverart)
|
||||
config.airplay_features |= (1 << 15); // 15 is artwork
|
||||
}
|
||||
#endif
|
||||
|
||||
debug(1, "Features: 0x%" PRIx64 ".", config.airplay_features);
|
||||
config.airplay_statusflags = 0x04;
|
||||
// Set to NULL to work with transient pairing
|
||||
config.airplay_pin = NULL;
|
||||
|
||||
// use the start of the config.hw_addr and the PID to generate the default airplay_device_id
|
||||
uint64_t apid = nctoh64(config.hw_addr);
|
||||
apid = apid >> 16; // we only use the first 6 bytes but have imported 8.
|
||||
|
||||
int64_t aid;
|
||||
|
||||
// add the airplay_device_id_offset if provided
|
||||
if (config_lookup_int64(config.cfg, "general.airplay_device_id_offset", &aid)) {
|
||||
apid += aid;
|
||||
}
|
||||
|
||||
// replace the airplay_device_id with this, if provided
|
||||
if (config_lookup_int64(config.cfg, "general.airplay_device_id", &aid)) {
|
||||
apid = aid;
|
||||
}
|
||||
|
||||
char shared_memory_interface_name[256] = "";
|
||||
snprintf(shared_memory_interface_name, sizeof(shared_memory_interface_name), "/%s-%" PRIx64 "",
|
||||
config.appName, apid);
|
||||
// debug(1, "smi name: \"%s\"", shared_memory_interface_name);
|
||||
|
||||
config.nqptp_shared_memory_interface_name = strdup(shared_memory_interface_name);
|
||||
|
||||
char apids[6 * 2 + 5 + 1]; // six pairs of digits, 5 colons and a NUL
|
||||
apids[6 * 2 + 5] = 0; // NUL termination
|
||||
int i;
|
||||
char hexchar[] = "0123456789abcdef";
|
||||
for (i = 5; i >= 0; i--) {
|
||||
apids[i * 3 + 1] = hexchar[apid & 0xF];
|
||||
apid = apid >> 4;
|
||||
apids[i * 3] = hexchar[apid & 0xF];
|
||||
apid = apid >> 4;
|
||||
if (i != 0)
|
||||
apids[i * 3 - 1] = ':';
|
||||
}
|
||||
|
||||
config.airplay_device_id = strdup(apids);
|
||||
|
||||
// now generate a UUID
|
||||
// from https://stackoverflow.com/questions/51053568/generating-a-random-uuid-in-c
|
||||
// with thanks
|
||||
uuid_t binuuid;
|
||||
uuid_generate_random(binuuid);
|
||||
|
||||
char *uuid = malloc(UUID_STR_LEN);
|
||||
// Produces a UUID string at uuid consisting of lower-case letters
|
||||
uuid_unparse_lower(binuuid, uuid);
|
||||
config.airplay_pi = uuid;
|
||||
debug(1, "Started in Airplay 2 mode on device \"%s\"!", config.airplay_device_id);
|
||||
uint64_t apf = config.airplay_features;
|
||||
uint64_t apfh = config.airplay_features;
|
||||
apfh = apfh >> 32;
|
||||
uint32_t apf32 = apf;
|
||||
uint32_t apfh32 = apfh;
|
||||
debug(1, "Started in Airplay 2 mode with features 0x%" PRIx32 ",0x%" PRIx32 " on device \"%s\"!",
|
||||
apf32, apfh32, config.airplay_device_id);
|
||||
#else
|
||||
debug(1, "Started in Airplay 1 mode!");
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user