Add connection wrappers.

It can actually send messages now!
This commit is contained in:
Tristan Hume 2015-04-28 21:00:48 -04:00
parent 0e0e8971b4
commit 9a028b3a29
2 changed files with 77 additions and 21 deletions

View file

@ -1,16 +1,19 @@
import std.stdio; import std.stdio;
import ddbus.c_lib; import ddbus.c_lib;
import ddbus.thin;
void main() void main()
{ {
DBusError err; Connection conn = connectToBus();
dbus_error_init(&err); for(int i = 0; i < 50; i++) {
DBusMessage *msg = dbus_message_new_method_call("org.blah.lolbus","/root","org.blah.iface","testStuff"); Message msg = new Message("ca.thume.transience","/ca/thume/transience/screensurface",
dbus_int32_t arg = 5; "ca.thume.transience.screensurface","testDot");
dbus_message_append_args(msg, 'i', &arg, '\0'); conn.sendBlocking(msg);
dbus_int32_t arg_out; }
dbus_message_get_args(msg,&err,'i',&arg_out); Message msg2 = new Message("ca.thume.transience","/ca/thume/transience/screensurface",
dbus_message_unref(msg); "ca.thume.transience.screensurface","testPing");
assert(arg_out == arg); Message res = conn.sendWithReplyBlocking(msg2,3000);
int result = res.read!int();
writeln(result);
writeln("It worked!"); writeln("It worked!");
} }

View file

@ -6,11 +6,33 @@ import ddbus.util;
import std.string; import std.string;
import std.typecons; 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 { class Message {
this(string dest, string path, string iface, string method) { this(string dest, string path, string iface, string method) {
msg = dbus_message_new_method_call(dest.toStringz(), path.toStringz(), iface.toStringz(), method.toStringz()); msg = dbus_message_new_method_call(dest.toStringz(), path.toStringz(), iface.toStringz(), method.toStringz());
} }
this(DBusMessage *m) {
msg = m;
}
~this() { ~this() {
dbus_message_unref(msg); dbus_message_unref(msg);
} }
@ -21,6 +43,12 @@ class Message {
buildIter(&iter, args); 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) { T read(T)() if(canDBus!T) {
DBusMessageIter iter; DBusMessageIter iter;
dbus_message_iter_init(msg, &iter); dbus_message_iter_init(msg, &iter);
@ -43,16 +71,41 @@ class Message {
DBusMessage *msg; DBusMessage *msg;
} }
// class MessageBuilder { class Connection {
// DBusMessageIter iter; DBusConnection *conn;
// // kept around for GC reasons, iterators need parent message. this(DBusConnection *connection) {
// Message parent; conn = connection;
// this(Message msg) { }
// parent = msg;
// dbus_message_iter_init(parent.msg, &iter);
// }
// void doBasic(int type, void *v) { void sendBlocking(Message msg) {
// dbus_message_iter_append_basic(&iter, type, v); 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();
}
}