[GnomeMeeting-devel-list] DBUS component for gnomemeeting
- From: PUYDT Julien <jpuydt free fr>
- To: GnomeMeeting Devel Liste <gnomemeeting-devel-list gnome org>
- Subject: [GnomeMeeting-devel-list] DBUS component for gnomemeeting
- Date: Sun, 22 Aug 2004 13:23:34 +0200
Hi,
this is a new snapshot of my little work on a DBUS component for
gnomemeeting.
The patch needs ./configure --enable-dbus to be enabled, and now
requires the version 0.22 of DBUS. It shouldn't change gnomemeeting's
behaviour in any way.
The remote control (I attach the Makefile I use to build it):
* detects if gnomemeeting is running (both at startup and during
runtime: its title is "Not running" when gnomemeeting, well, isn't
running);
* reflects the state of gnomemeeting in its title bar (Standy, Calling,
Connected, Called, or even Bogus, if something evil occurs);
* finally its buttons allow to update gnomemeeting's status (only "Not
running" is automatic for now), stop a call or launch a new call to the
address in the text entry.
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.
Of course, I'm still interested in getting feedback (problems,
congratulations, ideas of things to remote control through DBUS, ...).
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 11:37:40.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"
+ 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 11:38:28.000000000 +0200
@@ -0,0 +1,339 @@
+#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 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);
+
+
+/* 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,
+};
+
+
+/* declaration of the private part of the GObject */
+
+
+struct _DBusComponent
+{
+ GObject parent;
+
+ DBusConnection *connection;
+ gboolean is_first_instance;
+};
+
+
+struct _DBusComponentClass
+{
+ GObjectClass parent;
+};
+
+
+/* Implementation of the GObject */
+
+
+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;
+}
+
+
+DBusComponent*
+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 result;
+}
+
+
+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));
+}
+
+
+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));
+}
+
+
+void
+dbus_component_init (DBusComponent *self)
+{
+ self->connection = NULL;
+ self->is_first_instance = FALSE;
+}
+
+
+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;
+}
+
+
+gboolean
+dbus_component_is_first_instance (DBusComponent *object)
+{
+ g_return_val_if_fail (object != NULL, FALSE);
+
+ return object->is_first_instance;
+}
+
+
+void
+dbus_component_call_address (DBusComponent *object,
+ gchar *address)
+{
+ DBusMessage *message = NULL;
+
+ g_return_if_fail (object != NULL);
+
+ 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 (object->connection, message, NULL);
+ dbus_connection_flush (object->connection);
+ }
+}
+
+
+/* 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;
+ }
+
+ 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 ();
+}
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 11:37:40.000000000 +0200
@@ -0,0 +1,62 @@
+#ifndef _DBUS_COMPONENT_H_
+#define _DBUS_COMPONENT_H_
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+
+#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;
+
+
+GType dbus_component_get_type();
+
+
+DBusComponent* dbus_component_new();
+
+
+void dbus_component_dispose (DBusComponent *self);
+
+
+void dbus_component_finalize (DBusComponent *self);
+
+
+void dbus_component_init (DBusComponent *self);
+
+
+void dbus_component_class_init (DBusComponentClass *klass);
+
+
+gboolean dbus_component_is_first_instance (DBusComponent *object);
+
+
+void dbus_component_call_address (GObject *, gchar *);
+
+
+G_END_DECLS
+
+#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 11:37:40.000000000 +0200
@@ -54,6 +54,7 @@
#include "main_window.h"
#include "toolbar.h"
#include "misc.h"
+#include "dbus_component.h"
#include "history-combo.h"
#include "dialog.h"
@@ -148,6 +149,8 @@
gtk_widget_destroy (gm);
if (druid_window)
gtk_widget_destroy (druid_window);
+ if (dbus_component)
+ g_object_unref (G_OBJECT (dbus_component));
}
@@ -446,6 +449,8 @@
gw->docklet = gnomemeeting_tray_new ();
gw->tray_popup_menu = gnomemeeting_tray_init_menu (gw->docklet);
#endif
+ dbus_component = dbus_component_new ();
+
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 11:37:41.000000000 +0200
@@ -41,7 +41,7 @@
#include "common.h"
#include "endpoint.h"
-
+#include "dbus_component.h"
/**
* COMMON NOTICE: The Application must be initialized with Init after its
@@ -250,6 +250,9 @@
GtkWidget *druid_window;
GtkWidget *prefs_window;
+ /* other things */
+ DBusComponent *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 11:37:41.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 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 update_status_button_cb (GtkButton *button, gpointer user_data);
static void quit_button_cb (GtkButton *button, gpointer user_data);
/* 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_button_cb (NULL, my_data);
return DBUS_HANDLER_RESULT_HANDLED;
}
}
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
update_status_button_cb (GtkButton *button, gpointer user_data)
{
struct needed_data *my_data = (struct needed_data *)user_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);
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
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 *update_status_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);
update_status_button = gtk_button_new_with_label ("Update");
g_signal_connect (G_OBJECT (update_status_button), "clicked",
G_CALLBACK (update_status_button_cb), my_data);
gtk_box_pack_start (GTK_BOX (hbox), update_status_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);
if (!dbus_connection_add_filter (my_data->connection,
filter_func,
my_data, NULL)) {
g_print ("Couldn't add filter\n");
exit (-1);
}
update_status_button_cb (NULL, 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]