davemds pushed a commit to branch master.

commit 0a32be475ac04c91ce8b844fe722772bc230653c
Author: davemds <[email protected]>
Date:   Sat Apr 6 12:46:52 2013 +0200

    Python-EFL: first working dbus mainloop wrapper.
    
    This one don't require edbus2 nor the old e_dbus, it reimplement
    the dbus connection stuff that was in e_dbus (the old) in a
    py module.
---
 efl/dbus_mainloop/e_dbus.c                    | 531 ++++++++++++++++++++++++++
 efl/dbus_mainloop/e_dbus.h                    |  69 ++++
 efl/dbus_mainloop/module.c                    | 138 +++++++
 setup.py                                      |  10 +-
 tests/dbus_mainloop/test-bt-list-handles.py   |  28 ++
 tests/dbus_mainloop/test-bt-search-devices.py |  53 +++
 tests/dbus_mainloop/test-signal-emitter.py    |  37 ++
 tests/dbus_mainloop/test-signal-recipient.py  |  48 +++
 tests/dbus_mainloop/test-signal-simple.py     |  16 +
 9 files changed, 929 insertions(+), 1 deletion(-)

diff --git a/efl/dbus_mainloop/e_dbus.c b/efl/dbus_mainloop/e_dbus.c
new file mode 100644
index 0000000..a45f00c
--- /dev/null
+++ b/efl/dbus_mainloop/e_dbus.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (C) 2007-2013 various contributors (see AUTHORS)
+ * 
+ * This file is part of Python-EFL.
+ * 
+ * Python-EFL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * Python-EFL 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this Python-EFL.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include "e_dbus.h"
+
+
+int E_DBUS_EVENT_SIGNAL = 0;
+static int connection_slot = -1;
+static int e_dbus_idler_active = 0;
+static int close_connection = 0;
+static int _edbus_init_count = 0;
+
+
+static void
+e_dbus_fd_handler_del(E_DBus_Handler_Data *hd)
+{
+  if (!hd->fd_handler) return;
+
+  printf("handler disabled\n");
+  hd->cd->fd_handlers = eina_list_remove(hd->cd->fd_handlers, hd->fd_handler);
+  ecore_main_fd_handler_del(hd->fd_handler);
+  hd->fd_handler = NULL;
+}
+
+static Eina_Bool
+e_dbus_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+  E_DBus_Handler_Data *hd;
+  unsigned int condition = 0;
+
+  printf("fd handler (%p)!\n", fd_handler);
+
+  hd = data;
+
+  if (!hd->enabled)
+    {
+       e_dbus_fd_handler_del(hd);
+       return ECORE_CALLBACK_CANCEL;
+    }
+  if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) condition 
|= DBUS_WATCH_READABLE;
+  if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE)) condition 
|= DBUS_WATCH_WRITABLE;
+  if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR)) condition 
|= DBUS_WATCH_ERROR;
+  printf("fdh || READ: %d, WRITE: %d\n",
+      (condition & DBUS_WATCH_READABLE) == DBUS_WATCH_READABLE,
+      (condition & DBUS_WATCH_WRITABLE) == DBUS_WATCH_WRITABLE);
+
+  if (condition & DBUS_WATCH_ERROR) printf("DBUS watch error\n");
+  dbus_watch_handle(hd->watch, condition);
+  hd = NULL;
+
+  return ECORE_CALLBACK_RENEW;
+}
+
+static void
+e_dbus_fd_handler_add(E_DBus_Handler_Data *hd)
+{
+  unsigned int dflags;
+  Ecore_Fd_Handler_Flags eflags;
+  Eina_List *l;
+  Ecore_Fd_Handler *fdh;
+
+  if (hd->fd_handler) return;
+  dflags = dbus_watch_get_flags(hd->watch);
+  eflags = ECORE_FD_ERROR;
+  if (dflags & DBUS_WATCH_READABLE) eflags |= ECORE_FD_READ;
+  if (dflags & DBUS_WATCH_WRITABLE) eflags |= ECORE_FD_WRITE;
+
+  EINA_LIST_FOREACH(hd->cd->fd_handlers, l, fdh)
+    {
+       if (ecore_main_fd_handler_fd_get(fdh) == hd->fd) return;
+    }
+
+  printf("fd handler add (%d)\n", hd->fd);
+  hd->fd_handler = ecore_main_fd_handler_add(hd->fd,
+                                             eflags,
+                                             e_dbus_fd_handler,
+                                             hd,
+                                             NULL,
+                                             NULL);
+
+  hd->cd->fd_handlers = eina_list_append(hd->cd->fd_handlers, hd->fd_handler);
+}
+
+static void
+e_dbus_handler_data_free(void *data)
+{
+  E_DBus_Handler_Data *hd = data;
+  
+  printf("e_dbus_handler_data_free\n");
+  if (hd->fd_handler)
+  {
+    hd->cd->fd_handlers = eina_list_remove(hd->cd->fd_handlers, 
hd->fd_handler);
+    ecore_main_fd_handler_del(hd->fd_handler);
+  }
+  free(hd);
+}
+
+static void
+e_dbus_connection_data_watch_add(E_DBus_Connection *cd, DBusWatch *watch)
+{
+  E_DBus_Handler_Data *hd;
+
+  hd = calloc(1, sizeof(E_DBus_Handler_Data));
+  dbus_watch_set_data(watch, hd, e_dbus_handler_data_free);
+  hd->cd = cd;
+  hd->watch = watch;
+
+  hd->enabled = dbus_watch_get_enabled(watch);
+// #if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && 
DBUS_VERSION_MICRO>= 1) || (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR > 1) 
|| (DBUS_VERSION_MAJOR > 1)
+  hd->fd = dbus_watch_get_unix_fd(hd->watch);
+// #else
+  // hd->fd = dbus_watch_get_fd(hd->watch);
+// #endif
+  printf("watch add (enabled: %d)\n", hd->enabled);
+  if (hd->enabled) e_dbus_fd_handler_add(hd);
+}
+
+static void
+e_dbus_message_free(void *data, void *message)
+{
+  dbus_message_unref(message);
+}
+
+static DBusHandlerResult
+e_dbus_filter(DBusConnection *conn, DBusMessage *message, void *user_data)
+{
+  E_DBus_Connection *cd = user_data;
+  printf("-----------------\n");
+  printf("Message!\n");
+
+  printf("type: %s\n", 
dbus_message_type_to_string(dbus_message_get_type(message)));
+  printf("path: %s\n", dbus_message_get_path(message));
+  printf("interface: %s\n", dbus_message_get_interface(message));
+  printf("member: %s\n", dbus_message_get_member(message));
+  printf("sender: %s\n", dbus_message_get_sender(message));
+
+  switch (dbus_message_get_type(message))
+  {
+    case DBUS_MESSAGE_TYPE_METHOD_CALL:
+      printf("signature: %s\n", dbus_message_get_signature(message));
+      break;
+    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+      printf("reply serial %d\n", dbus_message_get_reply_serial(message));
+      break;
+    case DBUS_MESSAGE_TYPE_ERROR:
+      printf("error: %s\n", dbus_message_get_error_name(message));
+      break;
+    case DBUS_MESSAGE_TYPE_SIGNAL:
+      dbus_message_ref(message);
+      if (cd->signal_dispatcher) cd->signal_dispatcher(cd, message);
+      ecore_event_add(E_DBUS_EVENT_SIGNAL, message, e_dbus_message_free, NULL);
+      break;
+    default:
+      break;
+  }
+  printf("-----------------\n");
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static Eina_Bool
+e_dbus_idler(void *data)
+{
+  E_DBus_Connection *cd;
+  cd = data;
+
+  if (DBUS_DISPATCH_COMPLETE == dbus_connection_get_dispatch_status(cd->conn))
+  {
+    printf("done dispatching!\n");
+    cd->idler = NULL;
+    return ECORE_CALLBACK_CANCEL;
+  }
+  e_dbus_idler_active++;
+  dbus_connection_ref(cd->conn);
+  printf("dispatch()\n");
+  dbus_connection_dispatch(cd->conn);
+  dbus_connection_unref(cd->conn);
+  e_dbus_idler_active--;
+  // e_dbus_signal_handlers_clean(cd); // TODO XXX
+  if (!e_dbus_idler_active && close_connection)
+  {
+    do
+    {
+      e_dbus_connection_close(cd);
+    } while (--close_connection);
+  }
+  return ECORE_CALLBACK_RENEW;
+}
+
+static void
+cb_dispatch_status(DBusConnection *conn, DBusDispatchStatus new_status, void 
*data)
+{
+  E_DBus_Connection *cd;
+
+  printf("dispatch status: %d!\n", new_status);
+  cd = data;
+
+  if (new_status == DBUS_DISPATCH_DATA_REMAINS && !cd->idler)
+     cd->idler = ecore_idler_add(e_dbus_idler, cd);
+  else if (new_status != DBUS_DISPATCH_DATA_REMAINS && cd->idler) 
+    {
+       ecore_idler_del(cd->idler);
+       cd->idler = NULL;
+    }
+}
+
+
+/* watch */
+static dbus_bool_t 
+cb_watch_add(DBusWatch *watch, void *data)
+{
+  E_DBus_Connection *cd;
+  cd = data;
+
+  printf("cb_watch_add\n");
+  e_dbus_connection_data_watch_add(cd, watch);
+
+  return true;
+}
+
+static void
+cb_watch_del(DBusWatch *watch, void *data)
+{
+  E_DBus_Handler_Data *hd;
+
+  printf("cb_watch_del\n");
+  hd = (E_DBus_Handler_Data *)dbus_watch_get_data(watch);
+  e_dbus_fd_handler_del(hd);
+}
+
+static void
+cb_watch_toggle(DBusWatch *watch, void *data)
+{
+  E_DBus_Handler_Data *hd;
+
+  printf("cb_watch_toggle\n");
+  hd = dbus_watch_get_data(watch);
+
+  if (!hd) return;
+
+  hd->enabled = dbus_watch_get_enabled(watch);
+
+  printf("watch %p is %sabled\n", hd, hd->enabled ? "en" : "dis");
+  if (hd->enabled) e_dbus_fd_handler_add(hd);
+  else e_dbus_fd_handler_del(hd);
+}
+
+
+/* timeout */
+static Eina_Bool
+e_dbus_timeout_handler(void *data)
+{
+  E_DBus_Timeout_Data *td;
+
+  td = data;
+
+  if (!dbus_timeout_get_enabled(td->timeout))
+  {
+    printf("timeout_handler (not enabled, ending)\n");
+    td->handler = NULL;
+    return ECORE_CALLBACK_CANCEL;
+  }
+
+  printf("timeout handler!\n");
+  dbus_timeout_handle(td->timeout);
+  return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+e_dbus_timeout_data_free(void *timeout_data)
+{
+  E_DBus_Timeout_Data *td = timeout_data;
+  printf("e_dbus_timeout_data_free\n");
+  if (td->handler) ecore_timer_del(td->handler);
+  free(td);
+}
+
+static dbus_bool_t 
+cb_timeout_add(DBusTimeout *timeout, void *data)
+{
+  E_DBus_Connection *cd;
+  E_DBus_Timeout_Data *td;
+  
+  cd = data;
+  printf("timeout add!\n");
+  td = calloc(1, sizeof(E_DBus_Timeout_Data));
+  td->cd = cd;
+  dbus_timeout_set_data(timeout, (void *)td, e_dbus_timeout_data_free);
+
+  td->interval = dbus_timeout_get_interval(timeout);
+  td->timeout = timeout;
+
+  if (dbus_timeout_get_enabled(timeout))
+    td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
+  td->cd->timeouts = eina_list_append(td->cd->timeouts, td->handler);
+
+  return true;
+}
+
+static void
+cb_timeout_del(DBusTimeout *timeout, void *data)
+{
+  E_DBus_Timeout_Data *td;
+  printf("timeout del!\n");
+
+  td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
+
+  if (td->handler) 
+  {
+    td->cd->timeouts = eina_list_remove(td->cd->timeouts, td->handler);
+    ecore_timer_del(td->handler);
+    td->handler = NULL;
+  }
+
+  /* Note: timeout data gets freed when the timeout itself is freed by dbus */
+}
+
+static void
+cb_timeout_toggle(DBusTimeout *timeout, void *data)
+{
+  E_DBus_Timeout_Data *td;
+  printf("timeout toggle!\n");
+
+  td = (E_DBus_Timeout_Data *)dbus_timeout_get_data(timeout);
+
+  if (dbus_timeout_get_enabled(td->timeout))
+  {
+    td->interval = dbus_timeout_get_interval(timeout);
+    td->handler = ecore_timer_add(td->interval, e_dbus_timeout_handler, td);
+  }
+  else
+  {
+    ecore_timer_del(td->handler);
+    td->handler = NULL;
+  }
+}
+
+
+/* dbus connection */
+static E_DBus_Connection *
+e_dbus_connection_new(DBusConnection *conn)
+{
+  E_DBus_Connection *cd;
+  const char *conn_name;
+
+  cd = calloc(1, sizeof(E_DBus_Connection));
+  if (!cd) return NULL;
+
+  cd->conn = conn;
+  conn_name = dbus_bus_get_unique_name(conn);
+  if (conn_name)
+  {
+    printf("Connected! Name: %s\n", conn_name);
+    cd->conn_name = strdup(conn_name);
+  }
+  else
+    printf("Not connected\n");
+
+  cd->shared_type = (unsigned int)-1;
+  cd->fd_handlers = NULL;
+  cd->timeouts = NULL;
+
+  return cd;
+}
+
+static void
+e_dbus_connection_free(void *data)
+{
+  E_DBus_Connection *cd = data;
+  Ecore_Fd_Handler *fd_handler;
+  Ecore_Timer *timer;
+  printf("e_dbus_connection free!\n");
+
+  EINA_LIST_FREE(cd->fd_handlers, fd_handler)
+    ecore_main_fd_handler_del(fd_handler);
+
+  EINA_LIST_FREE(cd->timeouts, timer)
+    ecore_timer_del(timer);
+
+  // if (cd->shared_type != (unsigned int)-1)
+    // shared_connections[cd->shared_type] = NULL;
+
+  // e_dbus_signal_handlers_free_all(cd);
+
+  if (cd->conn_name) free(cd->conn_name);
+
+  if (cd->idler) ecore_idler_del(cd->idler);
+
+  free(cd);
+}
+
+
+/* public functions */
+int
+e_dbus_init(void)
+{
+  if (++_edbus_init_count != 1)
+    return _edbus_init_count;
+  
+  if (!eina_init())
+    {
+      fprintf(stderr,"E-dbus: Enable to initialize eina\n");
+      return --_edbus_init_count;
+    }
+
+  if (!ecore_init())
+    {
+      fprintf(stderr, "E-dbus: Unable to initialize ecore\n");
+      eina_shutdown();
+      return --_edbus_init_count;
+    }
+
+  E_DBUS_EVENT_SIGNAL = ecore_event_type_new();
+  // e_dbus_object_init();
+
+  return _edbus_init_count;
+}
+
+int
+e_dbus_shutdown(void)
+{
+  if (_edbus_init_count <= 0)
+     {
+        fprintf(stderr, "Init count not greater than 0 in shutdown.\n");
+        return 0;
+     }
+  if (--_edbus_init_count)
+    return _edbus_init_count;
+
+  // e_dbus_object_shutdown();
+  ecore_shutdown();
+  eina_shutdown();
+
+  return _edbus_init_count;
+}
+
+E_DBus_Connection *
+e_dbus_connection_setup(DBusConnection *conn)
+{
+  E_DBus_Connection *cd;
+
+  cd = e_dbus_connection_new(conn);
+  if (!cd) return NULL;
+
+  /* connection_setup */
+  dbus_connection_set_exit_on_disconnect(cd->conn, EINA_FALSE);
+  dbus_connection_allocate_data_slot(&connection_slot);
+
+  dbus_connection_set_data(cd->conn, connection_slot, (void *)cd, 
e_dbus_connection_free);
+  dbus_connection_set_watch_functions(cd->conn,
+                                      cb_watch_add,
+                                      cb_watch_del,
+                                      cb_watch_toggle,
+                                      cd,
+                                      NULL);
+
+  dbus_connection_set_timeout_functions(cd->conn,
+                                        cb_timeout_add,
+                                        cb_timeout_del,
+                                        cb_timeout_toggle,
+                                        cd,
+                                        NULL);
+
+  dbus_connection_set_dispatch_status_function(cd->conn, cb_dispatch_status, 
cd, NULL);
+  dbus_connection_add_filter(cd->conn, e_dbus_filter, cd, NULL);
+
+  cb_dispatch_status(cd->conn, dbus_connection_get_dispatch_status(cd->conn), 
cd);
+
+  return cd;
+}
+
+void
+e_dbus_connection_close(E_DBus_Connection *conn)
+{
+  if (!conn) return;
+  printf("e_dbus_connection_close\n");
+
+  if (e_dbus_idler_active)
+  {
+    close_connection++;
+    return;
+  }
+  if (--(conn->refcount) != 0) return;
+
+  dbus_connection_free_data_slot(&connection_slot);
+  dbus_connection_remove_filter(conn->conn, e_dbus_filter, conn);
+  dbus_connection_set_watch_functions (conn->conn,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       NULL, NULL);
+
+  dbus_connection_set_timeout_functions (conn->conn,
+                                         NULL,
+                                         NULL,
+                                         NULL,
+                                         NULL, NULL);
+
+  dbus_connection_set_dispatch_status_function (conn->conn, NULL, NULL, NULL);
+
+  /* Idler functin must be cancelled when dbus connection is  unreferenced */
+  if (conn->idler)
+    {
+      ecore_idler_del(conn->idler);
+      conn->idler = NULL;
+    }
+
+  dbus_connection_close(conn->conn);
+  dbus_connection_unref(conn->conn);
+
+  // Note: the E_DBus_Connection gets freed when the dbus_connection is 
cleaned up by the previous unref
+}
+
+
diff --git a/efl/dbus_mainloop/e_dbus.h b/efl/dbus_mainloop/e_dbus.h
new file mode 100644
index 0000000..8df98ae
--- /dev/null
+++ b/efl/dbus_mainloop/e_dbus.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2007-2013 various contributors (see AUTHORS)
+ * 
+ * This file is part of Python-EFL.
+ * 
+ * Python-EFL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * Python-EFL 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this Python-EFL.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Glue code to attach the Ecore main loop to D-Bus from within Python.
+ */
+
+#include <dbus/dbus.h>
+#include <Ecore.h>
+
+
+typedef struct E_DBus_Connection E_DBus_Connection;
+typedef struct E_DBus_Handler_Data E_DBus_Handler_Data;
+typedef struct E_DBus_Timeout_Data E_DBus_Timeout_Data;
+
+struct E_DBus_Connection
+{
+  DBusBusType shared_type;
+  DBusConnection *conn;
+  char *conn_name;
+
+  Eina_List *fd_handlers;
+  Eina_List *timeouts;
+  Eina_List *signal_handlers;
+  void (*signal_dispatcher)(E_DBus_Connection *conn, DBusMessage *msg);
+
+  Ecore_Idler *idler;
+
+  int refcount;
+};
+
+struct E_DBus_Handler_Data
+{
+  int fd;
+  Ecore_Fd_Handler *fd_handler;
+  E_DBus_Connection *cd;
+  DBusWatch *watch;
+  int enabled;
+};
+
+struct E_DBus_Timeout_Data
+{
+  Ecore_Timer *handler;
+  DBusTimeout *timeout;
+  E_DBus_Connection *cd;
+  int interval;
+};
+
+
+int e_dbus_init(void);
+int e_dbus_shutdown(void);
+E_DBus_Connection *e_dbus_connection_setup(DBusConnection *conn);
+void e_dbus_connection_close(E_DBus_Connection *conn);
diff --git a/efl/dbus_mainloop/module.c b/efl/dbus_mainloop/module.c
new file mode 100644
index 0000000..7f4068f
--- /dev/null
+++ b/efl/dbus_mainloop/module.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2007-2013 various contributors (see AUTHORS)
+ * 
+ * This file is part of Python-EFL.
+ * 
+ * Python-EFL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * Python-EFL 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this Python-EFL.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Glue code to attach the Ecore main loop to D-Bus from within Python.
+ */
+
+#include <Python.h>
+#include <dbus/dbus-python.h>
+#include "e_dbus.h"
+
+
+static dbus_bool_t
+dbus_py_ecore_set_up_conn(DBusConnection *conn, void *data)
+{
+    Py_BEGIN_ALLOW_THREADS
+    e_dbus_connection_setup(conn);
+    Py_END_ALLOW_THREADS
+
+    return TRUE;
+}
+
+static PyObject *
+dbus_ecore_native_mainloop(void *data)
+{
+    return DBusPyNativeMainLoop_New4(dbus_py_ecore_set_up_conn,
+                                     NULL, NULL, NULL);
+}
+
+PyDoc_STRVAR(DBusEcoreMainLoop__doc__,
+"Returns a NativeMainLoop to attach the Ecore main loop to D-Bus\n"
+"from within Python.\n");
+static PyObject *
+dbus_ecore_main_loop(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "set_as_default", NULL };
+    int set_as_default = 0;
+    PyObject *ml;
+
+    if (PyTuple_Size(args) != 0) {
+        PyErr_SetString(PyExc_TypeError,
+                        "DBusEcoreMainLoop() takes no positional arguments");
+        return NULL;
+    }
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
+                                     kwlist, &set_as_default))
+        return NULL;
+
+    ml = dbus_ecore_native_mainloop(NULL);
+
+    if (ml && set_as_default) {
+        PyObject *func, *res;
+
+        if (!_dbus_bindings_module) {
+            PyErr_SetString(PyExc_ImportError, "_dbus_bindings not imported");
+            Py_DECREF(ml);
+            return NULL;
+        }
+
+        func = PyObject_GetAttrString(_dbus_bindings_module,
+                                      "set_default_main_loop");
+        if (!func) {
+            Py_DECREF(ml);
+            return NULL;
+        }
+
+        res = PyObject_CallFunctionObjArgs(func, ml, NULL);
+        Py_DECREF(func);
+        if (!res) {
+            Py_DECREF(ml);
+            return NULL;
+        }
+
+        Py_DECREF(res);
+    }
+
+    return ml;
+}
+
+static PyMethodDef module_functions[] = {
+    { "DBusEcoreMainLoop", (PyCFunction)dbus_ecore_main_loop,
+      METH_VARARGS | METH_KEYWORDS, DBusEcoreMainLoop__doc__ },
+    { NULL, NULL, 0, NULL }
+};
+
+static void
+module_cleanup(void)
+{
+    e_dbus_shutdown();
+    ecore_shutdown();
+}
+
+PyDoc_STRVAR(module_doc,
+"D-Bus python integration for Ecore main loop.\n");
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+__attribute__ ((visibility("default")))
+#endif
+
+PyMODINIT_FUNC
+initdbus_mainloop(void)
+{
+    PyObject *mod;
+
+    if (import_dbus_bindings("efl.dbus_mainloop") < 0) {
+        PyErr_SetString(PyExc_ImportError, "failed to import D-Bus bindings");
+        return;
+    }
+
+    mod = Py_InitModule3("efl.dbus_mainloop", module_functions, module_doc);
+    if (!mod) {
+        PyErr_SetString(PyExc_ImportError,
+                        "Py_InitModule3(\"efl.dbus_mainloop\") failed");
+        return;
+    }
+
+    ecore_init();
+    e_dbus_init();
+
+    Py_AtExit(module_cleanup);
+}
diff --git a/setup.py b/setup.py
index bac77cc..9202d63 100755
--- a/setup.py
+++ b/setup.py
@@ -120,6 +120,14 @@ else:
                             #extra_link_args = edbus_libs)
     #modules.append(edbus_ext)
 
+    # dbus mainloop integration
+    dbus_cflags, dbus_libs = pkg_config('DBus', 'dbus-python', "0.83.0")
+    dbus_ml_ext = Extension("efl.dbus_mainloop",
+                            ["efl/dbus_mainloop/module.c",
+                             "efl/dbus_mainloop/e_dbus.c"],
+                            extra_compile_args = dbus_cflags + ecore_cflags,
+                            extra_link_args = dbus_libs + ecore_libs)
+
     # Elementary
     elm_exts = [
         Extension("efl.elementary.actionslider", 
["efl/elementary/actionslider.pyx"]),
@@ -220,5 +228,5 @@ if __name__ == "__main__":
                 #"builder": (None, "coverage"),
             },
         },
-        ext_modules = cythonize(modules, include_path=["include"]),
+        ext_modules = cythonize(modules, include_path=["include"]) + 
[dbus_ml_ext],
     )
diff --git a/tests/dbus_mainloop/test-bt-list-handles.py 
b/tests/dbus_mainloop/test-bt-list-handles.py
new file mode 100755
index 0000000..8c11d81
--- /dev/null
+++ b/tests/dbus_mainloop/test-bt-list-handles.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+import sys
+import dbus
+from efl import dbus_mainloop
+from efl import ecore
+
+
+def print_remote_handles(adapter, bdaddr):
+    handles = [hex(int(h)) \
+               for h in list(adapter.GetRemoteServiceHandles(bdaddr, ""))]
+    print "Handles:", handles
+    ecore.idler_add(ecore.main_loop_quit)
+    return False
+
+
+if len(sys.argv) != 2:
+    print "USAGE: %s <bdaddr>" % sys.argv[0]
+    sys.exit(1)
+
+dbus_ml = dbus_mainloop.DBusEcoreMainLoop()
+bus = dbus.SystemBus(mainloop=dbus_ml);
+
+obj = bus.get_object("org.bluez", "/org/bluez/hci0")
+adapter = dbus.Interface(obj, "org.bluez.Adapter")
+
+ecore.idler_add(print_remote_handles, adapter, sys.argv[1])
+ecore.main_loop_begin()
diff --git a/tests/dbus_mainloop/test-bt-search-devices.py 
b/tests/dbus_mainloop/test-bt-search-devices.py
new file mode 100755
index 0000000..9736f52
--- /dev/null
+++ b/tests/dbus_mainloop/test-bt-search-devices.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+import dbus
+from efl import dbus_mainloop
+from efl import ecore
+
+
+def disc_started_signal():
+        print "Signal: DiscoveryStarted()"
+
+
+def rem_dev_found_signal(address, cls, rssi):
+        print "Signal: RemoteDeviceFound(%s, %s, %s)" % (address, cls, rssi)
+
+
+def rem_dev_name_signal(address, name):
+        print "Signal: RemoteNameUpdated(%s, %s)" % (address, name)
+
+
+def disc_completed_signal():
+        print "Signal: DiscoveryCompleted()"
+        ecore.idler_add(ecore.main_loop_quit)
+
+
+dbus_ml = dbus_mainloop.DBusEcoreMainLoop()
+bus = dbus.SystemBus(mainloop=dbus_ml)
+
+bus.add_signal_receiver(disc_started_signal,
+                        "DiscoveryStarted",
+                        "org.bluez.Adapter",
+                        "org.bluez",
+                        "/org/bluez/hci0")
+bus.add_signal_receiver(rem_dev_found_signal,
+                        "RemoteDeviceFound",
+                        "org.bluez.Adapter",
+                        "org.bluez",
+                        "/org/bluez/hci0")
+bus.add_signal_receiver(rem_dev_name_signal,
+                        "RemoteNameUpdated",
+                        "org.bluez.Adapter",
+                        "org.bluez",
+                        "/org/bluez/hci0")
+bus.add_signal_receiver(disc_completed_signal,
+                        "DiscoveryCompleted",
+                        "org.bluez.Adapter",
+                        "org.bluez",
+                        "/org/bluez/hci0")
+
+obj = bus.get_object("org.bluez", "/org/bluez/hci0")
+adapter = dbus.Interface(obj, "org.bluez.Adapter")
+
+adapter.DiscoverDevices()
+ecore.main_loop_begin()
diff --git a/tests/dbus_mainloop/test-signal-emitter.py 
b/tests/dbus_mainloop/test-signal-emitter.py
new file mode 100755
index 0000000..37b1732
--- /dev/null
+++ b/tests/dbus_mainloop/test-signal-emitter.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+
+import dbus
+import dbus.service
+from efl import dbus_mainloop
+from efl import ecore
+
+
+class TestObject(dbus.service.Object):
+    def __init__(self, conn, object_path="/com/example/TestService/object"):
+        dbus.service.Object.__init__(self, conn, object_path)
+
+    @dbus.service.signal("com.example.TestService")
+    def HelloSignal(self, message):
+        # The signal is emitted when this method exits
+        # You can have code here if you wish
+        pass
+
+    @dbus.service.method("com.example.TestService")
+    def emitHelloSignal(self):
+        #you emit signals by calling the signal"s skeleton method
+        self.HelloSignal("Hello")
+        return "Signal emitted"
+
+    @dbus.service.method("com.example.TestService",
+                         in_signature="", out_signature="")
+    def Exit(self):
+        ecore.idler_add(ecore.main_loop_quit)
+
+
+dbus_ml = dbus_mainloop.DBusEcoreMainLoop()
+session_bus = dbus.SessionBus(mainloop=dbus_ml)
+
+name = dbus.service.BusName("com.example.TestService", session_bus)
+obj = TestObject(session_bus)
+
+ecore.main_loop_begin()
diff --git a/tests/dbus_mainloop/test-signal-recipient.py 
b/tests/dbus_mainloop/test-signal-recipient.py
new file mode 100755
index 0000000..9a97e11
--- /dev/null
+++ b/tests/dbus_mainloop/test-signal-recipient.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+
+import dbus
+from efl import dbus_mainloop
+from efl import ecore
+
+
+def emit_signal(obj):
+    obj.emitHelloSignal(dbus_interface="com.example.TestService")
+    obj.Exit(dbus_interface="com.example.TestService")
+
+    ecore.idler_add(ecore.main_loop_quit)
+    return False
+
+
+def hello_signal_handler(hello_string):
+    print "Received signal (by connecting using remote " \
+          "object) and it says: %s" % hello_string
+
+
+def catchall_hello_signals_handler(hello_string):
+    print "Received a hello signal and it says: %s" % hello_string
+
+
+def catchall_testservice_interface_handler(hello_string, dbus_message):
+    print "com.example.TestService interface says %s " \
+          "when it sent signal %s" % (hello_string, dbus_message.get_member())
+
+
+dbus_ml = dbus_mainloop.DBusEcoreMainLoop()
+bus = dbus.SessionBus(mainloop=dbus_ml)
+
+obj = bus.get_object("com.example.TestService",
+                     "/com/example/TestService/object")
+obj.connect_to_signal("HelloSignal",
+                      hello_signal_handler,
+                      dbus_interface="com.example.TestService",
+                      arg0="Hello")
+
+bus.add_signal_receiver(catchall_hello_signals_handler,
+                        dbus_interface = "com.example.TestService",
+                        signal_name = "HelloSignal")
+bus.add_signal_receiver(catchall_testservice_interface_handler,
+                        dbus_interface = "com.example.TestService",
+                        message_keyword="dbus_message")
+
+ecore.timer_add(1.0, emit_signal, obj)
+ecore.main_loop_begin()
diff --git a/tests/dbus_mainloop/test-signal-simple.py 
b/tests/dbus_mainloop/test-signal-simple.py
new file mode 100755
index 0000000..b113fbb
--- /dev/null
+++ b/tests/dbus_mainloop/test-signal-simple.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+import dbus
+from efl import dbus_mainloop
+from efl import ecore
+
+
+def print_name_owner_changed(obj, old, new):
+    print "Obj = '%s', Old = '%s', New = '%s'" % (obj, old, new)
+
+
+dbus_ml = dbus_mainloop.DBusEcoreMainLoop()
+bus = dbus.SystemBus(mainloop=dbus_ml)
+
+bus.add_signal_receiver(print_name_owner_changed, "NameOwnerChanged")
+ecore.main_loop_begin()

-- 

------------------------------------------------------------------------------
Minimize network downtime and maximize team effectiveness.
Reduce network management and security costs.Learn how to hire 
the most talented Cisco Certified professionals. Visit the 
Employer Resources Portal
http://www.cisco.com/web/learning/employer_resources/index.html

Reply via email to