summaryrefslogtreecommitdiff
path: root/src/pulse
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2012-02-23 07:17:06 +0100
committerArun Raghavan <arun.raghavan@collabora.co.uk>2012-03-11 12:23:46 +0530
commit793f46320e98aa10dca16bcc1b3a421a4f2b6b7e (patch)
treef6ec07a1375137a9f0d4aea5ada097f4263ba92d /src/pulse
parent752ae7285e0fafb5a9b7eba16f925f88980f8100 (diff)
introspect: Expose port info per card to clients
For volume control UIs to be able to show ports in inactive profiles, expose all ports together with the card info. This includes updating the protocol and the client API to show the connection between ports and for which profiles the ports are relevant. Update protocol to 26. Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Diffstat (limited to 'src/pulse')
-rw-r--r--src/pulse/def.h14
-rw-r--r--src/pulse/introspect.c110
-rw-r--r--src/pulse/introspect.h16
3 files changed, 134 insertions, 6 deletions
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 7ca0c4baf..b93931942 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -124,6 +124,20 @@ typedef enum pa_context_flags {
#define PA_CONTEXT_NOFAIL PA_CONTEXT_NOFAIL
/** \endcond */
+/** Direction bitfield - while we currently do not expose anything bidirectional,
+ one should test against the bit instead of the value (e g if (d & PA_DIRECTION_OUTPUT)),
+ because we might add bidirectional stuff in the future. \since 2.0
+*/
+typedef enum pa_direction {
+ PA_DIRECTION_OUTPUT = 0x0001U, /**< Output direction */
+ PA_DIRECTION_INPUT = 0x0002U /**< Input direction */
+} pa_direction_t;
+
+/** \cond fulldocs */
+#define PA_DIRECTION_OUTPUT PA_DIRECTION_OUTPUT
+#define PA_DIRECTION_INPUT PA_DIRECTION_INPUT
+/** \endcond */
+
/** The type of device we are dealing with */
typedef enum pa_device_type {
PA_DEVICE_TYPE_SINK, /**< Playback device */
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index c8bf7ca37..38a9d1c8d 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -763,9 +763,101 @@ pa_operation* pa_context_get_client_info_list(pa_context *c, pa_client_info_cb_t
/*** Card info ***/
+static void card_info_free(pa_card_info* i)
+{
+ if (i->proplist)
+ pa_proplist_free(i->proplist);
+
+ pa_xfree(i->profiles);
+
+ if (i->ports) {
+ uint32_t j;
+
+ for (j = 0; j < i->n_ports; j++) {
+ if (i->ports[j]) {
+ if (i->ports[j]->profiles)
+ pa_xfree(i->ports[j]->profiles);
+ if (i->ports[j]->proplist)
+ pa_proplist_free(i->ports[j]->proplist);
+ }
+ }
+
+ pa_xfree(i->ports[0]);
+ pa_xfree(i->ports);
+ }
+}
+
+static int fill_card_port_info(pa_tagstruct* t, pa_card_info* i)
+{
+ uint32_t j, k, l;
+
+ if (pa_tagstruct_getu32(t, &i->n_ports) < 0)
+ return -PA_ERR_PROTOCOL;
+
+ if (i->n_ports == 0) {
+ i->ports = NULL;
+ return 0;
+ }
+
+ i->ports = pa_xnew0(pa_card_port_info*, i->n_ports+1);
+ i->ports[0] = pa_xnew0(pa_card_port_info, i->n_ports);
+
+ for (j = 0; j < i->n_ports; j++) {
+ uint8_t direction;
+ uint32_t available;
+ pa_card_port_info* port = i->ports[j] = &i->ports[0][j];
+
+ port->proplist = pa_proplist_new();
+
+ if (pa_tagstruct_gets(t, &port->name) < 0 ||
+ pa_tagstruct_gets(t, &port->description) < 0 ||
+ pa_tagstruct_getu32(t, &port->priority) < 0 ||
+ pa_tagstruct_getu32(t, &available) < 0 ||
+ pa_tagstruct_getu8(t, &direction) < 0 ||
+ pa_tagstruct_get_proplist(t, port->proplist) < 0 ||
+ pa_tagstruct_getu32(t, &port->n_profiles) < 0) {
+
+ return -PA_ERR_PROTOCOL;
+ }
+
+ if (available > PA_PORT_AVAILABLE_YES ||
+ direction > PA_DIRECTION_OUTPUT + PA_DIRECTION_INPUT) {
+
+ return -PA_ERR_PROTOCOL;
+ }
+
+ port->direction = direction;
+ port->available = available;
+
+ if (port->n_profiles > 0) {
+ port->profiles = pa_xnew0(pa_card_profile_info*, i->n_profiles+1);
+
+ for (k = 0; k < port->n_profiles; k++) {
+ const char* profilename;
+
+ if (pa_tagstruct_gets(t, &profilename) < 0)
+ return -PA_ERR_PROTOCOL;
+
+ for (l = 0; l < i->n_profiles; l++) {
+ if (pa_streq(i->profiles[l].name, profilename)) {
+ port->profiles[k] = &i->profiles[l];
+ break;
+ }
+ }
+
+ if (l >= i->n_profiles)
+ return -PA_ERR_PROTOCOL;
+ }
+ }
+ }
+
+ return 0;
+}
+
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_card_info i;
pa_assert(pd);
pa_assert(o);
@@ -782,7 +874,6 @@ static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, u
} else {
while (!pa_tagstruct_eof(t)) {
- pa_card_info i;
uint32_t j;
const char*ap;
@@ -795,6 +886,7 @@ static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, u
pa_tagstruct_getu32(t, &i.n_profiles) < 0) {
pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ card_info_free(&i);
goto finish;
}
@@ -810,7 +902,7 @@ static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, u
pa_tagstruct_getu32(t, &i.profiles[j].priority) < 0) {
pa_context_fail(o->context, PA_ERR_PROTOCOL);
- pa_xfree(i.profiles);
+ card_info_free(&i);
goto finish;
}
}
@@ -826,8 +918,7 @@ static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, u
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);
+ card_info_free(&i);
goto finish;
}
@@ -839,13 +930,20 @@ static void context_get_card_info_callback(pa_pdispatch *pd, uint32_t command, u
}
}
+ if (o->context->version >= 26) {
+ if (fill_card_port_info(t, &i) < 0) {
+ pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ card_info_free(&i);
+ goto finish;
+ }
+ }
+
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);
+ card_info_free(&i);
}
}
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index b1fd6d47a..224432ca3 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -454,6 +454,20 @@ typedef struct pa_card_profile_info {
uint32_t priority; /**< The higher this value is the more useful this profile is as a default */
} pa_card_profile_info;
+/** Stores information about a specific port 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 2.0 */
+typedef struct pa_card_port_info {
+ const char *name; /**< Name of this port */
+ const char *description; /**< Description of this port */
+ uint32_t priority; /**< The higher this value is the more useful this port is as a default */
+ int available; /**< A \link pa_port_available_t, indicating availability status of this port. */
+ int direction; /**< This is a \link pa_direction_t enum, indicating the direction of this port. */
+ uint32_t n_profiles; /**< Number of entries in profile array */
+ pa_card_profile_info** profiles; /**< Array of pointers available profile, or NULL. Array is terminated by an entry set to NULL. */
+ pa_proplist *proplist; /**< Property list */
+} pa_card_port_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 */
@@ -466,6 +480,8 @@ typedef struct pa_card_info {
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 */
+ uint32_t n_ports; /**< Number of entries in port array */
+ pa_card_port_info **ports; /**< Array of pointers to ports, or NULL. Array is terminated by an entry set to NULL. */
} pa_card_info;
/** Callback prototype for pa_context_get_card_info_...() \since 0.9.15 */