📄 gupnp-binding-tool
字号:
#! /usr/bin/python# Copyright (C) 2008 OpenedHand Ltd## This program is free software; you can redistribute it and/or modify it under# the terms of the GNU General Public License as published by the Free Software# Foundation; either version 2, or (at your option) any later version.## This program is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more# details.## You should have received a copy of the GNU General Public License along with# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin# St, Fifth Floor, Boston, MA 02110-1301 USA# TODO:# - add the rest of the types# - finish code cleanup# - add optional service namespacing to functionsclass Action: def __init__(self): self.name = None self.in_args = [] self.out_args = []class Argument: def __init__(self): self.name = None self.direction = None self.gtype = None self.ctype = Nonedef findStateArgType(scpd, name): for argElement in scpd.findall("{urn:schemas-upnp-org:service-1-0}serviceStateTable/{urn:schemas-upnp-org:service-1-0}stateVariable"): arg_name = argElement.find("{urn:schemas-upnp-org:service-1-0}name").text if arg_name == name: return argElement.find("{urn:schemas-upnp-org:service-1-0}dataType").text return Nonedef mapTypes(scpd, argElement): dataType = findStateArgType(scpd, argElement.find("{urn:schemas-upnp-org:service-1-0}relatedStateVariable").text) if dataType == "string": return ("char *", "G_TYPE_STRING") elif dataType == "ui2": # Stupid GType doesn't have short types, so use an int anyway. return ("unsigned int", "G_TYPE_UINT") elif dataType == "ui4": return ("unsigned int", "G_TYPE_UINT") elif dataType == "boolean": return ("gboolean", "G_TYPE_BOOLEAN") # TODO: lots of types missing else: raise Exception("Unknown dataType %s" % dataType)def getActions(scpd): """ Parse the SCPD provided into a list of Action objects. """ actions = [] for actionElement in scpd.findall("{urn:schemas-upnp-org:service-1-0}actionList/{urn:schemas-upnp-org:service-1-0}action"): a = Action() actions.append(a) a.name = actionElement.find("{urn:schemas-upnp-org:service-1-0}name").text if a.name is None: raise Exception("No name found for action") for argElement in actionElement.findall("{urn:schemas-upnp-org:service-1-0}argumentList/{urn:schemas-upnp-org:service-1-0}argument"): arg = Argument() arg.name = argElement.find("{urn:schemas-upnp-org:service-1-0}name").text if arg.name is None: raise Exception("No name found for argument") (arg.ctype, arg.gtype) = mapTypes(scpd, argElement) arg.direction = argElement.find("{urn:schemas-upnp-org:service-1-0}direction").text if arg.direction == "in": a.in_args.append(arg) else: a.out_args.append(arg) return actionsdef printSyncBinding(a): indent = (2 + len (a.name)) * " " print "static inline gboolean" print "%s (GUPnPServiceProxy *proxy," % a.name for arg in a.in_args: print "%s%s in_%s," % (indent, arg.ctype, arg.name) for arg in a.out_args: print "%s%s* out_%s," % (indent, arg.ctype, arg.name) print "%sGError **error)" % indent print "{" print " return gupnp_service_proxy_send_action (proxy, \"%s\", error, " % a.name for arg in a.in_args: print " \"%s\", %s, in_%s," % (arg.name, arg.gtype, arg.name) print " NULL, " for arg in a.out_args: print " \"%s\", %s, out_%s," % (arg.name, arg.gtype, arg.name) print " NULL" print " );" print "}\n"def printAsyncBinding(a): # Magic struct to pass data around. Defined here so that we don't have # multiple copies of the struct definition. asyncdata = " struct {GCallback cb; gpointer userdata; } *cbdata;" # User-callback prototype indent = (24 + len (a.name)) * " " print "typedef void (*%s_reply) (GUPnPServiceProxy *proxy," % a.name for arg in a.out_args: print "%s%s out_%s," % (indent, arg.ctype, arg.name) print "%sGError *error," % indent print "%sgpointer userdata);" % indent print # Generated async callback handler, calls user-provided callback print "static void _%s_async_callback (GUPnPServiceProxy *proxy, GUPnPServiceProxyAction *action, gpointer user_data)" % a.name print "{" print asyncdata print " GError *error = NULL;" for arg in a.out_args: print " %s %s;" % (arg.ctype, arg.name) print " cbdata = user_data;" print " gupnp_service_proxy_end_action" print " (proxy, action, &error," for arg in a.out_args: print " \"%s\", %s, &%s," % (arg.name, arg.gtype, arg.name) print " NULL);" print " ((%s_reply)cbdata->cb) (proxy," % a.name for arg in a.out_args: print " %s," % arg.name print " error, cbdata->userdata);" print " g_slice_free1 (sizeof (*cbdata), cbdata);" print "}" print # Entry point indent = (8 + len (a.name)) * " " print "static inline GUPnPServiceProxyAction *" print "%s_async (GUPnPServiceProxy *proxy," % a.name for arg in a.in_args: print "%s%s in_%s," % (indent, arg.ctype, arg.name) print "%s%s_reply callback," % (indent, a.name) print "%sgpointer userdata)" % indent print "{" print " GUPnPServiceProxyAction* action;" print asyncdata print " cbdata = g_slice_alloc (sizeof (*cbdata));" print " cbdata->cb = G_CALLBACK (callback);" print " cbdata->userdata = userdata;" print " action = gupnp_service_proxy_begin_action" print " (proxy, \"%s\"," % a.name print " _%s_async_callback, cbdata," % a.name for arg in a.in_args: print " \"%s\", %s, in_%s," % (arg.name, arg.gtype, arg.name) print " NULL);" print " return action;" print "}" def printBindings(actions): print "#include <libgupnp/gupnp-service-proxy.h>" print print "G_BEGIN_DECLS" for a in actions: print "\n/* %s */\n" % a.name printSyncBinding(a) printAsyncBinding(a) print print "G_END_DECLS"import sys, xml.etree.ElementTree as ETprintBindings(getActions(ET.parse(sys.argv[1])))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -