[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.13-336-g601293d

Lennart Poettering gitmailer-noreply at 0pointer.de
Tue Jan 20 18:04:29 PST 2009


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  e8f93b125e0e0776024ae78a2bdd33daf4442326 (commit)

- Log -----------------------------------------------------------------
601293d... implement pactl set-card-profile
996bba7... implement PA_COMMAND_SET_CARD_PROFILE
1375a9a... enable module-card-restore by default
13315a7... add a card profile restore module
c512ebf... minor cleanups
10e5c70... don't restore mute/volume when already set
9661cd0... make pa_card_new_data::active_profile a string
-----------------------------------------------------------------------

Summary of changes:
 src/Makefile.am                     |    8 +
 src/daemon/default.pa.in            |    1 +
 src/modules/module-card-restore.c   |  284 +++++++++++++++++++++++++++++++++++
 src/modules/module-device-restore.c |   37 ++++--
 src/modules/module-stream-restore.c |    6 +-
 src/pulsecore/card.c                |   34 +++--
 src/pulsecore/card.h                |    3 +-
 src/pulsecore/protocol-native.c     |   40 +++++
 src/utils/pactl.c                   |   57 +++++---
 9 files changed, 427 insertions(+), 43 deletions(-)
 create mode 100644 src/modules/module-card-restore.c

-----------------------------------------------------------------------

commit 9661cd04442e88fa500654a4b7ccea68ede2e123
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 21 02:46:36 2009 +0100

    make pa_card_new_data::active_profile a string

diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index af2a178..397c6d7 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -76,6 +76,13 @@ void pa_card_new_data_set_name(pa_card_new_data *data, const char *name) {
     data->name = pa_xstrdup(name);
 }
 
+void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile) {
+    pa_assert(data);
+
+    pa_xfree(data->active_profile);
+    data->active_profile = pa_xstrdup(profile);
+}
+
 void pa_card_new_data_done(pa_card_new_data *data) {
 
     pa_assert(data);
@@ -92,6 +99,7 @@ void pa_card_new_data_done(pa_card_new_data *data) {
     }
 
     pa_xfree(data->name);
+    pa_xfree(data->active_profile);
 }
 
 pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
@@ -126,21 +134,27 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
     c->sinks = pa_idxset_new(NULL, NULL);
     c->sources = pa_idxset_new(NULL, NULL);
 
+    /* As a minor optimization we just steal the list instead of
+     * copying it here */
     c->profiles = data->profiles;
     data->profiles = NULL;
-    if (!(c->active_profile = data->active_profile))
-        if (c->profiles) {
-            void *state = NULL;
-            pa_card_profile *p;
 
-            while ((p = pa_hashmap_iterate(c->profiles, &state, NULL))) {
-                if (!c->active_profile ||
-                    p->priority > c->active_profile->priority)
+    c->active_profile = NULL;
 
-                    c->active_profile = p;
-            }
+    if (data->active_profile && c->profiles)
+        c->active_profile = pa_hashmap_get(c->profiles, data->active_profile);
+
+    if (!c->active_profile && c->profiles) {
+        void *state = NULL;
+        pa_card_profile *p;
+
+        while ((p = pa_hashmap_iterate(c->profiles, &state, NULL))) {
+            if (!c->active_profile ||
+                p->priority > c->active_profile->priority)
+
+                c->active_profile = p;
         }
-    data->active_profile = NULL;
+    }
 
     c->userdata = NULL;
     c->set_profile = NULL;
diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
index 17733c5..9aa8f37 100644
--- a/src/pulsecore/card.h
+++ b/src/pulsecore/card.h
@@ -77,7 +77,7 @@ typedef struct pa_card_new_data {
     pa_module *module;
 
     pa_hashmap *profiles;
-    pa_card_profile *active_profile;
+    char *active_profile;
 
     pa_bool_t namereg_fail:1;
 } pa_card_new_data;
@@ -87,6 +87,7 @@ void pa_card_profile_free(pa_card_profile *c);
 
 pa_card_new_data *pa_card_new_data_init(pa_card_new_data *data);
 void pa_card_new_data_set_name(pa_card_new_data *data, const char *name);
+void pa_card_new_data_set_profile(pa_card_new_data *data, const char *profile);
 void pa_card_new_data_done(pa_card_new_data *data);
 
 pa_card *pa_card_new(pa_core *c, pa_card_new_data *data);

commit 10e5c70286c05afc1a80209a81acad83c59a8961
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 21 02:47:26 2009 +0100

    don't restore mute/volume when already set

diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index c0cb0dc..a24c0b3 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -98,14 +98,14 @@ static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct
     pa_log_info("Synced.");
 }
 
-static struct entry* read_entry(struct userdata *u, char *name) {
+static struct entry* read_entry(struct userdata *u, const char *name) {
     datum key, data;
     struct entry *e;
 
     pa_assert(u);
     pa_assert(name);
 
-    key.dptr = name;
+    key.dptr = (char*) name;
     key.dsize = (int) strlen(name);
 
     data = gdbm_fetch(u->gdbm_file, key);
@@ -235,13 +235,22 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *
     if ((e = read_entry(u, name))) {
 
         if (u->restore_volume) {
-            pa_log_info("Restoring volume for sink %s.", new_data->name);
-            pa_sink_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
+
+            if (!new_data->volume_is_set) {
+                pa_log_info("Restoring volume for sink %s.", new_data->name);
+                pa_sink_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
+            } else
+                pa_log_debug("Not restoring volume for sink %s, because already set.", new_data->name);
+
         }
 
         if (u->restore_muted) {
-            pa_log_info("Restoring mute state for sink %s.", new_data->name);
-            pa_sink_new_data_set_muted(new_data, e->muted);
+
+            if (!new_data->muted_is_set) {
+                pa_log_info("Restoring mute state for sink %s.", new_data->name);
+                pa_sink_new_data_set_muted(new_data, e->muted);
+            } else
+                pa_log_debug("Not restoring mute state for sink %s, because already set.", new_data->name);
         }
 
         pa_xfree(e);
@@ -263,13 +272,21 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da
     if ((e = read_entry(u, name))) {
 
         if (u->restore_volume) {
-            pa_log_info("Restoring volume for source %s.", new_data->name);
-            pa_source_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
+
+            if (!new_data->volume_is_set) {
+                pa_log_info("Restoring volume for source %s.", new_data->name);
+                pa_source_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map));
+            } else
+                pa_log_debug("Not restoring volume for source %s, because already set.", new_data->name);
         }
 
         if (u->restore_muted) {
-            pa_log_info("Restoring mute state for source %s.", new_data->name);
-            pa_source_new_data_set_muted(new_data, e->muted);
+
+            if (!new_data->muted_is_set) {
+                pa_log_info("Restoring mute state for source %s.", new_data->name);
+                pa_source_new_data_set_muted(new_data, e->muted);
+            } else
+                pa_log_debug("Not restoring mute state for source %s, because already set.", new_data->name);
         }
 
         pa_xfree(e);

commit c512ebf4ab2b6363b810eb592dec7386ed144c4b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 21 02:47:49 2009 +0100

    minor cleanups

diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index dd54a79..734b2c5 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -137,14 +137,14 @@ static char *get_name(pa_proplist *p, const char *prefix) {
     return pa_sprintf_malloc("%s-fallback:%s", prefix, r);
 }
 
-static struct entry* read_entry(struct userdata *u, char *name) {
+static struct entry* read_entry(struct userdata *u, const char *name) {
     datum key, data;
     struct entry *e;
 
     pa_assert(u);
     pa_assert(name);
 
-    key.dptr = name;
+    key.dptr = (char*) name;
     key.dsize = (int) strlen(name);
 
     data = gdbm_fetch(u->gdbm_file, key);
@@ -266,7 +266,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
 
         if (pa_cvolume_equal(pa_cvolume_remap(&old->volume, &old->channel_map, &entry.channel_map), &entry.volume) &&
             !old->muted == !entry.muted &&
-            strcmp(old->device, entry.device) == 0) {
+            strncmp(old->device, entry.device, sizeof(entry.device)) == 0) {
 
             pa_xfree(old);
             pa_xfree(name);

commit 13315a7e4c58f63e5f03b1aec13d0e79a8ee86af
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 21 02:49:42 2009 +0100

    add a card profile restore module

diff --git a/src/Makefile.am b/src/Makefile.am
index 3151b49..8d1271c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -865,6 +865,7 @@ modlibexec_LTLIBRARIES += \
 		module-volume-restore.la \
 		module-device-restore.la \
 		module-stream-restore.la \
+		module-card-restore.la \
 		module-default-device-restore.la \
 		module-always-sink.la \
 		module-rescue-streams.la \
@@ -1064,6 +1065,7 @@ SYMDEF_FILES = \
 		modules/module-volume-restore-symdef.h \
 		modules/module-device-restore-symdef.h \
 		modules/module-stream-restore-symdef.h \
+		modules/module-card-restore-symdef.h \
 		modules/module-default-device-restore-symdef.h \
 		modules/module-always-sink-symdef.h \
 		modules/module-rescue-streams-symdef.h \
@@ -1343,6 +1345,12 @@ module_stream_restore_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_stream_restore_la_LIBADD = $(AM_LIBADD) libprotocol-native.la libpulsecore- at PA_MAJORMINORMICRO@.la -lgdbm libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
 module_stream_restore_la_CFLAGS = $(AM_CFLAGS)
 
+# Card profile restore module
+module_card_restore_la_SOURCES = modules/module-card-restore.c
+module_card_restore_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_card_restore_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la -lgdbm libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
+module_card_restore_la_CFLAGS = $(AM_CFLAGS)
+
 # Default sink/source restore module
 module_default_device_restore_la_SOURCES = modules/module-default-device-restore.c
 module_default_device_restore_la_LDFLAGS = $(MODULE_LDFLAGS)
diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
new file mode 100644
index 0000000..02e973c
--- /dev/null
+++ b/src/modules/module-card-restore.c
@@ -0,0 +1,284 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2006-2008 Lennart Poettering
+
+  PulseAudio is free software; you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published
+  by the Free Software Foundation; either version 2 of the License,
+  or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <gdbm.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/volume.h>
+#include <pulse/timeval.h>
+#include <pulse/util.h>
+
+#include <pulsecore/core-error.h>
+#include <pulsecore/module.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/modargs.h>
+#include <pulsecore/log.h>
+#include <pulsecore/core-subscribe.h>
+#include <pulsecore/card.h>
+#include <pulsecore/namereg.h>
+
+#include "module-card-restore-symdef.h"
+
+PA_MODULE_AUTHOR("Lennart Poettering");
+PA_MODULE_DESCRIPTION("Automatically restore profile of cards");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(TRUE);
+
+#define SAVE_INTERVAL 10
+
+static const char* const valid_modargs[] = {
+    NULL
+};
+
+struct userdata {
+    pa_core *core;
+    pa_module *module;
+    pa_subscription *subscription;
+    pa_hook_slot *card_new_hook_slot;
+    pa_time_event *save_time_event;
+    GDBM_FILE gdbm_file;
+};
+
+struct entry {
+    char profile[PA_NAME_MAX];
+};
+
+static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
+    struct userdata *u = userdata;
+
+    pa_assert(a);
+    pa_assert(e);
+    pa_assert(tv);
+    pa_assert(u);
+
+    pa_assert(e == u->save_time_event);
+    u->core->mainloop->time_free(u->save_time_event);
+    u->save_time_event = NULL;
+
+    gdbm_sync(u->gdbm_file);
+    pa_log_info("Synced.");
+}
+
+static struct entry* read_entry(struct userdata *u, const char *name) {
+    datum key, data;
+    struct entry *e;
+
+    pa_assert(u);
+    pa_assert(name);
+
+    key.dptr = (char*) name;
+    key.dsize = (int) strlen(name);
+
+    data = gdbm_fetch(u->gdbm_file, key);
+
+    if (!data.dptr)
+        goto fail;
+
+    if (data.dsize != sizeof(struct entry)) {
+        pa_log_warn("Database contains entry for card %s of wrong size %lu != %lu", name, (unsigned long) data.dsize, (unsigned long) sizeof(struct entry));
+        goto fail;
+    }
+
+    e = (struct entry*) data.dptr;
+
+    if (!memchr(e->profile, 0, sizeof(e->profile))) {
+        pa_log_warn("Database contains entry for card %s with missing NUL byte in profile name", name);
+        goto fail;
+    }
+
+    return e;
+
+fail:
+
+    pa_xfree(data.dptr);
+    return NULL;
+}
+
+static void trigger_save(struct userdata *u) {
+    struct timeval tv;
+
+    if (u->save_time_event)
+        return;
+
+    pa_gettimeofday(&tv);
+    tv.tv_sec += SAVE_INTERVAL;
+    u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u);
+}
+
+static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
+    struct userdata *u = userdata;
+    struct entry entry, *old;
+    datum key, data;
+    pa_card *card;
+
+    pa_assert(c);
+    pa_assert(u);
+
+    if (t != (PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_NEW) &&
+        t != (PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE))
+        return;
+
+    memset(&entry, 0, sizeof(entry));
+
+    if (!(card = pa_idxset_get_by_index(c->cards, idx)))
+        return;
+
+    pa_strlcpy(entry.profile, card->active_profile ? card->active_profile->name : "", sizeof(entry.profile));
+
+    if ((old = read_entry(u, card->name))) {
+
+        if (strncmp(old->profile, entry.profile, sizeof(entry.profile)) == 0) {
+            pa_xfree(old);
+            return;
+        }
+
+        pa_xfree(old);
+    }
+
+    key.dptr = card->name;
+    key.dsize = (int) strlen(card->name);
+
+    data.dptr = (void*) &entry;
+    data.dsize = sizeof(entry);
+
+    pa_log_info("Storing profile for card %s.", card->name);
+
+    gdbm_store(u->gdbm_file, key, data, GDBM_REPLACE);
+
+    trigger_save(u);
+}
+
+static pa_hook_result_t card_new_hook_callback(pa_core *c, pa_card_new_data *new_data, struct userdata *u) {
+    struct entry *e;
+
+    pa_assert(new_data);
+
+    if ((e = read_entry(u, new_data->name)) && e->profile) {
+
+        if (!new_data->active_profile) {
+            pa_card_new_data_set_profile(new_data, e->profile);
+            pa_log_info("Restoring profile for card %s.", new_data->name);
+        } else
+            pa_log_debug("Not restoring profile for card %s, because already set.", new_data->name);
+
+        pa_xfree(e);
+    }
+
+    return PA_HOOK_OK;
+}
+
+int pa__init(pa_module*m) {
+    pa_modargs *ma = NULL;
+    struct userdata *u;
+    char *fname, *fn;
+    pa_card *card;
+    uint32_t idx;
+    int gdbm_cache_size;
+
+    pa_assert(m);
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("Failed to parse module arguments");
+        goto fail;
+    }
+
+    m->userdata = u = pa_xnew(struct userdata, 1);
+    u->core = m->core;
+    u->module = m;
+    u->save_time_event = NULL;
+    u->gdbm_file = NULL;
+
+    u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_CARD, subscribe_callback, u);
+
+    u->card_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_CARD_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) card_new_hook_callback, u);
+
+    /* We include the host identifier in the file name because gdbm
+     * files are CPU dependant, and we don't want things to go wrong
+     * if we are on a multiarch system. */
+
+    fn = pa_sprintf_malloc("card-database."CANONICAL_HOST".gdbm");
+    fname = pa_state_path(fn, TRUE);
+    pa_xfree(fn);
+
+    if (!fname)
+        goto fail;
+
+    if (!(u->gdbm_file = gdbm_open(fname, 0, GDBM_WRCREAT|GDBM_NOLOCK, 0600, NULL))) {
+        pa_log("Failed to open volume database '%s': %s", fname, gdbm_strerror(gdbm_errno));
+        pa_xfree(fname);
+        goto fail;
+    }
+
+    /* By default the cache of gdbm is rather large, let's reduce it a bit to save memory */
+    gdbm_cache_size = 10;
+    gdbm_setopt(u->gdbm_file, GDBM_CACHESIZE, &gdbm_cache_size, sizeof(gdbm_cache_size));
+
+    pa_log_info("Sucessfully opened database file '%s'.", fname);
+    pa_xfree(fname);
+
+    for (card = pa_idxset_first(m->core->cards, &idx); card; card = pa_idxset_next(m->core->cards, &idx))
+        subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_NEW, card->index, u);
+
+    pa_modargs_free(ma);
+    return 0;
+
+fail:
+    pa__done(m);
+
+    if (ma)
+        pa_modargs_free(ma);
+
+    return  -1;
+}
+
+void pa__done(pa_module*m) {
+    struct userdata* u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->subscription)
+        pa_subscription_free(u->subscription);
+
+    if (u->card_new_hook_slot)
+        pa_hook_slot_free(u->card_new_hook_slot);
+
+    if (u->save_time_event)
+        u->core->mainloop->time_free(u->save_time_event);
+
+    if (u->gdbm_file)
+        gdbm_close(u->gdbm_file);
+
+    pa_xfree(u);
+}

commit 1375a9a0c2c7141d7ce9a404fa323dc5c3620a16
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 21 02:50:29 2009 +0100

    enable module-card-restore by default

diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 7de4c07..d761f5f 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -32,6 +32,7 @@
 ### Automatically restore the volume of streams and devices
 load-module module-device-restore
 load-module module-stream-restore
+load-module module-card-restore
 
 ### Load audio drivers statically (it's probably better to not load
 ### these drivers manually, but instead use module-hal-detect --

commit 996bba7522aa0fa4192103ae53ca1980a6a59a52
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 21 03:04:04 2009 +0100

    implement PA_COMMAND_SET_CARD_PROFILE

diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index aa541a8..af9c05b 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -256,6 +256,7 @@ static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command
 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
 
 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_ERROR] = NULL,
@@ -350,6 +351,8 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
     [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
     [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
 
+    [PA_COMMAND_SET_CARD_PROFILE] = command_set_card_profile,
+
     [PA_COMMAND_EXTENSION] = command_extension
 };
 
@@ -3989,6 +3992,43 @@ static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag,
         protocol_error(c);
 }
 
+static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+    pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
+    uint32_t idx = PA_INVALID_INDEX;
+    const char *name = NULL, *profile = NULL;
+    pa_card *card = NULL;
+
+    pa_native_connection_assert_ref(c);
+    pa_assert(t);
+
+    if (pa_tagstruct_getu32(t, &idx) < 0 ||
+        pa_tagstruct_gets(t, &name) < 0 ||
+        pa_tagstruct_gets(t, &profile) < 0 ||
+        !pa_tagstruct_eof(t)) {
+        protocol_error(c);
+        return;
+    }
+
+    CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+    CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
+    CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
+
+    if (idx != PA_INVALID_INDEX)
+        card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
+    else
+        card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
+
+    CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
+
+    if (pa_card_set_profile(card, profile) < 0) {
+        pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
+        return;
+    }
+
+    pa_pstream_send_simple_ack(c->pstream, tag);
+}
 
 /*** pstream callbacks ***/
 

commit 601293d346ef4bfc8f2ff80d6c13a0d66d9bdd57
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 21 03:04:19 2009 +0100

    implement pactl set-card-profile

diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index ba91f50..0820641 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -45,7 +45,7 @@
 static pa_context *context = NULL;
 static pa_mainloop_api *mainloop_api = NULL;
 
-static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL;
+static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL, *card_name = NULL, *profile_name = NULL;
 static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX;
 static uint32_t module_index;
 static int suspend;
@@ -73,6 +73,7 @@ static enum {
     UNLOAD_MODULE,
     SUSPEND_SINK,
     SUSPEND_SOURCE,
+    SET_CARD_PROFILE
 } action = NONE;
 
 static void quit(int ret) {
@@ -739,6 +740,10 @@ static void context_state_callback(pa_context *c, void *userdata) {
                         pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
                     break;
 
+                case SET_CARD_PROFILE:
+                    pa_operation_unref(pa_context_set_card_profile_by_name(c, card_name, profile_name, simple_callback, NULL));
+                    break;
+
                 default:
                     assert(0);
             }
@@ -763,22 +768,23 @@ static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig
 static void help(const char *argv0) {
 
     printf(_("%s [options] stat\n"
-           "%s [options] list\n"
-           "%s [options] exit\n"
-           "%s [options] upload-sample FILENAME [NAME]\n"
-           "%s [options] play-sample NAME [SINK]\n"
-           "%s [options] remove-sample NAME\n"
-           "%s [options] move-sink-input ID SINK\n"
-           "%s [options] move-source-output ID SOURCE\n"
-           "%s [options] load-module NAME [ARGS ...]\n"
-           "%s [options] unload-module ID\n"
-           "%s [options] suspend-sink [SINK] 1|0\n"
-           "%s [options] suspend-source [SOURCE] 1|0\n\n"
-           "  -h, --help                            Show this help\n"
-           "      --version                         Show version\n\n"
-           "  -s, --server=SERVER                   The name of the server to connect to\n"
-           "  -n, --client-name=NAME                How to call this client on the server\n"),
-           argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
+             "%s [options] list\n"
+             "%s [options] exit\n"
+             "%s [options] upload-sample FILENAME [NAME]\n"
+             "%s [options] play-sample NAME [SINK]\n"
+             "%s [options] remove-sample NAME\n"
+             "%s [options] move-sink-input ID SINK\n"
+             "%s [options] move-source-output ID SOURCE\n"
+             "%s [options] load-module NAME [ARGS ...]\n"
+             "%s [options] unload-module ID\n"
+             "%s [options] suspend-sink [SINK] 1|0\n"
+             "%s [options] suspend-source [SOURCE] 1|0\n"
+             "%s [options] set-card-profile [CARD] [PROFILE] \n\n"
+             "  -h, --help                            Show this help\n"
+             "      --version                         Show version\n\n"
+             "  -s, --server=SERVER                   The name of the server to connect to\n"
+             "  -n, --client-name=NAME                How to call this client on the server\n"),
+           argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
 }
 
 enum { ARG_VERSION = 256 };
@@ -959,7 +965,7 @@ int main(int argc, char *argv[]) {
             action = SUSPEND_SINK;
 
             if (argc > optind+3 || optind+1 >= argc) {
-                fprintf(stderr, _("You may not specify more than one sink. You have to specify at least one boolean value.\n"));
+                fprintf(stderr, _("You may not specify more than one sink. You have to specify a boolean value.\n"));
                 goto quit;
             }
 
@@ -972,7 +978,7 @@ int main(int argc, char *argv[]) {
             action = SUSPEND_SOURCE;
 
             if (argc > optind+3 || optind+1 >= argc) {
-                fprintf(stderr, _("You may not specify more than one source. You have to specify at least one boolean value.\n"));
+                fprintf(stderr, _("You may not specify more than one source. You have to specify a boolean value.\n"));
                 goto quit;
             }
 
@@ -980,6 +986,17 @@ int main(int argc, char *argv[]) {
 
             if (argc > optind+2)
                 source_name = pa_xstrdup(argv[optind+1]);
+        } else if (!strcmp(argv[optind], "set-card-profile")) {
+            action = SET_CARD_PROFILE;
+
+            if (argc != optind+3) {
+                fprintf(stderr, _("You have to specify a card name/index and a profile name\n"));
+                goto quit;
+            }
+
+            card_name = pa_xstrdup(argv[optind+1]);
+            profile_name = pa_xstrdup(argv[optind+2]);
+
         } else if (!strcmp(argv[optind], "help")) {
             help(bn);
             ret = 0;
@@ -1041,6 +1058,8 @@ quit:
     pa_xfree(source_name);
     pa_xfree(module_args);
     pa_xfree(client_name);
+    pa_xfree(card_name);
+    pa_xfree(profile_name);
 
     return ret;
 }

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list