Mercurial > pidgin
changeset 11241:66f872f30e40
[gaim-migrate @ 13404]
New shared library libgaim-client, which provides C bindings to
communicate with gaim.
committer: Tailor Script <tailor@pidgin.im>
author | Piotr Zielinski <zielaj> |
---|---|
date | Fri, 12 Aug 2005 16:56:45 +0000 |
parents | 2ab2de8add8b |
children | 01c06e7ae1f6 |
files | src/Makefile.am src/dbus-analyze-functions.py src/dbus-gaim.service src/gaim-client-example.c src/gaim-client.c src/gaim-client.h src/gaim-remote.py |
diffstat | 7 files changed, 636 insertions(+), 324 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Makefile.am Fri Aug 12 04:02:45 2005 +0000 +++ b/src/Makefile.am Fri Aug 12 16:56:45 2005 +0000 @@ -145,16 +145,21 @@ version.h \ xmlnode.h -bin_PROGRAMS = gaim gaim-remote +bin_PROGRAMS = gaim gaim-remote if ENABLE_DBUS +CLEANFILES = \ + dbus-bindings.c \ + dbus-client-binding.c \ + dbus-client-binding.h + +# gaim dbus server + dbus_sources = dbus-server.c dbus-useful.c dbus_headers = dbus-server.h dbus-useful.h dbus-maybe.h -CLEANFILES = dbus-bindings.c - dbus_exported = dbus-useful.h dbus-define-api.h account.h blist.h connection.h conversation.h core.h roomlist.h status.h server.h @@ -163,11 +168,36 @@ dbus-server.$(OBJEXT): dbus-bindings.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)' > $@ + +# libgaim-client + +lib_LTLIBRARIES = libgaim-client.la + +libgaim_client_la_SOURCES = gaim-client.c + +gaim-client-bindings.c: dbus-analyze-functions.py $(dbus_exported) + cat $(dbus_exported) | $(PYTHON) dbus-analyze-functions.py --client > $@ + +gaim-client-bindings.h: dbus-analyze-functions.py $(dbus_exported) + cat $(dbus_exported) | $(PYTHON) dbus-analyze-functions.py --client --headers > $@ + +$(libgaim_client_la_OBJECTS): gaim-client-bindings.h gaim-client-bindings.c -# 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)' > $@ + +# gaim-client-example + +gaim_client_example_SOURCES = gaim-client-example.c + +gaim_client_example_DEPENDENCIES = @LIBOBJS@ +gaim_client_example_LDADD = \ + @LIBOBJS@ \ + libgaim-client.la \ + $(GTK_LIBS) \ + $(DBUS_LIBS) + +bin_PROGRAMS += gaim-client-example + +gaim-client-example.$(OBJEXT): gaim-client-bindings.h endif
--- a/src/dbus-analyze-functions.py Fri Aug 12 04:02:45 2005 +0000 +++ b/src/dbus-analyze-functions.py Fri Aug 12 16:56:45 2005 +0000 @@ -4,22 +4,10 @@ # with option --mode=c: C wrappers # - - import re import string import sys -options = {} - -for arg in sys.argv[1:]: - 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 @@ -54,16 +42,6 @@ stringlists = [] pointer = "#pointer#" - -functions = [] - -dparams = "" -cparams = [] -cparamsout = [] -cdecls = [] -ccode = [] -ccodeout = [] - myexception = "My Exception" def ctopascal(name): @@ -72,314 +50,498 @@ newname += word.capitalize() return newname -def c_print(function): - print "static DBusMessage *%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" \ - % function - - print "DBusMessage *reply_DBUS;" - - for decl in cdecls: - print decl - - print "%s(message_DBUS, error_DBUS, " % argfunc, - 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 "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, dparams)) - -def c_clear(): - global cparams, cdecls, ccode, cparamsout, ccodeout, dparams, argfunc - dparams = "" - cparams = [] - cdecls = [] - ccode = [] - cparamsout = [] - ccodeout = [] - argfunc = "dbus_message_get_args" - - -def addstring(*items): - global dparams - for item in items: - dparams += item + r"\0" - -def addintype(type, name): - addstring("in", type, name) - -def addouttype(type, name): - addstring("out", type, name) - -def printdispatchtable(): - print "static GaimDBusBinding bindings_DBUS[] = { " - for function, params in functions: - print '{"%s", "%s", %s_DBUS},' % (ctopascal(function), params, 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 ccode, cparams, cdecls, ccodeout, argfunc - const = False - if mytype[0] == "const": - mytype = mytype[1:] - const = True - - - - - if len(mytype) == 1: - # simple types (int, gboolean, etc.) and enums - if (mytype[0] in simpletypes) or (mytype[0].startswith("Gaim")): - cdecls.append("dbus_int32_t %s;" % name) - cparams.append(("INT32", name)) - addintype("i", name) - return - - # va_list, replace by NULL - if mytype[0] == "va_list": - cdecls.append("va_list %s;" % name); - ccode.append("%s = NULL;" % name); - return - - # pointers ... - if (len(mytype) == 2) and (mytype[1] == pointer): - # strings - if mytype[0] == "char": - if const: - cdecls.append("const char *%s;" % name) - cparams.append(("STRING", name)) - ccode .append("NULLIFY(%s);" % name) - addintype("s", name) - return - else: - raise myexception +class Parameter: + def __init__(self, type, name): + self.name = name + self.type = type - # memory leak if an error occurs later ... - elif mytype[0] == "GHashTable": - argfunc = "gaim_dbus_message_get_args" - cdecls.append("DBusMessageIter %s_ITER;" % name) - cdecls.append("GHashTable *%s;" % name) - cparams.append(("ARRAY", "%s_ITER" % name)) - ccode.append("%s = gaim_dbus_iter_hash_table(&%s_ITER, error_DBUS);" \ - % (name, name)) - ccode.append("CHECK_ERROR(error_DBUS);") - ccodeout.append("g_hash_table_destroy(%s);" % name) - addintype("a{ss}", name) - return - - # known object types are transformed to integer handles - 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])) - addintype("i", name) - return - - # unknown pointers are always replaced with NULL - else: - 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) - addintype("i", name) - return - - raise myexception - - - -# processing an output parameter - -def outputvar(mytype, name, call, function): - # the "void" type is simple ... - if mytype == ["void"]: - ccode.append("%s;" % call) # just call the function - return - - const = False - if mytype[0] == "const": - mytype = mytype[1:] - const = True - - - # a string - if mytype == ["char", pointer]: - cdecls.append("const char *%s;" % name) - ccode.append("%s = null_to_empty(%s);" % (name, call)) - cparamsout.append(("STRING", name)) - addouttype("s", name) - if not const: - ccodeout.append("g_free(%s);" % name) - return - - # simple types (ints, booleans, enums, ...) - 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)) - addouttype("i", name) - return - - # pointers ... - if (len(mytype) == 2) and (mytype[1] == pointer): - - # handles - 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)) - addouttype("i", name) - return - - # GList*, GSList*, assume that list is a list of objects - - # fixme: at the moment, we do NOT free the memory occupied by - # the list, we should free it if the list has NOT been declared const - - # fixme: we assume that this is a list of objects, not a list - # of strings - - if mytype[0] in ["GList", "GSList"]: - cdecls.append("dbus_int32_t %s_LEN;" % name) - ccodeout.append("g_free(%s);" % name) - - if function in stringlists: - cdecls.append("char **%s;" % name) - ccode.append("%s = gaim_%s_to_array(%s, FALSE, &%s_LEN);" % \ - (name, mytype[0], call, name)) - cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \ - % (name, name)) - addouttype("as", name) - else: - 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)) - addouttype("ai", name) - return - - raise myexception - - - -def processfunction(functionparam, paramlist): - c_clear() - - ftokens = functionparam.split() - functiontype, function = ftokens[:-1], ftokens[-1] - - if function in excluded: - return - - origfunction = function - function = function.lower() - - names = [] - unnamed = 0 - for param in paramlist: - tokens = param.split() + def fromtokens(tokens, parameternumber = -1): if len(tokens) == 0: raise myexception if (len(tokens) == 1) or (tokens[-1] == pointer): - unnamed += 1 - type, name = tokens, "param%i" % unnamed + if parameternumber >= 0: + return Parameter(tokens, "param%i" % parameternumber) + else: + raise myexception else: - type, name = tokens[:-1], tokens[-1] - inputvar(type, name) - names.append(name) + return Parameter(tokens[:-1], tokens[-1]) + + fromtokens = staticmethod(fromtokens) + +class Binding: + def __init__(self, functiontext, paramtexts): + self.function = Parameter.fromtokens(functiontext.split()) + + if self.function.name in excluded: + raise myexception + + self.params = [] + for i in range(len(paramtexts)): + self.params.append(Parameter.fromtokens(paramtexts[i].split(), i)) + + self.call = "%s(%s)" % (self.function.name, + ", ".join([param.name for param in self.params])) + + + def process(self): + for param in self.params: + self.processinput(param.type, param.name) + + self.processoutput(self.function.type, "RESULT") + self.flush() + + + def processinput(self, type, name): + const = False + if type[0] == "const": + type = type[1:] + const = True + + if len(type) == 1: + # simple types (int, gboolean, etc.) and enums + if (type[0] in simpletypes) or (type[0].startswith("Gaim")): + return self.inputsimple(type, name) + + + # va_list, replace by NULL + if type[0] == "va_list": + return self.inputvalist(type, name) + + # pointers ... + if (len(type) == 2) and (type[1] == pointer): + # strings + if type[0] == "char": + if const: + return self.inputstring(type, name) + else: + raise myexception + + elif type[0] == "GHashTable": + return self.inputhash(type, name) + + # known object types are transformed to integer handles + elif type[0].startswith("Gaim"): + return self.inputgaimstructure(type, name) + + # unknown pointers are always replaced with NULL + else: + return self.inputpointer(type, name) + return + + raise myexception + + + def processoutput(self, type, name): + # the "void" type is simple ... + if type == ["void"]: + return self.outputvoid(type, name) + + const = False + if type[0] == "const": + type = type[1:] + const = True + + # a string + if type == ["char", pointer]: + return self.outputstring(type, name, const) + + # simple types (ints, booleans, enums, ...) + if (len(type) == 1) and \ + ((type[0] in simpletypes) or (type[0].startswith("Gaim"))): + return self.outputsimple(type, name) + + # pointers ... + if (len(type) == 2) and (type[1] == pointer): + + # handles + if type[0].startswith("Gaim"): + return self.outputgaimstructure(type, name) + + if type[0] in ["GList", "GSList"]: + return self.outputlist(type, name) + + raise myexception + - outputvar(functiontype, "RESULT", - "%s(%s)" % (origfunction, ", ".join(names)), function) +class ClientBinding (Binding): + def __init__(self, functiontext, paramtexts, knowntypes, headersonly): + Binding.__init__(self, functiontext, paramtexts) + self.knowntypes = knowntypes + self.headersonly = headersonly + self.paramshdr = [] + self.decls = [] + self.inputparams = [] + self.outputparams = [] + self.returncode = [] + + def flush(self): + print "%s %s(%s)" % (self.functiontype, self.function.name, + ", ".join(self.paramshdr)), + + if self.headersonly: + print ";" + return + + print "{" + + for decl in self.decls: + print decl + + print 'dbus_g_proxy_call(gaim_proxy, "%s", NULL,' % ctopascal(self.function.name) + + for type_name in self.inputparams: + print "G_TYPE_%s, %s, " % type_name, + print "G_TYPE_INVALID," + + for type_name in self.outputparams: + print "G_TYPE_%s, &%s, " % type_name, + print "G_TYPE_INVALID);" + + for code in self.returncode: + print code + + print "}\n" + + + def definegaimstructure(self, type): + if (self.headersonly) and (type[0] not in self.knowntypes): + print "struct _%s;" % type[0] + print "typedef struct _%s %s;" % (type[0], type[0]) + self.knowntypes.append(type[0]) - c_print(function) + # fixme + def definegaimenum(self, type): + if (self.headersonly) and (type[0] not in self.knowntypes) \ + and (type[0] not in simpletypes): + print "typedef int %s;" % type[0] + self.knowntypes.append(type[0]) + + def inputsimple(self, type, name): + self.paramshdr.append("%s %s" % (type[0], name)) + self.inputparams.append(("INT", name)) + self.definegaimenum(type) + + def inputvalist(self, type, name): + self.paramshdr.append("...") + + def inputstring(self, type, name): + self.paramshdr.append("const char *%s" % name) + self.inputparams.append(("STRING", name)) + + def inputgaimstructure(self, type, name): + self.paramshdr.append("%s *%s" % (type[0], name)) + self.inputparams.append(("INT", "GPOINTER_TO_INT(%s)" % name)) + self.definegaimstructure(type) + + def inputpointer(self, type, name): + self.paramshdr.append("%s *%s" % (type[0], name)) + self.inputparams.append(("INT", "0")) + + def inputhash(self, type, name): + raise myexception + + + def outputvoid(self, type, name): + self.functiontype = "void" + + def outputstring(self, type, name, const): + self.functiontype = "char*" + self.decls.append("char *%s = NULL;" % name) + self.outputparams.append(("STRING", name)) +# self.returncode.append("NULLIFY(%s);" % name) + self.returncode.append("return %s;" % name); + + def outputsimple(self, type, name): + self.functiontype = type[0] + self.decls.append("%s %s = 0;" % (type[0], name)) + self.outputparams.append(("INT", name)) + self.returncode.append("return %s;" % name); + self.definegaimenum(type) + + def outputgaimstructure(self, type, name): + name = name + "_ID" + self.functiontype = "%s*" % type[0] + self.decls.append("int %s = 0;" % name) + self.outputparams.append(("INT", "%s" % name)) + self.returncode.append("return (%s*) GINT_TO_POINTER(%s);" % (type[0], name)); + self.definegaimstructure(type) + + def outputlist(self, type, name): + raise myexception + +class ServerBinding (Binding): + def __init__(self, functiontext, paramtexts): + Binding.__init__(self, functiontext, paramtexts) + self.dparams = "" + self.cparams = [] + self.cdecls = [] + self.ccode = [] + self.cparamsout = [] + self.ccodeout = [] + self.argfunc = "dbus_message_get_args" - -print "/* Generated by %s. Do not edit! */" % sys.argv[0] + def flush(self): + print "static DBusMessage*" + print "%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" % \ + self.function.name + + print "DBusMessage *reply_DBUS;" + + for decl in self.cdecls: + print decl + + print "%s(message_DBUS, error_DBUS, " % self.argfunc, + for param in self.cparams: + print "DBUS_TYPE_%s, &%s," % param, + print "DBUS_TYPE_INVALID);" + + print "CHECK_ERROR(error_DBUS);" + + for code in self.ccode: + print code + + print "reply_DBUS = dbus_message_new_method_return (message_DBUS);" + + print "dbus_message_append_args(reply_DBUS, ", + for param in self.cparamsout: + if type(param) is str: + print "%s, " % param + else: + print "DBUS_TYPE_%s, &%s, " % param, + print "DBUS_TYPE_INVALID);" + + for code in self.ccodeout: + print code + + print "return reply_DBUS;\n}\n" + + + def addstring(self, *items): + for item in items: + self.dparams += item + r"\0" + + def addintype(self, type, name): + self.addstring("in", type, name) + + def addouttype(self, type, name): + self.addstring("out", type, name) + # input parameters -regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$"; + def inputsimple(self, type, name): + self.cdecls.append("dbus_int32_t %s;" % name) + self.cparams.append(("INT32", name)) + self.addintype("i", name) + + def inputvalist(self, type, name): + self.cdecls.append("va_list %s;" % name); + self.ccode.append("%s = NULL;" % name); + + def inputstring(self, type, name): + self.cdecls.append("const char *%s;" % name) + self.cparams.append(("STRING", name)) + self.ccode .append("NULLIFY(%s);" % name) + self.addintype("s", name) + + def inputhash(self, type, name): + self.argfunc = "gaim_dbus_message_get_args" + self.cdecls.append("DBusMessageIter %s_ITER;" % name) + self.cdecls.append("GHashTable *%s;" % name) + self.cparams.append(("ARRAY", "%s_ITER" % name)) + self.ccode.append("%s = gaim_dbus_iter_hash_table(&%s_ITER, error_DBUS);" \ + % (name, name)) + self.ccode.append("CHECK_ERROR(error_DBUS);") + self.ccodeout.append("g_hash_table_destroy(%s);" % name) + self.addintype("a{ss}", name) + + def inputgaimstructure(self, type, name): + self.cdecls.append("dbus_int32_t %s_ID;" % name) + self.cdecls.append("%s *%s;" % (type[0], name)) + self.cparams.append(("INT32", name + "_ID")) + self.ccode.append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s, error_DBUS);" % \ + (name, name, type[0])) + self.addintype("i", name) + + def inputpointer(self, type, name): + self.cdecls.append("dbus_int32_t %s_NULL;" % name) + self.cdecls .append("%s *%s;" % (type[0], name)) + self.cparams.append(("INT32", name + "_NULL")) + self.ccode .append("%s = NULL;" % name) + self.addintype("i", name) + + # output parameters + + def outputvoid(self, type, name): + self.ccode.append("%s;" % self.call) # just call the function + + def outputstring(self, type, name, const): + self.cdecls.append("const char *%s;" % name) + self.ccode.append("%s = null_to_empty(%s);" % (name, self.call)) + self.cparamsout.append(("STRING", name)) + self.addouttype("s", name) + if not const: + self.ccodeout.append("g_free(%s);" % name) + + def outputsimple(self, type, name): + self.cdecls.append("dbus_int32_t %s;" % name) + self.ccode.append("%s = %s;" % (name, self.call)) + self.cparamsout.append(("INT32", name)) + self.addouttype("i", name) + + def outputgaimstructure(self, type, name): + self.cdecls.append("dbus_int32_t %s;" % name) + self.ccode .append("GAIM_DBUS_POINTER_TO_ID(%s, %s, error_DBUS);" % (name, self.call)) + self.cparamsout.append(("INT32", name)) + self.addouttype("i", name) + + # GList*, GSList*, assume that list is a list of objects + + # fixme: at the moment, we do NOT free the memory occupied by + # the list, we should free it if the list has NOT been declared const + + # fixme: we assume that this is a list of objects, not a list + # of strings + + def outputlist(self, type, name): + self.cdecls.append("dbus_int32_t %s_LEN;" % name) + self.ccodeout.append("g_free(%s);" % name) + + if self.function.name in stringlists: + self.cdecls.append("char **%s;" % name) + self.ccode.append("%s = gaim_%s_to_array(%s, FALSE, &%s_LEN);" % \ + (name, type[0], self.call, name)) + self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \ + % (name, name)) + self.addouttype("as", name) + else: + self.cdecls.append("dbus_int32_t *%s;" % name) + self.ccode.append("%s = gaim_dbusify_%s(%s, FALSE, &%s_LEN);" % \ + (name, type[0], self.call, name)) + self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \ + % (name, name)) + self.addouttype("ai", name) + + +class BindingSet: + regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$"; + def __init__(self, inputfile, fprefix): + self.inputiter = iter(inputfile) + self.functionregexp = \ + re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix) + + + + def process(self): + print "/* Generated by %s. Do not edit! */" % sys.argv[0] + + for line in self.inputiter: + words = line.split() + if len(words) == 0: # empty line + continue + if line[0] == "#": # preprocessor directive + continue + if words[0] in ["typedef", "struct", "enum", "static"]: + continue + + # accumulate lines until the parentheses are balance or an + # empty line has been encountered + myline = line.strip() + while myline.count("(") > myline.count(")"): + newline = self.inputiter.next().strip() + if len(newline) == 0: + break + myline += " " + newline + + # is this a function declaration? + thematch = self.functionregexp.match( + myline.replace("*", " " + pointer + " ")) + + if thematch is None: + continue + + functiontext = thematch.group(1) + paramstext = thematch.group(2).strip() + + if (paramstext == "void") or (paramstext == ""): + paramtexts = [] + else: + paramtexts = paramstext.split(",") + + try: + self.processfunction(functiontext, paramtexts) + except myexception: + sys.stderr.write(myline + "\n") + except: + sys.stderr.write(myline + "\n") + raise + + self.flush() + +class ServerBindingSet (BindingSet): + def __init__(self, inputfile, fprefix): + BindingSet.__init__(self, inputfile, fprefix) + self.functions = [] + + + def processfunction(self, functiontext, paramtexts): + binding = ServerBinding(functiontext, paramtexts) + binding.process() + self.functions.append((binding.function.name, binding.dparams)) + + def flush(self): + print "static GaimDBusBinding bindings_DBUS[] = { " + for function, params in self.functions: + print '{"%s", "%s", %s_DBUS},' % \ + (ctopascal(function), params, function) + + print "{NULL, NULL}" + print "};" + + print "#define GAIM_DBUS_REGISTER_BINDINGS(handle) gaim_dbus_register_bindings(handle, bindings_DBUS)" + +class ClientBindingSet (BindingSet): + def __init__(self, inputfile, fprefix, headersonly): + BindingSet.__init__(self, inputfile, fprefix) + self.functions = [] + self.knowntypes = [] + self.headersonly = headersonly + + def processfunction(self, functiontext, paramtexts): + binding = ClientBinding(functiontext, paramtexts, self.knowntypes, self.headersonly) + binding.process() + + def flush(self): + pass + +# Main program + +options = {} + +for arg in sys.argv[1:]: + if arg[0:2] == "--": + mylist = arg[2:].split("=",1) + command = mylist[0] + if len(mylist) > 1: + options[command] = mylist[1] + else: + options[command] = None if "export-only" in options: fprefix = "DBUS_EXPORT\s+" else: fprefix = "" - -functionregexp = re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix) - -inputiter = iter(sys.stdin) - -for line in inputiter: - words = line.split() - if len(words) == 0: # empty line - continue - if line[0] == "#": # preprocessor directive - continue - if words[0] in ["typedef", "struct", "enum", "static"]: - continue - - # accumulate lines until the parentheses are balance or an - # empty line has been encountered - myline = line.strip() - while myline.count("(") > myline.count(")"): - newline = inputiter.next().strip() - if len(newline) == 0: - break - myline += " " + newline - # is this a function declaration? - thematch = functionregexp.match( - myline.replace("*", " " + pointer + " ")) - - if thematch is None: - continue - - function = thematch.group(1) - parameters = thematch.group(2).strip() +if "client" in options: + bindings = ClientBindingSet(sys.stdin, fprefix, + options.has_key("headers")) +else: + bindings = ServerBindingSet(sys.stdin, fprefix) +bindings.process() - if (parameters == "void") or (parameters == ""): - paramlist = [] - else: - paramlist = parameters.split(",") + - try: - processfunction(function, paramlist) - except myexception: - sys.stderr.write(myline + "\n") - except: - sys.stderr.write(myline + "\n") - raise -printdispatchtable() -
--- a/src/dbus-gaim.service Fri Aug 12 04:02:45 2005 +0000 +++ b/src/dbus-gaim.service Fri Aug 12 16:56:45 2005 +0000 @@ -2,4 +2,4 @@ Name=org.gaim.GaimService #replace this by the path to the gaim executable in your system -Exec=/usr/local/bin/gaim +Exec=/home/pz215/projects/gaim/src/gaim
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gaim-client-example.c Fri Aug 12 16:56:45 2005 +0000 @@ -0,0 +1,31 @@ +#define DBUS_API_SUBJECT_TO_CHANGE + +#include <stdio.h> +#include <stdlib.h> + +#include "gaim-client.h" + +/* + This example demonstrates how to use libgaim-client to communicate + with gaim. The names and signatures of functions provided by + libgaim-client are the same as those in gaim. However, all + structures (such as GaimAccount) are opaque, that is, you can only + use pointer to them. In fact, these pointers DO NOT actually point + to anything, they are just integer identifiers of assigned to these + structures by gaim. So NEVER try to dereference these pointers. + Integer ids as disguised as pointers to provide type checking and + prevent mistakes such as passing an id of GaimAccount when an id of + GaimBuddy is expected. According to glib manual, this technique is + portable. +*/ + +int main (int argc, char **argv) +{ + GaimAccount *account; + gaim_init(); + + account = gaim_accounts_find_any("", ""); + g_print("Alias: %s\n", gaim_account_get_alias(account)); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gaim-client.c Fri Aug 12 16:56:45 2005 +0000 @@ -0,0 +1,56 @@ +#define DBUS_API_SUBJECT_TO_CHANGE + +#include <dbus/dbus-glib.h> +#include <stdio.h> +#include <stdlib.h> + +#include "dbus-gaim.h" +#include "gaim-client-bindings.h" + +static DBusGConnection *bus; +static DBusGProxy *gaim_proxy; + +#include "gaim-client-bindings.c" + +static void lose (const char *fmt, ...) G_GNUC_NORETURN G_GNUC_PRINTF (1, 2); +static void lose_gerror (const char *prefix, GError *error) G_GNUC_NORETURN; + +static void +lose (const char *str, ...) +{ + va_list args; + + va_start (args, str); + + vfprintf (stderr, str, args); + fputc ('\n', stderr); + + va_end (args); + + exit (1); +} + +static void +lose_gerror (const char *prefix, GError *error) +{ + lose ("%s: %s", prefix, error->message); +} + +void gaim_init(void) { + GError *error = NULL; + + g_type_init (); + + bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); + if (!bus) + lose_gerror ("Couldn't connect to session bus", error); + + gaim_proxy = dbus_g_proxy_new_for_name (bus, + DBUS_SERVICE_GAIM, + DBUS_PATH_GAIM, + DBUS_INTERFACE_GAIM); + + if (!gaim_proxy) + lose_gerror ("Couldn't connect to the Gaim Service", error); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gaim-client.h Fri Aug 12 16:56:45 2005 +0000 @@ -0,0 +1,13 @@ +#ifndef _LIBGAIM_H_INCLUDED_ +#define _LIBGAIM_H_INCLUDED_ + +#include <glib.h> +#include "gaim-client-bindings.h" + +G_BEGIN_DECLS + +void gaim_init(void); + +G_END_DECLS + +#endif
--- a/src/gaim-remote.py Fri Aug 12 04:02:45 2005 +0000 +++ b/src/gaim-remote.py Fri Aug 12 16:56:45 2005 +0000 @@ -46,6 +46,20 @@ except: return value +def findaccount(accountname, protocolname): + try: + # prefer connected accounts + account = cgaim.GaimAccountsFindConnected(accountname, protocolname) + return account + except: + # try to get any account and connect it + account = cgaim.GaimAccountsFindAny(accountname, protocolname) + print gaim.GaimAccountGetUsername(account) + gaim.GaimAccountSetStatusVargs(account, "online", 1) + gaim.GaimAccountConnect(account) + return account + + def execute(uri): match = re.match(urlregexp, uri) protocol = match.group(2) @@ -62,7 +76,8 @@ accountname = params.get("account", "") if command == "goim": - account = cgaim.GaimAccountsFindConnected(accountname, protocol) + print params + account = findaccount(accountname, protocol) conversation = cgaim.GaimConversationNew(1, account, params["screenname"]) if "message" in params: im = cgaim.GaimConversationGetImData(conversation) @@ -70,29 +85,34 @@ return None elif command == "gochat": - account = cgaim.GaimAccountsFindConnected(accountname, protocol) + account = findaccount(accountname, protocol) connection = cgaim.GaimAccountGetConnection(account) return gaim.ServJoinChat(connection, params) elif command == "addbuddy": - account = cgaim.GaimAccountsFindConnected(accountname, protocol) + account = findaccount(accountname, protocol) return cgaim.GaimBlistRequestAddBuddy(account, params["screenname"], params.get("group", ""), "") elif command == "setstatus": if "account" in params: - accounts = [cgaim.GaimAccountsFindConnected(accountname, protocol)] + accounts = [cgaim.GaimAccountsFindAny(accountname, protocol)] else: accounts = gaim.GaimAccountsGetAllActive() for account in accounts: - status = gaim.GaimAccountGetStatus(account, params["status"]) + status = cgaim.GaimAccountGetStatus(account, params["status"]) for key, value in params.items(): - if key not in ["state", "account"]: + if key not in ["status", "account"]: gaim.GaimStatusSetAttrString(status, key, value) gaim.GaimAccountSetStatusVargs(account, params["status"], 1) return None + elif command == "getinfo": + account = findaccount(accountname, protocol) + connection = cgaim.GaimAccountGetConnection(account) + gaim.ServGetInfo(connection, params["screenname"]) + elif command == "quit": return gaim.GaimCoreQuit()