Re: [GnomeMeeting-devel-list] DBUS component for gnomemeeting



Le dim, 22/08/2004 à 13:23 +0200, PUYDT Julien a écrit :
> My future goals are:
> * reflect the state of gnomemeeting automatically;
> * get the name, url and application name of the remote user when in a
> call.

Done. [name, url and app printed in the console of gm_remote!]

Notice that I connected to "h323:turing:1740", and got
"h323:192.168.0.1" as remote address in the console ; that is bad for
two reasons:
* the port got lost: that address can't be used to call back right after
the call (the much too famous "Oops, I forgot to tell him/her that ..."
situation);
* the explicit address has been lost in favor of the ip, which means
that address is worthless for an addressbook.
==> Damien, is it something we can fix?

Snark
diff -urN gnomemeeting/configure.in gnomemeeting.patched/configure.in
--- gnomemeeting/configure.in	2004-08-13 10:56:21.000000000 +0200
+++ gnomemeeting.patched/configure.in	2004-08-22 19:27:48.000000000 +0200
@@ -406,6 +406,25 @@
 AC_CHECK_TYPES(xmlSAXHandlerV1,,, [#include <libxml/SAX.h>])
 CPPFLAGS="$CPPFLAGS_save"
 
+dnl #########################################################################
+dnl   Check for DBUS
+dnl #########################################################################
+AC_ARG_ENABLE(dbus,
+	[  --enable-dbus       Enable the DBUS component.],
+	enable_dbus=yes, enable_dbus=no)
+
+AC_MSG_CHECKING(whether the DBUS component should be compiled in)
+if test x"${enable_dbus}" = xyes ; then
+   AC_MSG_RESULT([yes])
+else
+   AC_MSG_RESULT([no])
+fi
+
+if test x"${enable_dbus}" = xyes ; then
+   PKG_CHECK_MODULES(DBUS,  dbus-1 = 0.22 dbus-glib-1 = 0.22)
+   GNOMEMEETING_CFLAGS="$GNOMEMEETING_CFLAGS $DBUS_CFLAGS -DHAS_DBUS"
+   GNOMEMEETING_LIBS="$GNOMEMEETING_LIBS $DBUS_LIBS"
+fi
 
 dnl ###########################################################################
 dnl  The various CFLAGS are merged into GNOMEMEETING_CFLAGS and 
diff -urN gnomemeeting/src/dbus_component.cpp gnomemeeting.patched/src/dbus_component.cpp
--- gnomemeeting/src/dbus_component.cpp	1970-01-01 01:00:00.000000000 +0100
+++ gnomemeeting.patched/src/dbus_component.cpp	2004-08-22 19:28:05.000000000 +0200
@@ -0,0 +1,480 @@
+#include "dbus_component.h"
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "gnomemeeting.h"
+#include "endpoint.h"
+
+
+/* declaration of the GObject */
+
+
+#define DBUS_COMPONENT_TYPE dbus_component_get_type ()
+
+
+#define DBUS_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+                             DBUS_COMPONENT_TYPE, DBusComponent))
+
+
+#define DBUS_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
+                                     DBUS_COMPONENT_TYPE, DBusComponentClass))
+
+
+#define IS_DBUS_COMPONENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
+			        DBUS_COMPONENT_TYPE))
+
+
+#define DBUS_COMPONENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+                                       DBUS_COMPONENT_TYPE, \
+                                       DBusComponentClass)) 
+
+
+typedef struct _DBusComponent DBusComponent;
+
+
+typedef struct _DBusComponentClass DBusComponentClass;
+
+
+struct _DBusComponent
+{
+  GObject parent;
+
+  DBusConnection *connection;
+  gboolean is_first_instance;
+};
+
+
+struct _DBusComponentClass
+{
+  GObjectClass parent;
+};
+
+
+static GType dbus_component_get_type();
+
+
+static void dbus_component_dispose (GObject *self);
+
+
+static void dbus_component_finalize (GObject *self);
+
+
+static void dbus_component_init (DBusComponent *self);
+
+
+static void dbus_component_class_init (DBusComponentClass *klass);
+
+
+/* declaration of the DBUS helper functions */
+
+
+static DBusHandlerResult filter_func(DBusConnection *connection,
+				     DBusMessage *message,
+				     void *user_data);
+
+
+
+static DBusHandlerResult path_message_func (DBusConnection *connection,
+					    DBusMessage *message,
+					    void *user_data);
+
+
+static void handle_call_address_message (DBusConnection *connection,
+					 DBusMessage *message);
+
+
+static void handle_get_state_message (DBusConnection *connection,
+				      DBusMessage *message);
+
+
+static void handle_end_call_message (DBusConnection *connection,
+				     DBusMessage *message);
+
+
+static void handle_get_connections_message (DBusConnection *connection,
+					    DBusMessage *message);
+
+
+static void handle_get_connection_info_message (DBusConnection *connection,
+						DBusMessage *message);
+
+
+/* definition of some helper DBUS-related data */
+
+#define OBJECT "/org/gnomemeeting/Endpoint"
+
+
+#define INTERFACE "org.gnomemeeting.CallService"
+
+
+#define SERVICE "org.gnomemeeting.CallService"
+
+
+static DBusObjectPathVTable call_vtable = {
+  NULL,
+  path_message_func,
+  NULL,
+};
+
+
+/* Implementation of the GObject */
+
+
+static GType
+dbus_component_get_type()
+{
+  static GType my_type = 0; 
+  
+  if (!my_type) {
+    static const GTypeInfo my_info = {
+      sizeof (DBusComponentClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) dbus_component_class_init,
+      NULL,
+      NULL,
+      sizeof(DBusComponent),
+      0,
+      (GInstanceInitFunc) dbus_component_init
+    };
+    my_type = g_type_register_static (G_TYPE_OBJECT ,
+				      "DBusComponent", &my_info, 
+				      (GTypeFlags)0);
+  }
+  
+  return my_type;
+}
+
+
+static void
+dbus_component_dispose (GObject *object)
+{
+  DBusComponent *self = NULL;
+  GObjectClass *parent_class = NULL;
+
+  g_return_if_fail (IS_DBUS_COMPONENT (object));
+
+  self = DBUS_COMPONENT (object);
+
+  if (self->connection != NULL) {
+    dbus_connection_disconnect (self->connection);
+    dbus_connection_unref (self->connection);
+    self->connection = NULL;
+  }
+  
+  parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (DBUS_COMPONENT_GET_CLASS (self)));
+
+  parent_class->dispose (G_OBJECT(self));
+}
+
+
+static void
+dbus_component_finalize (GObject *object)
+{
+  DBusComponent *self = NULL;
+  GObjectClass *parent_class = NULL;
+
+  g_return_if_fail (IS_DBUS_COMPONENT (object));
+
+  self = DBUS_COMPONENT (object);
+
+  parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (DBUS_COMPONENT_GET_CLASS (self)));
+
+  parent_class->finalize (G_OBJECT(self));
+}
+
+
+static void
+dbus_component_init (DBusComponent *self)
+{
+  self->connection = NULL;
+  self->is_first_instance = FALSE;
+}
+
+
+static void dbus_component_class_init (DBusComponentClass *klass)
+{
+  GObjectClass *object_klass = G_OBJECT_CLASS (klass);
+      
+  object_klass->dispose = dbus_component_dispose;
+
+  object_klass->finalize = dbus_component_finalize;
+}
+
+
+/* implementation of the internal helpers */
+
+
+static DBusHandlerResult
+filter_func(DBusConnection *connection,
+            DBusMessage *message,
+            void *user_data)
+{
+  DBusComponent *object = NULL;
+
+  g_return_val_if_fail (user_data != NULL,
+			DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+  object = DBUS_COMPONENT (user_data);
+
+  g_return_val_if_fail (object->connection == connection,
+			DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
+                              "Disconnected"))
+    {
+      dbus_connection_disconnect (object->connection);
+      object->connection = NULL;
+      object->is_first_instance = FALSE;
+
+      return DBUS_HANDLER_RESULT_HANDLED;
+    }
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static DBusHandlerResult
+path_message_func (DBusConnection *connection,
+                   DBusMessage *message,
+                   void *user_data)
+{
+  DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+  if (dbus_message_is_method_call (message,
+                                   SERVICE,
+                                   "Call")) {
+    handle_call_address_message (connection, message);
+    result = DBUS_HANDLER_RESULT_HANDLED;
+  }
+  else if (dbus_message_is_method_call (message,
+					SERVICE,
+					"GetState")) {
+    handle_get_state_message (connection, message);
+    result = DBUS_HANDLER_RESULT_HANDLED;
+  }
+  else if (dbus_message_is_method_call (message,
+					SERVICE,
+					"EndCall")) {
+    handle_end_call_message (connection, message);
+    result = DBUS_HANDLER_RESULT_HANDLED;
+  }
+  else if (dbus_message_is_method_call (message,
+					SERVICE,
+					"GetConnections")) {
+    handle_get_connections_message (connection, message);
+    result = DBUS_HANDLER_RESULT_HANDLED;
+  }
+  else if (dbus_message_is_method_call (message,
+					SERVICE,
+					"GetConnectionInfo")) {
+    handle_get_connection_info_message (connection, message);
+    result = DBUS_HANDLER_RESULT_HANDLED;
+  }
+  
+  return result;
+}
+
+
+static void
+handle_call_address_message (DBusConnection *connection,
+			     DBusMessage *message)
+{
+  gchar *address = NULL;
+
+  if (dbus_message_get_args (message, NULL,
+			     DBUS_TYPE_STRING, &address,
+			     DBUS_TYPE_INVALID)) {
+    GnomeMeeting::Process ()->Connect (address); /* FIXME! */
+  }
+}
+
+
+static void
+handle_get_state_message (DBusConnection *connection,
+			  DBusMessage *message)
+{
+  DBusMessage *reply = NULL;
+  gchar *state = NULL;
+  GMH323EndPoint *ep = NULL;
+
+  ep = GnomeMeeting::Process ()->Endpoint ();
+  
+  reply = dbus_message_new_method_return (message);
+
+  switch (ep->GetCallingState ()) {
+  case GMH323EndPoint::Standby:
+    state = "Standby";
+    break;
+  case GMH323EndPoint::Calling:
+    state = "Calling";
+    break;
+  case GMH323EndPoint::Connected:
+    state  = "Connected";
+    break;
+  case GMH323EndPoint::Called:
+    state = "Called";
+    break;
+  default:
+    state = "Bogus";
+  }
+
+  if (dbus_message_append_args (reply,
+				DBUS_TYPE_STRING, state,
+				DBUS_TYPE_INVALID)) {
+    (void)dbus_connection_send (connection, reply, NULL);
+    dbus_connection_flush (connection);
+  }
+}
+
+
+static void
+handle_end_call_message (DBusConnection *connection,
+			 DBusMessage *message)
+{
+  GnomeMeeting::Process ()->Disconnect ();
+}
+
+
+static void
+handle_get_connections_message (DBusConnection *connection,
+				DBusMessage *message)
+{
+  DBusMessage *reply = NULL;
+  const char *call_token = NULL;
+  GMH323EndPoint *ep = NULL;
+
+  ep = GnomeMeeting::Process ()->Endpoint ();
+  
+  reply = dbus_message_new_method_return (message);
+  call_token = (const char *)ep->GetCurrentCallToken ();
+  if (dbus_message_append_args (reply,
+				DBUS_TYPE_STRING, call_token,
+				DBUS_TYPE_INVALID)) {
+    (void)dbus_connection_send (connection, reply, NULL);
+    dbus_connection_flush (connection);
+  }
+}
+
+
+static void
+handle_get_connection_info_message (DBusConnection *connection,
+				    DBusMessage *message)
+{
+  DBusMessage *reply = NULL;
+  const char *call_token = NULL;
+  GMH323EndPoint *ep = NULL;
+  H323Connection *h323connection = NULL;
+  gchar *name = NULL;
+  gchar *url = NULL;
+  gchar *app = NULL;
+
+  ep = GnomeMeeting::Process ()->Endpoint ();
+
+  if (dbus_message_get_args (message, NULL,
+			     DBUS_TYPE_STRING, &call_token,
+			     DBUS_TYPE_INVALID)) {  
+    h323connection = ep->FindConnectionWithLock((PString)call_token);
+    if (h323connection) {
+      ep->GetRemoteConnectionInfo (*h323connection, name, app, url);
+      h323connection->Unlock ();
+    }
+    reply = dbus_message_new_method_return (message);
+    if (dbus_message_append_args (reply,
+				  DBUS_TYPE_STRING, name,
+				  DBUS_TYPE_STRING, url,
+				  DBUS_TYPE_STRING, app,
+				  DBUS_TYPE_INVALID)) {
+      (void)dbus_connection_send (connection, reply, NULL);
+      dbus_connection_flush (connection);
+      dbus_message_unref (reply);
+    }
+  }
+}
+
+
+/* implementation of the externally-visible api */
+
+
+GObject*
+dbus_component_new()
+{
+  DBusComponent *result = NULL;
+  gboolean ok = TRUE;
+
+  result = DBUS_COMPONENT (g_object_new (DBUS_COMPONENT_TYPE, NULL));
+
+  result->connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+  dbus_connection_setup_with_g_main (result->connection, NULL);
+
+  ok = (result->connection != NULL);
+
+  if (ok)
+    ok = dbus_connection_add_filter (result->connection, 
+				     filter_func,
+				     result, NULL);
+
+  if (ok)
+    ok = dbus_connection_register_object_path (result->connection, OBJECT,
+					       &call_vtable, NULL);
+
+  if (!ok) 
+    result->is_first_instance = FALSE;
+
+  if (ok)
+    ok = (dbus_bus_acquire_service (result->connection, 
+				    SERVICE, 0, NULL) >= 0);
+
+  return G_OBJECT (result);
+}
+
+
+gboolean
+dbus_component_is_first_instance (GObject *object)
+{
+  g_return_val_if_fail (IS_DBUS_COMPONENT (object), FALSE);
+
+  return DBUS_COMPONENT (object)->is_first_instance;
+}
+
+
+void
+dbus_component_call_address (GObject *object, 
+			     gchar *address)
+{
+  DBusMessage *message = NULL;
+
+  g_return_if_fail (IS_DBUS_COMPONENT (object));
+  
+  message = dbus_message_new_method_call (SERVICE, OBJECT, INTERFACE, "Call");
+
+  dbus_message_set_no_reply (message, TRUE);
+  
+  if (dbus_message_append_args (message,
+				DBUS_TYPE_STRING, address,
+				DBUS_TYPE_INVALID)) {
+    
+    (void)dbus_connection_send (DBUS_COMPONENT (object)->connection,
+				message, NULL);
+    dbus_connection_flush (DBUS_COMPONENT (object)->connection);
+  }
+}
+
+void
+dbus_component_state_changed (GObject *object)
+{
+  DBusMessage *message = NULL;
+  DBusConnection *connection = NULL;
+
+  if (object == NULL) return; /* the endpoint calls too early at launchtime! */
+
+  g_return_if_fail (IS_DBUS_COMPONENT (object));
+
+  message = dbus_message_new_signal (OBJECT, INTERFACE, "StateChanged");
+  connection = DBUS_COMPONENT (object)->connection;
+  (void)dbus_connection_send (connection, message, NULL);
+  dbus_connection_flush (connection);
+
+}
diff -urN gnomemeeting/src/dbus_component.h gnomemeeting.patched/src/dbus_component.h
--- gnomemeeting/src/dbus_component.h	1970-01-01 01:00:00.000000000 +0100
+++ gnomemeeting.patched/src/dbus_component.h	2004-08-22 19:27:48.000000000 +0200
@@ -0,0 +1,22 @@
+#ifndef _DBUS_COMPONENT_H_
+#define _DBUS_COMPONENT_H_
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+GObject *dbus_component_new();
+
+
+gboolean dbus_component_is_first_instance (GObject *object);
+
+
+void dbus_component_call_address (GObject *, gchar *);
+
+
+void dbus_component_state_changed (GObject *object);
+
+G_END_DECLS
+
+#endif
diff -urN gnomemeeting/src/endpoint.cpp gnomemeeting.patched/src/endpoint.cpp
--- gnomemeeting/src/endpoint.cpp	2004-08-18 21:04:43.000000000 +0200
+++ gnomemeeting.patched/src/endpoint.cpp	2004-08-22 19:27:48.000000000 +0200
@@ -56,6 +56,9 @@
 #include "main_window.h"
 #include "calls_history_window.h"
 #include "stats_drawing_area.h"
+#ifdef HAS_DBUS
+#include "dbus_component.h"
+#endif
 
 #include "dialog.h"
 #include "gm_conf.h"
@@ -289,6 +292,11 @@
   PWaitAndSignal m(cs_access_mutex);
   
   calling_state = i;
+
+#ifdef HAS_DBUS
+  dbus_component_state_changed (GnomeMeeting::Process ()->GetDBusComponent ());
+#endif
+
 }
 
 
diff -urN gnomemeeting/src/gnomemeeting.cpp gnomemeeting.patched/src/gnomemeeting.cpp
--- gnomemeeting/src/gnomemeeting.cpp	2004-08-18 21:04:43.000000000 +0200
+++ gnomemeeting.patched/src/gnomemeeting.cpp	2004-08-22 19:27:48.000000000 +0200
@@ -54,6 +54,9 @@
 #include "main_window.h"
 #include "toolbar.h"
 #include "misc.h"
+#ifdef HAS_DBUS
+#include "dbus_component.h"
+#endif
 
 #include "history-combo.h"
 #include "dialog.h"
@@ -148,6 +151,8 @@
     gtk_widget_destroy (gm);
   if (druid_window)
     gtk_widget_destroy (druid_window);
+  if (dbus_component)
+    g_object_unref (dbus_component);
 
 }
 
@@ -391,6 +396,13 @@
 }
 
 
+GObject *
+GnomeMeeting::GetDBusComponent ()
+{
+  return dbus_component;
+}
+
+
 void GnomeMeeting::Main ()
 {
 }
@@ -446,6 +458,12 @@
   gw->docklet = gnomemeeting_tray_new ();
   gw->tray_popup_menu = gnomemeeting_tray_init_menu (gw->docklet);
 #endif
+#ifdef HAS_DBUS
+  dbus_component = dbus_component_new ();
+#else
+  dbus_component = NULL;
+#endif
+
   gm_main_window_new (gw);
 
 
diff -urN gnomemeeting/src/gnomemeeting.h gnomemeeting.patched/src/gnomemeeting.h
--- gnomemeeting/src/gnomemeeting.h	2004-08-18 21:04:43.000000000 +0200
+++ gnomemeeting.patched/src/gnomemeeting.h	2004-08-22 19:27:48.000000000 +0200
@@ -42,7 +42,6 @@
 #include "common.h"
 #include "endpoint.h"
 
-
 /**
  * COMMON NOTICE: The Application must be initialized with Init after its
  * creation.
@@ -146,6 +145,13 @@
   GtkWidget *GetHistoryWindow ();
 
   
+  /* DESCRIPTION  : /
+   * BEHAVIOR     : Returns the DBUS component
+   * PRE          : /
+   */
+  GObject *GetDBusComponent ();
+  
+
   /* Needed for PProcess */
   void Main();
 
@@ -223,7 +229,7 @@
    */
   PStringArray GetVideoPlugins ();
   
-  
+
  private:
   GMH323EndPoint *endpoint;
   PThread *url_handler;
@@ -250,6 +256,9 @@
   GtkWidget *druid_window;
   GtkWidget *prefs_window;
 
+  /* other things */
+  GObject *dbus_component;
+
   static GnomeMeeting *GM;
 };
 
diff -urN gnomemeeting/src/Makefile.am gnomemeeting.patched/src/Makefile.am
--- gnomemeeting/src/Makefile.am	2004-08-20 15:33:08.000000000 +0200
+++ gnomemeeting.patched/src/Makefile.am	2004-08-22 19:27:48.000000000 +0200
@@ -57,7 +57,9 @@
 	lid.cpp			\
 	lid.h			\
 	addressbook_window.cpp	\
-	addressbook_window.h
+	addressbook_window.h	\
+	dbus_component.h	\
+	dbus_component.cpp
 
 if ! DISABLE_GNOME
 gnomemeeting_SOURCES += bonobo_component.cpp bonobo_component.h
#include <gtk/gtk.h>
#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>

#define OBJECT "/org/gnomemeeting/Endpoint"
#define INTERFACE "org.gnomemeeting.CallService"
#define SERVICE "org.gnomemeeting.CallService"

/* declarations */


struct needed_data {
  DBusConnection *connection;
  GtkWidget *window;
  GtkWidget *entry;
};


static void update_status (struct needed_data *);


static void print_connections_info (struct needed_data *);


static void print_connection_info (gpointer, gpointer);


static DBusHandlerResult filter_func(DBusConnection *connection,
				     DBusMessage *message,
				     void *user_data);

static void connect_button_cb (GtkButton *button,
			       gpointer user_data);


static void disconnect_button_cb (GtkButton *button,
				  gpointer user_data);


static void quit_button_cb (GtkButton *button, gpointer user_data);


/* implementation of the helper functions */

static void
update_status (struct needed_data *my_data)
{
  DBusMessage *message = NULL;
  DBusMessage *reply = NULL;
  DBusPendingCall *call = NULL;
  gchar *title = NULL;

  if (dbus_bus_service_exists (my_data->connection, SERVICE, NULL)) {
    
    message = dbus_message_new_method_call (SERVICE, OBJECT, 
					    INTERFACE, "GetState");
    dbus_message_set_no_reply (message, FALSE);
    (void)dbus_connection_send_with_reply (my_data->connection, message,
					   &call, -1);
    dbus_connection_flush (my_data->connection);
    
    dbus_pending_call_block (call);
    reply = dbus_pending_call_get_reply (call);
    if (dbus_message_get_args (reply, NULL,
			       DBUS_TYPE_STRING, &title,
			       DBUS_TYPE_INVALID)) {
      gtk_window_set_title (GTK_WINDOW (my_data->window), title);
      if (strcmp (title, "Connected") == 0)
	print_connections_info (my_data);
      g_free (title);
    }
    dbus_message_unref (message);
    dbus_message_unref (reply);
    dbus_pending_call_unref (call);
  }
  else
    gtk_window_set_title (GTK_WINDOW (my_data->window), "Not running");
 
}


static void
print_connections_info (struct needed_data *my_data)
{
  DBusMessage *message = NULL;
  DBusMessage *reply = NULL;
  DBusMessageIter iter;
  DBusPendingCall *call = NULL;
  GSList *connections = NULL;
  gchar *call_token = NULL;
  int arg_type = 0;
  
  message = dbus_message_new_method_call (SERVICE, OBJECT,
					  INTERFACE, "GetConnections");
  dbus_message_set_no_reply (message, FALSE);
  (void)dbus_connection_send_with_reply (my_data->connection, message,
					 &call, -1);
  dbus_connection_flush (my_data->connection);
  dbus_pending_call_block (call);
  
  reply = dbus_pending_call_get_reply (call);
  dbus_message_iter_init (reply, &iter);

  do {
    arg_type = dbus_message_iter_get_arg_type (&iter);
    
    if (arg_type != DBUS_TYPE_STRING)
      break;
    
    call_token = g_strdup (dbus_message_iter_get_string (&iter));
    connections = g_slist_prepend (connections, (gpointer)call_token);

  } while (dbus_message_iter_next (&iter));

  dbus_message_unref (message);
  dbus_message_unref (reply);
  dbus_pending_call_unref (call);
  
  g_slist_foreach (connections, (GFunc)print_connection_info, (gpointer)my_data);
  g_slist_foreach (connections, (GFunc)g_free, NULL);
  g_slist_free (connections);
}


static void
print_connection_info (gpointer p_call_token, gpointer p_my_data)
{
  gchar *call_token = (char *)p_call_token;
  struct needed_data *my_data = (struct needed_data *)p_my_data;
  DBusMessage *message = NULL;
  DBusMessage *reply = NULL;
  DBusMessageIter iter;
  DBusPendingCall *call = NULL;
  char *name = NULL;
  char *url = NULL;
  char *app = NULL;

  message = dbus_message_new_method_call (SERVICE, OBJECT,
					  INTERFACE, "GetConnectionInfo");
  (void)dbus_message_append_args (message,
				  DBUS_TYPE_STRING, call_token,
				  DBUS_TYPE_INVALID);
  dbus_message_set_no_reply (message, FALSE);
  (void)dbus_connection_send_with_reply (my_data->connection, message,
					 &call, -1);
  dbus_connection_flush (my_data->connection);
  dbus_pending_call_block (call);
  reply = dbus_pending_call_get_reply (call);
  if (dbus_message_get_args (reply, NULL,
			     DBUS_TYPE_STRING, &name,
			     DBUS_TYPE_STRING, &url,
			     DBUS_TYPE_STRING, &app,
			     DBUS_TYPE_INVALID)) {
    g_print ("Talking with \"%s\" at \"%s\" using \"%s\"\n", name, url, app);
    g_free (name);
    g_free (url);
    g_free (app);
  }
  dbus_message_unref (message);
  dbus_message_unref (reply);
  dbus_pending_call_unref (call);
}

/* implementation of the dbus callbacks */


static DBusHandlerResult
filter_func(DBusConnection *connection,
            DBusMessage *message,
            void *user_data)
{
  struct needed_data *my_data = (struct needed_data *)user_data;
  char *str = NULL;

  if (dbus_message_is_signal (message,
                              DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
                              "Disconnected"))
    {
      g_print ("Disconnected\n");
      dbus_connection_disconnect (connection);
      exit (-1);
      return DBUS_HANDLER_RESULT_HANDLED;
    }
  else if (dbus_message_is_signal (message,
				   DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
				   "ServiceCreated")
	   || dbus_message_is_signal (message,
				      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
				      "ServiceDeleted")) {
    dbus_message_get_args (message,
			   NULL,
			   DBUS_TYPE_STRING, &str,
			   DBUS_TYPE_INVALID);
    if (strcmp (str, SERVICE) == 0) {
      update_status (my_data);
      return DBUS_HANDLER_RESULT_HANDLED;
    }
  }
  else if (dbus_message_is_signal (message,
				   INTERFACE,
				   "StateChanged")) {
    update_status (my_data);
  }

  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}



/* implementation of the gtk callbacks */


static void
connect_button_cb (GtkButton *button, gpointer user_data)
{
  struct needed_data *my_data = (struct needed_data *)user_data;
  DBusMessage *message = NULL;

  message = dbus_message_new_method_call (SERVICE, OBJECT, 
					  INTERFACE, "Call");
  (void)dbus_message_append_args (message,
				  DBUS_TYPE_STRING,
				  gtk_entry_get_text (GTK_ENTRY (my_data->entry)),
				  DBUS_TYPE_INVALID);
  dbus_message_set_no_reply (message, TRUE);
  (void)dbus_connection_send (my_data->connection, message,NULL);
  dbus_connection_flush (my_data->connection);
  dbus_message_unref (message);
}


static void
disconnect_button_cb (GtkButton *button, gpointer user_data)
{
  struct needed_data *my_data = (struct needed_data *)user_data;
  DBusMessage *message = NULL;

  message = dbus_message_new_method_call (SERVICE, OBJECT, 
					  INTERFACE, "EndCall");
  dbus_message_set_no_reply (message, TRUE);
  (void)dbus_connection_send (my_data->connection, message, NULL);
  dbus_connection_flush (my_data->connection);
  dbus_message_unref (message);
}


static void
quit_button_cb (GtkButton *button, gpointer user_data)
{
  gtk_main_quit ();
}


/* the real stuff */


int main (int argc,
	  char *argv[])
{
  struct needed_data *my_data = NULL;
  GtkWidget *window = NULL;
  GtkWidget *vbox = NULL;
  GtkWidget *connect_button = NULL;
  GtkWidget *disconnect_button = NULL;
  GtkWidget *quit_button = NULL;
  GtkWidget *hbox = NULL;
  GtkWidget *entry = NULL;

  gtk_set_locale ();

  gtk_init (&argc, &argv);

  my_data = g_new0 (struct needed_data, 1);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  g_signal_connect (window, "delete-event",
                    G_CALLBACK (gtk_false), NULL);
  g_signal_connect (window, "destroy",
		    G_CALLBACK (gtk_main_quit), NULL);

  vbox = gtk_vbox_new (TRUE, 2);
  gtk_container_add (GTK_CONTAINER (window), vbox);

  entry = gtk_entry_new ();
  gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (entry), TRUE, TRUE, 2);

  hbox = gtk_hbox_new (TRUE, 2);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 2);

  connect_button = gtk_button_new_with_label ("Connect");
  g_signal_connect (G_OBJECT (connect_button), "clicked",
		    G_CALLBACK (connect_button_cb), my_data);
  gtk_box_pack_start (GTK_BOX (hbox), connect_button, TRUE, TRUE, 2);

  disconnect_button = gtk_button_new_with_label ("Disconnect");
  g_signal_connect (G_OBJECT (disconnect_button), "clicked",
		    G_CALLBACK (disconnect_button_cb), my_data);
  gtk_box_pack_start (GTK_BOX (hbox), disconnect_button, TRUE, TRUE, 2);

  quit_button = gtk_button_new_with_label ("Quit");
  g_signal_connect (G_OBJECT (quit_button), "clicked",
		    G_CALLBACK (quit_button_cb), my_data);
  gtk_box_pack_start (GTK_BOX (hbox), quit_button, TRUE, TRUE, 2);

  gtk_widget_show_all (window);

  my_data->window = window;
  my_data->entry = entry;
  my_data->connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);

  dbus_bus_add_match (my_data->connection,
		      "type='signal',"
		      "sender='" DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "',"
		      "interface='" DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "'",
		      NULL);
  dbus_bus_add_match (my_data->connection,
		      "type='signal',"
		      "interface='" INTERFACE "'",
		      NULL);

  if (!dbus_connection_add_filter (my_data->connection,
                                   filter_func,
                                   my_data, NULL)) {
    g_print ("Couldn't add filter\n");
    exit (-1);
  }

  update_status (my_data);

  dbus_connection_setup_with_g_main (my_data->connection, NULL);

  gtk_main ();

  return 0;
}
TARGETS = gm_remote

CC=gcc
CFLAGS = `pkg-config --cflags dbus-glib-1 glib-2.0 gtk+-2.0`
LDFLAGS = `pkg-config --libs dbus-glib-1 glib-2.0 gtk+-2.0`

all: $(TARGETS)

%: %.o

clean:
	rm -f *~ $(TARGETS)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]