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; pa_idxset *subscribed;
}; };
#define ENTRY_VERSION 2 #define ENTRY_VERSION 3
struct entry { struct entry {
uint8_t version; 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_bool_t muted:1;
pa_channel_map channel_map; pa_channel_map channel_map;
pa_cvolume volume; pa_cvolume volume;
char device[PA_NAME_MAX]; char device[PA_NAME_MAX];
char card[PA_NAME_MAX];
} PA_GCC_PACKED; } PA_GCC_PACKED;
enum { enum {
@ -196,11 +197,21 @@ static struct entry* read_entry(struct userdata *u, const char *name) {
goto fail; 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)) { if (e->device_valid && !pa_namereg_is_valid_name(e->device)) {
pa_log_warn("Invalid device name stored in database for stream %s", name); pa_log_warn("Invalid device name stored in database for stream %s", name);
goto fail; 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)) { if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) {
pa_log_warn("Invalid channel map stored in database for stream %s", name); pa_log_warn("Invalid channel map stored in database for stream %s", name);
goto fail; 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)))) (a->device_valid && strncmp(a->device, b->device, sizeof(a->device))))
return FALSE; 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 || if (a->muted_valid != b->muted_valid ||
(a->muted_valid && (a->muted != b->muted))) (a->muted_valid && (a->muted != b->muted)))
return FALSE; 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) { if (sink_input->save_sink) {
pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device)); pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device));
entry.device_valid = TRUE; 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 { } else {
@ -327,6 +347,11 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
if (source_output->save_source) { if (source_output->save_source) {
pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device)); pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device));
entry.device_valid = source_output->save_source; 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"))) if (!(name = get_name(new_data->proplist, "sink-input")))
return PA_HOOK_OK; 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) { if (e->device_valid)
pa_sink *s; s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK);
if ((s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK))) { if (!s && e->card_valid) {
if (!new_data->sink) { pa_card *card;
pa_log_info("Restoring device for stream %s.", name);
new_data->sink = s; if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
new_data->save_sink = TRUE; s = pa_idxset_first(card->sinks, NULL);
} else }
pa_log_debug("Not restoring device for stream %s, because already set.", name);
} /* 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); 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"))) if (!(name = get_name(new_data->proplist, "source-output")))
return PA_HOOK_OK; return PA_HOOK_OK;
if ((e = read_entry(u, name))) { if (new_data->source)
pa_source *s; 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 (e->device_valid)
if ((s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE))) { s = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE);
if (!new_data->source) {
pa_log_info("Restoring device for stream %s.", name); if (!s && e->card_valid) {
new_data->source = s; pa_card *card;
new_data->save_source = TRUE;
} else if ((card = pa_namereg_get(c, e->card, PA_NAMEREG_CARD)))
pa_log_debug("Not restoring device for stream %s, because already set", name); 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); 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) if (si->save_sink)
continue; 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"))) if (!(name = get_name(si->proplist, "sink-input")))
continue; 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) if (so->direct_on_input)
continue; 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"))) if (!(name = get_name(so->proplist, "source-input")))
continue; 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) { if (e->device_valid) {
pa_sink *d; 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); 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) { if (e->device_valid) {
pa_source *d; 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); pa_source_output_move_to(so, d, TRUE);
} }