[player] Sort devices and autoselect based on priority

This commit is contained in:
ejurgensen 2016-04-04 21:54:37 +02:00
parent c5bb83480d
commit acc1ff4a47
3 changed files with 57 additions and 14 deletions

View File

@ -315,6 +315,11 @@ outputs_metadata_free(struct output_metadata *omd)
} }
} }
int
outputs_priority(struct output_device *device)
{
return outputs[device->type]->priority;
}
const char * const char *
outputs_name(enum output_types type) outputs_name(enum output_types type)

View File

@ -147,7 +147,6 @@ struct output_definition
// Priority to give this output when autoselecting an output, 1 is highest // Priority to give this output when autoselecting an output, 1 is highest
// 1 = highest priority, 0 = don't autoselect // 1 = highest priority, 0 = don't autoselect
// TODO Not implemented yet
int priority; int priority;
// Set to 1 if the output initialization failed // Set to 1 if the output initialization failed
@ -240,6 +239,9 @@ outputs_metadata_prune(uint64_t rtptime);
void void
outputs_metadata_free(struct output_metadata *omd); outputs_metadata_free(struct output_metadata *omd);
int
outputs_priority(struct output_device *device);
const char * const char *
outputs_name(enum output_types type); outputs_name(enum output_types type);

View File

@ -1567,6 +1567,40 @@ player_playback_cb(int fd, short what, void *arg)
} }
/* Helpers */ /* Helpers */
static void
device_list_sort(void)
{
struct output_device *device;
struct output_device *next;
struct output_device *prev;
int swaps;
// Swap sorting since even the most inefficient sorting should do fine here
do
{
swaps = 0;
prev = NULL;
for (device = dev_list; device && device->next; device = device->next)
{
next = device->next;
if ( (outputs_priority(device) > outputs_priority(next)) ||
(outputs_priority(device) == outputs_priority(next) && strcasecmp(device->name, next->name) > 0) )
{
if (device == dev_list)
dev_list = next;
if (prev)
prev->next = next;
device->next = next->next;
next->next = device;
swaps++;
}
prev = device;
}
}
while (swaps > 0);
}
static void static void
device_remove(struct output_device *remove) device_remove(struct output_device *remove)
{ {
@ -1693,6 +1727,8 @@ device_add(struct player_command *cmd)
outputs_device_free(add); outputs_device_free(add);
} }
device_list_sort();
return 0; return 0;
} }
@ -2396,8 +2432,9 @@ playback_start_item(struct player_command *cmd, struct queue_item *qii)
if ((cmd->output_requests_pending == 0) && (output_sessions == 0)) if ((cmd->output_requests_pending == 0) && (output_sessions == 0))
for (device = dev_list; device; device = device->next) for (device = dev_list; device; device = device->next)
{ {
if (!device->session) if ((outputs_priority(device) == 0) || device->session)
{ continue;
speaker_select_output(device); speaker_select_output(device);
ret = outputs_device_start(device, device_restart_cb, last_rtptime + AIRTUNES_V2_PACKET_SAMPLES); ret = outputs_device_start(device, device_restart_cb, last_rtptime + AIRTUNES_V2_PACKET_SAMPLES);
if (ret < 0) if (ret < 0)
@ -2411,7 +2448,6 @@ playback_start_item(struct player_command *cmd, struct queue_item *qii)
cmd->output_requests_pending++; cmd->output_requests_pending++;
break; break;
} }
}
/* No luck finding valid output */ /* No luck finding valid output */
if ((cmd->output_requests_pending == 0) && (output_sessions == 0)) if ((cmd->output_requests_pending == 0) && (output_sessions == 0))