summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-01-20 03:25:29 +0100
committerLennart Poettering <lennart@poettering.net>2009-01-20 03:25:29 +0100
commita65c2c73369e6b2ce9350dfb542f5d529de38334 (patch)
tree60878e16a88f63b9acaf7827c77049484f396655
parent85bc5eb39aa19d0b6fab26d388415a3c066043f0 (diff)
add client API for querying card information
-rw-r--r--src/map-file5
-rw-r--r--src/pulse/introspect.c200
-rw-r--r--src/pulse/introspect.h48
-rw-r--r--src/pulsecore/native-common.h5
-rw-r--r--src/pulsecore/protocol-native.c43
-rw-r--r--src/utils/pactl.c48
6 files changed, 344 insertions, 5 deletions
diff --git a/src/map-file b/src/map-file
index 9c9e1c7c..042e2adb 100644
--- a/src/map-file
+++ b/src/map-file
@@ -30,6 +30,9 @@ pa_context_exit_daemon;
pa_context_get_autoload_info_by_index;
pa_context_get_autoload_info_by_name;
pa_context_get_autoload_info_list;
+pa_context_get_card_info_by_index;
+pa_context_get_card_info_by_name;
+pa_context_get_card_info_list;
pa_context_get_client_info;
pa_context_get_client_info_list;
pa_context_get_index;
@@ -73,6 +76,8 @@ pa_context_ref;
pa_context_remove_autoload_by_index;
pa_context_remove_autoload_by_name;
pa_context_remove_sample;
+pa_context_set_card_profile_by_index;
+pa_context_set_card_profile_by_name;
pa_context_set_default_sink;
pa_context_set_default_source;
pa_context_set_name;
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index a6a228ec..c5c96784 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -28,8 +28,10 @@
#include <pulse/context.h>
#include <pulse/gccmacro.h>
+#include <pulse/xmalloc.h>
#include <pulsecore/macro.h>
+#include <pulsecore/core-util.h>
#include <pulsecore/pstream-util.h>
#include "internal.h"
@@ -60,7 +62,8 @@ static void context_stat_callback(pa_pdispatch *pd, uint32_t command, uint32_t t
pa_tagstruct_getu32(t, &i.memblock_total_size) < 0 ||
pa_tagstruct_getu32(t, &i.memblock_allocated) < 0 ||
pa_tagstruct_getu32(t, &i.memblock_allocated_size) < 0 ||
- pa_tagstruct_getu32(t, &i.scache_size) < 0) {
+ pa_tagstruct_getu32(t, &i.scache_size) < 0 ||
+ !pa_tagstruct_eof(t)) {
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
}
@@ -467,6 +470,201 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t
return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, (pa_operation_cb_t) cb, userdata);
}
+/*** Card info ***/
+
+static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_operation *o = userdata;
+ int eol = 1;
+
+ pa_assert(pd);
+ pa_assert(o);
+ pa_assert(PA_REFCNT_VALUE(o) >= 1);
+
+ if (!o->context)
+ goto finish;
+
+ if (command != PA_COMMAND_REPLY) {
+ if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
+ goto finish;
+
+ eol = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ pa_card_info i;
+ uint32_t j;
+ const char*ap;
+
+ memset(&i, 0, sizeof(i));
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
+ pa_tagstruct_gets(t, &i.driver) < 0 ||
+ pa_tagstruct_getu32(t, &i.n_profiles) < 0) {
+
+ pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (i.n_profiles > 0) {
+ i.profiles = pa_xnew(pa_card_profile_info, i.n_profiles+1);
+
+ for (j = 0; j < i.n_profiles; j++) {
+
+ if (pa_tagstruct_gets(t, &i.profiles[j].name) < 0 ||
+ pa_tagstruct_gets(t, &i.profiles[j].description) < 0) {
+
+ pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ pa_xfree(i.profiles);
+ goto finish;
+ }
+ }
+
+ /* Terminate with an extra NULL entry, just to make sure */
+ i.profiles[j].name = NULL;
+ i.profiles[j].description = NULL;
+ }
+
+ i.proplist = pa_proplist_new();
+
+ if (pa_tagstruct_gets(t, &ap) < 0 ||
+ pa_tagstruct_get_proplist(t, i.proplist) < 0) {
+
+ pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ pa_xfree(i.profiles);
+ pa_proplist_free(i.proplist);
+ goto finish;
+ }
+
+ if (ap) {
+ for (j = 0; j < i.n_profiles; j++)
+ if (pa_streq(i.profiles[j].name, ap)) {
+ i.active_profile = &i.profiles[j];
+ break;
+ }
+ }
+
+ if (o->callback) {
+ pa_card_info_cb_t cb = (pa_card_info_cb_t) o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+
+ pa_proplist_free(i.proplist);
+ pa_xfree(i.profiles);
+ }
+ }
+
+ if (o->callback) {
+ pa_card_info_cb_t cb = (pa_card_info_cb_t) o->callback;
+ cb(o->context, NULL, eol, o->userdata);
+ }
+
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
+}
+
+pa_operation* pa_context_get_card_info_by_index(pa_context *c, uint32_t idx, pa_card_info_cb_t cb, void *userdata) {
+ pa_tagstruct *t;
+ pa_operation *o;
+ uint32_t tag;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ pa_assert(cb);
+
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_GET_CARD_INFO, &tag);
+ pa_tagstruct_putu32(t, idx);
+ pa_tagstruct_puts(t, NULL);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_card_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ return o;
+}
+
+pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char*name, pa_card_info_cb_t cb, void *userdata) {
+ pa_tagstruct *t;
+ pa_operation *o;
+ uint32_t tag;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+ pa_assert(cb);
+
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_GET_CARD_INFO, &tag);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, name);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_card_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ return o;
+}
+
+pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_CARD_INFO_LIST, context_get_card_info_callback, (pa_operation_cb_t) cb, userdata);
+}
+
+pa_operation* pa_context_set_card_profile_by_index(pa_context *c, uint32_t idx, const char*profile, pa_context_success_cb_t cb, void *userdata) {
+ pa_operation *o;
+ pa_tagstruct *t;
+ uint32_t tag;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_SET_CARD_PROFILE, &tag);
+ pa_tagstruct_putu32(t, idx);
+ pa_tagstruct_puts(t, NULL);
+ pa_tagstruct_puts(t, profile);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ return o;
+}
+
+pa_operation* pa_context_set_card_profile_by_name(pa_context *c, const char *name, const char*profile, pa_context_success_cb_t cb, void *userdata) {
+ pa_operation *o;
+ pa_tagstruct *t;
+ uint32_t tag;
+
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 15, PA_ERR_NOTSUPPORTED);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_SET_CARD_PROFILE, &tag);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, name);
+ pa_tagstruct_puts(t, profile);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ return o;
+}
+
/*** Module info ***/
static void context_get_module_info_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 07318c72..972b454c 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -222,7 +222,7 @@ typedef void (*pa_sink_info_cb_t)(pa_context *c, const pa_sink_info *i, int eol,
pa_operation* pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata);
/** Get information about a sink by its index */
-pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t id, pa_sink_info_cb_t cb, void *userdata);
+pa_operation* pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_sink_info_cb_t cb, void *userdata);
/** Get the complete sink list */
pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata);
@@ -279,7 +279,7 @@ typedef void (*pa_source_info_cb_t)(pa_context *c, const pa_source_info *i, int
pa_operation* pa_context_get_source_info_by_name(pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata);
/** Get information about a source by its index */
-pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t id, pa_source_info_cb_t cb, void *userdata);
+pa_operation* pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, pa_source_info_cb_t cb, void *userdata);
/** Get the complete source list */
pa_operation* pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata);
@@ -385,6 +385,50 @@ pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_suc
/** @} */
+/** @{ \name Cards */
+
+/** Stores information about a specific profile of a card. Please
+ * note that this structure can be extended as part of evolutionary
+ * API updates at any time in any new release. \since 0.9.15 */
+typedef struct pa_card_profile_info {
+ const char *name; /**< Name of this profile */
+ const char *description; /**< Description of this profile */
+} pa_card_profile_info;
+
+/** Stores information about cards. Please note that this structure
+ * can be extended as part of evolutionary API updates at any time in
+ * any new release. \since 0.9.15 */
+typedef struct pa_card_info {
+ uint32_t index; /**< Index of this card */
+ const char *name; /**< Name of this card */
+ uint32_t owner_module; /**< Index of the owning module, or PA_INVALID_INDEX */
+ const char *driver; /**< Driver name */
+ uint32_t n_profiles; /**< Number of entries in profile array */
+ pa_card_profile_info* profiles; /**< Array of available profile, or NULL. Array is terminated by an entry with name set to NULL. Number of entries is stored in n_profiles */
+ pa_card_profile_info* active_profile; /**< Pointer to active profile in the array, or NULL */
+ pa_proplist *proplist; /**< Property list */
+} pa_card_info;
+
+/** Callback prototype for pa_context_get_card_info() and firends \since 0.9.15 */
+typedef void (*pa_card_info_cb_t) (pa_context *c, const pa_card_info*i, int eol, void *userdata);
+
+/** Get information about a card by its index \since 0.9.15 */
+pa_operation* pa_context_get_card_info_by_index(pa_context *c, uint32_t idx, pa_card_info_cb_t cb, void *userdata);
+
+/** Get information about a card by its name \since 0.9.15 */
+pa_operation* pa_context_get_card_info_by_name(pa_context *c, const char *name, pa_card_info_cb_t cb, void *userdata);
+
+/** Get the complete card list \since 0.9.15 */
+pa_operation* pa_context_get_card_info_list(pa_context *c, pa_card_info_cb_t cb, void *userdata);
+
+/** Change the profile of a card. \since 0.9.15 */
+pa_operation* pa_context_set_card_profile_by_index(pa_context *c, uint32_t idx, const char*profile, pa_context_success_cb_t cb, void *userdata);
+
+/** Change the profile of a card. \since 0.9.15 */
+pa_operation* pa_context_set_card_profile_by_name(pa_context *c, const char*name, const char*profile, pa_context_success_cb_t cb, void *userdata);
+
+/** @} */
+
/** @{ \name Sink Inputs */
/** Stores information about sink inputs. Please note that this structure
diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h
index 11643a72..b31a5da1 100644
--- a/src/pulsecore/native-common.h
+++ b/src/pulsecore/native-common.h
@@ -152,6 +152,11 @@ enum {
/* Supported since protocol v14 (0.9.12) */
PA_COMMAND_EXTENSION,
+ /* Supported since protocol v15 (0.9.15*/
+ PA_COMMAND_GET_CARD_INFO,
+ PA_COMMAND_GET_CARD_INFO_LIST,
+ PA_COMMAND_SET_CARD_PROFILE,
+
PA_COMMAND_MAX
};
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index f1735a78..87cf5838 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -283,6 +283,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_GET_SINK_INFO] = command_get_info,
[PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
[PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
+ [PA_COMMAND_GET_CARD_INFO] = command_get_info,
[PA_COMMAND_GET_MODULE_INFO] = command_get_info,
[PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
[PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
@@ -291,6 +292,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
[PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
[PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
+ [PA_COMMAND_GET_CARD_INFO_LIST] = command_get_info_list,
[PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
[PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
[PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
@@ -2740,6 +2742,31 @@ static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_c
pa_tagstruct_put_proplist(t, client->proplist);
}
+static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
+ void *state = NULL;
+ pa_card_profile *p;
+
+ pa_assert(t);
+ pa_assert(card);
+
+ pa_tagstruct_putu32(t, card->index);
+ pa_tagstruct_puts(t, card->name);
+ pa_tagstruct_putu32(t, card->module ? card->module->index : PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, card->driver);
+
+ pa_tagstruct_putu32(t, card->profiles ? pa_hashmap_size(card->profiles) : 0);
+
+ if (card->profiles) {
+ while ((p = pa_hashmap_iterate(card->profiles, &state, NULL))) {
+ pa_tagstruct_puts(t, p->name);
+ pa_tagstruct_puts(t, p->description);
+ }
+ }
+
+ pa_tagstruct_puts(t, card->active_profile ? card->active_profile->name : NULL);
+ pa_tagstruct_put_proplist(t, card->proplist);
+}
+
static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module) {
pa_assert(t);
pa_assert(module);
@@ -2839,6 +2866,8 @@ static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
pa_sink *sink = NULL;
pa_source *source = NULL;
pa_client *client = NULL;
+ pa_card *card = NULL;
+ pa_core *core = NULL;
pa_module *module = NULL;
pa_sink_input *si = NULL;
pa_source_output *so = NULL;
@@ -2851,6 +2880,7 @@ static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
if (pa_tagstruct_getu32(t, &idx) < 0 ||
(command != PA_COMMAND_GET_CLIENT_INFO &&
+ command != PA_COMMAND_GET_CARD_INFO &&
command != PA_COMMAND_GET_MODULE_INFO &&
command != PA_COMMAND_GET_SINK_INPUT_INFO &&
command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
@@ -2876,6 +2906,11 @@ static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
else
source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
+ } else if (command == PA_COMMAND_GET_CARD_INFO) {
+ 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);
} else if (command == PA_COMMAND_GET_CLIENT_INFO)
client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
else if (command == PA_COMMAND_GET_MODULE_INFO)
@@ -2892,7 +2927,7 @@ static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
}
- if (!sink && !source && !client && !module && !si && !so && !sce) {
+ if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
return;
}
@@ -2904,6 +2939,8 @@ static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
source_fill_tagstruct(c, reply, source);
else if (client)
client_fill_tagstruct(c, reply, client);
+ else if (client)
+ card_fill_tagstruct(c, reply, card);
else if (module)
module_fill_tagstruct(c, reply, module);
else if (si)
@@ -2940,6 +2977,8 @@ static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t t
i = c->protocol->core->sources;
else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
i = c->protocol->core->clients;
+ else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
+ i = c->protocol->core->cards;
else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
i = c->protocol->core->modules;
else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
@@ -2959,6 +2998,8 @@ static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t t
source_fill_tagstruct(c, reply, p);
else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
client_fill_tagstruct(c, reply, p);
+ else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
+ card_fill_tagstruct(c, reply, p);
else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
module_fill_tagstruct(c, reply, p);
else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index dbc9ba71..75b46d2d 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -384,6 +384,51 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int
pa_xfree(pl);
}
+static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_last, void *userdata) {
+ char t[32];
+ char *pl;
+
+ if (is_last < 0) {
+ fprintf(stderr, _("Failed to get card information: %s\n"), pa_strerror(pa_context_errno(c)));
+ complete_action();
+ return;
+ }
+
+ if (is_last) {
+ complete_action();
+ return;
+ }
+
+ assert(i);
+
+ if (nl)
+ printf("\n");
+ nl = 1;
+
+ snprintf(t, sizeof(t), "%u", i->owner_module);
+
+ printf(_("Card #%u\n"
+ "\tName: %s\n"
+ "\tDriver: %s\n"
+ "\tOwner Module: %s\n"
+ "\tProperties:\n\t\t%s\n"),
+ i->index,
+ i->name,
+ pa_strnull(i->driver),
+ i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
+ pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
+
+ if (i->profiles) {
+ pa_card_profile_info *p;
+
+ printf(_("\tProfiles:\n"));
+ for (p = i->profiles; p->name; p++)
+ printf("\t\t%s: %s\n", p->name, p->description);
+ }
+
+ pa_xfree(pl);
+}
+
static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) {
char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
char *pl;
@@ -649,7 +694,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
break;
case LIST:
- actions = 7;
+ actions = 8;
pa_operation_unref(pa_context_get_module_info_list(c, get_module_info_callback, NULL));
pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL));
pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL));
@@ -657,6 +702,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL));
pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL));
pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL));
+ pa_operation_unref(pa_context_get_card_info_list(c, get_card_info_callback, NULL));
break;
case MOVE_SINK_INPUT: