mirror of
https://github.com/owntone/owntone-server.git
synced 2025-02-05 10:48:09 -05:00
[airplay] Fix so that AirPlay 2 devices are removed
This commit is contained in:
parent
5ece7b9591
commit
f105958a64
@ -202,6 +202,8 @@ struct airplay_extra
|
|||||||
{
|
{
|
||||||
enum airplay_devtype devtype;
|
enum airplay_devtype devtype;
|
||||||
|
|
||||||
|
char *mdns_name;
|
||||||
|
|
||||||
uint16_t wanted_metadata;
|
uint16_t wanted_metadata;
|
||||||
bool supports_auth_setup;
|
bool supports_auth_setup;
|
||||||
bool supports_pairing_transient;
|
bool supports_pairing_transient;
|
||||||
@ -609,6 +611,53 @@ device_id_colon_make(char *id_str, int size, uint64_t id)
|
|||||||
id_str[size - 1] = 0; // Zero terminate
|
id_str[size - 1] = 0; // Zero terminate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts AA:BB:CC:DD:EE:FF -> AABBCCDDEEFF -> uint64 id
|
||||||
|
static int
|
||||||
|
device_id_colon_parse(uint64_t *id, const char *id_str)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
char *ptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
s = calloc(1, strlen(id_str) + 1);
|
||||||
|
for (ptr = s; *id_str != '\0'; id_str++)
|
||||||
|
{
|
||||||
|
if (*id_str == ':')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*ptr = *id_str;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = safe_hextou64(s, id);
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
device_id_find_byname(uint64_t *id, const char *name)
|
||||||
|
{
|
||||||
|
struct output_device *device;
|
||||||
|
struct airplay_extra *re;
|
||||||
|
|
||||||
|
for (device = outputs_list(); device; device = device->next)
|
||||||
|
{
|
||||||
|
if (device->type != OUTPUT_TYPE_AIRPLAY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
re = device->extra_device_info;
|
||||||
|
if (strcmp(name, re->mdns_name) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*id = device->id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------- Crypto ----------------------------------- */
|
/* ------------------------------- Crypto ----------------------------------- */
|
||||||
|
|
||||||
@ -3987,6 +4036,7 @@ features_parse(struct keyval *features_kv, const char *fs1, const char *fs2, con
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Examples of txt content:
|
/* Examples of txt content:
|
||||||
* Airport Express 2:
|
* Airport Express 2:
|
||||||
["pk=7de...39" "gcgl=0" "gid=0fd...4" "pi=0fd...a4" "srcvers=366.0" "protovers=1.1" "serialNumber=C8...R" "manufacturer=Apple Inc." "model=AirPort10,115" "flags=0x4" "fv=p20.78100.3" "rsf=0x0" "features=0x445D0A00,0x1C340" "deviceid=74:1B:B2:D1:1A:B7" "acl=0"]
|
["pk=7de...39" "gcgl=0" "gid=0fd...4" "pi=0fd...a4" "srcvers=366.0" "protovers=1.1" "serialNumber=C8...R" "manufacturer=Apple Inc." "model=AirPort10,115" "flags=0x4" "fv=p20.78100.3" "rsf=0x0" "features=0x445D0A00,0x1C340" "deviceid=74:1B:B2:D1:1A:B7" "acl=0"]
|
||||||
@ -4008,36 +4058,35 @@ airplay_device_cb(const char *name, const char *type, const char *domain, const
|
|||||||
cfg_t *devcfg;
|
cfg_t *devcfg;
|
||||||
cfg_opt_t *cfgopt;
|
cfg_opt_t *cfgopt;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
const char *nickname = NULL;
|
||||||
const char *features;
|
const char *features;
|
||||||
char *s;
|
|
||||||
char *ptr;
|
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
p = keyval_get(txt, "deviceid");
|
if (port > 0)
|
||||||
if (!p)
|
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_AIRPLAY, "AirPlay device '%s' is missing a device ID\n", name);
|
p = keyval_get(txt, "deviceid");
|
||||||
return;
|
if (!p)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_AIRPLAY, "AirPlay device '%s' is missing a device ID\n", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = device_id_colon_parse(&id, p);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_AIRPLAY, "Could not extract AirPlay device ID ('%s'): %s\n", name, p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Convert AA:BB:CC:DD:EE:FF -> AABBCCDDEEFF -> uint64 id
|
|
||||||
s = calloc(1, strlen(p) + 1);
|
|
||||||
for (ptr = s; *p != '\0'; p++)
|
|
||||||
{
|
{
|
||||||
if (*p == ':')
|
ret = device_id_find_byname(&id, name);
|
||||||
continue;
|
if (ret < 0)
|
||||||
|
{
|
||||||
*ptr = *p;
|
DPRINTF(E_WARN, L_AIRPLAY, "Could not remove, AirPlay device '%s' not in our list\n", name);
|
||||||
ptr++;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = safe_hextou64(s, &id);
|
|
||||||
free(s);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_AIRPLAY, "Could not extract AirPlay device ID ('%s')\n", name);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_AIRPLAY, "Event for AirPlay device '%s' (port %d, id %" PRIx64 ")\n", name, port, id);
|
DPRINTF(E_DBG, L_AIRPLAY, "Event for AirPlay device '%s' (port %d, id %" PRIx64 ")\n", name, port, id);
|
||||||
@ -4053,12 +4102,17 @@ airplay_device_cb(const char *name, const char *type, const char *domain, const
|
|||||||
DPRINTF(E_INFO, L_AIRPLAY, "AirPlay device '%s' disappeared, but set as permanent in config\n", name);
|
DPRINTF(E_INFO, L_AIRPLAY, "AirPlay device '%s' disappeared, but set as permanent in config\n", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (devcfg && cfg_getstr(devcfg, "nickname"))
|
||||||
|
{
|
||||||
|
nickname = cfg_getstr(devcfg, "nickname");
|
||||||
|
}
|
||||||
|
|
||||||
CHECK_NULL(L_AIRPLAY, rd = calloc(1, sizeof(struct output_device)));
|
CHECK_NULL(L_AIRPLAY, rd = calloc(1, sizeof(struct output_device)));
|
||||||
CHECK_NULL(L_AIRPLAY, re = calloc(1, sizeof(struct airplay_extra)));
|
CHECK_NULL(L_AIRPLAY, re = calloc(1, sizeof(struct airplay_extra)));
|
||||||
|
|
||||||
rd->id = id;
|
rd->id = id;
|
||||||
rd->name = strdup(name);
|
rd->name = nickname ? strdup(nickname) : strdup(name);
|
||||||
|
re->mdns_name = strdup(name); // Used for identifying device when it disappears
|
||||||
rd->type = OUTPUT_TYPE_AIRPLAY;
|
rd->type = OUTPUT_TYPE_AIRPLAY;
|
||||||
rd->type_name = outputs_name(rd->type);
|
rd->type_name = outputs_name(rd->type);
|
||||||
rd->extra_device_info = re;
|
rd->extra_device_info = re;
|
||||||
@ -4257,6 +4311,7 @@ airplay_device_free_extra(struct output_device *device)
|
|||||||
{
|
{
|
||||||
struct airplay_extra *re = device->extra_device_info;
|
struct airplay_extra *re = device->extra_device_info;
|
||||||
|
|
||||||
|
free(re->mdns_name);
|
||||||
free(re);
|
free(re);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user