module-stream-restore: don't fiddle with sinks/sources/streams that are not fully set up yet

This commit is contained in:
Lennart Poettering 2009-08-14 23:55:32 +02:00
parent 0f2a4ed422
commit 7891f964e4

View file

@ -102,15 +102,16 @@ struct userdata {
pa_idxset *subscribed;
};
#define ENTRY_VERSION 2
#define ENTRY_VERSION 3
struct entry {
uint8_t version;
pa_bool_t muted_valid:1, volume_valid:1, device_valid:1;
pa_bool_t muted_valid:1, volume_valid:1, device_valid:1, card_valid:1;
pa_bool_t muted:1;
pa_channel_map channel_map;
pa_cvolume volume;
char device[PA_NAME_MAX];
char card[PA_NAME_MAX];
} PA_GCC_PACKED;
enum {
@ -196,11 +197,21 @@ static struct entry* read_entry(struct userdata *u, const char *name) {
goto fail;
}
if (!memchr(e->card, 0, sizeof(e->card))) {
pa_log_warn("Database contains entry for stream %s with missing NUL byte in card name", name);
goto fail;
}
if (e->device_valid && !pa_namereg_is_valid_name(e->device)) {
pa_log_warn("Invalid device name stored in database for stream %s", name);
goto fail;
}
if (e->card_valid && !pa_namereg_is_valid_name(e->card)) {
pa_log_warn("Invalid card name stored in database for stream %s", name);
goto fail;
}
if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
pa_log_warn("Invalid channel map stored in database for stream %s", name);
goto fail;
@ -252,6 +263,10 @@ static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) {
(a->device_valid && strncmp(a->device, b->device, sizeof(a->device))))
return FALSE;
if (a->card_valid != b->card_valid ||
(a->card_valid && strncmp(a->card, b->card, sizeof(a->card))))
return FALSE;
if (a->muted_valid != b->muted_valid ||
(a->muted_valid && (a->muted != b->muted)))
return FALSE;
@ -308,6 +323,11 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
if (sink_input->save_sink) {
pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device));
entry.device_valid = TRUE;
if (sink_input->sink->card) {
pa_strlcpy(entry.card, sink_input->sink->card->name, sizeof(entry.card));
entry.card_valid = TRUE;
}
}
} else {
@ -327,6 +347,11 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
if (source_output->save_source) {
pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device));
entry.device_valid = source_output->save_source;
if (source_output->source->card) {
pa_strlcpy(entry.card, source_output->source->card->name, sizeof(entry.card));
entry.card_valid = TRUE;
}
}
}
@ -368,19 +393,28 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n
if (!(name = get_name(new_data->proplist, "sink-input")))
return PA_HOOK_OK;
if ((e = read_entry(u, name))) {
if (new_data->sink)
pa_log_debug("Not restoring device for stream %s, because already set.", name);
else if ((e = read_entry(u, name))) {
pa_sink *s = NULL;
if (e->device_valid) {
pa_sink *s;
if (e->device_valid)
s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK);
if ((s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK))) {
if (!new_data->sink) {
pa_log_info("Restoring device for stream %s.", name);
new_data->sink = s;
new_data->save_sink = TRUE;
} else
pa_log_debug("Not restoring device for stream %s, because already set.", name);
}
if (!s && e->card_valid) {
pa_card *card;
if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
s = pa_idxset_first(card->sinks, NULL);
}
/* It might happen that a stream and a sink are set up at the
same time, in which case we want to make sure we don't
interfere with that */
if (s && PA_SINK_IS_LINKED(pa_sink_get_state(s))) {
pa_log_info("Restoring device for stream %s.", name);
new_data->sink = s;
new_data->save_sink = TRUE;
}
pa_xfree(e);
@ -455,18 +489,28 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou
if (!(name = get_name(new_data->proplist, "source-output")))
return PA_HOOK_OK;
if ((e = read_entry(u, name))) {
pa_source *s;
if (new_data->source)
pa_log_debug("Not restoring device for stream %s, because already set", name);
else if ((e = read_entry(u, name))) {
pa_source *s = NULL;
if (e->device_valid) {
if ((s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE))) {
if (!new_data->source) {
pa_log_info("Restoring device for stream %s.", name);
new_data->source = s;
new_data->save_source = TRUE;
} else
pa_log_debug("Not restoring device for stream %s, because already set", name);
}
if (e->device_valid)
s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE);
if (!s && e->card_valid) {
pa_card *card;
if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
s = pa_idxset_first(card->sources, NULL);
}
/* It might happen that a stream and a sink are set up at the
same time, in which case we want to make sure we don't
interfere with that */
if (s && PA_SOURCE_IS_LINKED(pa_source_get_state(s))) {
pa_log_info("Restoring device for stream %s.", name);
new_data->source = s;
new_data->save_source = TRUE;
}
pa_xfree(e);
@ -496,6 +540,12 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct
if (si->save_sink)
continue;
/* It might happen that a stream and a sink are set up at the
same time, in which case we want to make sure we don't
interfere with that */
if (!PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(si)))
continue;
if (!(name = get_name(si->proplist, "sink-input")))
continue;
@ -534,6 +584,12 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
if (so->direct_on_input)
continue;
/* It might happen that a stream and a sink are set up at the
same time, in which case we want to make sure we don't
interfere with that */
if (!PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(so)))
continue;
if (!(name = get_name(so->proplist, "source-input")))
continue;
@ -575,7 +631,9 @@ static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, str
if (e->device_valid) {
pa_sink *d;
if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) && d != sink)
if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) &&
d != sink &&
PA_SINK_IS_LINKED(pa_sink_get_state(d)))
pa_sink_input_move_to(si, d, TRUE);
}
@ -613,7 +671,9 @@ static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *sourc
if (e->device_valid) {
pa_source *d;
if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) && d != source)
if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) &&
d != source &&
PA_SOURCE_IS_LINKED(pa_source_get_state(d)))
pa_source_output_move_to(so, d, TRUE);
}