[pulseaudio-commits] 8 commits - src/modules src/pulsecore

Tanu Kaskinen tanuk at kemper.freedesktop.org
Sat Nov 21 19:01:42 PST 2015


 src/modules/alsa/alsa-mixer.c                 |    8 +
 src/modules/alsa/alsa-mixer.h                 |    3 
 src/modules/alsa/module-alsa-card.c           |    2 
 src/modules/module-card-restore.c             |   58 ++++++--
 src/modules/module-switch-on-port-available.c |  179 ++++++++++++++++----------
 src/pulsecore/card.c                          |   20 ++
 src/pulsecore/card.h                          |    8 +
 src/pulsecore/device-port.c                   |   11 +
 src/pulsecore/device-port.h                   |    2 
 9 files changed, 212 insertions(+), 79 deletions(-)

New commits:
commit bea37613ceda60c6843e2afc5e7c5859dbe570c1
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Tue Nov 17 15:10:36 2015 +0100

    module-card-restore: Remove "version" from internal entry struct
    
    If we always write entries of the latest version, we can simplify
    code a little by only handling old versions in the "entry_read"
    function and assume we have the latest version everywhere else.
    
    Suggested-by: Tanu Kaskinen <tanuk at iki.fi>
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
index b30fa36..f906843 100644
--- a/src/modules/module-card-restore.c
+++ b/src/modules/module-card-restore.c
@@ -73,7 +73,6 @@ struct port_info {
 };
 
 struct entry {
-    uint8_t version;
     char *profile;
     pa_hashmap *ports; /* Port name -> struct port_info */
 };
@@ -110,7 +109,6 @@ static void port_info_free(struct port_info *p_info) {
 
 static struct entry* entry_new(void) {
     struct entry *r = pa_xnew0(struct entry, 1);
-    r->version = ENTRY_VERSION;
     r->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) port_info_free);
     return r;
 }
@@ -193,15 +191,14 @@ static bool entry_write(struct userdata *u, const char *name, const struct entry
     pa_assert(e);
 
     t = pa_tagstruct_new();
-    pa_tagstruct_putu8(t, e->version);
+    pa_tagstruct_putu8(t, ENTRY_VERSION);
     pa_tagstruct_puts(t, e->profile);
     pa_tagstruct_putu32(t, pa_hashmap_size(e->ports));
 
     PA_HASHMAP_FOREACH(p_info, e->ports, state) {
         pa_tagstruct_puts(t, p_info->name);
         pa_tagstruct_puts64(t, p_info->offset);
-        if (e->version >= 3)
-            pa_tagstruct_puts(t, p_info->profile);
+        pa_tagstruct_puts(t, p_info->profile);
     }
 
     key.data = (char *) name;
@@ -258,6 +255,7 @@ static struct entry* entry_read(struct userdata *u, const char *name) {
     struct entry *e = NULL;
     pa_tagstruct *t = NULL;
     const char* profile;
+    uint8_t version;
 
     pa_assert(u);
     pa_assert(name);
@@ -275,8 +273,8 @@ static struct entry* entry_read(struct userdata *u, const char *name) {
     t = pa_tagstruct_new_fixed(data.data, data.size);
     e = entry_new();
 
-    if (pa_tagstruct_getu8(t, &e->version) < 0 ||
-        e->version > ENTRY_VERSION ||
+    if (pa_tagstruct_getu8(t, &version) < 0 ||
+        version > ENTRY_VERSION ||
         pa_tagstruct_gets(t, &profile) < 0) {
 
         goto fail;
@@ -287,7 +285,7 @@ static struct entry* entry_read(struct userdata *u, const char *name) {
 
     e->profile = pa_xstrdup(profile);
 
-    if (e->version >= 2) {
+    if (version >= 2) {
         uint32_t port_count = 0;
         const char *port_name = NULL, *profile_name = NULL;
         int64_t port_offset = 0;
@@ -303,7 +301,7 @@ static struct entry* entry_read(struct userdata *u, const char *name) {
                 pa_hashmap_get(e->ports, port_name) ||
                 pa_tagstruct_gets64(t, &port_offset) < 0)
                 goto fail;
-            if (e->version >= 3 && pa_tagstruct_gets(t, &profile_name) < 0)
+            if (version >= 3 && pa_tagstruct_gets(t, &profile_name) < 0)
                 goto fail;
 
             p_info = port_info_new(NULL);
@@ -399,7 +397,6 @@ static void update_profile_for_port(struct entry *entry, pa_card *card, pa_devic
     if (!pa_safe_streq(p_info->profile, p->preferred_profile)) {
         pa_xfree(p_info->profile);
         p_info->profile = pa_xstrdup(p->preferred_profile);
-        entry->version = ENTRY_VERSION;
         pa_log_info("Storing profile %s for port %s on card %s.", p_info->profile, p->name, card->name);
     }
 }

commit e87100d41ef6d14f8dc7f803582191d9f8d8f183
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Tue Nov 17 15:10:35 2015 +0100

    module-switch-on-port-available: Route to preferred profile
    
    This makes the routing slightly more aggressive:
    
     * It will try to route to another profile, if such a profile
       is preferred by the port.
    
     * It will allow changing profiles on transitions both to
       PA_AVAILABLE_YES and PA_AVAILABLE_NO
    
    To accommodate there is also some refactoring.
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index 8de68a3..5dd9786 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -74,22 +74,25 @@ static bool profile_good_for_input(pa_card_profile *profile) {
 static int try_to_switch_profile(pa_device_port *port) {
     pa_card_profile *best_profile = NULL, *profile;
     void *state;
+    unsigned best_prio = 0;
 
-    pa_log_debug("Finding best profile");
+    pa_log_debug("Finding best profile for port %s, preferred = %s",
+                 port->name, pa_strnull(port->preferred_profile));
 
     PA_HASHMAP_FOREACH(profile, port->profiles, state) {
         bool good = false;
-
-        if (best_profile && best_profile->priority >= profile->priority)
-            continue;
+        const char *name;
+        unsigned prio = profile->priority;
 
         /* We make a best effort to keep other direction unchanged */
         switch (port->direction) {
             case PA_DIRECTION_OUTPUT:
+                name = profile->output_name;
                 good = profile_good_for_output(profile);
                 break;
 
             case PA_DIRECTION_INPUT:
+                name = profile->input_name;
                 good = profile_good_for_input(profile);
                 break;
         }
@@ -97,7 +100,15 @@ static int try_to_switch_profile(pa_device_port *port) {
         if (!good)
             continue;
 
+        /* Give a high bonus in case this is the preferred profile */
+        if (port->preferred_profile && pa_streq(name ? name : profile->name, port->preferred_profile))
+            prio += 1000000;
+
+        if (best_profile && best_prio >= prio)
+            continue;
+
         best_profile = profile;
+        best_prio = prio;
     }
 
     if (!best_profile) {
@@ -113,98 +124,125 @@ static int try_to_switch_profile(pa_device_port *port) {
     return 0;
 }
 
-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;
+struct port_pointers {
+    pa_device_port *port;
+    pa_sink *sink;
+    pa_source *source;
+    bool is_possible_profile_active;
+    bool is_preferred_profile_active;
+    bool is_port_active;
+};
+
+static const char* profile_name_for_dir(pa_card_profile *cp, pa_direction_t dir) {
+    if (dir == PA_DIRECTION_OUTPUT && cp->output_name)
+        return cp->output_name;
+    if (dir == PA_DIRECTION_INPUT && cp->input_name)
+        return cp->input_name;
+    return cp->name;
+}
+
+static struct port_pointers find_port_pointers(pa_device_port *port) {
+    struct port_pointers pp = { .port = port };
     uint32_t state;
+    pa_card *card;
+
+    pa_assert(port);
+    pa_assert_se(card = port->card);
 
     switch (port->direction) {
         case PA_DIRECTION_OUTPUT:
-            PA_IDXSET_FOREACH(sink, card->sinks, state)
-                if (port == pa_hashmap_get(sink->ports, port->name))
+            PA_IDXSET_FOREACH(pp.sink, card->sinks, state)
+                if (port == pa_hashmap_get(pp.sink->ports, port->name))
                     break;
             break;
 
         case PA_DIRECTION_INPUT:
-            PA_IDXSET_FOREACH(source, card->sources, state)
-                if (port == pa_hashmap_get(source->ports, port->name))
+            PA_IDXSET_FOREACH(pp.source, card->sources, state)
+                if (port == pa_hashmap_get(pp.source->ports, port->name))
                     break;
             break;
     }
 
-    *si = sink;
-    *so = source;
-}
+    pp.is_possible_profile_active =
+        card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
+    pp.is_preferred_profile_active = pp.is_possible_profile_active && (!port->preferred_profile ||
+        pa_safe_streq(port->preferred_profile, profile_name_for_dir(card->active_profile, port->direction)));
+    pp.is_port_active = (pp.sink && pp.sink->active_port == port) || (pp.source && pp.source->active_port == port);
 
-static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
-    pa_card* card;
-    pa_sink *sink;
-    pa_source *source;
-    bool is_active_profile, is_active_port;
+    return pp;
+}
 
-    if (port->available == PA_AVAILABLE_UNKNOWN)
-        return PA_HOOK_OK;
+/* Switches to a port, switching profiles if necessary or preferred */
+static bool switch_to_port(pa_device_port *port) {
+    struct port_pointers pp = find_port_pointers(port);
 
-    card = port->card;
+    if (pp.is_port_active)
+        return true; /* Already selected */
 
-    if (!card) {
-        pa_log_warn("Port %s does not have a card", port->name);
-        return PA_HOOK_OK;
+    pa_log_debug("Trying to switch to port %s", port->name);
+    if (!pp.is_preferred_profile_active) {
+        if (try_to_switch_profile(port) < 0) {
+            if (pp.is_possible_profile_active)
+                return false;
+        }
+        else
+            /* Now that profile has changed, our sink and source pointers must be updated */
+            pp = find_port_pointers(port);
     }
 
-    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;
+    if (pp.source)
+        pa_source_set_port(pp.source, port->name, false);
+    if (pp.sink)
+        pa_sink_set_port(pp.sink, port->name, false);
+    return true;
+}
 
-    find_sink_and_source(card, port, &sink, &source);
+/* Switches away from a port, switching profiles if necessary or preferred */
+static bool switch_from_port(pa_device_port *port) {
+    struct port_pointers pp = find_port_pointers(port);
+    pa_device_port *p, *best_port = NULL;
+    void *state;
 
-    is_active_profile = card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name);
-    is_active_port = (sink && sink->active_port == port) || (source && source->active_port == port);
+    if (!pp.is_port_active)
+        return true; /* Already deselected */
 
-    if (port->available == PA_AVAILABLE_NO && !is_active_port)
-        return PA_HOOK_OK;
+    /* Try to find a good enough port to switch to */
+    PA_HASHMAP_FOREACH(p, port->card->ports, state)
+        if (p->direction == port->direction && p != port && p->available != PA_AVAILABLE_NO &&
+           (!best_port || best_port->priority < p->priority))
+           best_port = p;
 
-    if (port->available == PA_AVAILABLE_YES) {
-        if (is_active_port)
-            return PA_HOOK_OK;
+    pa_log_debug("Trying to switch away from port %s, found %s", port->name, best_port ? best_port->name : "no better option");
 
-        if (!is_active_profile) {
-            if (try_to_switch_profile(port) < 0)
-                return PA_HOOK_OK;
+    if (best_port)
+        return switch_to_port(best_port);
 
-            pa_assert(card->active_profile == pa_hashmap_get(port->profiles, card->active_profile->name));
+    return false;
+}
 
-            /* Now that profile has changed, our sink and source pointers must be updated */
-            find_sink_and_source(card, port, &sink, &source);
-        }
 
-        if (source)
-            pa_source_set_port(source, port->name, false);
-        if (sink)
-            pa_sink_set_port(sink, port->name, false);
-    }
-
-    if (port->available == PA_AVAILABLE_NO) {
-        if (sink) {
-            pa_device_port *p2 = pa_device_port_find_best(sink->ports);
+static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
+    pa_assert(port);
 
-            if (p2 && p2->available != PA_AVAILABLE_NO)
-                pa_sink_set_port(sink, p2->name, false);
-            else {
-                /* Maybe try to switch to another profile? */
-            }
-        }
+    if (!port->card) {
+        pa_log_warn("Port %s does not have a card", port->name);
+        return PA_HOOK_OK;
+    }
 
-        if (source) {
-            pa_device_port *p2 = pa_device_port_find_best(source->ports);
+    if (pa_idxset_size(port->card->sinks) == 0 && pa_idxset_size(port->card->sources) == 0)
+        /* This card is not initialized yet. We'll handle it in
+           sink_new / source_new callbacks later. */
+        return PA_HOOK_OK;
 
-            if (p2 && p2->available != PA_AVAILABLE_NO)
-                pa_source_set_port(source, p2->name, false);
-            else {
-                /* Maybe try to switch to another profile? */
-            }
-        }
+    switch (port->available) {
+    case PA_AVAILABLE_YES:
+        switch_to_port(port);
+        break;
+    case PA_AVAILABLE_NO:
+        switch_from_port(port);
+        break;
+    default:
+        break;
     }
 
     return PA_HOOK_OK;

commit 063a1d350fad1cb6fac28dbffe26a7e805626cb2
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Tue Nov 17 15:10:34 2015 +0100

    module-switch-on-port-available: Use input and output names
    
    In case input or output names are filled in, we can use this to
    get a better match in the profile_good_for_input/output functions
    instead of guessing based on number of sources and channels.
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index eb8f2d7..8de68a3 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -23,6 +23,7 @@
 #endif
 
 #include <pulsecore/core.h>
+#include <pulsecore/core-util.h>
 #include <pulsecore/device-port.h>
 #include <pulsecore/hashmap.h>
 
@@ -34,6 +35,9 @@ static bool profile_good_for_output(pa_card_profile *profile) {
 
     pa_assert(profile);
 
+    if (!pa_safe_streq(profile->card->active_profile->input_name, profile->input_name))
+        return false;
+
     if (profile->card->active_profile->n_sources != profile->n_sources)
         return false;
 
@@ -55,6 +59,9 @@ static bool profile_good_for_output(pa_card_profile *profile) {
 static bool profile_good_for_input(pa_card_profile *profile) {
     pa_assert(profile);
 
+    if (!pa_safe_streq(profile->card->active_profile->output_name, profile->output_name))
+        return false;
+
     if (profile->card->active_profile->n_sinks != profile->n_sinks)
         return false;
 

commit 9059fb3b4ed7ade607846f4846842c2b1ce699fa
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Tue Nov 17 15:10:33 2015 +0100

    card-restore: Save and restore "preferred profile" of port
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
index 3725d30..b30fa36 100644
--- a/src/modules/module-card-restore.c
+++ b/src/modules/module-card-restore.c
@@ -64,11 +64,12 @@ struct userdata {
     pa_database *database;
 };
 
-#define ENTRY_VERSION 2
+#define ENTRY_VERSION 3
 
 struct port_info {
     char *name;
     int64_t offset;
+    char *profile;
 };
 
 struct entry {
@@ -102,6 +103,7 @@ static void trigger_save(struct userdata *u) {
 static void port_info_free(struct port_info *p_info) {
     pa_assert(p_info);
 
+    pa_xfree(p_info->profile);
     pa_xfree(p_info->name);
     pa_xfree(p_info);
 }
@@ -117,9 +119,11 @@ static struct port_info *port_info_new(pa_device_port *port) {
     struct port_info *p_info;
 
     if (port) {
-        p_info = pa_xnew(struct port_info, 1);
+        p_info = pa_xnew0(struct port_info, 1);
         p_info->name = pa_xstrdup(port->name);
         p_info->offset = port->latency_offset;
+        if (port->preferred_profile)
+            p_info->profile = pa_xstrdup(port->preferred_profile);
     } else
         p_info = pa_xnew0(struct port_info, 1);
 
@@ -196,6 +200,8 @@ static bool entry_write(struct userdata *u, const char *name, const struct entry
     PA_HASHMAP_FOREACH(p_info, e->ports, state) {
         pa_tagstruct_puts(t, p_info->name);
         pa_tagstruct_puts64(t, p_info->offset);
+        if (e->version >= 3)
+            pa_tagstruct_puts(t, p_info->profile);
     }
 
     key.data = (char *) name;
@@ -283,7 +289,7 @@ static struct entry* entry_read(struct userdata *u, const char *name) {
 
     if (e->version >= 2) {
         uint32_t port_count = 0;
-        const char *port_name = NULL;
+        const char *port_name = NULL, *profile_name = NULL;
         int64_t port_offset = 0;
         struct port_info *p_info;
         unsigned i;
@@ -297,10 +303,14 @@ static struct entry* entry_read(struct userdata *u, const char *name) {
                 pa_hashmap_get(e->ports, port_name) ||
                 pa_tagstruct_gets64(t, &port_offset) < 0)
                 goto fail;
+            if (e->version >= 3 && pa_tagstruct_gets(t, &profile_name) < 0)
+                goto fail;
 
             p_info = port_info_new(NULL);
             p_info->name = pa_xstrdup(port_name);
             p_info->offset = port_offset;
+            if (profile_name)
+                p_info->profile = pa_xstrdup(profile_name);
 
             pa_assert_se(pa_hashmap_put(e->ports, p_info->name, p_info) >= 0);
         }
@@ -375,8 +385,30 @@ finish:
     return PA_HOOK_OK;
 }
 
+static void update_profile_for_port(struct entry *entry, pa_card *card, pa_device_port *p) {
+    struct port_info *p_info;
+
+    if (p == NULL)
+        return;
+
+    if (!(p_info = pa_hashmap_get(entry->ports, p->name))) {
+        p_info = port_info_new(p);
+        pa_assert_se(pa_hashmap_put(entry->ports, p_info->name, p_info) >= 0);
+    }
+
+    if (!pa_safe_streq(p_info->profile, p->preferred_profile)) {
+        pa_xfree(p_info->profile);
+        p_info->profile = pa_xstrdup(p->preferred_profile);
+        entry->version = ENTRY_VERSION;
+        pa_log_info("Storing profile %s for port %s on card %s.", p_info->profile, p->name, card->name);
+    }
+}
+
 static pa_hook_result_t card_profile_changed_callback(pa_core *c, pa_card *card, struct userdata *u) {
     struct entry *entry;
+    pa_sink *sink;
+    pa_source *source;
+    uint32_t state;
 
     pa_assert(card);
 
@@ -392,6 +424,11 @@ static pa_hook_result_t card_profile_changed_callback(pa_core *c, pa_card *card,
         show_full_info(card);
     }
 
+    PA_IDXSET_FOREACH(sink, card->sinks, state)
+        update_profile_for_port(entry, card, sink->active_port);
+    PA_IDXSET_FOREACH(source, card->sources, state)
+        update_profile_for_port(entry, card, source->active_port);
+
     if (entry_write(u, card->name, entry))
         trigger_save(u);
 
@@ -508,9 +545,11 @@ static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new
     pa_log_info("Restoring port latency offsets for card %s.", new_data->name);
 
     PA_HASHMAP_FOREACH(p_info, e->ports, state)
-        if ((p = pa_hashmap_get(new_data->ports, p_info->name)))
+        if ((p = pa_hashmap_get(new_data->ports, p_info->name))) {
             p->latency_offset = p_info->offset;
-
+            if (!p->preferred_profile && p_info->profile)
+                pa_device_port_set_preferred_profile(p, p_info->profile);
+        }
     entry_free(e);
 
     return PA_HOOK_OK;

commit 5c545ba38be33bfc5334a70edacba24f06271af5
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Tue Nov 17 15:10:32 2015 +0100

    card: Update preferred_profile for ports when profile changes
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index bb21d0f..0ca78bb 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -250,8 +250,19 @@ void pa_card_add_profile(pa_card *c, pa_card_profile *profile) {
     pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], profile);
 }
 
+static const char* profile_name_for_dir(pa_card_profile *cp, pa_direction_t dir) {
+    if (dir == PA_DIRECTION_OUTPUT && cp->output_name)
+        return cp->output_name;
+    if (dir == PA_DIRECTION_INPUT && cp->input_name)
+        return cp->input_name;
+    return cp->name;
+}
+
 int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save) {
     int r;
+    pa_sink *sink;
+    pa_source *source;
+    uint32_t state;
 
     pa_assert(c);
     pa_assert(profile);
@@ -277,6 +288,13 @@ int pa_card_set_profile(pa_card *c, pa_card_profile *profile, bool save) {
     c->active_profile = profile;
     c->save_profile = save;
 
+    PA_IDXSET_FOREACH(sink, c->sinks, state)
+        if (sink->active_port)
+            pa_device_port_set_preferred_profile(sink->active_port, profile_name_for_dir(profile, PA_DIRECTION_OUTPUT));
+    PA_IDXSET_FOREACH(source, c->sources, state)
+        if (source->active_port)
+            pa_device_port_set_preferred_profile(source->active_port, profile_name_for_dir(profile, PA_DIRECTION_INPUT));
+
     pa_hook_fire(&c->core->hooks[PA_CORE_HOOK_CARD_PROFILE_CHANGED], c);
 
     return 0;

commit b1d9b4f62c2f132292efaba862e8490114882ad2
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Tue Nov 17 15:10:31 2015 +0100

    device-port: Add preferred_profile field to pa_device_port
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index 906ab1f..5807d3e 100644
--- a/src/pulsecore/device-port.c
+++ b/src/pulsecore/device-port.c
@@ -21,6 +21,7 @@
 
 #include "device-port.h"
 #include <pulsecore/card.h>
+#include <pulsecore/core-util.h>
 
 PA_DEFINE_PUBLIC_CLASS(pa_device_port, pa_object);
 
@@ -65,6 +66,15 @@ void pa_device_port_new_data_done(pa_device_port_new_data *data) {
     pa_xfree(data->description);
 }
 
+void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp) {
+    pa_assert(p);
+
+    if (!pa_safe_streq(p->preferred_profile, new_pp)) {
+        pa_xfree(p->preferred_profile);
+        p->preferred_profile = pa_xstrdup(new_pp);
+    }
+}
+
 void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
     pa_assert(p);
 
@@ -100,6 +110,7 @@ static void device_port_free(pa_object *o) {
     if (p->profiles)
         pa_hashmap_free(p->profiles);
 
+    pa_xfree(p->preferred_profile);
     pa_xfree(p->name);
     pa_xfree(p->description);
     pa_xfree(p);
diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h
index f35d07c..e3224fd 100644
--- a/src/pulsecore/device-port.h
+++ b/src/pulsecore/device-port.h
@@ -43,6 +43,7 @@ struct pa_device_port {
 
     char *name;
     char *description;
+    char *preferred_profile;
 
     unsigned priority;
     pa_available_t available;         /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
@@ -80,6 +81,7 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si
 void pa_device_port_set_available(pa_device_port *p, pa_available_t available);
 
 void pa_device_port_set_latency_offset(pa_device_port *p, int64_t offset);
+void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp);
 
 pa_device_port *pa_device_port_find_best(pa_hashmap *ports);
 

commit 2a71fd7597dd76eb6abab867cd3762429792f680
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Tue Nov 17 15:10:30 2015 +0100

    alsa-mixer: Fill in input and output names
    
    Fill in input_name and output_name to make routing easier for
    routing modules.
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index af7adea..3f51717 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -3473,6 +3473,8 @@ static void profile_free(pa_alsa_profile *p) {
 
     pa_xfree(p->name);
     pa_xfree(p->description);
+    pa_xfree(p->input_name);
+    pa_xfree(p->output_name);
 
     pa_xstrfreev(p->input_mapping_names);
     pa_xstrfreev(p->output_mapping_names);
@@ -4123,6 +4125,7 @@ static void profile_set_add_auto_pair(
     p->name = name;
 
     if (m) {
+        p->output_name = pa_xstrdup(m->name);
         p->output_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
         pa_idxset_put(p->output_mappings, m, NULL);
         p->priority += m->priority * 100;
@@ -4130,6 +4133,7 @@ static void profile_set_add_auto_pair(
     }
 
     if (n) {
+        p->input_name = pa_xstrdup(n->name);
         p->input_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
         pa_idxset_put(p->input_mappings, n, NULL);
         p->priority += n->priority;
@@ -4292,9 +4296,11 @@ void pa_alsa_profile_dump(pa_alsa_profile *p) {
     pa_alsa_mapping *m;
     pa_assert(p);
 
-    pa_log_debug("Profile %s (%s), priority=%u, supported=%s n_input_mappings=%u, n_output_mappings=%u",
+    pa_log_debug("Profile %s (%s), input=%s, output=%s priority=%u, supported=%s n_input_mappings=%u, n_output_mappings=%u",
                  p->name,
                  pa_strnull(p->description),
+                 pa_strnull(p->input_name),
+                 pa_strnull(p->output_name),
                  p->priority,
                  pa_yes_no(p->supported),
                  p->input_mappings ? pa_idxset_size(p->input_mappings) : 0,
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 621a71b..4ebf192 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -293,6 +293,9 @@ struct pa_alsa_profile {
     char *description;
     unsigned priority;
 
+    char *input_name;
+    char *output_name;
+
     bool supported:1;
     bool fallback_input:1;
     bool fallback_output:1;
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index e173e51..286cfc9 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -143,6 +143,8 @@ static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) {
 
         cp = pa_card_profile_new(ap->name, ap->description, sizeof(struct profile_data));
         cp->priority = ap->priority;
+        cp->input_name = pa_xstrdup(ap->input_name);
+        cp->output_name = pa_xstrdup(ap->output_name);
 
         if (ap->output_mappings) {
             cp->n_sinks = pa_idxset_size(ap->output_mappings);

commit b9818b016f021a80ab8c4ca9f2360756eefe2a87
Author: David Henningsson <david.henningsson at canonical.com>
Date:   Tue Nov 17 15:10:29 2015 +0100

    card: Add variables for splitting up a profile
    
    It can be useful for routing modules to know a profile's input
    and output parts, in order to e g change output profile
    while keeping the input profile unchanged.
    
    For now filling in these fields is optional and a routing module
    must be able to handle NULL in these fields.
    
    Signed-off-by: David Henningsson <david.henningsson at canonical.com>

diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index c8b97b7..bb21d0f 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -52,6 +52,8 @@ pa_card_profile *pa_card_profile_new(const char *name, const char *description,
 void pa_card_profile_free(pa_card_profile *c) {
     pa_assert(c);
 
+    pa_xfree(c->input_name);
+    pa_xfree(c->output_name);
     pa_xfree(c->name);
     pa_xfree(c->description);
     pa_xfree(c);
diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
index 3e2c004..a72c8c2 100644
--- a/src/pulsecore/card.h
+++ b/src/pulsecore/card.h
@@ -40,6 +40,14 @@ typedef struct pa_card_profile {
     char *name;
     char *description;
 
+    /* Identifiers for the profile's input and output parts, i e, if two different profiles
+       have the same input_name string, they have the same source(s).
+       Same for output_name and sink(s).
+       Can be NULL (and in case of an input- or output- only profile, the other direction
+       will be NULL). */
+    char *input_name;
+    char *output_name;
+
     unsigned priority;
     pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
 



More information about the pulseaudio-commits mailing list