From 9a028b3a29c25641cf2298cbfeee4de800034db3 Mon Sep 17 00:00:00 2001 From: Tristan Hume Date: Tue, 28 Apr 2015 21:00:48 -0400 Subject: [PATCH] Add connection wrappers. It can actually send messages now! --- source/app.d | 21 +++++++------ source/ddbus/thin.d | 77 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/source/app.d b/source/app.d index e9ed24e..71808ac 100644 --- a/source/app.d +++ b/source/app.d @@ -1,16 +1,19 @@ import std.stdio; import ddbus.c_lib; +import ddbus.thin; void main() { - DBusError err; - dbus_error_init(&err); - DBusMessage *msg = dbus_message_new_method_call("org.blah.lolbus","/root","org.blah.iface","testStuff"); - dbus_int32_t arg = 5; - dbus_message_append_args(msg, 'i', &arg, '\0'); - dbus_int32_t arg_out; - dbus_message_get_args(msg,&err,'i',&arg_out); - dbus_message_unref(msg); - assert(arg_out == arg); + Connection conn = connectToBus(); + for(int i = 0; i < 50; i++) { + Message msg = new Message("ca.thume.transience","/ca/thume/transience/screensurface", + "ca.thume.transience.screensurface","testDot"); + conn.sendBlocking(msg); + } + Message msg2 = new Message("ca.thume.transience","/ca/thume/transience/screensurface", + "ca.thume.transience.screensurface","testPing"); + Message res = conn.sendWithReplyBlocking(msg2,3000); + int result = res.read!int(); + writeln(result); writeln("It worked!"); } diff --git a/source/ddbus/thin.d b/source/ddbus/thin.d index 7c7d1ec..c8d67db 100644 --- a/source/ddbus/thin.d +++ b/source/ddbus/thin.d @@ -6,11 +6,33 @@ import ddbus.util; import std.string; import std.typecons; +class DBusException : Exception { + this(DBusError *err) { + super(err.message.fromStringz().idup); + } +} + +T wrapErrors(T)(T delegate(DBusError *err) del) { + DBusError error; + dbus_error_init(&error); + T ret = del(&error); + if(dbus_error_is_set(&error)) { + auto ex = new DBusException(&error); + dbus_error_free(&error); + throw ex; + } + return ret; +} + class Message { this(string dest, string path, string iface, string method) { msg = dbus_message_new_method_call(dest.toStringz(), path.toStringz(), iface.toStringz(), method.toStringz()); } + this(DBusMessage *m) { + msg = m; + } + ~this() { dbus_message_unref(msg); } @@ -21,6 +43,12 @@ class Message { buildIter(&iter, args); } + /** + Reads the first argument of the message. + Note that this creates a new iterator every time so calling it multiple times will always + read the first argument. This is suitable for single item returns. + To read multiple arguments use readTuple. + */ T read(T)() if(canDBus!T) { DBusMessageIter iter; dbus_message_iter_init(msg, &iter); @@ -43,16 +71,41 @@ class Message { DBusMessage *msg; } -// class MessageBuilder { -// DBusMessageIter iter; -// // kept around for GC reasons, iterators need parent message. -// Message parent; -// this(Message msg) { -// parent = msg; -// dbus_message_iter_init(parent.msg, &iter); -// } +class Connection { + DBusConnection *conn; + this(DBusConnection *connection) { + conn = connection; + } -// void doBasic(int type, void *v) { -// dbus_message_iter_append_basic(&iter, type, v); -// } -// } + void sendBlocking(Message msg) { + dbus_connection_send(conn,msg.msg,null); + dbus_connection_flush(conn); + } + + Message sendWithReplyBlocking(Message msg, int timeout = 100) { + DBusMessage *reply = wrapErrors((err) { + return dbus_connection_send_with_reply_and_block(conn,msg.msg,timeout,err); + }); + return new Message(reply); + } + + ~this() { + dbus_connection_unref(conn); + } +} + +Connection connectToBus(DBusBusType bus = DBusBusType.DBUS_BUS_SESSION) { + DBusConnection *conn = wrapErrors((err) { return dbus_bus_get(bus,err); }); + return new Connection(conn); +} + +unittest { + import dunit.toolkit; + // This test will only pass if DBus is installed. + Connection conn = connectToBus(); + conn.conn.assertTruthy(); + // We can only count on no system bus on OSX + version(OSX) { + connectToBus(DBusBusType.DBUS_BUS_SYSTEM).assertThrow!DBusException(); + } +}