return result;
}
-static pa_bool_t try_to_switch_profile(pa_card *card, pa_device_port *port) {
+static bool profile_good_for_output(pa_card_profile *profile) {
+ pa_sink *sink;
+ uint32_t idx;
+
+ pa_assert(profile);
+
+ if (profile->card->active_profile->n_sources != profile->n_sources)
+ return false;
+
+ if (profile->card->active_profile->max_source_channels != profile->max_source_channels)
+ return false;
+
+ /* Try not to switch to HDMI sinks from analog when HDMI is becoming available */
+ PA_IDXSET_FOREACH(sink, profile->card->sinks, idx) {
+ if (!sink->active_port)
+ continue;
+
+ if (sink->active_port->available != PA_AVAILABLE_NO)
+ return false;
+ }
+
+ return true;
+}
+
+static bool profile_good_for_input(pa_card_profile *profile) {
+ pa_assert(profile);
+
+ if (profile->card->active_profile->n_sinks != profile->n_sinks)
+ return false;
+
+ if (profile->card->active_profile->max_sink_channels != profile->max_sink_channels)
+ return false;
+
+ return true;
+}
+
+static int try_to_switch_profile(pa_device_port *port) {
pa_card_profile *best_profile = NULL, *profile;
void *state;
pa_log_debug("Finding best profile");
PA_HASHMAP_FOREACH(profile, port->profiles, state) {
+ bool good = false;
+
if (best_profile && best_profile->priority >= profile->priority)
continue;
/* We make a best effort to keep other direction unchanged */
- if (!port->is_input) {
- if (card->active_profile->n_sources != profile->n_sources)
- continue;
-
- if (card->active_profile->max_source_channels != profile->max_source_channels)
- continue;
- }
-
- if (!port->is_output) {
- if (card->active_profile->n_sinks != profile->n_sinks)
- continue;
+ switch (port->direction) {
+ case PA_DIRECTION_OUTPUT:
+ good = profile_good_for_output(profile);
+ break;
- if (card->active_profile->max_sink_channels != profile->max_sink_channels)
- continue;
+ case PA_DIRECTION_INPUT:
+ good = profile_good_for_input(profile);
+ break;
}
- if (port->is_output) {
- /* Try not to switch to HDMI sinks from analog when HDMI is becoming available */
- uint32_t state2;
- pa_sink *sink;
- pa_bool_t found_active_port = FALSE;
-
- PA_IDXSET_FOREACH(sink, card->sinks, state2) {
- if (!sink->active_port)
- continue;
- if (sink->active_port->available != PA_AVAILABLE_NO)
- found_active_port = TRUE;
- }
-
- if (found_active_port)
- continue;
- }
+ if (!good)
+ continue;
best_profile = profile;
}
if (!best_profile) {
pa_log_debug("No suitable profile found");
- return FALSE;
+ return -1;
}
- if (pa_card_set_profile(card, best_profile->name, FALSE) != 0) {
+ if (pa_card_set_profile(port->card, best_profile, false) != 0) {
pa_log_debug("Could not set profile %s", best_profile->name);
- return FALSE;
+ return -1;
}
- return TRUE;
+ return 0;
}
-static void find_sink_and_source(pa_card *card, pa_device_port *port, pa_sink **si, pa_source **so)
-{
+static void find_sink_and_source(pa_card *card, pa_device_port *port, pa_sink **si, pa_source **so) {
pa_sink *sink = NULL;
pa_source *source = NULL;
uint32_t state;
- if (port->is_output)
- PA_IDXSET_FOREACH(sink, card->sinks, state)
- if (port == pa_hashmap_get(sink->ports, port->name))
- break;
+ switch (port->direction) {
+ case PA_DIRECTION_OUTPUT:
+ PA_IDXSET_FOREACH(sink, card->sinks, state)
+ if (port == pa_hashmap_get(sink->ports, port->name))
+ break;
+ break;
- if (port->is_input)
- PA_IDXSET_FOREACH(source, card->sources, state)
- if (port == pa_hashmap_get(source->ports, port->name))
- break;
+ case PA_DIRECTION_INPUT:
+ PA_IDXSET_FOREACH(source, card->sources, state)
+ if (port == pa_hashmap_get(source->ports, port->name))
+ break;
+ break;
+ }
*si = sink;
*so = source;
pa_card* card;
pa_sink *sink;
pa_source *source;
- pa_bool_t is_active_profile, is_active_port;
+ bool is_active_profile, is_active_port;
if (port->available == PA_AVAILABLE_UNKNOWN)
return PA_HOOK_OK;
return PA_HOOK_OK;
}
+ if (pa_idxset_size(card->sinks) == 0 && pa_idxset_size(card->sources) == 0)
+ /* This card is not initialized yet. We'll handle it in
+ sink_new / source_new callbacks later. */
+ return PA_HOOK_OK;
+
find_sink_and_source(card, port, &sink, &source);
is_active_profile = card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
return PA_HOOK_OK;
if (!is_active_profile) {
- if (!try_to_switch_profile(card, port))
+ if (try_to_switch_profile(port) < 0)
return PA_HOOK_OK;
pa_assert(card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name));
}
if (source)
- pa_source_set_port(source, port->name, FALSE);
+ pa_source_set_port(source, port->name, false);
if (sink)
- pa_sink_set_port(sink, port->name, FALSE);
+ pa_sink_set_port(sink, port->name, false);
}
if (port->available == PA_AVAILABLE_NO) {
pa_device_port *p2 = find_best_port(sink->ports);
if (p2 && p2->available != PA_AVAILABLE_NO)
- pa_sink_set_port(sink, p2->name, FALSE);
+ pa_sink_set_port(sink, p2->name, false);
else {
/* Maybe try to switch to another profile? */
}
pa_device_port *p2 = find_best_port(source->ports);
if (p2 && p2->available != PA_AVAILABLE_NO)
- pa_source_set_port(source, p2->name, FALSE);
+ pa_source_set_port(source, p2->name, false);
else {
/* Maybe try to switch to another profile? */
}
return PA_HOOK_OK;
}
-
int pa__init(pa_module*m) {
struct userdata *u;