[pulseaudio-discuss] [PATCH 1/3] protocol-native: add message sending capability
Georg Chini
georg at chini.tk
Fri Aug 4 20:30:00 UTC 2017
This patch adds the PA_COMMAND_SEND_OBJECT_MESSAGE command to protocol-native
so that clients can use the messaging feature introduced in patch "core: add
generic message interface".
Sending messages can in effect replace the extension system for modules. The
approach is more flexible than the extension interface because a generic string
format is used to exchange information. Furthermore the messaging system can be
used for any object, not only for modules, and is easier to implement than
extensions.
---
PROTOCOL | 7 +++++
configure.ac | 2 +-
src/map-file | 1 +
src/pulse/introspect.c | 59 +++++++++++++++++++++++++++++++++++++++++
src/pulse/introspect.h | 7 +++++
src/pulsecore/native-common.h | 2 ++
src/pulsecore/pdispatch.c | 2 ++
src/pulsecore/protocol-native.c | 44 ++++++++++++++++++++++++++++++
8 files changed, 123 insertions(+), 1 deletion(-)
diff --git a/PROTOCOL b/PROTOCOL
index e11aaa01..5cf95364 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -425,6 +425,13 @@ Check commit 451d1d676237c81 for further details.
Added signal subscription functions. Clients can now subscribe to signals
that PulseAudio sends.
+## v34, implemented by > 11.0
+
+Added new command for communication with objects.
+
+PA_COMMAND_SEND_OBJECT_MESSAGE:
+sends a message to an object that registered a named message handler
+
#### If you just changed the protocol, read this
## module-tunnel depends on the sink/source/sink-input/source-input protocol
## internals, so if you changed these, you might have broken module-tunnel.
diff --git a/configure.ac b/configure.ac
index e28755b0..011b45eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -40,7 +40,7 @@ AC_SUBST(PA_MINOR, pa_minor)
AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor)
AC_SUBST(PA_API_VERSION, 12)
-AC_SUBST(PA_PROTOCOL_VERSION, 33)
+AC_SUBST(PA_PROTOCOL_VERSION, 34)
# The stable ABI for client applications, for the version info x:y:z
# always will hold y=z
diff --git a/src/map-file b/src/map-file
index d6cc06c1..83301eba 100644
--- a/src/map-file
+++ b/src/map-file
@@ -120,6 +120,7 @@ pa_context_suspend_sink_by_name;
pa_context_suspend_source_by_index;
pa_context_suspend_source_by_name;
pa_context_unload_module;
+pa_context_send_message_to_object;
pa_context_unref;
pa_cvolume_avg;
pa_cvolume_avg_mask;
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 510d784a..f23ff932 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -2184,3 +2184,62 @@ pa_operation* pa_context_suspend_source_by_index(pa_context *c, uint32_t idx, in
return o;
}
+
+/** Object response string **/
+
+static void context_string_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_operation *o = userdata;
+ const char *response;
+
+ 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;
+
+ response = NULL;
+ } else if (pa_tagstruct_gets(t, &response) ||
+ !pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ pa_context_string_cb_t cb = (pa_context_string_cb_t) o->callback;
+ cb(o->context, response, o->userdata);
+ }
+
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
+}
+
+pa_operation* pa_context_send_message_to_object(pa_context *c, const char *recipient_name, const char *message, const char *message_parameters, pa_context_string_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, !pa_detect_fork(), PA_ERR_FORKED);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+
+ o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
+
+ t = pa_tagstruct_command(c, PA_COMMAND_SEND_OBJECT_MESSAGE, &tag);
+
+ pa_tagstruct_puts(t, recipient_name);
+ pa_tagstruct_puts(t, message);
+ pa_tagstruct_puts(t, message_parameters);
+
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_string_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
+
+ return o;
+}
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 43389b73..e78f6665 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -423,6 +423,9 @@ typedef struct pa_module_info {
/** Callback prototype for pa_context_get_module_info() and friends */
typedef void (*pa_module_info_cb_t) (pa_context *c, const pa_module_info*i, int eol, void *userdata);
+/** Callback prototype for pa_context_send_message_to_object() */
+typedef void (*pa_context_string_cb_t)(pa_context *c, const char *response, void *userdata);
+
/** Get some information about a module by its index */
pa_operation* pa_context_get_module_info(pa_context *c, uint32_t idx, pa_module_info_cb_t cb, void *userdata);
@@ -438,6 +441,10 @@ pa_operation* pa_context_load_module(pa_context *c, const char*name, const char
/** Unload a module. */
pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
+/** Send a message to an object. This does not only apply to modules but to any object
+ * that registered a message handler. */
+pa_operation* pa_context_send_message_to_object(pa_context *c, const char *recipient_name, const char *message, const char *message_parameters, pa_context_string_cb_t cb, void *userdata);
+
/** @} */
/** @{ \name Clients */
diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h
index 5b9d5f0c..06c7c576 100644
--- a/src/pulsecore/native-common.h
+++ b/src/pulsecore/native-common.h
@@ -188,6 +188,8 @@ enum {
* BOTH DIRECTIONS */
PA_COMMAND_REGISTER_MEMFD_SHMID,
+ PA_COMMAND_SEND_OBJECT_MESSAGE,
+
PA_COMMAND_MAX
};
diff --git a/src/pulsecore/pdispatch.c b/src/pulsecore/pdispatch.c
index f5aa5a24..22ea90c5 100644
--- a/src/pulsecore/pdispatch.c
+++ b/src/pulsecore/pdispatch.c
@@ -200,6 +200,8 @@ static const char *command_names[PA_COMMAND_MAX] = {
/* Supported since protocol v31 (9.0) */
/* BOTH DIRECTIONS */
[PA_COMMAND_REGISTER_MEMFD_SHMID] = "REGISTER_MEMFD_SHMID",
+
+ [PA_COMMAND_SEND_OBJECT_MESSAGE] = "SEND_OBJECT_MESSAGE",
};
#endif
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index e31562cf..6f6c50f7 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -4707,6 +4707,48 @@ static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag,
protocol_error(c);
}
+/* Send message to an object which registered a handler. Result must be returned as string. */
+static void command_send_object_message(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
+ const char *recipient_name = NULL;
+ const char *message = NULL;
+ const char *message_parameters = NULL;
+ char *response = NULL;
+ pa_tagstruct *reply;
+
+ pa_native_connection_assert_ref(c);
+ pa_assert(t);
+
+ if (pa_tagstruct_gets(t, &recipient_name) < 0 ||
+ pa_tagstruct_gets(t, &message) < 0 ||
+ pa_tagstruct_gets(t, &message_parameters) < 0 ||
+ !pa_tagstruct_eof(t)) {
+ protocol_error(c);
+ return;
+ }
+
+ CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
+ CHECK_VALIDITY(c->pstream, pa_utf8_valid(recipient_name), tag, PA_ERR_INVALID);
+ CHECK_VALIDITY(c->pstream, message != NULL, tag, PA_ERR_INVALID);
+
+ if (pa_core_message_handler_test(c->protocol->core, recipient_name) != PA_CORE_HANDLER_PUBLIC) {
+ pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
+ return;
+ }
+
+ if (pa_core_send_message(c->protocol->core, recipient_name, message, message_parameters, NULL, &response) != PA_CORE_SEND_OK) {
+ pa_pstream_send_error(c->pstream, tag, 1);
+ pa_xfree(response);
+ return;
+ }
+
+ reply = reply_new(tag);
+ pa_tagstruct_puts(reply, (const char *)response);
+ pa_xfree(response);
+
+ pa_pstream_send_tagstruct(c->pstream, reply);
+}
+
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;
@@ -4959,6 +5001,8 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_REGISTER_MEMFD_SHMID] = command_register_memfd_shmid,
+ [PA_COMMAND_SEND_OBJECT_MESSAGE] = command_send_object_message,
+
[PA_COMMAND_EXTENSION] = command_extension
};
--
2.11.0
More information about the pulseaudio-discuss
mailing list