summaryrefslogtreecommitdiff
path: root/hfpd/dbus.h
diff options
context:
space:
mode:
authorsamr7 <samr7@126591fb-c623-4b62-a76d-97a8e4f34109>2008-10-17 21:28:01 +0000
committersamr7 <samr7@126591fb-c623-4b62-a76d-97a8e4f34109>2008-10-17 21:28:01 +0000
commitb9526d2a82d25d2800e5d76ee45e561ec5870458 (patch)
treed3eab6e4bc413696e5ebd967bf6db529f5e5c7d8 /hfpd/dbus.h
downloadnohands-b9526d2a82d25d2800e5d76ee45e561ec5870458.tar.gz
Initial hfpforlinux submission to sourceforge.
git-svn-id: http://nohands.svn.sourceforge.net/svnroot/nohands/trunk@1 126591fb-c623-4b62-a76d-97a8e4f34109
Diffstat (limited to 'hfpd/dbus.h')
-rw-r--r--hfpd/dbus.h300
1 files changed, 300 insertions, 0 deletions
diff --git a/hfpd/dbus.h b/hfpd/dbus.h
new file mode 100644
index 0000000..e06346a
--- /dev/null
+++ b/hfpd/dbus.h
@@ -0,0 +1,300 @@
+/* -*- C++ -*- */
+/*
+ * Software Bluetooth Hands-Free Implementation
+ *
+ * Copyright (C) 2008 Sam Revitch <samr7@cs.washington.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if !defined(__HFPD_DBUS_H__)
+#define __HFPD_DBUS_H__
+
+#include <stdarg.h>
+#include <dbus/dbus.h>
+#include <libhfp/events.h>
+#include <libhfp/list.h>
+
+
+class DbusSession;
+class DbusExportObject;
+class DbusInterface;
+
+
+struct DbusMethod {
+ typedef bool (*handler_t)(DbusExportObject *, DBusMessage *msgp);
+
+ const char *meth_name;
+ handler_t meth_func;
+ const char *meth_sig;
+ const char *ret_sig;
+};
+
+#define DbusMethodEntryName(NAME, CLASS, METHOD, SIG, RET) \
+ { NAME, DbusMethodRawMember<CLASS, &CLASS::METHOD>, SIG, RET }
+#define DbusMethodEntry(CLASS, METHOD, SIG, RET) \
+ DbusMethodEntryName(#METHOD, CLASS, METHOD, SIG, RET)
+
+#define DbusSignalEntry(METHOD, SIG) \
+ { #METHOD, 0, SIG, 0 }
+
+struct DbusProperty {
+ typedef bool (*fn_t)(DbusExportObject *objp, DBusMessage *msgp,
+ const DbusProperty *prop, DBusMessageIter &iter);
+ const char *prop_name;
+ const char *prop_sig;
+ fn_t prop_get;
+ fn_t prop_set;
+};
+
+
+#define DbusPropertyRaw(SIG, NAME, CLASS, GET, SET) { \
+ #NAME, \
+ SIG, \
+ DbusPropGetRawMember<CLASS, &CLASS::GET>, \
+ DbusPropSetRawMember<CLASS, &CLASS::SET> \
+}
+
+#define DbusPropertyRawImmutable(SIG, NAME, CLASS, GET) { \
+ #NAME, \
+ SIG, \
+ DbusPropGetRawMember<CLASS, &CLASS::GET>, \
+ 0 \
+}
+
+#define DbusPropertyMarshall(TYPE, NAME, CLASS, GET, SET) { \
+ #NAME, \
+ DbusTypeTraits<TYPE>::Signature(), \
+ DbusPropGetMarshallMember<DbusTypeTraits<TYPE>, \
+ CLASS, &CLASS::GET>, \
+ DbusPropSetMarshallMember<DbusTypeTraits<TYPE>, \
+ CLASS, &CLASS::SET> \
+}
+
+#define DbusPropertyMarshallImmutable(TYPE, NAME, CLASS, GET) { \
+ #NAME, \
+ DbusTypeTraits<TYPE>::Signature(), \
+ DbusPropGetMarshallMember<DbusTypeTraits<TYPE>, \
+ CLASS, &CLASS::GET>, \
+ 0 \
+}
+
+struct DbusInterface {
+ const char *if_name;
+ const DbusMethod *if_meths;
+ const DbusMethod *if_sigs;
+ const DbusProperty *if_props;
+};
+
+class DbusExportObject {
+ friend class DbusSession;
+ DbusSession *m_session;
+ const char *m_path;
+ const DbusInterface *m_ifaces;
+
+ static const DbusInterface s_ifaces_common[];
+ static const DbusMethod s_methods_introspect[];
+ static const DbusMethod s_methods_properties[];
+ static const DBusObjectPathVTable s_vtable;
+
+ static DBusHandlerResult DispatchHelper(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+ static void UnregisterHelper(DBusConnection *conn, void *ptr);
+
+ bool DbusRegister(DbusSession *sessp);
+ void DbusUnregister(void);
+
+protected:
+ /* The main message dispatch method */
+ virtual DBusHandlerResult DbusDispatch(DBusMessage *msgp);
+
+ /* Metadata search helpers */
+ static const DbusInterface *DbusFindInterface(const DbusInterface *ifs,
+ const char *name);
+ static const DbusMethod *DbusFindMethod(const DbusMethod *meths,
+ const char *name);
+ static const DbusProperty *DbusFindProperty(const DbusProperty *props,
+ const char *name);
+
+ /* Common interface method implementations */
+ /* org.freedesktop.DBus.Introspectable */
+ virtual bool DbusIntrospect(DBusMessage *msgp);
+
+ /* org.freedesktop.DBus.Properties */
+ const DbusProperty *DbusPropertyCommon(DBusMessage *msgp,
+ DBusMessageIter &mi, bool &ret);
+ virtual bool DbusPropertyGet(DBusMessage *msgp);
+ virtual bool DbusPropertySet(DBusMessage *msgp);
+ virtual bool DbusPropertyGetAll(DBusMessage *msgp);
+
+public:
+ DbusExportObject(const char *name, const DbusInterface *iface_tbl = 0)
+ : m_session(0), m_path(name), m_ifaces(iface_tbl) {}
+ virtual ~DbusExportObject();
+
+ DbusSession *GetDbusSession(void) const { return m_session; }
+ bool IsDbusExported(void) const { return GetDbusSession() != 0; }
+ const char *GetDbusPath(void) const { return m_path; }
+
+ bool SendSignalArgs(const char *iface, const char *name,
+ int first_arg_type, ...);
+ bool SendSignalArgsVa(const char *iface, const char *signame,
+ int first_arg_type, va_list ap);
+ bool SendReplyArgs(DBusMessage *src, int first_arg_type, ...);
+ bool SendReplyArgsVa(DBusMessage *src, int first_arg_type, va_list ap);
+ bool SendReplyError(DBusMessage *src, const char *name,
+ const char *msg, ...);
+ DBusMessage *NewMethodReturn(DBusMessage *srcp);
+ bool SendMessage(DBusMessage *out);
+};
+
+
+/*
+ * The match notifier diverts D-Bus messages matching a given
+ * expression to a callback. The expression is given when the
+ * object is created.
+ */
+
+class DbusMatchNotifier :
+ public libhfp::Callback<void, class DbusMatchNotifier*, DBusMessage*> {
+public:
+ virtual bool SetEnabled(bool enable) = 0;
+ virtual ~DbusMatchNotifier() {}
+};
+
+
+/*
+ * The completion object notifies when an asynchronous remote method call
+ * has completed. The subject DBusMessage is provided if it is available,
+ * and the working reference is released when the callback returns.
+ */
+
+class DbusCompletion
+ : public libhfp::Callback<void, class DbusCompletion *, DBusMessage*> {
+ friend class DbusSession;
+ static void CompletionHelper(DBusPendingCall *pc, void *ud);
+ DBusPendingCall *m_pend;
+public:
+ virtual ~DbusCompletion();
+};
+
+
+/*
+ * The DbusPeer object supports the DbusPeerDisconnectNotifier object
+ * below.
+ */
+
+class DbusPeerDisconnectNotifier;
+
+class DbusPeer {
+protected:
+ DbusPeer(void) {}
+ virtual ~DbusPeer() {};
+
+public:
+ virtual const char *GetName(void) const = 0;
+ virtual DbusPeerDisconnectNotifier *NewDisconnectNotifier(void) = 0;
+ virtual void Get(void) = 0;
+ virtual void Put(void) = 0;
+};
+
+/*
+ * The peer disconnect notifier is useful for cleaning up objects
+ * referenced by specific D-Bus peers when those peers disconnect.
+ */
+
+class DbusPeerDisconnectNotifier
+ : public libhfp::Callback<void, DbusPeerDisconnectNotifier *> {
+ friend class DbusPeerImpl;
+
+ libhfp::ListItem m_links;
+ DbusPeer *m_peer;
+
+public:
+ DbusPeer *GetPeer(void) const { return m_peer; }
+ virtual ~DbusPeerDisconnectNotifier();
+};
+
+
+/*
+ * "connection" is the right word for this, but I don't want the
+ * distinction between this object and DBusConnection to rest on
+ * the captalization of a 'b'.
+ */
+
+class DbusSession {
+ friend class DbusObjectLocal;
+ friend class DbusMatchNotifierImpl;
+
+ libhfp::DispatchInterface *m_di;
+ DBusConnection *m_conn;
+ libhfp::TimerNotifier *m_dodispatch;
+ DbusExportObject *m_local;
+ bool m_owner;
+ libhfp::ListItem m_match_exprs;
+ libhfp::ListItem m_peers;
+
+ void Dispatch(libhfp::TimerNotifier *notp);
+ static void SetDispatchStatus(DBusConnection *conn,
+ DBusDispatchStatus new_stat,
+ void *ptr);
+ bool SetupDispatchOwner(void);
+ bool SetupEventsOwner(void);
+ bool SetupEventsCommon(void);
+ void __Disconnect(bool notify = false);
+
+ static DBusHandlerResult FilterHelper(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+
+ bool AddMatchNotifier(class DbusMatchNotifierImpl *matchp);
+ void RemoveMatchNotifier(class DbusMatchNotifierImpl *matchp);
+
+public:
+ DbusSession(libhfp::DispatchInterface *di);
+ ~DbusSession();
+
+ libhfp::Callback<void, DbusSession *> cb_NotifyDisconnect;
+
+ libhfp::DispatchInterface *GetDi(void) const { return m_di; }
+ DBusConnection *GetConn(void) const { return m_conn; }
+
+ bool Connect(DBusBusType bustype = DBUS_BUS_SESSION);
+ void Disconnect(void) { __Disconnect(); }
+ bool IsConnected(void) const { return m_conn != 0; }
+
+ bool AddUniqueName(const char *name);
+ bool RemoveUniqueName(const char *name);
+
+ bool ExportObject(DbusExportObject *objp)
+ { return objp->DbusRegister(this); }
+ void UnexportObject(DbusExportObject *objp)
+ { objp->DbusUnregister(); }
+
+ DbusMatchNotifier *NewMatchNotifier(const char *expression);
+
+ DbusPeer *GetPeer(const char *nm);
+ DbusPeer *GetPeer(DBusMessage *from_sender) {
+ return GetPeer(dbus_message_get_sender(from_sender));
+ }
+
+ bool SendMessage(DBusMessage *msgp);
+ DbusCompletion *SendWithCompletion(DBusMessage *msgp);
+};
+
+#include <dbus-marshall.h>
+
+#endif /* !defined(__HFPD_DBUS_H__) */