changeset 11171:ebb02ea3c789

[gaim-migrate @ 13272] Moved DBUS init call from gtkmain.c to core.c Reimplemented DBUS bindings mechamism to use low-level GLib bindings as described in my last blog entry. This way plugins can add new DBUS methods on the fly. Also wrote an example plugin that demonstrate how to do it. committer: Tailor Script <tailor@pidgin.im>
author Piotr Zielinski <zielaj>
date Sat, 30 Jul 2005 00:23:21 +0000
parents 0e9e2b923d09
children 1f0844561c7e
files configure.ac plugins/Makefile.am src/Makefile.am src/conversation.c src/core.c src/dbus-analyze-functions.py src/dbus-analyze-types.py src/dbus-maybe.h src/dbus-server.c src/dbus-server.h src/dbus-types.c src/dbus-types.h src/gtkmain.c src/signals.c
diffstat 14 files changed, 636 insertions(+), 478 deletions(-) [+]
line wrap: on
line diff
--- a/configure.ac	Fri Jul 29 13:38:00 2005 +0000
+++ b/configure.ac	Sat Jul 30 00:23:21 2005 +0000
@@ -324,11 +324,6 @@
 	[
 		enable_dbus=no
 	])
-	AC_PATH_PROG([DBUS_BINDING_TOOL], [dbus-binding-tool], [no])
-	if test x$DBUS_BINDING_TOOL = "xno" ; then
-		AC_MSG_WARN([dbus-binding-tool executable not found in your path])
-		enable_dbus=no
-	fi
 fi
 
 dnl  Why do we need python?  
--- a/plugins/Makefile.am	Fri Jul 29 13:38:00 2005 +0000
+++ b/plugins/Makefile.am	Sat Jul 30 00:23:21 2005 +0000
@@ -46,6 +46,7 @@
 	timestamp.la
 
 autorecon_la_SOURCES    = autorecon.c
+
 extplacement_la_SOURCES = extplacement.c
 gaimrc_la_SOURCES       = gaimrc.c
 history_la_SOURCES      = history.c
@@ -57,6 +58,22 @@
 statenotify_la_SOURCES  = statenotify.c
 timestamp_la_SOURCES    = timestamp.c
 
+if ENABLE_DBUS
+
+CLEANFILES              = dbus-example-bindings.c
+dbus_example_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS) $(DBUS_LIBS)
+dbus_example_la_SOURCES = dbus-example.c
+plugin_LTLIBRARIES     += dbus-example.la
+
+dbus-example-bindings.c: ../src/dbus-analyze-functions.py $(dbus_example_la_SOURCES) $(dbus_example_la_HEADERS)
+	cat $(dbus_example_la_SOURCES) $(dbus_example_la_HEADERS) | \
+	$(PYTHON) ../src/dbus-analyze-functions.py --export-only > $@
+
+$(dbus_example_la_OBJECTS) dbus-example.so: dbus-example-bindings.c
+
+
+endif # ENABLE_DBUS
+
 endif # PLUGINS
 
 EXTRA_DIST = \
@@ -78,7 +95,8 @@
 	-I$(top_srcdir)/src \
 	$(DEBUG_CFLAGS) \
 	$(GTK_CFLAGS) \
-	$(PLUGIN_CFLAGS)
+	$(PLUGIN_CFLAGS) \
+	$(DBUS_CFLAGS)
 
 #
 # This part allows people to build their own plugins in here.
--- a/src/Makefile.am	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/Makefile.am	Sat Jul 30 00:23:21 2005 +0000
@@ -146,37 +146,25 @@
 
 if ENABLE_DBUS
 
-dbus_sources = dbus-server.c dbus-useful.c
+dbus_sources  = dbus-server.c dbus-useful.c
 dbus_headers  = dbus-server.h dbus-useful.h dbus-maybe.h 
-dbus_exported_headers = dbus-useful.h dbus-define-api.h account.h blist.h connection.h conversation.h core.h roomlist.h
-
-CLEANFILES=dbus-auto-enum-types.h dbus-auto-enums.txt dbus-auto-structs.txt dbus-generated-code.c dbus-generated-code.xml dbus-service-all.xml dbus-server-bindings.c
-
-dbus-auto-structs.txt: dbus-analyze-types.py $(gaim_coreheaders)
-	cat $(gaim_coreheaders) | $(PYTHON) dbus-analyze-types.py --keyword=struct --list > $@
-
-dbus-auto-enums.txt: dbus-analyze-types.py $(gaim_coreheaders)
-	cat $(gaim_coreheaders) | $(PYTHON) dbus-analyze-types.py --keyword=enum --list > $@
 
-dbus-auto-enum-types.h: dbus-analyze-types.py $(gaim_coreheaders)
-	cat $(gaim_coreheaders) | $(PYTHON) dbus-analyze-types.py --keyword=struct --enum > $@
-
-dbus-generated-code.c: dbus-analyze-functions.py dbus-auto-structs.txt dbus-auto-enums.txt $(dbus_exported_headers)
-	cat $(dbus_exported_headers) | $(PYTHON) dbus-analyze-functions.py --mode=c > $@
+CLEANFILES    = dbus-bindings.c
 
-dbus-generated-code.xml: dbus-analyze-functions.py dbus-auto-structs.txt dbus-auto-enums.txt $(dbus_exported_headers)
-	cat $(dbus_exported_headers) | $(PYTHON) dbus-analyze-functions.py --mode=xml > $@
-
-dbus-service-all.xml: dbus-service.xml dbus-generated-code.xml dbus-service-end.xml
-	cat $^ > $@
-
-dbus-server-bindings.c: dbus-service-all.xml $(DBUS_BINDING_TOOL)
-	$(DBUS_BINDING_TOOL) --prefix=gaim_object --mode=glib-server --output=$@ $<
+dbus_exported = dbus-useful.h dbus-define-api.h account.h blist.h connection.h conversation.h core.h roomlist.h
 
 
-$(gaim_OBJECTS): dbus-auto-enum-types.h
+dbus-bindings.c: dbus-analyze-functions.py $(dbus_exported)
+	cat $(dbus_exported) | $(PYTHON) dbus-analyze-functions.py > $@
+
+dbus-server.$(OBJEXT): dbus-bindings.c 
 
-dbus-server.$(OBJEXT): dbus-server-bindings.c dbus-generated-code.c
+# dbus-types.c: dbus-analyze-types.py $(gaim_coreheaders)
+# 	cat $(gaim_coreheaders) | $(PYTHON) dbus-analyze-types.py --keyword=struct '--pattern=GAIM_DBUS_DEFINE_TYPE(%s)' > $@
+
+# dbus-types.h: dbus-analyze-types.py $(gaim_coreheaders)
+# 	cat $(gaim_coreheaders) | $(PYTHON) dbus-analyze-types.py --keyword=struct '--pattern=GAIM_DBUS_DECLARE_TYPE(%s)' > $@
+
 
 endif
 
--- a/src/conversation.c	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/conversation.c	Sat Jul 30 00:23:21 2005 +0000
@@ -875,6 +875,7 @@
 			gaim_buddy_icon_unref(conv->u.im->icon);
 		conv->u.im->icon = NULL;
 
+		GAIM_DBUS_UNREGISTER_POINTER(conv->u.im);
 		g_free(conv->u.im);
 		conv->u.im = NULL;
 
--- a/src/core.c	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/core.c	Sat Jul 30 00:23:21 2005 +0000
@@ -40,6 +40,11 @@
 #include "status.h"
 #include "sound.h"
 
+#ifdef HAVE_DBUS
+#  include "dbus-server.h"
+#endif
+
+
 struct GaimCore
 {
 	char *ui;
@@ -89,6 +94,10 @@
 
 	gaim_debug_register_category("main");
 
+#ifdef HAVE_DBUS
+	gaim_dbus_init();
+#endif
+
 	/* Initialize all static protocols. */
 	static_proto_init();
 
--- a/src/dbus-analyze-functions.py	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/dbus-analyze-functions.py	Sat Jul 30 00:23:21 2005 +0000
@@ -10,113 +10,131 @@
 import string
 import sys
 
-# mode: "c" or "xml"
-
-mode = None
+options = {}
 
 for arg in sys.argv[1:]:
-    if arg.startswith("--mode="):
-        mode = arg[len("--mode="):]
+    if arg[0:2] == "--":
+        mylist = arg[2:].split("=",1)
+        command = mylist[0]
+        if len(mylist) > 1:
+            options[command] = mylist[1]
+        else:
+            options[command] = None
 
 # list of object types
 
-objecttypes = []
+# objecttypes = []
 
-for objecttype in file("dbus-auto-structs.txt"):
-    objecttypes.append(objecttype.strip())
+# for objecttype in file("dbus-auto-structs.txt"):
+#     objecttypes.append(objecttype.strip())
 
 # a dictionary of simple types
 # each TYPE maps into a pair (dbus-type-name, compatible-c-type-name)
 # if compatible-c-type-name is None then it is the same as TYPE
 
-simpletypes = {
-    "int" : ("i", None),
-    "gint" : ("i", None),
-    "guint" : ("u", None),
-    "gboolean" : ("i", "int")
-    }
+# simpletypes = {
+#     "int" : ("i", None),
+#     "gint" : ("i", None),
+#     "guint" : ("u", None),
+#     "gboolean" : ("i", "int")
+#     }
 
-for enum in file("dbus-auto-enums.txt"):
-    simpletypes[enum.strip()] = ("i", "int")
+simpletypes = ["int", "gint", "guint", "gboolean"]
+
+# for enum in file("dbus-auto-enums.txt"):
+#     simpletypes[enum.strip()] = ("i", "int")
 
 # functions that shouldn't be exported 
 
-excluded = ["gaim_accounts_load", "gaim_account_set_presence"]
+excluded = ["gaim_accounts_load", "gaim_account_set_presence",
+            "gaim_conv_placement_get_fnc_id", "gaim_conv_placement_add_fnc"]
 
 pointer = "#pointer#"
-prefix = "gaim_object_"
+
+functions = []
 
 cparams = []
+cparamsout = []
 cdecls  = []
 ccode  = []
-dargs  = []
+ccodeout  = []
 
 myexception = "My Exception"
 
-
 def ctopascal(name):
     newname = ""
     for word in name.split("_"):
         newname += word.capitalize()
     return newname
 
-def dbus_print(function):
-    print '<method name="%s">' % ctopascal(function)
-
-    for name, type, direction in dargs:
-        print '<arg type="%s" name="%s" direction="%s" />' % \
-              (type, name, direction)
-
-    print '</method>'
-    print 
+def c_print(function):
+    print "static DBusMessage *%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" \
+          % function
 
-def dbus_clear():
-    global dargs
-    dargs = []
-
-def c_print(function):
-    print "static gboolean %s%s(GaimObject *gaim_object," % (prefix, function),
-
-    for param in cparams:
-        print "%s," % param,
-
-    print "GError **error) {"
+    print "DBusMessage *reply_DBUS;"
 
     for decl in cdecls:
         print decl
 
+    print "dbus_message_get_args(message_DBUS, error_DBUS, ",
+    for param in cparams:
+        print "DBUS_TYPE_%s, &%s," % param,
+    print "DBUS_TYPE_INVALID);"
+
+    print "CHECK_ERROR(error_DBUS);"
+
     for code in ccode:
         print code
 
-    print "return TRUE;\n}\n"
-   
+    print "reply_DBUS =  dbus_message_new_method_return (message_DBUS);"
+
+    print "dbus_message_append_args(reply_DBUS, ",
+    for param in cparamsout:
+        if type(param) is str:
+            print "%s, " % param
+        else:
+            print "DBUS_TYPE_%s, &%s, " % param,
+    print "DBUS_TYPE_INVALID);"
+
+    for code in ccodeout:
+        print code
+
+    print "return reply_DBUS;\n}\n"
+
+    functions.append(function)
+
 def c_clear():
-    global cparams, cdecls, ccode
+    global cparams, cdecls, ccode, cparamsout, ccodeout
     cparams = []
     cdecls  = []
     ccode  = []
+    cparamsout = []
+    ccodeout = []
 
 
+def printdispatchtable():
+    print "static GaimDBusBinding bindings_DBUS[] = { "
+    for function in functions:
+        print '{"%s", %s_DBUS},' % (ctopascal(function), function)
+    print "{NULL, NULL}"
+    print "};"
+    
+    print "#define GAIM_DBUS_REGISTER_BINDINGS(handle) gaim_dbus_register_bindings(handle, bindings_DBUS)"
+
 # processing an input parameter
 
 def inputvar(mytype, name):
-    global dargs, ccode, cparams, cdecls
+    global ccode, cparams, cdecls
     const = False
     if mytype[0] == "const":
         mytype = mytype[1:]
         const = True
 
     # simple types (int, gboolean, etc.) and enums
-    if (len(mytype) == 1) and (mytype[0] in simpletypes):
-        dbustype, ctype = simpletypes[mytype[0]]
-        dargs.append((name, dbustype, "in"))
-        if ctype is None:
-            cparams.append(mytype[0] + " " + name)
-        else:
-            cparams.append(ctype + " " + name + "_ORIG")
-            cdecls .append("%s %s;\n" % (mytype[0], name))
-            ccode  .append("%s = (%s) %s_ORIG;\n" % \
-                           (name, mytype[0], name))
+    if (len(mytype) == 1) and \
+           ((mytype[0] in simpletypes) or (mytype[0].startswith("Gaim"))):
+        cdecls.append("dbus_int32_t %s;" % name)
+        cparams.append(("INT32", name))
         return
 
     # pointers ...
@@ -125,27 +143,27 @@
         # strings
         if mytype[0] == "char":
             if const:
-                dargs  .append((name, "s", "in"))
-                cparams.append("const char *" + name)
+                cdecls.append("const char *%s;" % name)
+                cparams.append(("STRING", name))
                 ccode  .append("NULLIFY(%s);" % name)
                 return
             else:
                 raise myexception
 
         # known object types are transformed to integer handles
-        elif mytype[0] in objecttypes:
-            dargs  .append((name, "i", "in"))
-            cparams.append("int " + name + "_ID")
-            cdecls .append("%s *%s;" % (mytype[0], name))
-            ccode  .append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s);"  % \
+        elif mytype[0].startswith("Gaim"):
+            cdecls.append("dbus_int32_t %s_ID;" %  name)
+            cdecls.append("%s *%s;" % (mytype[0], name))
+            cparams.append(("INT32", name + "_ID"))
+            ccode.append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s, error_DBUS);"  % \
                            (name, name, mytype[0]))
             return
 
         # unknown pointers are always replaced with NULL
         else:
-            dargs  .append((name, "i", "in"))
-            cparams.append("int " + name + "_NULL")
+            cdecls.append("dbus_int32_t %s_NULL;" %  name)
             cdecls .append("%s *%s;" % (mytype[0], name))
+            cparams.append(("INT32", name + "_NULL"))
             ccode  .append("%s = NULL;" % name)
             return
 
@@ -163,40 +181,40 @@
 
     # a constant string
     if mytype == ["const", "char", pointer]:
-        dargs  .append((name, "s", "out"))
-        cparams.append("char **%s" % name)
-        ccode  .append("*%s = g_strdup(null_to_empty(%s));" % (name, call))
+        cdecls.append("const char *%s;" % name)
+        ccode.append("%s = null_to_empty(%s);" % (name, call))
+        cparamsout.append(("STRING", name))
         return
 
     # simple types (ints, booleans, enums, ...)
-    if (len(mytype) == 1) and (mytype[0] in simpletypes): 
-        dbustype, ctype = simpletypes[mytype[0]]
-
-        if ctype is None:
-            ctype = mytype[0]
-            
-        dargs  .append((name, dbustype, "out"))
-        ccode  .append("*%s = %s;" % (name, call))
-        cparams.append("%s *%s" % (ctype, name))
+    if (len(mytype) == 1) and \
+           ((mytype[0] in simpletypes) or (mytype[0].startswith("Gaim"))):
+        cdecls.append("dbus_int32_t %s;" % name)
+        ccode.append("%s = %s;" % (name, call))
+        cparamsout.append(("INT32", name))
         return
             
     # pointers ...
     if (len(mytype) == 2) and (mytype[1] == pointer):
 
         # handles
-        if mytype[0] in objecttypes:
-            dargs  .append((name, "i", "out"))
-            cparams.append("int *%s" % name)
-            ccode  .append("GAIM_DBUS_POINTER_TO_ID(*%s, %s);" % (name, call))
+        if mytype[0].startswith("Gaim"):
+            cdecls.append("dbus_int32_t %s;" % name)
+            ccode .append("GAIM_DBUS_POINTER_TO_ID(%s, %s, error_DBUS);" % (name, call))
+            cparamsout.append(("INT32", name))
             return
 
         # GList*, GSList*, assume that list is a list of objects
         # not a list of strings!!!
+        # this does NOT release memory occupied by the list
         if mytype[0] in ["GList", "GSList"]:
-            dargs  .append((name, "ai", "out"))
-            cparams.append("GArray **%s" % name)
-            ccode  .append("*%s = gaim_dbusify_%s(%s, TRUE);" % \
-                           (name, mytype[0],call))
+            cdecls.append("dbus_int32_t %s_LEN;" % name)
+            cdecls.append("dbus_int32_t *%s;" % name)
+            ccode.append("%s = gaim_dbusify_%s(%s, FALSE, &%s_LEN);" % \
+                         (name, mytype[0], call, name))
+            cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \
+                              % (name, name))
+            ccodeout.append("g_free(%s);" % name)
             return
 
     raise myexception
@@ -204,7 +222,6 @@
 
 
 def processfunction(functionparam, paramlist):
-    dbus_clear()
     c_clear()
 
     ftokens = functionparam.split()
@@ -228,20 +245,24 @@
     outputvar(functiontype, "RESULT",
               "%s(%s)" % (origfunction, ", ".join(names)))
 
-    if mode == "c":
-        c_print(function)
+    c_print(function)
+
+
 
-    if mode == "xml":
-        dbus_print(function)
+    
+print "/* Generated by %s.  Do not edit! */" % sys.argv[0]
+
 
 
-if mode == "c":
-    print "/* Generated by %s.  Do not edit! */" % sys.argv[0]
+regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$";
+
 
-if mode == "xml":
-    print "<!-- Generated by %s.  Do not edit! -->" % sys.argv[0]
-
-functionregexp = re.compile(r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$")
+if "export-only" in options:
+    fprefix = "DBUS_EXPORT\s+"
+else:
+    fprefix = ""
+    
+functionregexp = re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix)
 
 inputiter = iter(sys.stdin)
 
@@ -286,7 +307,5 @@
             sys.stderr.write(myline + "\n")
             raise
 
-
+printdispatchtable()
 
-
-
--- a/src/dbus-analyze-types.py	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/dbus-analyze-types.py	Sat Jul 30 00:23:21 2005 +0000
@@ -18,35 +18,20 @@
 import re
 import sys
 
-myinput = iter(sys.stdin)
-
-def outputenum(name):
-    print "DBUS_POINTER_%s," % name
-
-def outputdeclare(name):
-    print "DECLARE_TYPE(%s, NONE);" % name
-
-def outputtext(name):
-    print name
-
-myoutput = outputtext
 keyword = "struct"
+pattern = "%s"
 
 for arg in sys.argv[1:]:
     if arg[0:2] == "--":
-        mylist = arg[2:].split("=")
+        mylist = arg[2:].split("=",1)
         command = mylist[0]
         if len(mylist) > 1:
             value = mylist[1]
         else:
             value = None
             
-    if command == "enum":
-        myoutput = outputenum
-    if command == "declare":
-        myoutput = outputdeclare
-    if command == "list":
-        myoutput = outputtext
+    if command == "pattern":
+        pattern = value
     if command == "keyword":
         keyword = value
         
@@ -55,10 +40,12 @@
 structregexp2 = re.compile(r"^(typedef\s+)?%s" % keyword)
 structregexp3 = re.compile(r"^}\s+(\w+)\s*;")
 
+myinput = iter(sys.stdin)
+
 for line in myinput:
     match = structregexp1.match(line)
     if match is not None:
-        myoutput(match.group(2))        
+        print pattern % match.group(2)
         continue
 
     match = structregexp2.match(line)
@@ -67,7 +54,7 @@
             line = myinput.next()
             match = structregexp3.match(line)
             if match is not None:
-                myoutput(match.group(1))
+                print pattern % match.group(1)
                 break
             if line[0] not in [" ", "\t", "{", "\n"]:
                 break
--- a/src/dbus-maybe.h	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/dbus-maybe.h	Sat Jul 30 00:23:21 2005 +0000
@@ -13,7 +13,7 @@
 /* this provides a type check */
 #define GAIM_DBUS_REGISTER_POINTER(ptr, type) { \
     type *typed_ptr = ptr; \
-    gaim_dbus_register_pointer(typed_ptr, DBUS_POINTER_##type); \
+    gaim_dbus_register_pointer(typed_ptr, GAIM_DBUS_TYPE(type));	\
 }
 #define GAIM_DBUS_UNREGISTER_POINTER(ptr) gaim_dbus_unregister_pointer(ptr)
 
@@ -21,6 +21,7 @@
 
 #define GAIM_DBUS_REGISTER_POINTER(ptr, type) 
 #define GAIM_DBUS_UNREGISTER_POINTER(ptr)
+#define DBUS_EXPORT
 
 #endif	/* HAVE_DBUS */
 
--- a/src/dbus-server.c	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/dbus-server.c	Sat Jul 30 00:23:21 2005 +0000
@@ -23,16 +23,9 @@
 
 #define DBUS_API_SUBJECT_TO_CHANGE
 
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <dbus/dbus-glib-bindings.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <glib/gi18n.h>
-#include <glib-object.h>
-#include <glib/gquark.h>
-#include <glib.h>
 
 #include "account.h"
 #include "blist.h"
@@ -40,50 +33,122 @@
 #include "dbus-gaim.h"
 #include "dbus-server.h"
 #include "dbus-useful.h"
+#include "dbus-bindings.h"
 #include "debug.h"
 #include "core.h"
 #include "value.h"
 
 
-
 /**************************************************************************/
-/** @name Lots of GObject stuff I don't really understand                 */
+/** @name Gaim DBUS pointer registration mechanism                        */
 /**************************************************************************/
 
-GType gaim_object_get_type(void);
+/* 
+   Here we include the list of #GAIM_DBUS_DEFINE_TYPE statements for
+   all structs defined in gaim.  This file has been generated by the
+   #dbus-analize-types.py script.
+*/
 
-struct _GaimObject {
-    GObject parent;
-    DBusGProxy *proxy;
-};
+#include "dbus-types.c"
 
-typedef struct {
-	GObjectClass parent;
-} GaimObjectClass;
+/* The following three hashtables map are used to translate between
+   pointers (nodes) and the corresponding handles (ids).  */
+
+static GHashTable *map_node_id; 
+static GHashTable *map_id_node; 
+static GHashTable *map_id_type; 
 
 
-#define GAIM_DBUS_TYPE_OBJECT              (gaim_object_get_type ())
-#define GAIM_DBUS_OBJECT(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GAIM_DBUS_TYPE_OBJECT, GaimObject))
-#define GAIM_DBUS_OBJECT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GAIM_DBUS_TYPE_OBJECT, GaimObjectClass))
-#define GAIM_DBUS_IS_OBJECT(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GAIM_DBUS_TYPE_OBJECT))
-#define GAIM_DBUS_IS_OBJECT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GAIM_DBUS_TYPE_OBJECT))
-#define GAIM_DBUS_OBJECT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GAIM_DBUS_TYPE_OBJECT, GaimObjectClass))
+/* This function initializes the pointer-id traslation system.  It
+   creates the three above hashtables and defines parents of some types.
+ */
+void gaim_dbus_init_ids(void) {
+    map_id_node = g_hash_table_new (g_direct_hash, g_direct_equal);
+    map_id_type = g_hash_table_new (g_direct_hash, g_direct_equal);
+    map_node_id = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+    GAIM_DBUS_TYPE(GaimBuddy)->parent   = GAIM_DBUS_TYPE(GaimBlistNode);
+    GAIM_DBUS_TYPE(GaimContact)->parent = GAIM_DBUS_TYPE(GaimBlistNode);
+    GAIM_DBUS_TYPE(GaimChat)->parent    = GAIM_DBUS_TYPE(GaimBlistNode);
+    GAIM_DBUS_TYPE(GaimGroup)->parent   = GAIM_DBUS_TYPE(GaimBlistNode);
+}
+
+void gaim_dbus_register_pointer(gpointer node, GaimDBusType *type) 
+{
+    static gint last_id = 0;
+
+    g_assert(map_node_id);
+    g_assert(g_hash_table_lookup(map_node_id, node) == NULL);
+	
+    last_id++;
+    g_hash_table_insert(map_node_id, node, GINT_TO_POINTER(last_id));
+    g_hash_table_insert(map_id_node, GINT_TO_POINTER(last_id), node);
+    g_hash_table_insert(map_id_type, GINT_TO_POINTER(last_id), type);
+}
+
+void gaim_dbus_unregister_pointer(gpointer node) {
+    gpointer id = g_hash_table_lookup(map_node_id, node);
+	
+    g_hash_table_remove(map_node_id, node);
+    g_hash_table_remove(map_id_node, GINT_TO_POINTER(id));
+    g_hash_table_remove(map_id_type, GINT_TO_POINTER(id));
+}
 
-G_DEFINE_TYPE(GaimObject, gaim_object, G_TYPE_OBJECT)
+gint gaim_dbus_pointer_to_id(gpointer node) {
+    gint id = GPOINTER_TO_INT(g_hash_table_lookup(map_node_id, node));
+    g_return_val_if_fail(id, 0);
+    return id;
+}
+	
+gpointer gaim_dbus_id_to_pointer(gint id,  GaimDBusType *type) {
+    GaimDBusType *objtype = 
+	(GaimDBusType*) g_hash_table_lookup(map_id_type, 
+						  GINT_TO_POINTER(id));
+							    
+    while (objtype != type && objtype != NULL)
+	objtype = objtype->parent;
+
+    if (objtype == type)
+	return g_hash_table_lookup(map_id_node, GINT_TO_POINTER(id));
+    else
+	return NULL;
+}
+
+gint  gaim_dbus_pointer_to_id_error(gpointer ptr, DBusError *error) 
+{
+    gint id = gaim_dbus_pointer_to_id(ptr);
 
-GaimObject *gaim_dbus_object;
-static GQuark gaim_object_error_quark;
+    if (ptr != NULL && id == 0)
+	dbus_set_error(error, "org.gaim.ObjectNotFound",
+		       "The return object is not mapped (this is a Gaim error)");
+
+    return id;
+}
+
+gpointer gaim_dbus_id_to_pointer_error(gint id, GaimDBusType *type,
+				       const char *typename, DBusError *error) 
+{
+    gpointer ptr = gaim_dbus_id_to_pointer(id, type);
 
-#define NULLIFY(id) id = empty_to_null(id)
+    if (ptr == NULL && id != 0) 
+	dbus_set_error(error, "org.gaim.InvalidHandle",
+		       "%s object with ID = %i not found", typename, id);	
+    
+    return ptr;
+}
+	
+/**************************************************************************/
+/** @name Useful functions                                                */
+/**************************************************************************/
 
-static const char* empty_to_null(const char *str) {
+const char* empty_to_null(const char *str) {
     if (str == NULL || str[0] == 0)
 	return NULL;
     else
 	return str;
 }
 
-static const char* null_to_empty(const char *s) {
+const char* null_to_empty(const char *s) {
 	if (s)
 		return s;
 	else
@@ -92,128 +157,180 @@
 
 
 
-static void gaim_object_class_init(GaimObjectClass *klass) 
-{ 
-}
+
+dbus_int32_t* gaim_dbusify_GList(GList *list, gboolean free_memory,
+				 dbus_int32_t *len)
+ {
+	dbus_int32_t *array;
+	int i;
+	GList *elem;
 
-static void gaim_object_init(GaimObject *object) 
-{
+	*len = g_list_length(list);
+	array = g_new0(dbus_int32_t, g_list_length(list));
+	for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) 
+		array[i] = gaim_dbus_pointer_to_id(elem->data);
+
+	if (free_memory)
+		g_list_free(list);
+
+	return array;
 }
 
-/**************************************************************************/
-/** @name Gaim DBUS pointer registration mechanism                        */
-/**************************************************************************/
-
-GaimDBusPointerType dbus_type_parent[DBUS_POINTER_LASTTYPE];
-
-static GHashTable *map_id_node; 
-static GHashTable *map_id_type; 
-static GHashTable *map_node_id; 
-
-
-#define DECLARE_TYPE(type, parent) \
-	dbus_type_parent[DBUS_POINTER_##type] = DBUS_POINTER_##parent
-
-void gaim_dbus_init_ids(void) {
+dbus_int32_t* gaim_dbusify_GSList(GSList *list, gboolean free_memory,
+				  dbus_int32_t *len) 
+{
+	dbus_int32_t *array;
 	int i;
-
-	map_id_node = g_hash_table_new (g_direct_hash, g_direct_equal);
-	map_id_type = g_hash_table_new (g_direct_hash, g_direct_equal);
-	map_node_id = g_hash_table_new (g_direct_hash, g_direct_equal);
+	GSList *elem;
 
-	for (i = 0; i < DBUS_POINTER_LASTTYPE; i++)
-		dbus_type_parent[i] = DBUS_POINTER_NONE;
-
-	/* some manual corrections */
-	DECLARE_TYPE(GaimBuddy, GaimBlistNode);
-	DECLARE_TYPE(GaimContact, GaimBlistNode);
-	DECLARE_TYPE(GaimChat, GaimBlistNode);
-	DECLARE_TYPE(GaimGroup, GaimBlistNode);
-}
+	*len = g_slist_length(list);
+	array = g_new0(dbus_int32_t, g_slist_length(list));
+	for(i = 0, elem = list; elem != NULL; elem = elem->next, i++) 
+		array[i] = gaim_dbus_pointer_to_id(elem->data);
 
-void gaim_dbus_register_pointer(gpointer node, GaimDBusPointerType type) 
-{
-	static gint last_id = 0;
+	if (free_memory)
+		g_slist_free(list);
 
-	g_assert(map_node_id);
-	g_assert(g_hash_table_lookup(map_node_id, node) == NULL);
-	
-
-	last_id++;
-	g_hash_table_insert(map_node_id, node, GINT_TO_POINTER(last_id));
-	g_hash_table_insert(map_id_node, GINT_TO_POINTER(last_id), node);
-	g_hash_table_insert(map_id_type, GINT_TO_POINTER(last_id), 
-			    GINT_TO_POINTER(type));
+	return array;
 }
 
 
-void gaim_dbus_unregister_pointer(gpointer node) {
-	gpointer id = g_hash_table_lookup(map_node_id, node);
-	
-	g_hash_table_remove(map_node_id, node);
-	g_hash_table_remove(map_id_node, GINT_TO_POINTER(id));
-	g_hash_table_remove(map_id_node, GINT_TO_POINTER(id));
+/**************************************************************/
+/* DBus bindings ...                                          */
+/**************************************************************/
+
+static DBusConnection *gaim_dbus_connection;
+
+DBusConnection *gaim_dbus_get_connection(void) {
+    return gaim_dbus_connection;
+}
+
+#include "dbus-bindings.c"
+
+void *gaim_dbus_get_handle(void) {
+    static int handle;
+
+    return &handle;
 }
 
-static gint gaim_dbus_pointer_to_id(gpointer node) {
-	gint id = GPOINTER_TO_INT(g_hash_table_lookup(map_node_id, node));
-	g_return_val_if_fail(id, 0);
-	return id;
+static gboolean
+gaim_dbus_dispatch_cb(DBusConnection *connection,
+		   DBusMessage *message,
+		   void *user_data) 
+{
+    const char *name;
+    GaimDBusBinding *bindings;
+    int i;
+
+    bindings = (GaimDBusBinding*) user_data;
+
+    if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+	return FALSE;
+
+    if (!dbus_message_has_path(message, DBUS_PATH_GAIM))
+	return FALSE;
+
+    name = dbus_message_get_member(message);
+
+    if (name == NULL)
+	return FALSE;
+
+    for(i=0; bindings[i].name; i++)
+	if (!strcmp(name, bindings[i].name)) {
+	    DBusMessage *reply;
+	    DBusError error;
+
+	    dbus_error_init(&error);
+	    
+	    reply = bindings[i].handler(message, &error);
+    
+	    if (reply == NULL && dbus_error_is_set(&error)) 
+		reply = dbus_message_new_error (message,
+						error.name,
+						error.message);
+	    
+	    if (reply != NULL) {
+		dbus_connection_send (connection, reply, NULL);
+		dbus_message_unref(reply);
+	    }
+	    
+	    return TRUE;		/* return reply! */
+	}
+
+    return FALSE;
 }
-	
-static gpointer gaim_dbus_id_to_pointer(gint id, GaimDBusPointerType type) {
-	GaimDBusPointerType objtype = 
-		GPOINTER_TO_INT(g_hash_table_lookup(map_id_type, 
-						    GINT_TO_POINTER(id)));
-							    
-	while (objtype != type && objtype != DBUS_POINTER_NONE)
-		objtype = dbus_type_parent[objtype];
 
-	if (objtype == type)
-		return g_hash_table_lookup(map_id_node, GINT_TO_POINTER(id));
-	else
-		return NULL;
+static DBusHandlerResult gaim_dbus_dispatch(DBusConnection *connection,
+					    DBusMessage *message,
+					    void *user_data)
+{
+    if (gaim_signal_emit_return_1(gaim_dbus_get_handle(), 
+				  "dbus-method-called", 
+				  connection, message))
+	return DBUS_HANDLER_RESULT_HANDLED;
+    else 
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
-	
-/**************************************************************************/
-/** @name Useful functions                                                */
-/**************************************************************************/
+
+void gaim_dbus_register_bindings(void *handle, GaimDBusBinding *bindings) {
+    gaim_signal_connect(gaim_dbus_get_handle(), "dbus-method-called",
+			handle, 
+			GAIM_CALLBACK(gaim_dbus_dispatch_cb),
+			bindings);
+}
 
 
-#define error_unless_1(condition, str, parameter)		\
-	if (!(condition)) {					\
-		    g_set_error(error, gaim_object_error_quark,	\
-				DBUS_ERROR_NOT_FOUND,		\
-				str, parameter);		\
-		    return FALSE;				\
-	    }
+
+gboolean gaim_dbus_dispatch_init(void) 
+{
+    static DBusObjectPathVTable vtable = {NULL, &gaim_dbus_dispatch};
+
+    DBusError error;
+    int result;
+    
+    dbus_error_init (&error);
+    gaim_dbus_connection = dbus_bus_get (DBUS_BUS_STARTER, &error);    
 
-#define error_unless_2(condition, str, a,b)			\
-	if (!(condition)) {					\
-		    g_set_error(error, gaim_object_error_quark,	\
-				DBUS_ERROR_NOT_FOUND,		\
-				str, a,b);			\
-		    return FALSE;				\
-	    }
+    if (gaim_dbus_connection == NULL) {
+	gaim_debug_error("dbus", "Failed to get connection\n");
+	dbus_error_free(&error);
+	return FALSE;
+    }
+
+    if (!dbus_connection_register_object_path (gaim_dbus_connection,
+					       DBUS_PATH_GAIM, &vtable, NULL))
+    {
+	gaim_debug_error("dbus", "Failed to get name: %s\n", error.name);
+        dbus_error_free(&error);
+	return FALSE;
+    }
+	    
 
-#define GAIM_DBUS_ID_TO_POINTER(ptr, id, type)				\
-	G_STMT_START {							\
-		ptr = ((type*) gaim_dbus_id_to_pointer			\
-		       (id, DBUS_POINTER_##type));			\
-		error_unless_2(ptr != NULL || id == 0,			\
-			       "%s object with ID = %i not found",	\
-			       #type, id);				\
-	} G_STMT_END
-	       
+    result = dbus_bus_request_name (gaim_dbus_connection, DBUS_SERVICE_GAIM, 
+				    0, &error);
+    
+    if (dbus_error_is_set (&error)) {
+	dbus_connection_unref(gaim_dbus_connection);
+	dbus_error_free(&error);
+	gaim_debug_error("dbus", "Failed to get serv name: %s\n", error.name);
+	return FALSE;
+    }
+	
+    dbus_connection_setup_with_g_main(gaim_dbus_connection, NULL);
 
-#define GAIM_DBUS_POINTER_TO_ID(id, ptr)				\
-	G_STMT_START {							\
-		gpointer _ptr = ptr;					\
-		id = gaim_dbus_pointer_to_id(_ptr);			\
-		error_unless_1(ptr == NULL || id != 0,			\
-			       "Result object not registered (%i)",	\
-			       id);					\
-	} G_STMT_END
+    gaim_debug_misc ("dbus", "okkk\n");
+
+    gaim_signal_register(gaim_dbus_get_handle(), "dbus-method-called",
+			 gaim_marshal_BOOLEAN__POINTER_POINTER,
+			 gaim_value_new(GAIM_TYPE_BOOLEAN), 2,
+			 gaim_value_new(GAIM_TYPE_POINTER),
+			 gaim_value_new(GAIM_TYPE_POINTER));
+
+    GAIM_DBUS_REGISTER_BINDINGS(gaim_dbus_get_handle());
+
+    return TRUE;
+}
+
 
 
 /**************************************************************************/
@@ -265,22 +382,18 @@
 	
 	switch(gaim_values[i]->type) {
 	case  GAIM_TYPE_INT:  
-	    g_print("appending int\n");
 	    xint = my_arg(gint);
 	    dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &xint);
 	    break;
 	case  GAIM_TYPE_UINT:  
 	    xuint = my_arg(guint);
-	    g_print("appending uint\n");
 	    dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &xuint);
 	    break;
 	case  GAIM_TYPE_BOOLEAN:  
-	    g_print("appending boolean\n");
 	    xboolean = my_arg(gboolean);
 	    dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &xboolean);
 	    break;
 	case GAIM_TYPE_STRING: 
-	    g_print("appending string\n");
 	    str = null_to_empty(my_arg(char*));
 	    dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &str);
 	    break;
@@ -288,7 +401,6 @@
 	case GAIM_TYPE_POINTER:
 	case GAIM_TYPE_OBJECT: 
 	case GAIM_TYPE_BOXED:		
-	    g_print("appending obj\n");
 	    id = gaim_dbus_pointer_to_id(my_arg(gpointer));
 	    dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &id);
 	    break;
@@ -300,7 +412,7 @@
 
 #undef my_arg
 
-void gaim_dbus_signal_emit_gaim(GaimObject *object, char *name, int num_values, 
+void gaim_dbus_signal_emit_gaim(char *name, int num_values, 
 				GaimValue **values, va_list vargs)
 {
 	/* pass name */
@@ -308,8 +420,7 @@
     DBusMessageIter iter;
     char *newname;
 
-    g_print("Emitting %s\n", name);    
-    g_return_if_fail(object->proxy);
+    g_return_if_fail(gaim_dbus_connection);
     
     newname =  gaim_dbus_convert_signal_name(name);
     signal = dbus_message_new_signal(DBUS_PATH_GAIM, DBUS_INTERFACE_GAIM, newname);
@@ -317,157 +428,23 @@
 
     gaim_dbus_message_append_gaim_values(&iter, num_values, values, vargs);
 
-    dbus_g_proxy_send(object->proxy, signal, NULL);
+    dbus_connection_send(gaim_dbus_connection, signal, NULL);
 
     g_free(newname);
     dbus_message_unref(signal);
 }
 
 
-/**************************************************************/
-/* DBus bindings ...                                          */
-/**************************************************************/
-
-
-
-GArray* gaim_dbusify_GList(GList *list, gboolean free_memory) {
-	GArray *array;
-	GList *elem;
-
-	array = g_array_new (FALSE, TRUE, sizeof (guint32));
-	for(elem = list; elem != NULL; elem = elem->next) {
-		int objectid;
-
-		objectid = gaim_dbus_pointer_to_id(elem->data);
-		g_array_append_val(array, objectid);
-	}
-
-	if (free_memory)
-		g_list_free(list);
-
-	return array;
-}
-
-GArray* gaim_dbusify_GSList(GSList *list, gboolean free_memory) {
-	GArray *array;
-	GSList *elem;
-
-	array = g_array_new (FALSE, TRUE, sizeof (guint32));
-	for(elem = list; elem != NULL; elem = elem->next) {
-		int objectid;
-
-		objectid = gaim_dbus_pointer_to_id(elem->data);
-		g_array_append_val(array, objectid);
-	}
-
-	if (free_memory)
-		g_slist_free(list);
-	return array;
-}
-
-#include "dbus-generated-code.c"
-
-#include "dbus-server-bindings.c"
-
-
-
-
-
-/**************************************************************************/
-/** @name Gaim DBUS init function                                         */
-/**************************************************************************/
-
-
-/* fixme: why do we need two functions here instead of one?  */
-
-gboolean gaim_dbus_connect(GaimObject *object) 
-{
-	DBusGConnection *connection;
-	GError *error = NULL;
-	DBusGProxy *driver_proxy;
-	guint32 request_name_ret;
-
-	gaim_debug_misc("dbus", "launching dbus server\n");
-					
-	dbus_g_object_type_install_info (GAIM_DBUS_TYPE_OBJECT,
-					 &dbus_glib_gaim_object_object_info);	/* Connect to the bus */
-
-	error = NULL;
-	connection = dbus_g_bus_get(DBUS_BUS_STARTER, &error);
-
-	if (connection == NULL) {
-		g_assert(error);
-		gaim_debug_error("dbus", "Failed to open connection to bus: %s\n",
-				 error->message);
-		g_error_free (error);
-		return FALSE;
-	}
-
-	/* Instantiate the gaim dbus object and register it */
-	
-
-
-
-	/* Obtain a proxy for the DBus object  */
-
-	driver_proxy = dbus_g_proxy_new_for_name (connection,
-						  DBUS_SERVICE_DBUS,
-						  DBUS_PATH_DBUS,
-						  DBUS_INTERFACE_DBUS);
-
-	g_assert(driver_proxy);
-
-	/* Test whether the registration was successful */
-
-	org_freedesktop_DBus_request_name(driver_proxy, DBUS_SERVICE_GAIM,
-					  DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &request_name_ret, &error);
-
-	if (error) {
-		gaim_debug_error("dbus", "Failed to get name: %s\n", error->message);
-		g_error_free (error);
-		return FALSE;
-	}
-
-	if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
-	{
-		gaim_debug_error ("dbus", "Got result code %u from requesting name\n",
-				  request_name_ret);
-		return FALSE;
-	}
-
-	gaim_debug_misc ("dbus", "GLib test service has name '%s'\n", 
-			 DBUS_SERVICE_GAIM);
-
-
-
-	dbus_g_connection_register_g_object (connection, DBUS_PATH_GAIM,
-					     (GObject*) object);
-
-	object->proxy = dbus_g_proxy_new_for_name (connection,
-						  DBUS_SERVICE_GAIM,
-						  DBUS_PATH_GAIM,
-						  DBUS_INTERFACE_GAIM);
-
-	gaim_debug_misc ("dbus", "GLib test service entering main loop\n");
-
-	return TRUE;
-}
 
 
 
 
 gboolean gaim_dbus_init(void) 
 {
-    gaim_dbus_init_ids();
-    gaim_object_error_quark =
-	g_quark_from_static_string("org.gaim.GaimError");
-
+    gaim_debug_register_category("dbus");
 
-
-	gaim_dbus_object = GAIM_DBUS_OBJECT(g_object_new (GAIM_DBUS_TYPE_OBJECT, NULL));
-
-	gaim_dbus_object->proxy = NULL;
-	return TRUE;
+    gaim_dbus_init_ids();
+    return gaim_dbus_dispatch_init() ;
 }
 
 
--- a/src/dbus-server.h	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/dbus-server.h	Sat Jul 30 00:23:21 2005 +0000
@@ -27,41 +27,53 @@
 #ifndef _GAIM_DBUS_SERVER_H_
 #define _GAIM_DBUS_SERVER_H_
 
-#include <glib-object.h>
 #include "value.h"
 
+
 G_BEGIN_DECLS
 
-/* These are the categories of codes used by gaim dbus implementation
-   for remote calls.  In practice, they don't matter
- */
-typedef enum {
-  DBUS_ERROR_NONE = 0,
-  DBUS_ERROR_NOT_FOUND = 1
-} DbusErrorCodes;
+/** 
+   Types of pointers are identified by the ADDRESS of a GaimDbusType
+   object.  This way, plugins can easily access types defined in gaim
+   proper as well as introduce their own types that will not conflict
+   with those introduced by other plugins.
+
+   The structure GaimDbusType has only one element #parent, which
+   contains a pointer to the parent type, or #NULL if the type has no
+   parent.  Parent means the same as the base class is object oriented
+   programming.  
+   */
+
+typedef struct _GaimDBusType GaimDBusType;
+
+struct _GaimDBusType {
+    GaimDBusType *parent;
+};
 
-/* Types of pointers that can be registered with the gaim dbus pointer
-   registration engine.  See below */
-typedef enum {
-  DBUS_POINTER_NONE = 0,
-#include "dbus-auto-enum-types.h"
-  DBUS_POINTER_LASTTYPE
-} GaimDBusPointerType;
+/* By convesion, the GaimDBusType variable representing each structure
+   GaimSomeStructure has the name GAIM_DBUS_TYPE_GaimSomeStructure.
+   The following macros facilitate defining such variables
 
-typedef struct _GaimObject GaimObject;
+   #GAIM_DBUS_DECLARE_TYPE declares an extern variable representing a
+   given type, for use in header files.
+
+   #GAIM_DBUS_DEFINE_TYPE defines a variable representing a given
+   type, use in .c files.  It defines a new type without a parent; for
+   types with a parent use #GAIM_DBUS_DEFINE_INHERITING_TYPE.
+  */
 
-/** The main GaimObject  */
-GaimObject * gaim_dbus_object;
+#define GAIM_DBUS_TYPE(type) (&GAIM_DBUS_TYPE_##type)
+
+
+#define GAIM_DBUS_DECLARE_TYPE(type) \
+    extern GaimDBusType GAIM_DBUS_TYPE_##type;
 
-/**
- * Starts the gaim DBUS server.  It is responsible for handling DBUS
- * requests from other applications.
- *
- * @return TRUE if successful, FALSE otherwise.
- */
-gboolean gaim_dbus_init(void);
+#define GAIM_DBUS_DEFINE_TYPE(type) \
+    GaimDBusType GAIM_DBUS_TYPE_##type = { NULL };
 
-gboolean gaim_dbus_connect(GaimObject *object);
+#define GAIM_DBUS_DEFINE_INHERITING_TYPE(type, parent) \
+    GaimDBusType GAIM_DBUS_TYPE_##type = { GAIM_DBUS_TYPE(parent) };
+
 
 /**
    Initializes gaim dbus pointer registration engine.
@@ -98,7 +110,7 @@
     @param node   The pointer to register.
     @param type   Type of that pointer.
  */
-void gaim_dbus_register_pointer(gpointer node, GaimDBusPointerType type);
+void gaim_dbus_register_pointer(gpointer node, GaimDBusType *type);
 
 /** 
     Unregisters a pointer previously registered with
@@ -113,22 +125,44 @@
 /**
     Emits a dbus signal.
 
-    @param object      The #GaimObject (usually #gaim_dbus_object)
-    @param dbus_id     Id of the signal.
+    @param name        The name of the signal ("bla-bla-blaa")
     @param num_values  The number of parameters.
     @param values      Array of pointers to #GaimValue objects representing
                        the types of the parameters.
     @param vargs       A va_list containing the actual parameters.
+  */
+void gaim_dbus_signal_emit_gaim(char *name, int num_values, 
+				GaimValue **values, va_list vargs);
 
-    This function is intended to be used in signal.h, where it
-    automatically emits all gaim signals to dbus.  For your own dbus
-    signals, use #gaim_dbus_emit.
-  */
-void gaim_dbus_signal_emit_gaim(GaimObject *object, char *name,
-				int num_values, GaimValue **values, 
-				va_list vargs);
+/**
+ * Starts the gaim DBUS server.  It is responsible for handling DBUS
+ * requests from other applications.
+ *
+ * @return TRUE if successful, FALSE otherwise.
+ */
+gboolean gaim_dbus_init(void);
+
 
 
+/**
+
+ Macro #DBUS_EXPORT expands to nothing.  It is used to indicate to the
+ #dbus-analize-functions.py script that the given function should be
+ available to other applications through DBUS.  If
+ #dbus-analize-functions.py is run without the "--export-only" option,
+ this prefix is ignored.
+
+ */
+
+#define DBUS_EXPORT
+
+/* 
+   Here we include the list of #GAIM_DBUS_DECLARE_TYPE statements for
+   all structs defined in gaim.  This file has been generated by the
+   #dbus-analize-types.py script.
+*/
+
+#include "dbus-types.h"
 
 G_END_DECLS
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dbus-types.c	Sat Jul 30 00:23:21 2005 +0000
@@ -0,0 +1,71 @@
+GAIM_DBUS_DEFINE_TYPE(GaimAccountUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimAccount)
+GAIM_DBUS_DEFINE_TYPE(GaimAccountOption)
+GAIM_DBUS_DEFINE_TYPE(GaimAccountUserSplit)
+GAIM_DBUS_DEFINE_TYPE(GaimBuddyList)
+GAIM_DBUS_DEFINE_TYPE(GaimBlistUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimBlistNode)
+GAIM_DBUS_DEFINE_TYPE(GaimBlistNodeAction)
+GAIM_DBUS_DEFINE_TYPE(GaimChat)
+GAIM_DBUS_DEFINE_TYPE(GaimGroup)
+GAIM_DBUS_DEFINE_TYPE(GaimContact)
+GAIM_DBUS_DEFINE_TYPE(GaimBuddy)
+GAIM_DBUS_DEFINE_TYPE(GaimBuddyIcon)
+GAIM_DBUS_DEFINE_TYPE(GaimCipher)
+GAIM_DBUS_DEFINE_TYPE(GaimCipherOps)
+GAIM_DBUS_DEFINE_TYPE(GaimCipherContext)
+GAIM_DBUS_DEFINE_TYPE(GaimConnection)
+GAIM_DBUS_DEFINE_TYPE(GaimConnectionUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimConvWindowUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimConvWindow)
+GAIM_DBUS_DEFINE_TYPE(GaimConversationUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimConversation)
+GAIM_DBUS_DEFINE_TYPE(GaimConvIm)
+GAIM_DBUS_DEFINE_TYPE(GaimConvChat)
+GAIM_DBUS_DEFINE_TYPE(GaimConvChatBuddy)
+GAIM_DBUS_DEFINE_TYPE(GaimCore)
+GAIM_DBUS_DEFINE_TYPE(GaimCoreUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimDebugUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimDesktopItem)
+GAIM_DBUS_DEFINE_TYPE(GaimEventLoopUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimXfer)
+GAIM_DBUS_DEFINE_TYPE(GaimXferUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimLog)
+GAIM_DBUS_DEFINE_TYPE(GaimLogLogger)
+GAIM_DBUS_DEFINE_TYPE(GaimLogCommonLoggerData)
+GAIM_DBUS_DEFINE_TYPE(GaimLogSet)
+GAIM_DBUS_DEFINE_TYPE(GaimMimeDocument)
+GAIM_DBUS_DEFINE_TYPE(GaimMimePart)
+GAIM_DBUS_DEFINE_TYPE(GaimNotifyUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimPlugin)
+GAIM_DBUS_DEFINE_TYPE(GaimPluginInfo)
+GAIM_DBUS_DEFINE_TYPE(GaimPluginUiInfo)
+GAIM_DBUS_DEFINE_TYPE(GaimPluginLoaderInfo)
+GAIM_DBUS_DEFINE_TYPE(GaimPluginAction)
+GAIM_DBUS_DEFINE_TYPE(GaimPluginPrefFrame)
+GAIM_DBUS_DEFINE_TYPE(GaimPluginPref)
+GAIM_DBUS_DEFINE_TYPE(GaimPounce)
+GAIM_DBUS_DEFINE_TYPE(GaimPrivacyUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimProxyInfo)
+GAIM_DBUS_DEFINE_TYPE(GaimPluginProtocolInfo)
+GAIM_DBUS_DEFINE_TYPE(GaimBuddyIconSpec)
+GAIM_DBUS_DEFINE_TYPE(GaimRequestFields)
+GAIM_DBUS_DEFINE_TYPE(GaimRequestFieldGroup)
+GAIM_DBUS_DEFINE_TYPE(GaimRequestField)
+GAIM_DBUS_DEFINE_TYPE(GaimRequestUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimRoomlist)
+GAIM_DBUS_DEFINE_TYPE(GaimRoomlistRoom)
+GAIM_DBUS_DEFINE_TYPE(GaimRoomlistField)
+GAIM_DBUS_DEFINE_TYPE(GaimRoomlistUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimSavedStatus)
+GAIM_DBUS_DEFINE_TYPE(GaimSavedStatusSub)
+GAIM_DBUS_DEFINE_TYPE(GaimStatusType)
+GAIM_DBUS_DEFINE_TYPE(GaimStatusAttr)
+GAIM_DBUS_DEFINE_TYPE(GaimPresence)
+GAIM_DBUS_DEFINE_TYPE(GaimStatus)
+GAIM_DBUS_DEFINE_TYPE(GaimStringref)
+GAIM_DBUS_DEFINE_TYPE(GaimSoundUiOps)
+GAIM_DBUS_DEFINE_TYPE(GaimSslConnection)
+GAIM_DBUS_DEFINE_TYPE(GaimSslOps)
+GAIM_DBUS_DEFINE_TYPE(GaimValue)
+GAIM_DBUS_DEFINE_TYPE(xmlnode)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dbus-types.h	Sat Jul 30 00:23:21 2005 +0000
@@ -0,0 +1,71 @@
+GAIM_DBUS_DECLARE_TYPE(GaimAccountUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimAccount)
+GAIM_DBUS_DECLARE_TYPE(GaimAccountOption)
+GAIM_DBUS_DECLARE_TYPE(GaimAccountUserSplit)
+GAIM_DBUS_DECLARE_TYPE(GaimBuddyList)
+GAIM_DBUS_DECLARE_TYPE(GaimBlistUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimBlistNode)
+GAIM_DBUS_DECLARE_TYPE(GaimBlistNodeAction)
+GAIM_DBUS_DECLARE_TYPE(GaimChat)
+GAIM_DBUS_DECLARE_TYPE(GaimGroup)
+GAIM_DBUS_DECLARE_TYPE(GaimContact)
+GAIM_DBUS_DECLARE_TYPE(GaimBuddy)
+GAIM_DBUS_DECLARE_TYPE(GaimBuddyIcon)
+GAIM_DBUS_DECLARE_TYPE(GaimCipher)
+GAIM_DBUS_DECLARE_TYPE(GaimCipherOps)
+GAIM_DBUS_DECLARE_TYPE(GaimCipherContext)
+GAIM_DBUS_DECLARE_TYPE(GaimConnection)
+GAIM_DBUS_DECLARE_TYPE(GaimConnectionUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimConvWindowUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimConvWindow)
+GAIM_DBUS_DECLARE_TYPE(GaimConversationUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimConversation)
+GAIM_DBUS_DECLARE_TYPE(GaimConvIm)
+GAIM_DBUS_DECLARE_TYPE(GaimConvChat)
+GAIM_DBUS_DECLARE_TYPE(GaimConvChatBuddy)
+GAIM_DBUS_DECLARE_TYPE(GaimCore)
+GAIM_DBUS_DECLARE_TYPE(GaimCoreUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimDebugUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimDesktopItem)
+GAIM_DBUS_DECLARE_TYPE(GaimEventLoopUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimXfer)
+GAIM_DBUS_DECLARE_TYPE(GaimXferUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimLog)
+GAIM_DBUS_DECLARE_TYPE(GaimLogLogger)
+GAIM_DBUS_DECLARE_TYPE(GaimLogCommonLoggerData)
+GAIM_DBUS_DECLARE_TYPE(GaimLogSet)
+GAIM_DBUS_DECLARE_TYPE(GaimMimeDocument)
+GAIM_DBUS_DECLARE_TYPE(GaimMimePart)
+GAIM_DBUS_DECLARE_TYPE(GaimNotifyUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimPlugin)
+GAIM_DBUS_DECLARE_TYPE(GaimPluginInfo)
+GAIM_DBUS_DECLARE_TYPE(GaimPluginUiInfo)
+GAIM_DBUS_DECLARE_TYPE(GaimPluginLoaderInfo)
+GAIM_DBUS_DECLARE_TYPE(GaimPluginAction)
+GAIM_DBUS_DECLARE_TYPE(GaimPluginPrefFrame)
+GAIM_DBUS_DECLARE_TYPE(GaimPluginPref)
+GAIM_DBUS_DECLARE_TYPE(GaimPounce)
+GAIM_DBUS_DECLARE_TYPE(GaimPrivacyUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimProxyInfo)
+GAIM_DBUS_DECLARE_TYPE(GaimPluginProtocolInfo)
+GAIM_DBUS_DECLARE_TYPE(GaimBuddyIconSpec)
+GAIM_DBUS_DECLARE_TYPE(GaimRequestFields)
+GAIM_DBUS_DECLARE_TYPE(GaimRequestFieldGroup)
+GAIM_DBUS_DECLARE_TYPE(GaimRequestField)
+GAIM_DBUS_DECLARE_TYPE(GaimRequestUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimRoomlist)
+GAIM_DBUS_DECLARE_TYPE(GaimRoomlistRoom)
+GAIM_DBUS_DECLARE_TYPE(GaimRoomlistField)
+GAIM_DBUS_DECLARE_TYPE(GaimRoomlistUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimSavedStatus)
+GAIM_DBUS_DECLARE_TYPE(GaimSavedStatusSub)
+GAIM_DBUS_DECLARE_TYPE(GaimStatusType)
+GAIM_DBUS_DECLARE_TYPE(GaimStatusAttr)
+GAIM_DBUS_DECLARE_TYPE(GaimPresence)
+GAIM_DBUS_DECLARE_TYPE(GaimStatus)
+GAIM_DBUS_DECLARE_TYPE(GaimStringref)
+GAIM_DBUS_DECLARE_TYPE(GaimSoundUiOps)
+GAIM_DBUS_DECLARE_TYPE(GaimSslConnection)
+GAIM_DBUS_DECLARE_TYPE(GaimSslOps)
+GAIM_DBUS_DECLARE_TYPE(GaimValue)
+GAIM_DBUS_DECLARE_TYPE(xmlnode)
--- a/src/gtkmain.c	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/gtkmain.c	Sat Jul 30 00:23:21 2005 +0000
@@ -71,9 +71,6 @@
 # include <gdk/gdkx.h>
 #endif
 
-#ifdef HAVE_DBUS
-#  include "dbus-server.h"
-#endif
 
 
 #ifdef HAVE_STARTUP_NOTIFICATION
@@ -617,10 +614,6 @@
 	wgaim_init(hint);
 #endif
 
-#ifdef HAVE_DBUS
-	gaim_dbus_init();
-#endif
-
 	gaim_core_set_ui_ops(gaim_gtk_core_get_ui_ops());
 	gaim_eventloop_set_ui_ops(gaim_gtk_eventloop_get_ui_ops());
 
@@ -726,10 +719,6 @@
 	gaim_debug_register_category("server");
 	gaim_debug_register_category("stringref");
 
-#ifdef HAVE_DBUS
- 	gaim_dbus_connect(gaim_dbus_object); 
-#endif
-
 	gtk_main();
 
 #ifdef _WIN32
--- a/src/signals.c	Fri Jul 29 13:38:00 2005 +0000
+++ b/src/signals.c	Sat Jul 30 00:23:21 2005 +0000
@@ -489,8 +489,7 @@
 	}
 
 #ifdef HAVE_DBUS
-	gaim_dbus_signal_emit_gaim(gaim_dbus_object, signal, 
-				   signal_data->num_values, 
+	gaim_dbus_signal_emit_gaim(signal, signal_data->num_values, 
 				   signal_data->values, args);
 #endif	/* HAVE_DBUS */
 
@@ -541,8 +540,7 @@
 	}
 
 #ifdef HAVE_DBUS
-	gaim_dbus_signal_emit_gaim(gaim_dbus_object, signal,
-				   signal_data->num_values, 
+	gaim_dbus_signal_emit_gaim(signal, signal_data->num_values, 
 				   signal_data->values, args);
 #endif	/* HAVE_DBUS */