summaryrefslogtreecommitdiffstats
path: root/src/pulsecore/dbus-objs
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore/dbus-objs')
-rw-r--r--src/pulsecore/dbus-objs/core.c414
1 files changed, 388 insertions, 26 deletions
diff --git a/src/pulsecore/dbus-objs/core.c b/src/pulsecore/dbus-objs/core.c
index f59c478a..18bbf789 100644
--- a/src/pulsecore/dbus-objs/core.c
+++ b/src/pulsecore/dbus-objs/core.c
@@ -27,62 +27,414 @@
#include <pulse/xmalloc.h>
+#include <pulsecore/core-util.h>
#include <pulsecore/dbus-common.h>
#include <pulsecore/macro.h>
#include "core.h"
-#define OBJECT_NAME "/org/pulseaudio/core"
-#define INTERFACE_NAME "org.pulseaudio.Core"
+#define OBJECT_PATH "/org/pulseaudio1"
+#define INTERFACE_CORE "org.PulseAudio.Core1"
struct pa_dbusobj_core {
pa_core *core;
};
static const char *introspection_snippet =
- " <interface name=\""INTERFACE_NAME"\">"
- " <method name=\"Test\">"
- " <arg name=\"result\" type=\"s\" direction=\"out\"/>"
- " </method>"
- " </interface>";
+ " <interface name=\"" INTERFACE_CORE "\">\n"
+ " <method name=\"GetCardByName\">\n"
+ " <arg name=\"Name\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Card\" type=\"o\" direction=\"out\"/>\n"
+ " </method>\n"
+ " <method name=\"GetSinkByName\">\n"
+ " <arg name=\"Name\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Sink\" type=\"o\" direction=\"out\"/>\n"
+ " </method>\n"
+ " <method name=\"GetSourceByName\">\n"
+ " <arg name=\"Name\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Source\" type=\"o\" direction=\"out\"/>\n"
+ " </method>\n"
+ " <method name=\"GetSampleByName\">\n"
+ " <arg name=\"Name\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Sample\" type=\"o\" direction=\"out\"/>\n"
+ " </method>\n"
+ " <method name=\"UploadSample\">\n"
+ " <arg name=\"Name\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"SampleFormat\" type=\"y\" direction=\"in\"/>\n"
+ " <arg name=\"SampleRate\" type=\"u\" direction=\"in\"/>\n"
+ " <arg name=\"Channels\" type=\"ay\" direction=\"in\"/>\n"
+ " <arg name=\"DefaultVolume\" type=\"au\" direction=\"in\"/>\n"
+ " <arg name=\"Proplist\" type=\"a{say}\" direction=\"in\"/>\n"
+ " <arg name=\"Data\" type=\"ay\" direction=\"in\"/>\n"
+ " <arg name=\"Sample\" type=\"o\" direction=\"out\"/>\n"
+ " </method>\n"
+ " <method name=\"LoadSampleFromFile\">\n"
+ " <arg name=\"Name\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Filepath\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Sample\" type=\"o\" direction=\"out\"/>\n"
+ " </method>\n"
+ " <method name=\"AddLazySample\">\n"
+ " <arg name=\"Name\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Filepath\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Sample\" type=\"o\" direction=\"out\"/>\n"
+ " </method>\n"
+ " <method name=\"AddLazySamplesFromDirectory\">\n"
+ " <arg name=\"Dirpath\" type=\"s\" direction=\"in\"/>\n"
+ " </method>\n"
+ " <method name=\"LoadModule\">\n"
+ " <arg name=\"Name\" type=\"s\" direction=\"in\"/>\n"
+ " <arg name=\"Arguments\" type=\"a{ss}\" direction=\"in\"/>\n"
+ " <arg name=\"Module\" type=\"o\" direction=\"out\"/>\n"
+ " </method>\n"
+ " <method name=\"Exit\"/>\n"
+ " <signal name=\"NewCard\">\n"
+ " <arg name=\"Card\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"CardRemoved\">\n"
+ " <arg name=\"Card\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NewSink\">\n"
+ " <arg name=\"Sink\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"SinkRemoved\">\n"
+ " <arg name=\"Sink\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"FallbackSinkUpdated\">\n"
+ " <arg name=\"Sink\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NewSource\">\n"
+ " <arg name=\"Source\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"SourceRemoved\">\n"
+ " <arg name=\"Source\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"FallbackSourceUpdated\">\n"
+ " <arg name=\"Source\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NewPlaybackStream\">\n"
+ " <arg name=\"PlaybackStream\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"PlaybackStreamRemoved\">\n"
+ " <arg name=\"PlaybackStream\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NewRecordStream\">\n"
+ " <arg name=\"RecordStream\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"RecordStreamRemoved\">\n"
+ " <arg name=\"RecordStream\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NewSample\">\n"
+ " <arg name=\"Sample\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"SampleRemoved\">\n"
+ " <arg name=\"Sample\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NewModule\">\n"
+ " <arg name=\"Module\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"ModuleRemoved\">\n"
+ " <arg name=\"Module\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NewClient\">\n"
+ " <arg name=\"Client\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <signal name=\"ClientRemoved\">\n"
+ " <arg name=\"Client\" type=\"o\"/>\n"
+ " </signal>\n"
+ " <property name=\"InterfaceRevision\" type=\"u\" access=\"read\"/>\n"
+ " <property name=\"Name\" type=\"s\" access=\"read\"/>\n"
+ " <property name=\"Version\" type=\"s\" access=\"read\"/>\n"
+ " <property name=\"Username\" type=\"s\" access=\"read\"/>\n"
+ " <property name=\"Hostname\" type=\"s\" access=\"read\"/>\n"
+ " <property name=\"DefaultChannels\" type=\"ay\" access=\"readwrite\"/>\n"
+ " <property name=\"DefaultSampleFormat\" type=\"y\" access=\"readwrite\"/>\n"
+ " <property name=\"DefaultSampleRate\" type=\"u\" access=\"readwrite\"/>\n"
+ " <property name=\"Sinks\" type=\"ao\" access=\"read\"/>\n"
+ " <property name=\"FallbackSink\" type=\"s\" access=\"readwrite\"/>\n"
+ " <property name=\"Sources\" type=\"ao\" access=\"read\"/>\n"
+ " <property name=\"FallbackSource\" type=\"o\" access=\"readwrite\"/>\n"
+ " <property name=\"PlaybackStreams\" type=\"ao\" access=\"read\"/>\n"
+ " <property name=\"RecordStreams\" type=\"ao\" access=\"read\"/>\n"
+ " <property name=\"Samples\" type=\"ao\" access=\"read\"/>\n"
+ " <property name=\"Modules\" type=\"ao\" access=\"read\"/>\n"
+ " <property name=\"Clients\" type=\"ao\" access=\"read\"/>\n"
+ " <property name=\"Extensions\" type=\"as\" access=\"read\"/>\n"
+ " </interface>\n";
+
+/* If you need to modify this list, note that handle_get_all() uses hard-coded
+ * indexes to point to these strings, so make sure the indexes don't go wrong
+ * there. */
+static const char *properties[] = {
+ "InterfaceRevision",
+ "Name",
+ "Version",
+ "Username",
+ "Hostname",
+ "DefaultChannels",
+ "DefaultSampleFormat",
+ "DefaultSampleRate",
+ "Sinks",
+ "FallbackSink",
+ "Sources",
+ "FallbackSource",
+ "PlaybackStreams",
+ "RecordStreams",
+ "Samples",
+ "Modules",
+ "Clients",
+ "Extensions",
+ NULL
+};
static const char *methods[] = {
- "Test",
+ "GetCardByName",
+ "GetSinkByName",
+ "GetSourceByName",
+ "GetSampleByName",
+ "UploadSample",
+ "LoadSampleFromFile",
+ "AddLazySample",
+ "AddLazySamplesFromDirectory",
+ "LoadModule",
+ "Exit",
NULL
};
-static DBusHandlerResult handle_test(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_core *c) {
+static DBusHandlerResult handle_get_name(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_core *c) {
+ DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
DBusMessage *reply = NULL;
- const char *reply_message = "Hello!";
+ const char *server_name = PACKAGE_NAME;
+ DBusMessageIter msg_iter;
+ DBusMessageIter variant_iter;
pa_assert(conn);
pa_assert(msg);
pa_assert(c);
- if (!(reply = dbus_message_new_method_return(msg)))
- goto oom;
+ if (!(reply = dbus_message_new_method_return(msg))) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ dbus_message_iter_init_append(reply, &msg_iter);
+ if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &server_name)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_close_container(&msg_iter, &variant_iter)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+
+finish:
+ if (reply)
+ dbus_message_unref(reply);
+
+ return r;
+}
- if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &reply_message, DBUS_TYPE_INVALID))
- goto fail;
+static DBusHandlerResult handle_get(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_core *c) {
+ DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
+ const char* interface;
+ const char* property;
+ DBusMessage *reply = NULL;
- if (!dbus_connection_send(conn, reply, NULL))
- goto oom;
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(c);
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
+ if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+ goto finish;
+ }
+
+ if (*interface && !pa_streq(interface, INTERFACE_CORE)) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+
+ if (pa_streq(property, "Name")) {
+ r = handle_get_name(conn, msg, c);
+ goto finish;
+ }
+
+ if (!(reply = dbus_message_new_error_printf(msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s: No such property", property))) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+
+finish:
+ if (reply)
+ dbus_message_unref(reply);
+
+ return r;
+}
- dbus_message_unref(reply);
+static DBusHandlerResult handle_set(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_core *c) {
+ DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
+ const char* interface;
+ const char* property;
+ DBusMessage *reply = NULL;
- return DBUS_HANDLER_RESULT_HANDLED;
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(c);
-fail:
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
+ if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+ goto finish;
+ }
+
+ if (*interface && !pa_streq(interface, INTERFACE_CORE)) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+
+ if (pa_streq(property, "Name")) {
+ if (!(reply = dbus_message_new_error_printf(msg, DBUS_ERROR_ACCESS_DENIED, "%s: Property not settable", property))) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+ goto finish;
+ }
+
+ if (!(reply = dbus_message_new_error_printf(msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s: No such property", property))) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+ goto finish;
+
+ if (!(reply = dbus_message_new_error_printf(msg, DBUS_ERROR_ACCESS_DENIED, "%s: Property not settable", property))) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+
+finish:
if (reply)
dbus_message_unref(reply);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ return r;
+}
+
+static DBusHandlerResult handle_get_all(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_core *c) {
+ DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED;
+ DBusMessage *reply = NULL;
+ char *interface = NULL;
+ char const *server_name = PACKAGE_NAME;
+ DBusMessageIter msg_iter;
+ DBusMessageIter dict_iter;
+ DBusMessageIter dict_entry_iter;
+ DBusMessageIter variant_iter;
-oom:
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(c);
+
+ if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface, DBUS_TYPE_INVALID)) {
+ if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"))) {
+ r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+ goto finish;
+ }
+
+ if (!(reply = dbus_message_new_method_return(msg))) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ dbus_message_iter_init_append(reply, &msg_iter);
+ if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &properties[1])) { /* Name */
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_open_container(&dict_entry_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &server_name)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_close_container(&dict_entry_iter, &variant_iter)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_message_iter_close_container(&msg_iter, &dict_iter)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ if (!dbus_connection_send(conn, reply, NULL)) {
+ r = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto finish;
+ }
+ r = DBUS_HANDLER_RESULT_HANDLED;
+
+finish:
if (reply)
dbus_message_unref(reply);
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ return r;
}
static DBusHandlerResult receive_cb(DBusConnection *connection, DBusMessage *message, void *user_data) {
@@ -92,8 +444,17 @@ static DBusHandlerResult receive_cb(DBusConnection *connection, DBusMessage *mes
pa_assert(message);
pa_assert(c);
- if (dbus_message_is_method_call(message, INTERFACE_NAME, "Test"))
- return handle_test(connection, message, c);
+ if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "Get") ||
+ (!dbus_message_get_interface(message) && dbus_message_has_member(message, "Get")))
+ return handle_get(connection, message, c);
+
+ if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "Set") ||
+ (!dbus_message_get_interface(message) && dbus_message_has_member(message, "Set")))
+ return handle_set(connection, message, c);
+
+ if (dbus_message_is_method_call(message, DBUS_INTERFACE_PROPERTIES, "GetAll") ||
+ (!dbus_message_get_interface(message) && dbus_message_has_member(message, "GetAll")))
+ return handle_get_all(connection, message, c);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
@@ -106,7 +467,8 @@ pa_dbusobj_core *pa_dbusobj_core_new(pa_core *core) {
c = pa_xnew(pa_dbusobj_core, 1);
c->core = core;
- pa_dbus_add_interface(core, OBJECT_NAME, INTERFACE_NAME, methods, introspection_snippet, receive_cb, c);
+ pa_dbus_add_interface(core, OBJECT_PATH, INTERFACE_CORE, properties, methods, introspection_snippet, receive_cb, c);
+
return c;
}
@@ -114,7 +476,7 @@ pa_dbusobj_core *pa_dbusobj_core_new(pa_core *core) {
void pa_dbusobj_core_free(pa_dbusobj_core *c) {
pa_assert(c);
- pa_dbus_remove_interface(c->core, OBJECT_NAME, INTERFACE_NAME);
+ pa_dbus_remove_interface(c->core, OBJECT_PATH, INTERFACE_CORE);
pa_xfree(c);
}