Skip to content

Commit e9e788c

Browse files
committed
PIN-based pairing working
1 parent b2ca351 commit e9e788c

File tree

8 files changed

+58
-15
lines changed

8 files changed

+58
-15
lines changed

src/airplay.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3972,9 +3972,6 @@ airplay_device_authorize(struct output_device *device, const char *pin, int call
39723972
if (!rs)
39733973
return -1;
39743974

3975-
DPRINTF(E_DBG, L_AIRPLAY, "%s:Calling sequence_start(AIRPLAY_SEQ_PAIR_SETUP,...) for %s with PIN %s\n",
3976-
__func__, device->name, pin
3977-
);
39783975
sequence_start(AIRPLAY_SEQ_PAIR_SETUP, rs, (void *)pin, "device_authorize");
39793976

39803977
return 1;

src/cliap2.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,13 @@ usage(char *program)
147147
printf(" --loglevel <number> Log level (0-5)\n");
148148
printf(" --logfile <filename> Log filename. Not supplying this argument will result in logging to stderr only.\n");
149149
printf(" --logdomains <dom,dom..> Log domains\n");
150-
printf(" --config <file> Use <file> as the configuration file\n");
150+
printf(" --config <file> Use <file> for the configuration file.\n");
151151
printf(" --name <name> Name of the airplay 2 device. Mandatory in absence of --ntpstart.\n");
152152
printf(" --hostname <hostname> Hostname of AirPlay 2 device. Mandatory in absence of --ntpstart.\n");
153153
printf(" --address <address> IP address to bind to for AirPlay 2 service. Mandatory in absence of --ntpstart.\n");
154154
printf(" --port <port> Port number to bind to for AirPlay 2 service. Mandatory in absence of --ntpstart.\n");
155155
printf(" --txt <txt> txt keyvals returned in mDNS for AirPlay 2 service. Mandatory in absence of --ntpstart.\n");
156+
printf(" --auth <auth_key> Authorization key.\n");
156157
printf(" --pipe <audio_filename> filename of named pipe to read streamed audio. Mandatory in absence of --ntpstart.\n");
157158
printf(" --command_pipe <command_filename> filename of named pipe to read commands and metadata. Defaults to <audio_filename>.metadata\n");
158159
printf(" --ntp Print current NTP time and exit.\n");
@@ -524,6 +525,7 @@ main(int argc, char **argv)
524525
{ "testrun", 0, NULL, 514 }, // Used for CI, not documented to user
525526
{ "pipe", 1, NULL, 515 },
526527
{ "command_pipe", 1, NULL, 517 },
528+
{ "auth", 1, NULL, 518 },
527529

528530
{ NULL, 0, NULL, 0 }
529531
};
@@ -629,6 +631,10 @@ main(int argc, char **argv)
629631
mass_named_pipes.metadata_pipe = optarg;
630632
break;
631633

634+
case 518: // authorization key
635+
ap2_device_info.auth_key = optarg;
636+
break;
637+
632638
default:
633639
case '?':
634640
usage(argv[0]);
@@ -683,7 +689,6 @@ main(int argc, char **argv)
683689
conffile_unload();
684690
return EXIT_FAILURE;
685691
}
686-
// logger_detach(); // Eliminate logging to stderr
687692

688693
if (testrun) {
689694
ret = create_pipes(TESTRUN_PIPE);
@@ -694,7 +699,7 @@ main(int argc, char **argv)
694699
mass_named_pipes.audio_pipe = TESTRUN_PIPE;
695700
}
696701
else {
697-
// Check that named pipe exists for audio streaming. Metadata one too?
702+
// Check that named pipes exist for audio streaming and metadata
698703
ret = check_pipe(mass_named_pipes.audio_pipe);
699704
if (ret < 0) {
700705
return EXIT_FAILURE;

src/cliap2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ typedef struct ap2_device_info
1010
const char *address;
1111
int port;
1212
struct keyval *txt;
13+
const char *auth_key;
1314
uint64_t ntpstart;
1415
uint32_t wait;
1516
struct timespec start_ts;

src/conffile.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static cfg_opt_t sec_general[] =
5252
CFG_STR_LIST("trusted_networks", "{lan}", CFGF_NONE),
5353
CFG_BOOL("ipv6", cfg_false, CFGF_NONE),
5454
CFG_STR("bind_address", NULL, CFGF_NONE),
55-
CFG_BOOL("speaker_autoselect", cfg_false, CFGF_NONE),
55+
CFG_BOOL("speaker_autoselect", cfg_true, CFGF_NONE),
5656
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
5757
CFG_BOOL("high_resolution_clock", cfg_false, CFGF_NONE),
5858
#else
@@ -70,7 +70,7 @@ static cfg_opt_t sec_general[] =
7070
/* library section structure */
7171
static cfg_opt_t sec_library[] =
7272
{
73-
CFG_STR("name", "My Music on %h", CFGF_NONE),
73+
CFG_STR("name", "Music Assistant", CFGF_NONE),
7474
CFG_INT("port", 3689, CFGF_NONE),
7575
CFG_STR("password", NULL, CFGF_NONE),
7676
CFG_STR_LIST("directories", NULL, CFGF_NONE),

src/mass.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,9 @@ pipe_metadata_read_cb(evutil_socket_t fd, short event, void *arg)
12381238
}
12391239
if (message & PIPE_METADATA_MSG_PIN) {
12401240
DPRINTF(E_DBG, L_PLAYER, "%s:Setting PIN from metadata pipe to %s\n", __func__, pipe_metadata.prepared.pin);
1241-
player_raop_verification_kickoff(&pipe_metadata.prepared.pin);
1241+
// We only support AirPlay2 at the moment. The below code will need to be changed if we add support
1242+
// for RAOP.
1243+
player_verification_kickoff(&pipe_metadata.prepared.pin, OUTPUT_TYPE_AIRPLAY);
12421244
free(pipe_metadata.prepared.pin);
12431245

12441246
}
@@ -1590,6 +1592,9 @@ mass_timer_cb(int fd, short what, void *arg)
15901592
int
15911593
mass_init(void)
15921594
{
1595+
// Maybe we can add a call to player_device_add(device) in here somewhere to initiate device connection before
1596+
// audio is streamed to the named pipe. Currently, device connection is initiatied on receipt of data on the
1597+
// audio named pipe.
15931598
DPRINTF(E_DBG, L_PLAYER, "mass_init()\n");
15941599

15951600
CHECK_ERR(L_PLAYER, mutex_init(&pipe_metadata.prepared.lock));
@@ -1599,6 +1604,8 @@ mass_init(void)
15991604
if (!tid_pipe) {
16001605
// main thread
16011606
// Create a persistent event timer in the main event loop to monitor and report playback status
1607+
// Using the main thread may not be necessary anymore - test moving this into the pipe thread at some time
1608+
// to understand the implications.
16021609
mass_timer_event = event_new(evbase_main, -1, EV_PERSIST | EV_TIMEOUT, mass_timer_cb, NULL);
16031610
DPRINTF(E_DBG, L_PLAYER,
16041611
"%s:Activating persistent event timer with timeval %d sec, %d usec\n,",

src/player.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,8 +1494,6 @@ device_auth_kickoff(void *arg, int *retval)
14941494
}
14951495

14961496
// We're async, so we don't care about return values or callbacks with result
1497-
DPRINTF(E_DBG, L_PLAYER, "%s:Device: %d sending PIN: %s to outputs_device_authorize()\n",
1498-
__func__, device->name, cmdarg->auth.pin);
14991497
outputs_device_authorize(device, cmdarg->auth.pin, NULL);
15001498

15011499
*retval = 0;
@@ -2137,8 +2135,11 @@ playback_start_item(void *arg, int *retval)
21372135

21382136
*retval = outputs_device_start(device, device_activate_cb, false);
21392137
DPRINTF(E_DBG, L_PLAYER,
2140-
"%s:outputs_device_start(device, device_activate_cb, false) returned %d for device %s, requires auth:%s\n",
2141-
__func__, *retval, device->name, device->requires_auth ? "true" : "false"
2138+
"%s:retval %d, Device %s, state: %d, requires auth:%s, prevent playback:%s, busy:%s\n",
2139+
__func__, *retval, device->name, device->state,
2140+
device->requires_auth ? "true" : "false",
2141+
device->prevent_playback ? "true" : "false",
2142+
device->busy ? "true" : "false"
21422143
);
21432144
if (*retval < 0)
21442145
continue;
@@ -3872,6 +3873,25 @@ player_raop_verification_kickoff(char **arglist)
38723873

38733874
}
38743875

3876+
void
3877+
player_verification_kickoff(char **arglist, enum output_types type)
3878+
{
3879+
union player_arg *cmdarg;
3880+
3881+
cmdarg = calloc(1, sizeof(union player_arg));
3882+
if (!cmdarg)
3883+
{
3884+
DPRINTF(E_LOG, L_PLAYER, "Could not allocate player_command\n");
3885+
return;
3886+
}
3887+
3888+
cmdarg->auth.type = type;
3889+
memcpy(cmdarg->auth.pin, arglist[0], 4);
3890+
3891+
commands_exec_async(cmdbase, device_auth_kickoff, cmdarg);
3892+
3893+
}
3894+
38753895

38763896
/* ---------------------------- Thread: player ------------------------------ */
38773897

src/player.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ player_device_remove(void *device);
203203
void
204204
player_raop_verification_kickoff(char **arglist);
205205

206+
void
207+
player_verification_kickoff(char **arglist, enum output_types type);
208+
206209
const char *
207210
player_pmap(void *p);
208211

src/wrappers.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,11 @@ db_perthread_deinit(void)
387387
int
388388
db_speaker_save(struct output_device *device)
389389
{
390-
// It has been tested that it is ok to do nothing
390+
if (device->auth_key) {
391+
DPRINTF(E_DBG, L_DB, "%s:Device %s has authorization key '%s'\n",
392+
__func__, device->name, device->auth_key
393+
);
394+
}
391395
return 0;
392396
}
393397

@@ -397,7 +401,7 @@ db_speaker_get(struct output_device *device, uint64_t id)
397401
device->id = id;
398402
device->selected = 1;
399403
device->volume = ap2_device_info.volume;
400-
//device->auth_key = ?? // might need to pass this as command line argument for some devices
404+
device->auth_key = (char *)ap2_device_info.auth_key; // lose the const qualifier
401405
device->selected_format = MEDIA_FORMAT_ALAC;
402406

403407
return 0;
@@ -472,6 +476,12 @@ db_escape_string(const char *str)
472476
/*
473477
* Wrappers for mdns.c
474478
*/
479+
480+
// Immediately call the mdns_browse_cb with the information about the
481+
// airplay device we want to stream to.
482+
// TODO: @bradkeifer - see if we can trigger device connection after
483+
// the callback is complete. At the moment, device connection is triggered
484+
// on receipt of first audio streaming data on the named pipe.
475485
int
476486
mdns_browse(char *type, mdns_browse_cb cb, enum mdns_options flags)
477487
{

0 commit comments

Comments
 (0)