]> code.delx.au - pulseaudio/commitdiff
module-stream-restore: don't fiddle with sinks/sources/streams that are not fully...
authorLennart Poettering <lennart@poettering.net>
Fri, 14 Aug 2009 21:55:32 +0000 (23:55 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 14 Aug 2009 21:55:32 +0000 (23:55 +0200)
src/modules/module-stream-restore.c

index 8c0bb6b0083b4042d7844bfe5740854f3fb1fc0f..727a52752fb5b78513a9829305b5a9f8ee5189a3 100644 (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);
             }