diff options
67 files changed, 1398 insertions, 4324 deletions
@@ -13,7 +13,7 @@ config.h config.h.in cscope.out stamp-h1 -data/org.freedesktop.Telepathy.ConnectionManager.haze.service +data/im.telepathy.v1.ConnectionManager.haze.service depcomp /extensions/extensions.html install-sh @@ -29,14 +29,14 @@ m4/lt~obsolete.m4 missing .deps .libs -src/telepathy-haze -src/telepathy-haze.8 +src/telepathy-haze-1 +src/telepathy-haze-1.8 tags /tests/haze-testing.log -/tests/twisted/tools/org.freedesktop.Telepathy.ConnectionManager.haze.service +/tests/twisted/tools/im.telepathy.v1.ConnectionManager.haze.service /tests/twisted/tools/tmp-session-bus.conf /tests/twisted/config.py -/tests/twisted/haze-twisted-tests.list +/tests/twisted/twisted-tests.list /tests/twisted/run-test.sh /telepathy-haze*.tar.gz* /telepathy-haze*/ diff --git a/Makefile.am b/Makefile.am index 3997cc3..b5e9b88 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = tools extensions src data m4 tests +SUBDIRS = tools src data m4 tests EXTRA_DIST = autogen.sh @@ -1,11 +1,35 @@ -telepathy-haze 0.9.0 (UNRELEASED) -================================= +telepathy-haze 0.99.12 (UNRELEASED) +=================================== + +... + +telepathy-haze 0.99.11 (2014-05-14) +=================================== + +The “electioneering” release. + +Dependencies: + +• telepathy-glib ≥ 0.99.11 + +• GLib ≥ 2.40 + +Enhancements: + +• GNOME-style installed-tests (configure with --enable-installed-tests) + +telepathy-haze 0.99.10 (2014-04-03) +=================================== + +The “you and whose army?” release. Dependencies: -• telepathy-glib ≥ 0.21.0 is required +• telepathy-glib-1 ≥ 0.99.10 is required + +Incompatible changes: -Features removed: +• Switch to Telepathy 1 D-Bus API • StreamedMedia channels are no longer supported. We'd potentially accept patches to bring back audio/video support, but only via the @@ -1,31 +1,23 @@ #!/bin/sh set -e -if test -n "$AUTOMAKE"; then - : # don't override an explicit user request -elif automake-1.11 --version >/dev/null 2>/dev/null && \ - aclocal-1.11 --version >/dev/null 2>/dev/null; then - # If we have automake-1.11, use it. This is the oldest version (=> least - # likely to introduce undeclared dependencies) that will give us - # --enable-silent-rules support. - AUTOMAKE=automake-1.11 - export AUTOMAKE - ACLOCAL=aclocal-1.11 - export ACLOCAL -fi - -autoreconf -i -f +autoreconf -i -Wno-portability -f -run_configure=true -for arg in $*; do - case $arg in - --no-configure) - run_configure=false - ;; - *) - ;; - esac -done +# Honor NOCONFIGURE for compatibility with gnome-autogen.sh +if test x"$NOCONFIGURE" = x; then + run_configure=true + for arg in $*; do + case $arg in + --no-configure) + run_configure=false + ;; + *) + ;; + esac + done +else + run_configure=false +fi if test $run_configure = true; then ./configure "$@" diff --git a/configure.ac b/configure.ac index 3dbf15d..019d2a6 100644 --- a/configure.ac +++ b/configure.ac @@ -7,8 +7,8 @@ AC_PREREQ([2.60]) # set nano_version to 1 m4_define([haze_major_version], [0]) -m4_define([haze_minor_version], [8]) -m4_define([haze_micro_version], [99]) +m4_define([haze_minor_version], [99]) +m4_define([haze_micro_version], [11]) m4_define([haze_nano_version], [1]) m4_define([haze_base_version], @@ -34,7 +34,6 @@ AC_CONFIG_FILES([Makefile tests/twisted/Makefile tests/twisted/tools/Makefile tools/Makefile - extensions/Makefile ]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) @@ -73,18 +72,17 @@ AC_ARG_ENABLE(leaky-request-stubs, AC_SUBST(ENABLE_LEAKY_REQUEST_STUBS) PKG_CHECK_MODULES(PURPLE,[purple >= 2.7]) -PKG_CHECK_MODULES(GLIB,[glib-2.0 >= 2.22, gobject-2.0, gio-2.0]) +PKG_CHECK_MODULES(GLIB,[glib-2.0 >= 2.40, gobject-2.0, gio-2.0]) PKG_CHECK_MODULES(DBUS_GLIB,[dbus-glib-1 >= 0.73]) AC_DEFINE([TP_SEAL_ENABLE], [], [Prevent to use sealed variables]) -AC_DEFINE([TP_DISABLE_SINGLE_INCLUDE], [], [Disable single header include]) -AC_DEFINE([TP_VERSION_MIN_REQUIRED], [TP_VERSION_0_22], [Ignore post 0.22 deprecations]) -AC_DEFINE([TP_VERSION_MAX_ALLOWED], [TP_VERSION_0_22], [Prevent post 0.22 APIs]) -PKG_CHECK_MODULES(TP_GLIB,[telepathy-glib >= 0.21]) +AC_DEFINE([TP_VERSION_MIN_REQUIRED], [TP_VERSION_1_0], [Ignore post 1.0 deprecations]) +AC_DEFINE([TP_VERSION_MAX_ALLOWED], [TP_VERSION_1_0], [Prevent post 1.0 APIs]) +PKG_CHECK_MODULES([TP_GLIB], [telepathy-glib-1 >= 0.99.11, telepathy-glib-1-dbus >= 0.99.11]) dnl MIN_REQUIRED must stay to 2.30 because of GValueArray AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_30], [Ignore post 2.30 deprecations]) -AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_30], [Prevent post 2.30 APIs]) +AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_40], [Prevent post 2.40 APIs]) GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` AC_SUBST(GLIB_GENMARSHAL) @@ -114,6 +112,14 @@ AC_MSG_RESULT([$TEST_PYTHON]) AC_SUBST(TEST_PYTHON) AM_CONDITIONAL([WANT_TWISTED_TESTS], test false != "$TEST_PYTHON") +AC_ARG_ENABLE([installed-tests], + [AC_HELP_STRING([--enable-installed-tests], + [enable as-installed regression tests])], + [], + [enable_installed_tests=no]) +AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], + [test "x$enable_installed_tests" = xyes]) + #AS_AC_EXPAND(DATADIR, $datadir) #DBUS_SERVICES_DIR="$DATADIR/dbus-1/services" #AC_SUBST(DBUS_SERVICES_DIR) diff --git a/data/Makefile.am b/data/Makefile.am index 9386bc5..ec715f7 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,7 +1,7 @@ # Dbus service file servicedir = $(datadir)/dbus-1/services -service_in_files = org.freedesktop.Telepathy.ConnectionManager.haze.service.in -service_DATA = $(service_in_files:.service.in=.service) +service_in_files = haze.service.in +service_DATA = im.telepathy.v1.ConnectionManager.haze.service BUILT_FILES = $(service_DATA) diff --git a/data/haze.service.in b/data/haze.service.in new file mode 100644 index 0000000..997d35c --- /dev/null +++ b/data/haze.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=im.telepathy.v1.ConnectionManager.haze +Exec=@libexecdir@/telepathy-haze-1 diff --git a/data/org.freedesktop.Telepathy.ConnectionManager.haze.service.in b/data/org.freedesktop.Telepathy.ConnectionManager.haze.service.in deleted file mode 100644 index 32b41e9..0000000 --- a/data/org.freedesktop.Telepathy.ConnectionManager.haze.service.in +++ /dev/null @@ -1,3 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Telepathy.ConnectionManager.haze -Exec=@libexecdir@/telepathy-haze diff --git a/extensions/Makefile.am b/extensions/Makefile.am deleted file mode 100644 index ef94a8a..0000000 --- a/extensions/Makefile.am +++ /dev/null @@ -1,86 +0,0 @@ -tools_dir = $(top_srcdir)/tools - -EXTRA_DIST = \ - all.xml \ - $(NULL) - -noinst_LTLIBRARIES = libhaze-extensions.la - -libhaze_extensions_la_SOURCES = \ - extensions.c \ - extensions.h - -nodist_libhaze_extensions_la_SOURCES = \ - _gen/signals-marshal.c \ - _gen/signals-marshal.h \ - _gen/signals-marshal.list \ - _gen/enums.h \ - _gen/gtypes.h \ - _gen/gtypes-body.h \ - _gen/interfaces.h \ - _gen/interfaces-body.h \ - _gen/svc.h \ - _gen/svc.c - -BUILT_SOURCES = \ - _gen/all.xml \ - $(nodist_libhaze_extensions_la_SOURCES) \ - extensions.html - -CLEANFILES = $(BUILT_SOURCES) - -AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_GLIB_CFLAGS@ @TP_GLIB_CFLAGS@ -AM_LDFLAGS = @DBUS_LIBS@ @GLIB_LIBS@ @TP_GLIB_LIBS@ - -# Generated stuff - -DROP_NAMESPACE = sed -e 's@xmlns:tp="http://telepathy\.freedesktop\.org/wiki/DbusSpec.extensions-v0"@@g' -XSLTPROCFLAGS = --nonet --novalid - -_gen/all.xml: all.xml $(wildcard *.xml) Makefile.am - @$(MKDIR_P) _gen - $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) --xinclude $(tools_dir)/identity.xsl \ - $< > $@ - -extensions.html: _gen/all.xml $(tools_dir)/doc-generator.xsl Makefile.am - $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \ - --param "allow-undefined-interfaces" "true()" \ - $(tools_dir)/doc-generator.xsl \ - $< > $@ - -_gen/svc.c _gen/svc.h: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py \ - Makefile.am - $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \ - --filename=_gen/svc --signal-marshal-prefix=_haze_ext \ - --include='<telepathy-glib/telepathy-glib.h>' \ - --include='"_gen/signals-marshal.h"' \ - --allow-unstable \ - --not-implemented-func='tp_dbus_g_method_return_not_implemented' \ - $< Haze_Svc_ - -_gen/signals-marshal.list: _gen/all.xml \ - $(tools_dir)/glib-signals-marshal-gen.py \ - Makefile.am - $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-signals-marshal-gen.py $< > $@ - -_gen/signals-marshal.h: _gen/signals-marshal.list Makefile.am - $(AM_V_GEN)$(GLIB_GENMARSHAL) --header --prefix=_haze_ext_marshal $< > $@ - -_gen/signals-marshal.c: _gen/signals-marshal.list Makefile.am - $(AM_V_GEN){ echo '#include "_gen/signals-marshal.h"' && \ - $(GLIB_GENMARSHAL) --body --prefix=_haze_ext_marshal $< ; } > $@ - -_gen/enums.h: _gen/all.xml $(tools_dir)/c-constants-gen.py \ - Makefile.am - $(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py Haze $< > $@ - -_gen/interfaces.h _gen/interfaces-body.h: _gen/all.xml \ - $(tools_dir)/glib-interfaces-gen.py \ - Makefile.am - $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-interfaces-gen.py \ - Haze _gen/interfaces-body.h _gen/interfaces.h $< - -_gen/gtypes.h _gen/gtypes-body.h: _gen/all.xml \ - $(tools_dir)/glib-gtypes-generator.py Makefile.am - $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-gtypes-generator.py \ - $< _gen/gtypes Haze diff --git a/extensions/all.xml b/extensions/all.xml deleted file mode 100644 index 66b4a89..0000000 --- a/extensions/all.xml +++ /dev/null @@ -1,27 +0,0 @@ -<tp:spec - xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" - xmlns:xi="http://www.w3.org/2001/XInclude"> - -<tp:title>Haze-specific extensions to the Telepathy interfaces</tp:title> - -<tp:copyright>Copyright (C) 2010 Collabora Limited</tp:copyright> - -<tp:license xmlns="http://www.w3.org/1999/xhtml"> -<p>This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version.</p> - -<p>This library 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 -Lesser General Public License for more details.</p> - -<p>You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p> -</tp:license> - -<!-- currently empty --> - -</tp:spec> diff --git a/extensions/extensions.c b/extensions/extensions.c deleted file mode 100644 index 77cc3f2..0000000 --- a/extensions/extensions.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <config.h> -#include "extensions.h" - -/* auto-generated stubs */ -#include "_gen/gtypes-body.h" -#include "_gen/interfaces-body.h" diff --git a/extensions/extensions.h b/extensions/extensions.h deleted file mode 100644 index 14870eb..0000000 --- a/extensions/extensions.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef _HAZE_EXTENSIONS_H -#define _HAZE_EXTENSIONS_H - -#include "extensions/_gen/enums.h" -#include "extensions/_gen/svc.h" - -G_BEGIN_DECLS - -#include "extensions/_gen/gtypes.h" -#include "extensions/_gen/interfaces.h" - -G_END_DECLS - -#endif /* _HAZE_EXTENSIONS_H */ - diff --git a/src/Makefile.am b/src/Makefile.am index 59bae17..4d65771 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,14 +1,14 @@ -libexec_PROGRAMS = telepathy-haze +libexec_PROGRAMS = telepathy-haze-1 -man_MANS = telepathy-haze.8 +man_MANS = telepathy-haze-1.8 %.8: %.8.in Makefile $(AM_V_GEN)sed -e 's,[@]libexecdir[@],@libexecdir@,' < $< > $@ -EXTRA_DIST = telepathy-haze.8.in +EXTRA_DIST = telepathy-haze-1.8.in CLEANFILES = $(man_MANS) -telepathy_haze_SOURCES = main.c \ +telepathy_haze_1_SOURCES = main.c \ defines.h \ debug.c \ debug.h \ @@ -42,8 +42,6 @@ telepathy_haze_SOURCES = main.c \ util.h \ $(NULL) -telepathy_haze_LDADD = $(top_builddir)/extensions/libhaze-extensions.la - AM_CFLAGS = \ -I$(top_srcdir) \ -I$(top_builddir) \ diff --git a/src/connection-aliasing.c b/src/connection-aliasing.c index 3ed3ade..90f25c2 100644 --- a/src/connection-aliasing.c +++ b/src/connection-aliasing.c @@ -23,6 +23,7 @@ #include "connection-aliasing.h" #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "connection.h" #include "debug.h" @@ -39,24 +40,56 @@ can_alias (HazeConnection *conn) return (prpl->alias_buddy != NULL); } +typedef enum { + DP_FLAGS +} AliasingDBusProperty; + +static TpDBusPropertiesMixinPropImpl props[] = { + { "AliasFlags", GINT_TO_POINTER (DP_FLAGS), NULL }, + { NULL } +}; + static void -haze_connection_get_alias_flags (TpSvcConnectionInterfaceAliasing *self, - DBusGMethodInvocation *context) +haze_connection_aliasing_properties_getter (GObject *object, + GQuark interface, + GQuark name, + GValue *value, + gpointer getter_data) { - TpBaseConnection *base = TP_BASE_CONNECTION (self); - HazeConnection *conn = HAZE_CONNECTION (base); - guint flags = 0; + AliasingDBusProperty which = GPOINTER_TO_INT (getter_data); + HazeConnection *conn = HAZE_CONNECTION (object); + TpBaseConnection *base = (TpBaseConnection *) conn; - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (can_alias (conn)) + if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { - flags = TP_CONNECTION_ALIAS_FLAG_USER_SET; + /* not CONNECTED yet, so our connection doesn't have the prpl info + * yet - return dummy values */ + if (G_VALUE_HOLDS_UINT (value)) + g_value_set_uint (value, 0); + else + g_assert_not_reached (); + + return; } - DEBUG ("alias flags: %u", flags); - tp_svc_connection_interface_aliasing_return_from_get_alias_flags ( - context, flags); + switch (which) + { + case DP_FLAGS: + { + guint flags = 0; + + if (can_alias (conn)) + { + flags = TP_CONNECTION_ALIAS_FLAG_USER_SET; + } + + g_value_set_uint (value, flags); + } + break; + + default: + g_assert_not_reached (); + } } static const gchar * @@ -65,7 +98,7 @@ get_alias (HazeConnection *self, { TpBaseConnection *base = TP_BASE_CONNECTION (self); TpHandleRepoIface *contact_handles = - tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base, TP_ENTITY_TYPE_CONTACT); const gchar *bname = tp_handle_inspect (contact_handles, handle); const gchar *alias; @@ -98,56 +131,21 @@ get_alias (HazeConnection *self, } static void -haze_connection_get_aliases (TpSvcConnectionInterfaceAliasing *self, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - HazeConnection *conn = HAZE_CONNECTION (self); - TpBaseConnection *base = TP_BASE_CONNECTION (conn); - TpHandleRepoIface *contact_handles = - tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); - guint i; - GError *error = NULL; - GHashTable *aliases; - - if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - aliases = g_hash_table_new (NULL, NULL); - - for (i = 0; i < contacts->len; i++) - { - TpHandle handle = g_array_index (contacts, TpHandle, i); - - g_hash_table_insert (aliases, GUINT_TO_POINTER (handle), - (gchar *) get_alias (conn, handle)); - } - - tp_svc_connection_interface_aliasing_return_from_get_aliases ( - context, aliases); - g_hash_table_destroy (aliases); -} - -static void -haze_connection_request_aliases (TpSvcConnectionInterfaceAliasing *self, +haze_connection_request_aliases (TpSvcConnectionInterfaceAliasing1 *self, const GArray *contacts, - DBusGMethodInvocation *context) + GDBusMethodInvocation *context) { HazeConnection *conn = HAZE_CONNECTION (self); TpBaseConnection *base = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_handles = - tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base, TP_ENTITY_TYPE_CONTACT); guint i; GError *error = NULL; const gchar **aliases; if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error)) { - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); g_error_free (error); return; } @@ -161,7 +159,7 @@ haze_connection_request_aliases (TpSvcConnectionInterfaceAliasing *self, aliases[i] = get_alias (conn, handle); } - tp_svc_connection_interface_aliasing_return_from_request_aliases ( + tp_svc_connection_interface_aliasing1_return_from_request_aliases ( context, aliases); g_free (aliases); } @@ -178,31 +176,22 @@ set_alias_success_cb (PurpleAccount *account, const char *new_alias) { TpBaseConnection *base_conn; - GPtrArray *aliases; - GValue entry = {0, }; + GHashTable *aliases; DEBUG ("purple_account_set_public_alias succeeded, new alias %s", new_alias); base_conn = ACCOUNT_GET_TP_BASE_CONNECTION (account); - g_value_init (&entry, TP_STRUCT_TYPE_ALIAS_PAIR); - g_value_take_boxed (&entry, - dbus_g_type_specialized_construct (TP_STRUCT_TYPE_ALIAS_PAIR)); - - dbus_g_type_struct_set (&entry, - 0, tp_base_connection_get_self_handle (base_conn), - 1, new_alias, - G_MAXUINT); - - aliases = g_ptr_array_sized_new (1); - g_ptr_array_add (aliases, g_value_get_boxed (&entry)); + aliases = g_hash_table_new (NULL, NULL); + g_hash_table_insert (aliases, + GUINT_TO_POINTER (tp_base_connection_get_self_handle (base_conn)), + (gchar *) new_alias); - tp_svc_connection_interface_aliasing_emit_aliases_changed (base_conn, + tp_svc_connection_interface_aliasing1_emit_aliases_changed (base_conn, aliases); - g_value_unset (&entry); - g_ptr_array_free (aliases, TRUE); + g_hash_table_unref (aliases); } static void @@ -275,22 +264,22 @@ set_aliases_foreach (gpointer key, } static void -haze_connection_set_aliases (TpSvcConnectionInterfaceAliasing *self, +haze_connection_set_aliases (TpSvcConnectionInterfaceAliasing1 *self, GHashTable *aliases, - DBusGMethodInvocation *context) + GDBusMethodInvocation *context) { HazeConnection *conn = HAZE_CONNECTION (self); TpBaseConnection *base = TP_BASE_CONNECTION (conn); GError *error = NULL; struct _g_hash_table_foreach_all_in_my_brain data = { conn, NULL, &error }; data.contact_handles = - tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base, TP_ENTITY_TYPE_CONTACT); if (!can_alias (conn)) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "You can't set aliases on this protocol"); - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); g_error_free (error); return; } @@ -299,12 +288,12 @@ haze_connection_set_aliases (TpSvcConnectionInterfaceAliasing *self, if (error) { - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); g_error_free (error); } else { - tp_svc_connection_interface_aliasing_return_from_set_aliases (context); + tp_svc_connection_interface_aliasing1_return_from_set_aliases (context); } } @@ -313,13 +302,11 @@ void haze_connection_aliasing_iface_init (gpointer g_iface, gpointer iface_data) { - TpSvcConnectionInterfaceAliasingClass *klass = - (TpSvcConnectionInterfaceAliasingClass *) g_iface; + TpSvcConnectionInterfaceAliasing1Class *klass = + (TpSvcConnectionInterfaceAliasing1Class *) g_iface; -#define IMPLEMENT(x) tp_svc_connection_interface_aliasing_implement_##x (\ +#define IMPLEMENT(x) tp_svc_connection_interface_aliasing1_implement_##x (\ klass, haze_connection_##x) - IMPLEMENT(get_alias_flags); - IMPLEMENT(get_aliases); IMPLEMENT(request_aliases); IMPLEMENT(set_aliases); #undef IMPLEMENT @@ -332,7 +319,7 @@ blist_node_aliased_cb (PurpleBlistNode *node, { PurpleBuddy *buddy; TpBaseConnection *base_conn; - GPtrArray *aliases; + GHashTable *aliases; TpHandle handle; TpHandleRepoIface *contact_handles; @@ -342,19 +329,18 @@ blist_node_aliased_cb (PurpleBlistNode *node, buddy = (PurpleBuddy *)node; base_conn = ACCOUNT_GET_TP_BASE_CONNECTION (buddy->account); contact_handles = - tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base_conn, TP_ENTITY_TYPE_CONTACT); handle = tp_handle_ensure (contact_handles, buddy->name, NULL, NULL); - aliases = g_ptr_array_sized_new (1); - g_ptr_array_add (aliases, tp_value_array_build (2, - G_TYPE_UINT, handle, - G_TYPE_STRING, purple_buddy_get_alias (buddy), - G_TYPE_INVALID)); + aliases = g_hash_table_new (NULL, NULL); + g_hash_table_insert (aliases, + GUINT_TO_POINTER (handle), + (gchar *) purple_buddy_get_alias (buddy)); - tp_svc_connection_interface_aliasing_emit_aliases_changed (base_conn, + tp_svc_connection_interface_aliasing1_emit_aliases_changed (base_conn, aliases); - g_ptr_array_free (aliases, TRUE); + g_hash_table_unref (aliases); } void @@ -364,33 +350,26 @@ haze_connection_aliasing_class_init (GObjectClass *object_class) purple_signal_connect (blist_handle, "blist-node-aliased", object_class, PURPLE_CALLBACK (blist_node_aliased_cb), NULL); + + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CONNECTION_INTERFACE_ALIASING1, + haze_connection_aliasing_properties_getter, NULL, + props); } -static void -fill_contact_attributes (GObject *object, - const GArray *contacts, - GHashTable *attributes_hash) +gboolean +haze_connection_aliasing_fill_contact_attributes (HazeConnection *self, + const gchar *dbus_interface, + TpHandle handle, + GVariantDict *attributes) { - HazeConnection *self = HAZE_CONNECTION (object); - guint i; - - for (i = 0; i < contacts->len; i++) + if (!tp_strdiff (dbus_interface, TP_IFACE_CONNECTION_INTERFACE_ALIASING1)) { - TpHandle handle = g_array_index (contacts, guint, i); - GValue *value = tp_g_value_slice_new (G_TYPE_STRING); - - g_value_set_string (value, get_alias (self, handle)); - - /* this steals the GValue */ - tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, - TP_IFACE_CONNECTION_INTERFACE_ALIASING "/alias", value); + g_variant_dict_insert_value (attributes, + TP_TOKEN_CONNECTION_INTERFACE_ALIASING1_ALIAS, + g_variant_new_string (get_alias (self, handle))); + return TRUE; } -} -void -haze_connection_aliasing_init (GObject *object) -{ - tp_contacts_mixin_add_contact_attributes_iface (object, - TP_IFACE_CONNECTION_INTERFACE_ALIASING, - fill_contact_attributes); + return FALSE; } diff --git a/src/connection-aliasing.h b/src/connection-aliasing.h index b1002ec..d3807d6 100644 --- a/src/connection-aliasing.h +++ b/src/connection-aliasing.h @@ -23,10 +23,18 @@ #include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + +#include "connection.h" void haze_connection_aliasing_iface_init (gpointer g_iface, gpointer iface_data); void haze_connection_aliasing_class_init (GObjectClass *object_class); -void haze_connection_aliasing_init (GObject *object); + +gboolean haze_connection_aliasing_fill_contact_attributes ( + HazeConnection *self, + const gchar *dbus_interface, + TpHandle handle, + GVariantDict *attributes); #endif diff --git a/src/connection-avatars.c b/src/connection-avatars.c index f4dca89..7f0a7d5 100644 --- a/src/connection-avatars.c +++ b/src/connection-avatars.c @@ -25,6 +25,7 @@ #include <string.h> #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include <libpurple/cipher.h> @@ -88,9 +89,8 @@ static TpDBusPropertiesMixinPropImpl props[] = { { "SupportedAvatarMIMETypes", GINT_TO_POINTER (DP_TYPES), NULL }, { NULL } }; -TpDBusPropertiesMixinPropImpl *haze_connection_avatars_properties = props; -void +static void haze_connection_avatars_properties_getter (GObject *object, GQuark interface, GQuark name, @@ -189,32 +189,6 @@ haze_connection_get_icon_spec_requirements (PurpleBuddyIconSpec *icon_spec, *max_bytes = icon_spec->max_filesize; } -static void -haze_connection_get_avatar_requirements (TpSvcConnectionInterfaceAvatars *self, - DBusGMethodInvocation *context) -{ - HazeConnection *conn = HAZE_CONNECTION (self); - TpBaseConnection *base = TP_BASE_CONNECTION (conn); - PurplePluginProtocolInfo *prpl_info; - PurpleBuddyIconSpec *icon_spec; - guint min_height, min_width, max_height, max_width, max_bytes; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - prpl_info = HAZE_CONNECTION_GET_PRPL_INFO (conn); - icon_spec = &(prpl_info->icon_spec); - - /* If the spec or the formats are null, this iface wasn't implemented. */ - g_assert (icon_spec != NULL && icon_spec->format != NULL); - - haze_connection_get_icon_spec_requirements (icon_spec, NULL, &min_height, - &min_width, NULL, NULL, &max_height, &max_width, &max_bytes); - - tp_svc_connection_interface_avatars_return_from_get_avatar_requirements ( - context, (const gchar **) _get_acceptable_mime_types (conn), - min_width, min_height, max_width, max_height, max_bytes); -} - static GArray * get_avatar (HazeConnection *conn, TpHandle handle) @@ -222,7 +196,7 @@ get_avatar (HazeConnection *conn, GArray *avatar = NULL; TpBaseConnection *base = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_handles = - tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base, TP_ENTITY_TYPE_CONTACT); gconstpointer icon_data = NULL; size_t icon_size = 0; @@ -308,33 +282,9 @@ get_handle_token (HazeConnection *conn, } static void -haze_connection_get_avatar_tokens (TpSvcConnectionInterfaceAvatars *self, - const GArray *contacts, - DBusGMethodInvocation *context) -{ - gchar **icons; - HazeConnection *conn = HAZE_CONNECTION (self); - TpBaseConnection *base = TP_BASE_CONNECTION (self); - guint i; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - icons = g_new0 (gchar *, contacts->len + 1); - for (i = 0; i < contacts->len; i++) - { - TpHandle handle = g_array_index (contacts, TpHandle, i); - icons[i] = get_handle_token (conn, handle); - } - - tp_svc_connection_interface_avatars_return_from_get_avatar_tokens ( - context, (const gchar **) icons); - g_strfreev (icons); -} - -static void -haze_connection_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *self, +haze_connection_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars1 *self, const GArray *contacts, - DBusGMethodInvocation *context) + GDBusMethodInvocation *context) { HazeConnection *conn = HAZE_CONNECTION (self); TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); @@ -343,11 +293,11 @@ haze_connection_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *self, GError *err = NULL; TpHandleRepoIface *contact_repo = - tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base_conn, TP_ENTITY_TYPE_CONTACT); if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &err)) { - dbus_g_method_return_error (context, err); + g_dbus_method_invocation_return_gerror (context, err); g_error_free (err); return; } @@ -388,49 +338,16 @@ haze_connection_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *self, g_hash_table_insert (tokens, GUINT_TO_POINTER (handle), token); } - tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens ( + tp_svc_connection_interface_avatars1_return_from_get_known_avatar_tokens ( context, tokens); g_hash_table_unref (tokens); } static void -haze_connection_request_avatar (TpSvcConnectionInterfaceAvatars *self, - guint contact, - DBusGMethodInvocation *context) -{ - HazeConnection *conn = HAZE_CONNECTION (self); - TpBaseConnection *base = TP_BASE_CONNECTION (conn); - GArray *avatar; - GError *error = NULL; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - avatar = get_avatar (conn, contact); - if (avatar) - { - DEBUG ("returning avatar for %u, length %u", contact, avatar->len); - tp_svc_connection_interface_avatars_return_from_request_avatar ( - context, avatar, "" /* no way to get MIME type from purple */); - g_array_free (avatar, TRUE); - } - else - { - DEBUG ("handle %u has no avatar", contact); - g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, - "handle %u has no avatar", contact); - - - dbus_g_method_return_error (context, error); - - g_error_free (error); - } -} - -static void -haze_connection_request_avatars (TpSvcConnectionInterfaceAvatars *self, +haze_connection_request_avatars (TpSvcConnectionInterfaceAvatars1 *self, const GArray *contacts, - DBusGMethodInvocation *context) + GDBusMethodInvocation *context) { HazeConnection *conn = HAZE_CONNECTION (self); TpBaseConnection *base = TP_BASE_CONNECTION (conn); @@ -445,19 +362,19 @@ haze_connection_request_avatars (TpSvcConnectionInterfaceAvatars *self, if (avatar != NULL) { gchar *token = get_token (avatar); - tp_svc_connection_interface_avatars_emit_avatar_retrieved ( + tp_svc_connection_interface_avatars1_emit_avatar_retrieved ( conn, handle, token, avatar, "" /* unknown MIME type */); g_free (token); g_array_free (avatar, TRUE); } } - tp_svc_connection_interface_avatars_return_from_request_avatars (context); + tp_svc_connection_interface_avatars1_return_from_request_avatars (context); } static void -haze_connection_clear_avatar (TpSvcConnectionInterfaceAvatars *self, - DBusGMethodInvocation *context) +haze_connection_clear_avatar (TpSvcConnectionInterfaceAvatars1 *self, + GDBusMethodInvocation *context) { HazeConnection *conn = HAZE_CONNECTION (self); TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); @@ -465,16 +382,16 @@ haze_connection_clear_avatar (TpSvcConnectionInterfaceAvatars *self, purple_buddy_icons_set_account_icon (account, NULL, 0); - tp_svc_connection_interface_avatars_return_from_clear_avatar (context); - tp_svc_connection_interface_avatars_emit_avatar_updated (conn, + tp_svc_connection_interface_avatars1_return_from_clear_avatar (context); + tp_svc_connection_interface_avatars1_emit_avatar_updated (conn, tp_base_connection_get_self_handle (base_conn), ""); } static void -haze_connection_set_avatar (TpSvcConnectionInterfaceAvatars *self, +haze_connection_set_avatar (TpSvcConnectionInterfaceAvatars1 *self, const GArray *avatar, const gchar *mime_type, - DBusGMethodInvocation *context) + GDBusMethodInvocation *context) { HazeConnection *conn = HAZE_CONNECTION (self); TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); @@ -499,7 +416,7 @@ haze_connection_set_avatar (TpSvcConnectionInterfaceAvatars *self, "but the limit is %" G_GSIZE_FORMAT "B", icon_len, max_filesize); - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); g_error_free (error); return; @@ -526,7 +443,7 @@ haze_connection_set_avatar (TpSvcConnectionInterfaceAvatars *self, g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a supported MIME type", mime_type); - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); g_error_free (error); @@ -543,8 +460,8 @@ haze_connection_set_avatar (TpSvcConnectionInterfaceAvatars *self, token = get_token (avatar); DEBUG ("%s", token); - tp_svc_connection_interface_avatars_return_from_set_avatar (context, token); - tp_svc_connection_interface_avatars_emit_avatar_updated (conn, + tp_svc_connection_interface_avatars1_return_from_set_avatar (context, token); + tp_svc_connection_interface_avatars1_emit_avatar_updated (conn, tp_base_connection_get_self_handle (base_conn), token); g_free (token); } @@ -553,15 +470,12 @@ void haze_connection_avatars_iface_init (gpointer g_iface, gpointer iface_data) { - TpSvcConnectionInterfaceAvatarsClass *klass = - (TpSvcConnectionInterfaceAvatarsClass *) g_iface; + TpSvcConnectionInterfaceAvatars1Class *klass = + (TpSvcConnectionInterfaceAvatars1Class *) g_iface; -#define IMPLEMENT(x) tp_svc_connection_interface_avatars_implement_##x (\ +#define IMPLEMENT(x) tp_svc_connection_interface_avatars1_implement_##x (\ klass, haze_connection_##x) - IMPLEMENT(get_avatar_requirements); - IMPLEMENT(get_avatar_tokens); IMPLEMENT(get_known_avatar_tokens); - IMPLEMENT(request_avatar); IMPLEMENT(request_avatars); IMPLEMENT(set_avatar); IMPLEMENT(clear_avatar); @@ -575,7 +489,7 @@ buddy_icon_changed_cb (PurpleBuddy *buddy, HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (buddy->account); TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_repo = - tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base_conn, TP_ENTITY_TYPE_CONTACT); const char* bname = purple_buddy_get_name (buddy); TpHandle contact = tp_handle_ensure (contact_repo, bname, NULL, NULL); @@ -584,7 +498,7 @@ buddy_icon_changed_cb (PurpleBuddy *buddy, DEBUG ("%s '%s'", bname, token); - tp_svc_connection_interface_avatars_emit_avatar_updated (conn, contact, + tp_svc_connection_interface_avatars1_emit_avatar_updated (conn, contact, token); g_free (token); } @@ -596,35 +510,30 @@ haze_connection_avatars_class_init (GObjectClass *object_class) purple_signal_connect (blist_handle, "buddy-icon-changed", object_class, PURPLE_CALLBACK (buddy_icon_changed_cb), NULL); + + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CONNECTION_INTERFACE_AVATARS1, + haze_connection_avatars_properties_getter, NULL, + props); } -static void -fill_contact_attributes (GObject *object, - const GArray *contacts, - GHashTable *attributes_hash) +gboolean +haze_connection_avatars_fill_contact_attributes (HazeConnection *self, + const gchar *dbus_interface, + TpHandle handle, + GVariantDict *attributes) { - HazeConnection *self = HAZE_CONNECTION (object); - guint i; - - for (i = 0; i < contacts->len; i++) + if (!tp_strdiff (dbus_interface, TP_IFACE_CONNECTION_INTERFACE_AVATARS1)) { - TpHandle handle = g_array_index (contacts, guint, i); gchar *token = get_handle_token (self, handle); - GValue *value = tp_g_value_slice_new (G_TYPE_STRING); g_assert (token != NULL); - g_value_set_string (value, token); - - /* this steals the GValue */ - tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, - TP_IFACE_CONNECTION_INTERFACE_AVATARS "/token", value); + g_variant_dict_insert_value (attributes, + TP_TOKEN_CONNECTION_INTERFACE_AVATARS1_TOKEN, + g_variant_new_string (token)); + g_free (token); + return TRUE; } -} -void -haze_connection_avatars_init (GObject *object) -{ - tp_contacts_mixin_add_contact_attributes_iface (object, - TP_IFACE_CONNECTION_INTERFACE_AVATARS, - fill_contact_attributes); + return FALSE; } diff --git a/src/connection-avatars.h b/src/connection-avatars.h index 8ac37ab..cf4f29b 100644 --- a/src/connection-avatars.h +++ b/src/connection-avatars.h @@ -27,13 +27,10 @@ #include <libpurple/purple.h> +#include "connection.h" + void haze_connection_avatars_iface_init (gpointer g_iface, gpointer iface_data); void haze_connection_avatars_class_init (GObjectClass *object_class); -void haze_connection_avatars_init (GObject *object); - -extern TpDBusPropertiesMixinPropImpl *haze_connection_avatars_properties; -void haze_connection_avatars_properties_getter (GObject *object, - GQuark interface, GQuark name, GValue *value, gpointer getter_data); void haze_connection_get_icon_spec_requirements (PurpleBuddyIconSpec *icon_spec, GStrv *mime_types, @@ -45,4 +42,10 @@ void haze_connection_get_icon_spec_requirements (PurpleBuddyIconSpec *icon_spec, guint *max_width, guint *max_bytes); +gboolean haze_connection_avatars_fill_contact_attributes ( + HazeConnection *self, + const gchar *dbus_interface, + TpHandle handle, + GVariantDict *attributes); + #endif diff --git a/src/connection-capabilities.c b/src/connection-capabilities.c index ce6fd8f..7da1c24 100644 --- a/src/connection-capabilities.c +++ b/src/connection-capabilities.c @@ -25,170 +25,60 @@ #include "connection-capabilities.h" #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "connection.h" #include "debug.h" static void -free_rcc_list (GPtrArray *rccs) -{ - g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, rccs); -} - -static void -haze_connection_update_capabilities (TpSvcConnectionInterfaceContactCapabilities *iface, +haze_connection_update_capabilities (TpSvcConnectionInterfaceContactCapabilities1 *iface, const GPtrArray *clients, - DBusGMethodInvocation *context) + GDBusMethodInvocation *context) { HazeConnection *self = HAZE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - tp_svc_connection_interface_contact_capabilities_return_from_update_capabilities ( + tp_svc_connection_interface_contact_capabilities1_return_from_update_capabilities ( context); } -static GPtrArray * -haze_connection_get_handle_contact_capabilities (HazeConnection *self, - TpHandle handle) -{ - GPtrArray *arr = g_ptr_array_new (); - GValue monster = {0, }; - GHashTable *fixed_properties; - GValue *channel_type_value; - GValue *target_handle_type_value; - const gchar * const text_allowed_properties[] = { - TP_PROP_CHANNEL_TARGET_HANDLE, NULL }; - - if (0 == handle) - { - /* obsolete request for the connection's capabilities, do nothing */ - return arr; - } - - /* TODO: Check for presence */ - - g_value_init (&monster, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS); - g_value_take_boxed (&monster, - dbus_g_type_specialized_construct ( - TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS)); - - fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, - (GDestroyNotify) tp_g_value_slice_free); - - channel_type_value = tp_g_value_slice_new (G_TYPE_STRING); - g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_TEXT); - g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".ChannelType", - channel_type_value); - - target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT); - g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT); - g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".TargetHandleType", - target_handle_type_value); - - dbus_g_type_struct_set (&monster, - 0, fixed_properties, - 1, text_allowed_properties, - G_MAXUINT); - - g_hash_table_unref (fixed_properties); - - g_ptr_array_add (arr, g_value_get_boxed (&monster)); - - return arr; -} - -static void -conn_capabilities_fill_contact_attributes_contact_caps ( - GObject *obj, - const GArray *contacts, - GHashTable *attributes_hash) -{ - HazeConnection *self = HAZE_CONNECTION (obj); - guint i; - - for (i = 0; i < contacts->len; i++) - { - TpHandle handle = g_array_index (contacts, TpHandle, i); - GPtrArray *array; - - array = haze_connection_get_handle_contact_capabilities (self, handle); - - if (array->len > 0) - { - GValue *val = tp_g_value_slice_new ( - TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST); - - g_value_take_boxed (val, array); - tp_contacts_mixin_set_contact_attribute (attributes_hash, - handle, TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES "/capabilities", - val); - } - else - g_ptr_array_free (array, TRUE); - } -} - -static void -haze_connection_get_contact_capabilities ( - TpSvcConnectionInterfaceContactCapabilities *svc, - const GArray *handles, - DBusGMethodInvocation *context) +gboolean +haze_connection_contact_capabilities_fill_contact_attributes ( + HazeConnection *self, + const gchar *dbus_interface, + TpHandle handle, + GVariantDict *attributes) { - HazeConnection *self = HAZE_CONNECTION (svc); - TpBaseConnection *base = (TpBaseConnection *) self; - TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, - TP_HANDLE_TYPE_CONTACT); - guint i; - GHashTable *ret; - GError *error = NULL; - - TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); - - if (!tp_handles_are_valid (contact_handles, handles, FALSE, &error)) - { - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - ret = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) free_rcc_list); - - for (i = 0; i < handles->len; i++) + if (!tp_strdiff (dbus_interface, + TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES1)) { - TpHandle handle = g_array_index (handles, TpHandle, i); - GPtrArray *arr; - - arr = haze_connection_get_handle_contact_capabilities (self, handle); - g_hash_table_insert (ret, GUINT_TO_POINTER (handle), arr); + /* TODO: Check for presence */ + g_variant_dict_insert_value (attributes, + TP_TOKEN_CONNECTION_INTERFACE_CONTACT_CAPABILITIES1_CAPABILITIES, + g_variant_new_parsed ("[({%s: <%s>, %s: <%u>}, [%s])]", + /* Fixed properties */ + TP_PROP_CHANNEL_CHANNEL_TYPE, TP_IFACE_CHANNEL_TYPE_TEXT, + TP_PROP_CHANNEL_TARGET_ENTITY_TYPE, + (guint32) TP_ENTITY_TYPE_CONTACT, + /* Allowed properties */ + TP_PROP_CHANNEL_TARGET_HANDLE)); + return TRUE; } - tp_svc_connection_interface_contact_capabilities_return_from_get_contact_capabilities - (context, ret); - - g_hash_table_unref (ret); + return FALSE; } void haze_connection_contact_capabilities_iface_init (gpointer g_iface, gpointer iface_data) { - TpSvcConnectionInterfaceContactCapabilitiesClass *klass = g_iface; + TpSvcConnectionInterfaceContactCapabilities1Class *klass = g_iface; #define IMPLEMENT(x) \ - tp_svc_connection_interface_contact_capabilities_implement_##x (\ + tp_svc_connection_interface_contact_capabilities1_implement_##x (\ klass, haze_connection_##x) IMPLEMENT(update_capabilities); - IMPLEMENT(get_contact_capabilities); #undef IMPLEMENT } - -void -haze_connection_capabilities_init (GObject *object) -{ - tp_contacts_mixin_add_contact_attributes_iface (object, - TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, - conn_capabilities_fill_contact_attributes_contact_caps); -} diff --git a/src/connection-capabilities.h b/src/connection-capabilities.h index e98bf98..a817c02 100644 --- a/src/connection-capabilities.h +++ b/src/connection-capabilities.h @@ -23,8 +23,17 @@ #include <glib-object.h> +#include <telepathy-glib/telepathy-glib.h> + +#include "connection.h" + void haze_connection_contact_capabilities_iface_init (gpointer g_iface, gpointer iface_data); -void haze_connection_capabilities_init (GObject *object); + +gboolean haze_connection_contact_capabilities_fill_contact_attributes ( + HazeConnection *self, + const gchar *dbus_interface, + TpHandle handle, + GVariantDict *attributes); #endif diff --git a/src/connection-mail.c b/src/connection-mail.c index 767ee2d..2614b27 100644 --- a/src/connection-mail.c +++ b/src/connection-mail.c @@ -19,8 +19,6 @@ */ #include "config.h" -#include "extensions/extensions.h" - #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> @@ -43,21 +41,21 @@ static GPtrArray empty_array = { 0 }; static void haze_connection_mail_request_inbox_url ( - TpSvcConnectionInterfaceMailNotification *iface, - DBusGMethodInvocation *context) + TpSvcConnectionInterfaceMailNotification1 *iface, + GDBusMethodInvocation *context) { GError e = {TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "LibPurple does not provide Inbox URL"}; - dbus_g_method_return_error (context, &e); + g_dbus_method_invocation_return_gerror (context, &e); } static void haze_connection_mail_request_mail_url ( - TpSvcConnectionInterfaceMailNotification *iface, + TpSvcConnectionInterfaceMailNotification1 *iface, const gchar *in_id, const GValue *in_url_data, - DBusGMethodInvocation *context) + GDBusMethodInvocation *context) { GValueArray *result; @@ -65,7 +63,7 @@ haze_connection_mail_request_mail_url ( { GError e = {TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Wrong type for url-data"}; - dbus_g_method_return_error (context, &e); + g_dbus_method_invocation_return_gerror (context, &e); return; } @@ -75,7 +73,7 @@ haze_connection_mail_request_mail_url ( TP_ARRAY_TYPE_HTTP_POST_DATA_LIST, &empty_array, G_TYPE_INVALID); - tp_svc_connection_interface_mail_notification_return_from_request_inbox_url ( + tp_svc_connection_interface_mail_notification1_return_from_request_inbox_url ( context, result); g_value_array_free (result); @@ -93,9 +91,9 @@ void haze_connection_mail_iface_init (gpointer g_iface, gpointer iface_data) { - TpSvcConnectionInterfaceMailNotificationClass *klass = g_iface; + TpSvcConnectionInterfaceMailNotification1Class *klass = g_iface; -#define IMPLEMENT(x) tp_svc_connection_interface_mail_notification_implement_##x (\ +#define IMPLEMENT(x) tp_svc_connection_interface_mail_notification1_implement_##x (\ klass, haze_connection_mail_##x) IMPLEMENT(request_inbox_url); IMPLEMENT(request_mail_url); @@ -222,8 +220,8 @@ haze_connection_mail_notify_emails (PurpleConnection *pc, const char **urls) { GPtrArray *mails; - TpSvcConnectionInterfaceMailNotification *conn = - TP_SVC_CONNECTION_INTERFACE_MAIL_NOTIFICATION ( + TpSvcConnectionInterfaceMailNotification1 *conn = + TP_SVC_CONNECTION_INTERFACE_MAIL_NOTIFICATION1 ( ACCOUNT_GET_TP_BASE_CONNECTION ( purple_connection_get_account (pc))); @@ -292,7 +290,7 @@ haze_connection_mail_notify_emails (PurpleConnection *pc, } } - tp_svc_connection_interface_mail_notification_emit_mails_received ( + tp_svc_connection_interface_mail_notification1_emit_mails_received ( conn, mails); g_ptr_array_unref (mails); diff --git a/src/connection-presence.c b/src/connection-presence.c index 23c8764..071ed21 100644 --- a/src/connection-presence.c +++ b/src/connection-presence.c @@ -25,11 +25,7 @@ #include "debug.h" #include <telepathy-glib/telepathy-glib.h> - -static const TpPresenceStatusOptionalArgumentSpec arg_specs[] = { - { "message", "s" }, - { NULL, NULL } -}; +#include <telepathy-glib/telepathy-glib-dbus.h> typedef enum { HAZE_STATUS_AVAILABLE = 0, @@ -45,18 +41,14 @@ typedef enum { /* Indexed by HazeStatusIndex */ static const TpPresenceStatusSpec statuses[] = { - { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE, - arg_specs, NULL, NULL }, - { "busy", TP_CONNECTION_PRESENCE_TYPE_BUSY, TRUE, - arg_specs, NULL, NULL }, - { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY, TRUE, - arg_specs, NULL, NULL }, - { "xa", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, TRUE, - arg_specs, NULL, NULL }, - { "hidden", TP_CONNECTION_PRESENCE_TYPE_HIDDEN, TRUE, NULL, NULL, NULL }, - { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE, FALSE, NULL, NULL, NULL }, - { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN, FALSE, NULL, NULL, NULL }, - { NULL, TP_CONNECTION_PRESENCE_TYPE_UNSET, FALSE, NULL, NULL, NULL } + { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE, TRUE }, + { "busy", TP_CONNECTION_PRESENCE_TYPE_BUSY, TRUE, TRUE }, + { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY, TRUE, TRUE }, + { "xa", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, TRUE, TRUE }, + { "hidden", TP_CONNECTION_PRESENCE_TYPE_HIDDEN, TRUE, FALSE }, + { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE, FALSE, FALSE }, + { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN, FALSE, FALSE }, + { NULL } }; /* Indexed by HazeStatusIndex */ @@ -85,11 +77,9 @@ _get_tp_status (PurpleStatus *p_status) { PurpleStatusType *type; PurpleStatusPrimitive prim; - GHashTable *arguments = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, (GDestroyNotify) tp_g_value_slice_free); guint status_ix = -1; const gchar *xhtml_message; - gchar *message; + gchar *message = NULL; TpPresenceStatus *tp_status; if (p_status == NULL) @@ -114,18 +104,12 @@ _get_tp_status (PurpleStatus *p_status) xhtml_message = purple_status_get_attr_string (p_status, "message"); if (xhtml_message) { - GValue *message_v = g_slice_new0 (GValue); - message = purple_markup_strip_html (xhtml_message); - g_value_init (message_v, G_TYPE_STRING); - g_value_set_string (message_v, message); - g_hash_table_insert (arguments, "message", message_v); - g_free (message); } } - tp_status = tp_presence_status_new (status_ix, arguments); - g_hash_table_destroy (arguments); + tp_status = tp_presence_status_new (status_ix, message); + g_free (message); return tp_status; } @@ -151,10 +135,10 @@ _get_purple_status_id (HazeConnection *self, } static gboolean -_status_available (GObject *obj, +_status_available (TpPresenceMixin *mixin, guint index) { - HazeConnection *self = HAZE_CONNECTION (obj); + HazeConnection *self = HAZE_CONNECTION (mixin); /* FIXME: (a) should we be able to set offline on ourselves; * (b) deal with some protocols not having status messages. */ @@ -162,57 +146,45 @@ _status_available (GObject *obj, } -static GHashTable * -_get_contact_statuses (GObject *obj, - const GArray *contacts, - GError **error) +static TpPresenceStatus * +_get_contact_status (TpPresenceMixin *mixin, + TpHandle handle) { - GHashTable *status_table = g_hash_table_new_full (g_direct_hash, - g_direct_equal, NULL, NULL); - HazeConnection *conn = HAZE_CONNECTION (obj); - TpBaseConnection *base_conn = TP_BASE_CONNECTION (obj); + HazeConnection *conn = HAZE_CONNECTION (mixin); + TpBaseConnection *base_conn = TP_BASE_CONNECTION (mixin); TpHandleRepoIface *handle_repo = - tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); - guint i; + tp_base_connection_get_handles (base_conn, TP_ENTITY_TYPE_CONTACT); + PurpleStatus *p_status; - for (i = 0; i < contacts->len; i++) + g_assert (tp_handle_is_valid (handle_repo, handle, NULL)); + + if (handle == tp_base_connection_get_self_handle (base_conn)) + { + p_status = purple_account_get_active_status (conn->account); + } + else { - TpHandle handle = g_array_index (contacts, TpHandle, i); const gchar *bname; - TpPresenceStatus *tp_status; PurpleBuddy *buddy; - PurpleStatus *p_status; - g_assert (tp_handle_is_valid (handle_repo, handle, NULL)); + bname = tp_handle_inspect (handle_repo, handle); + buddy = purple_find_buddy (conn->account, bname); - if (handle == tp_base_connection_get_self_handle (base_conn)) + if (buddy) { - p_status = purple_account_get_active_status (conn->account); + PurplePresence *presence = purple_buddy_get_presence (buddy); + + p_status = purple_presence_get_active_status (presence); } else { - bname = tp_handle_inspect (handle_repo, handle); - buddy = purple_find_buddy (conn->account, bname); - - if (buddy) - { - PurplePresence *presence = purple_buddy_get_presence (buddy); - - p_status = purple_presence_get_active_status (presence); - } - else - { - DEBUG ("[%s] %s isn't on the blist, ergo no status!", - conn->account->username, bname); - p_status = NULL; - } + DEBUG ("[%s] %s isn't on the blist, ergo no status!", + conn->account->username, bname); + p_status = NULL; } - - tp_status = _get_tp_status (p_status); - g_hash_table_insert (status_table, GINT_TO_POINTER (handle), tp_status); } - return status_table; + return _get_tp_status (p_status); } void @@ -231,7 +203,8 @@ haze_connection_presence_account_status_changed (PurpleAccount *account, base_conn = ACCOUNT_GET_TP_BASE_CONNECTION (account); tp_status = _get_tp_status (status); - tp_presence_mixin_emit_one_presence_update (G_OBJECT (base_conn), + tp_presence_mixin_emit_one_presence_update ( + TP_PRESENCE_MIXIN (base_conn), tp_base_connection_get_self_handle (base_conn), tp_status); } } @@ -244,7 +217,7 @@ update_status (PurpleBuddy *buddy, HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (account); TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); TpHandleRepoIface *handle_repo = - tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base_conn, TP_ENTITY_TYPE_CONTACT); const gchar *bname = purple_buddy_get_name (buddy); TpHandle handle = tp_handle_ensure (handle_repo, bname, NULL, NULL); @@ -255,8 +228,8 @@ update_status (PurpleBuddy *buddy, tp_status = _get_tp_status (status); - tp_presence_mixin_emit_one_presence_update (G_OBJECT (conn), handle, - tp_status); + tp_presence_mixin_emit_one_presence_update (TP_PRESENCE_MIXIN (conn), + handle, tp_status); } static void @@ -280,11 +253,11 @@ signed_on_off_cb (PurpleBuddy *buddy, } static gboolean -_set_own_status (GObject *obj, +_set_own_status (TpPresenceMixin *mixin, const TpPresenceStatus *status, GError **error) { - HazeConnection *self = HAZE_CONNECTION (obj); + HazeConnection *self = HAZE_CONNECTION (mixin); const char *status_id = NULL; const gchar *message = NULL; GList *attrs = NULL; @@ -292,9 +265,7 @@ _set_own_status (GObject *obj, if (status != NULL) { status_id = _get_purple_status_id (self, status->index); - - if (status->optional_arguments != NULL) - message = tp_asv_get_string (status->optional_arguments, "message"); + message = status->message; } if (status_id == NULL) @@ -328,18 +299,13 @@ haze_connection_presence_class_init (GObjectClass *object_class) PURPLE_CALLBACK (signed_on_off_cb), GINT_TO_POINTER (TRUE)); purple_signal_connect (blist_handle, "buddy-signed-off", object_class, PURPLE_CALLBACK (signed_on_off_cb), GINT_TO_POINTER (FALSE)); - - tp_presence_mixin_class_init (object_class, - G_STRUCT_OFFSET (HazeConnectionClass, presence_class), - _status_available, _get_contact_statuses, _set_own_status, statuses); - - tp_presence_mixin_simple_presence_init_dbus_properties (object_class); } void -haze_connection_presence_init (GObject *object) +haze_connection_presence_iface_init (TpPresenceMixinInterface *iface) { - tp_presence_mixin_init (object, G_STRUCT_OFFSET (HazeConnection, - presence)); - tp_presence_mixin_simple_presence_register_with_contacts_mixin (object); + iface->status_available = _status_available; + iface->get_contact_status = _get_contact_status; + iface->set_own_status = _set_own_status; + iface->statuses = statuses; } diff --git a/src/connection-presence.h b/src/connection-presence.h index 9f248c0..111b741 100644 --- a/src/connection-presence.h +++ b/src/connection-presence.h @@ -25,10 +25,11 @@ #include "connection.h" void haze_connection_presence_class_init (GObjectClass *object_class); -void haze_connection_presence_init (GObject *object); void haze_connection_presence_account_status_changed (PurpleAccount *account, PurpleStatus *status); +void haze_connection_presence_iface_init (TpPresenceMixinInterface *iface); + #endif diff --git a/src/connection.c b/src/connection.c index 10da219..697fe17 100644 --- a/src/connection.c +++ b/src/connection.c @@ -24,6 +24,7 @@ #include <string.h> #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include <libpurple/accountopt.h> #include <libpurple/version.h> @@ -36,7 +37,6 @@ #include "connection-aliasing.h" #include "connection-avatars.h" #include "connection-mail.h" -#include "extensions/extensions.h" #include "request.h" #include "connection-capabilities.h" @@ -61,49 +61,37 @@ enum G_DEFINE_TYPE_WITH_CODE(HazeConnection, haze_connection, TP_TYPE_BASE_CONNECTION, - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, - tp_dbus_properties_mixin_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE, - tp_presence_mixin_simple_presence_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING, + G_IMPLEMENT_INTERFACE (TP_TYPE_PRESENCE_MIXIN, + haze_connection_presence_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING1, haze_connection_aliasing_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS1, haze_connection_avatars_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES1, haze_connection_contact_capabilities_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS, - tp_contacts_mixin_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_LIST, - tp_base_contact_list_mixin_list_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_GROUPS, - tp_base_contact_list_mixin_groups_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_BLOCKING, - tp_base_contact_list_mixin_blocking_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_MAIL_NOTIFICATION, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_MAIL_NOTIFICATION1, haze_connection_mail_iface_init); ); static const gchar * implemented_interfaces[] = { /* Conditionally present */ - TP_IFACE_CONNECTION_INTERFACE_AVATARS, - TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION, - TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING, + TP_IFACE_CONNECTION_INTERFACE_AVATARS1, + TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION1, + TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING1, # define HAZE_NUM_CONDITIONAL_INTERFACES 3 /* Always present */ - TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST, - TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS, - TP_IFACE_CONNECTION_INTERFACE_REQUESTS, - TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE, - TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, - TP_IFACE_CONNECTION_INTERFACE_CONTACTS, + TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST1, + TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS1, + TP_IFACE_CONNECTION_INTERFACE_PRESENCE1, + TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES1, /* TODO: This is a lie. Not all protocols supported by libpurple * actually have the concept of a user-settable alias, but * there's no way for the UI to know (yet). */ - TP_IFACE_CONNECTION_INTERFACE_ALIASING, + TP_IFACE_CONNECTION_INTERFACE_ALIASING1, NULL }; @@ -117,21 +105,9 @@ add_always_present_connection_interfaces (GPtrArray *interfaces) g_ptr_array_add (interfaces, (gchar *) *iter); } -static GPtrArray * -haze_connection_get_interfaces_always_present (TpBaseConnection *base) -{ - GPtrArray *interfaces; - - interfaces = TP_BASE_CONNECTION_CLASS ( - haze_connection_parent_class)->get_interfaces_always_present (base); - - add_always_present_connection_interfaces (interfaces); - - return interfaces; -} - static void add_optional_connection_interfaces (GPtrArray *ifaces, - PurplePluginProtocolInfo *prpl_info); + GDBusObjectSkeleton *skel, + PurplePluginProtocolInfo *prpl_info); /* Returns a (transfer container) not NULL terminated of (const gchar *) * interface names. */ @@ -142,7 +118,7 @@ haze_connection_dup_implemented_interfaces (PurplePluginProtocolInfo *prpl_info) ifaces = g_ptr_array_new (); add_always_present_connection_interfaces (ifaces); - add_optional_connection_interfaces (ifaces, prpl_info); + add_optional_connection_interfaces (ifaces, NULL, prpl_info); return ifaces; } @@ -173,8 +149,9 @@ struct _HazeConnectionPrivate #define PC_GET_BASE_CONN(pc) \ (ACCOUNT_GET_TP_BASE_CONNECTION (purple_connection_get_account (pc))) -static gboolean -protocol_info_supports_avatar (PurplePluginProtocolInfo *prpl_info) +gboolean +haze_connection_protocol_info_supports_avatar ( + PurplePluginProtocolInfo *prpl_info) { return (prpl_info->icon_spec.format != NULL); } @@ -192,37 +169,67 @@ protocol_info_supports_mail_notification (PurplePluginProtocolInfo *prpl_info) } static void +object_skeleton_take_interface (GDBusObjectSkeleton *skel, + GDBusInterfaceSkeleton *iface) +{ + g_dbus_object_skeleton_add_interface (skel, iface); + g_object_unref (iface); +} + +static void +object_skeleton_take_svc_interface (GDBusObjectSkeleton *skel, + GType type) +{ + object_skeleton_take_interface (skel, + tp_svc_interface_skeleton_new (skel, type)); +} + +static void add_optional_connection_interfaces (GPtrArray *ifaces, - PurplePluginProtocolInfo *prpl_info) + GDBusObjectSkeleton *skel, + PurplePluginProtocolInfo *prpl_info) { - if (protocol_info_supports_avatar (prpl_info)) - g_ptr_array_add (ifaces, - TP_IFACE_CONNECTION_INTERFACE_AVATARS); + if (haze_connection_protocol_info_supports_avatar (prpl_info)) + { + if (ifaces != NULL) + g_ptr_array_add (ifaces, TP_IFACE_CONNECTION_INTERFACE_AVATARS1); + + if (skel != NULL) + object_skeleton_take_svc_interface (skel, + TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS1); + } if (protocol_info_supports_blocking (prpl_info)) - g_ptr_array_add (ifaces, - TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING); + { + if (ifaces != NULL) + g_ptr_array_add (ifaces, + TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING1); + + /* TpBaseContactList deals with exporting the interface so don't + * try to duplicate that here */ + } if (protocol_info_supports_mail_notification (prpl_info)) - g_ptr_array_add (ifaces, - TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION); + { + if (ifaces != NULL) + g_ptr_array_add (ifaces, + TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION1); + + if (skel != NULL) + object_skeleton_take_svc_interface (skel, + TP_TYPE_SVC_CONNECTION_INTERFACE_MAIL_NOTIFICATION1); + } } static void connected_cb (PurpleConnection *pc) { TpBaseConnection *base_conn = PC_GET_BASE_CONN (pc); + GDBusObjectSkeleton *skel = G_DBUS_OBJECT_SKELETON (base_conn); HazeConnection *conn = HAZE_CONNECTION (base_conn); PurplePluginProtocolInfo *prpl_info = HAZE_CONNECTION_GET_PRPL_INFO (conn); - GPtrArray *ifaces; - ifaces = g_ptr_array_new (); - add_optional_connection_interfaces (ifaces, prpl_info); - g_ptr_array_add (ifaces, NULL); - - tp_base_connection_add_interfaces (base_conn, - (const gchar **) ifaces->pdata); - g_ptr_array_unref (ifaces); + add_optional_connection_interfaces (NULL, skel, prpl_info); tp_base_contact_list_set_list_received ( (TpBaseContactList *) conn->contact_list); @@ -338,7 +345,7 @@ haze_report_disconnect_reason (PurpleConnection *gc, HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (account); HazeConnectionPrivate *priv = conn->priv; TpBaseConnection *base_conn = ACCOUNT_GET_TP_BASE_CONNECTION (account); - GHashTable *details; + GVariant *details; TpConnectionStatusReason tp_reason; const gchar *tp_error_name; @@ -351,10 +358,11 @@ haze_report_disconnect_reason (PurpleConnection *gc, (tp_base_connection_get_status (base_conn) == TP_CONNECTION_STATUS_CONNECTING), &tp_reason, &tp_error_name); - details = tp_asv_new ("debug-message", G_TYPE_STRING, text, NULL); + + details = g_variant_new_parsed ("{ 'debug-message': <%s> }", text); + tp_base_connection_disconnect_with_dbus_error (base_conn, tp_error_name, details, tp_reason); - g_hash_table_unref (details); } static gboolean @@ -544,7 +552,7 @@ _haze_connection_start_connecting (TpBaseConnection *base, HazeConnection *self = HAZE_CONNECTION(base); HazeConnectionPrivate *priv = self->priv; TpHandleRepoIface *contact_handles = - tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base, TP_ENTITY_TYPE_CONTACT); const gchar *password; TpHandle self_handle; @@ -643,12 +651,12 @@ _contact_normalize (TpHandleRepoIface *repo, static void _haze_connection_create_handle_repos (TpBaseConnection *base, - TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES]) + TpHandleRepoIface *repos[TP_NUM_ENTITY_TYPES]) { - repos[TP_HANDLE_TYPE_CONTACT] = - tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_CONTACT, _contact_normalize, + repos[TP_ENTITY_TYPE_CONTACT] = + tp_dynamic_handle_repo_new (TP_ENTITY_TYPE_CONTACT, _contact_normalize, base); - /* repos[TP_HANDLE_TYPE_ROOM] = XXX MUC */ + /* repos[TP_ENTITY_TYPE_ROOM] = XXX MUC */ } static GPtrArray * @@ -661,10 +669,6 @@ _haze_connection_create_channel_managers (TpBaseConnection *base) g_object_new (HAZE_TYPE_IM_CHANNEL_FACTORY, "connection", self, NULL)); g_ptr_array_add (channel_managers, self->im_factory); - self->contact_list = HAZE_CONTACT_LIST ( - g_object_new (HAZE_TYPE_CONTACT_LIST, "connection", self, NULL)); - g_ptr_array_add (channel_managers, self->contact_list); - self->password_manager = tp_simple_password_manager_new ( TP_BASE_CONNECTION (self)); g_ptr_array_add (channel_managers, self->password_manager); @@ -751,7 +755,6 @@ haze_connection_constructor (GType type, HazeConnection *self = HAZE_CONNECTION ( G_OBJECT_CLASS (haze_connection_parent_class)->constructor ( type, n_construct_properties, construct_params)); - TpBaseConnection *base_conn = TP_BASE_CONNECTION (self); GObject *object = (GObject *) self; HazeConnectionPrivate *priv = self->priv; @@ -763,21 +766,34 @@ haze_connection_constructor (GType type, priv->disconnecting = FALSE; - tp_contacts_mixin_init (object, - G_STRUCT_OFFSET (HazeConnection, contacts)); - tp_base_connection_register_with_contacts_mixin (base_conn); - tp_base_contact_list_mixin_register_with_contacts_mixin (base_conn); + self->contact_list = HAZE_CONTACT_LIST ( + g_object_new (HAZE_TYPE_CONTACT_LIST, "connection", self, NULL)); - haze_connection_aliasing_init (object); - haze_connection_avatars_init (object); - haze_connection_capabilities_init (object); - haze_connection_presence_init (object); + tp_presence_mixin_init (TP_PRESENCE_MIXIN (self)); haze_connection_mail_init (object); return (GObject *)self; } static void +haze_connection_constructed (GObject *object) +{ + GDBusObjectSkeleton *skel = G_DBUS_OBJECT_SKELETON (object); + + G_OBJECT_CLASS (haze_connection_parent_class)->constructed (object); + + /* TODO: This is a lie. Not all protocols supported by libpurple + * actually have the concept of a user-settable alias, but + * there's no way for the UI to know (yet). + */ + object_skeleton_take_svc_interface (skel, + TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING1); + + object_skeleton_take_svc_interface (skel, + TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES1); +} + +static void haze_connection_dispose (GObject *object) { HazeConnection *self = HAZE_CONNECTION(object); @@ -802,9 +818,6 @@ haze_connection_finalize (GObject *object) HazeConnection *self = HAZE_CONNECTION (object); HazeConnectionPrivate *priv = self->priv; - tp_contacts_mixin_finalize (object); - tp_presence_mixin_finalize (object); - g_strfreev (self->acceptable_avatar_mime_types); g_free (priv->username); g_free (priv->password); @@ -819,6 +832,39 @@ haze_connection_finalize (GObject *object) } static void +haze_connection_fill_contact_attributes (TpBaseConnection *base, + const gchar *dbus_interface, + TpHandle handle, + GVariantDict *attributes) +{ + HazeConnection *self = HAZE_CONNECTION (base); + + if (haze_connection_aliasing_fill_contact_attributes (self, + dbus_interface, handle, attributes)) + return; + + if (haze_connection_avatars_fill_contact_attributes (self, + dbus_interface, handle, attributes)) + return; + + if (haze_connection_contact_capabilities_fill_contact_attributes (self, + dbus_interface, handle, attributes)) + return; + + if (tp_base_contact_list_fill_contact_attributes ( + TP_BASE_CONTACT_LIST (self->contact_list), + dbus_interface, handle, attributes)) + return; + + if (tp_presence_mixin_fill_contact_attributes (TP_PRESENCE_MIXIN (self), + dbus_interface, handle, attributes)) + return; + + TP_BASE_CONNECTION_CLASS (haze_connection_parent_class)-> + fill_contact_attributes (base, dbus_interface, handle, attributes); +} + +static void haze_connection_class_init (HazeConnectionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -831,18 +877,6 @@ haze_connection_class_init (HazeConnectionClass *klass) { "MailAddress", NULL, NULL }, { NULL } }; - static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { - { TP_IFACE_CONNECTION_INTERFACE_AVATARS, - haze_connection_avatars_properties_getter, - NULL, - NULL }, /* initialized a bit later */ - { TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION, - haze_connection_mail_properties_getter, - NULL, - mail_props, - }, - { NULL } - }; DEBUG ("Initializing (HazeConnectionClass *)%p", klass); @@ -850,6 +884,7 @@ haze_connection_class_init (HazeConnectionClass *klass) object_class->get_property = haze_connection_get_property; object_class->set_property = haze_connection_set_property; object_class->constructor = haze_connection_constructor; + object_class->constructed = haze_connection_constructed; object_class->dispose = haze_connection_dispose; object_class->finalize = haze_connection_finalize; @@ -860,8 +895,8 @@ haze_connection_class_init (HazeConnectionClass *klass) haze_connection_get_unique_connection_name; base_class->start_connecting = _haze_connection_start_connecting; base_class->shut_down = _haze_connection_shut_down; - base_class->get_interfaces_always_present = - haze_connection_get_interfaces_always_present; + base_class->fill_contact_attributes = + haze_connection_fill_contact_attributes; param_spec = g_param_spec_boxed ("parameters", "gchar * => GValue", "Connection parameters (password, etc.)", @@ -889,14 +924,10 @@ haze_connection_class_init (HazeConnectionClass *klass) G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PRPL_INFO, param_spec); - prop_interfaces[0].props = haze_connection_avatars_properties; - klass->properties_class.interfaces = prop_interfaces; - tp_dbus_properties_mixin_class_init (object_class, - G_STRUCT_OFFSET (HazeConnectionClass, properties_class)); - tp_contacts_mixin_class_init (object_class, - G_STRUCT_OFFSET (HazeConnectionClass, contacts_class)); - tp_base_contact_list_mixin_class_init (base_class); + tp_dbus_properties_mixin_implement_interface (object_class, + TP_IFACE_QUARK_CONNECTION_INTERFACE_MAIL_NOTIFICATION1, + haze_connection_mail_properties_getter, NULL, mail_props); haze_connection_presence_class_init (object_class); haze_connection_aliasing_class_init (object_class); @@ -957,12 +988,12 @@ haze_get_connection_ui_ops () const gchar * haze_connection_handle_inspect (HazeConnection *conn, - TpHandleType handle_type, + TpEntityType entity_type, TpHandle handle) { TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); TpHandleRepoIface *handle_repo = - tp_base_connection_get_handles (base_conn, handle_type); + tp_base_connection_get_handles (base_conn, entity_type); g_assert (tp_handle_is_valid (handle_repo, handle, NULL)); return tp_handle_inspect (handle_repo, handle); } diff --git a/src/connection.h b/src/connection.h index 0eef922..1a18e18 100644 --- a/src/connection.h +++ b/src/connection.h @@ -38,9 +38,6 @@ typedef struct _HazeConnectionClass HazeConnectionClass; struct _HazeConnectionClass { TpBaseConnectionClass parent_class; - TpDBusPropertiesMixinClass properties_class; - TpContactsMixinClass contacts_class; - TpPresenceMixinClass presence_class; }; struct _HazeConnection { @@ -52,9 +49,6 @@ struct _HazeConnection { HazeImChannelFactory *im_factory; TpSimplePasswordManager *password_manager; - TpContactsMixin contacts; - TpPresenceMixin presence; - gchar **acceptable_avatar_mime_types; HazeConnectionPrivate *priv; @@ -72,7 +66,7 @@ PurpleConnectionUiOps *haze_get_connection_ui_ops (void); const gchar * haze_connection_handle_inspect (HazeConnection *conn, - TpHandleType handle_type, + TpEntityType entity_type, TpHandle handle); gboolean haze_connection_create_account (HazeConnection *self, GError **error); @@ -107,6 +101,9 @@ void haze_connection_request_password (PurpleAccount *account, gpointer user_data); void haze_connection_cancel_password_request (PurpleAccount *account); +gboolean haze_connection_protocol_info_supports_avatar ( + PurplePluginProtocolInfo *prpl_info); + G_END_DECLS #endif /* #ifndef __HAZE_CONNECTION_H__*/ diff --git a/src/contact-list.c b/src/contact-list.c index 58b7a9d..4bd5ce1 100644 --- a/src/contact-list.c +++ b/src/contact-list.c @@ -124,7 +124,7 @@ haze_contact_list_constructor (GType type, guint n_props, /* not reffed, for the moment */ contact_repo = tp_base_connection_get_handles ( - (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); + (TpBaseConnection *) self->priv->conn, TP_ENTITY_TYPE_CONTACT); self->priv->publishing_to = tp_handle_set_new (contact_repo); self->priv->not_publishing_to = tp_handle_set_new (contact_repo); @@ -175,7 +175,7 @@ haze_contact_list_dup_contacts (TpBaseContactList *cl) HazeContactList *self = HAZE_CONTACT_LIST (cl); TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); /* The list initially contains anyone we're definitely publishing to. * Because libpurple, that's only people whose request we accepted during * this session :-( */ @@ -217,7 +217,7 @@ haze_contact_list_dup_states (TpBaseContactList *cl, { HazeContactList *self = HAZE_CONTACT_LIST (cl); const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, contact); + TP_ENTITY_TYPE_CONTACT, contact); PurpleBuddy *buddy = purple_find_buddy (self->priv->conn->account, bname); TpSubscriptionState pub, sub; PublishRequestData *pub_req = g_hash_table_lookup ( @@ -296,7 +296,7 @@ buddy_added_cb (PurpleBuddy *buddy, gpointer unused) HazeContactList *contact_list = conn->contact_list; TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( - base_conn, TP_HANDLE_TYPE_CONTACT); + base_conn, TP_ENTITY_TYPE_CONTACT); const gchar *name = purple_buddy_get_name (buddy); TpHandle handle = tp_handle_ensure (contact_repo, name, NULL, NULL); const char *group_name; @@ -305,8 +305,8 @@ buddy_added_cb (PurpleBuddy *buddy, gpointer unused) (TpBaseContactList *) contact_list, handle); group_name = purple_group_get_name (purple_buddy_get_group (buddy)); - tp_base_contact_list_one_contact_groups_changed ( - (TpBaseContactList *) contact_list, handle, &group_name, 1, NULL, 0); + tp_contact_group_list_one_contact_groups_changed ( + (TpContactGroupList *) contact_list, handle, &group_name, 1, NULL, 0); } static void @@ -330,14 +330,14 @@ buddy_removed_cb (PurpleBuddy *buddy, gpointer unused) contact_list = conn->contact_list; contact_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); buddy_name = purple_buddy_get_name (buddy); handle = tp_handle_ensure (contact_repo, buddy_name, NULL, NULL); group_name = purple_group_get_name (purple_buddy_get_group (buddy)); - tp_base_contact_list_one_contact_groups_changed ( - (TpBaseContactList *) contact_list, handle, NULL, 0, &group_name, 1); + tp_contact_group_list_one_contact_groups_changed ( + (TpContactGroupList *) contact_list, handle, NULL, 0, &group_name, 1); buddies = purple_find_buddies (conn->account, buddy_name); @@ -393,7 +393,7 @@ haze_contact_list_accept_publish_request (HazeContactList *self, PublishRequestData *request_data = g_hash_table_lookup ( self->priv->pending_publish_requests, key); const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, handle); + TP_ENTITY_TYPE_CONTACT, handle); if (request_data == NULL) return; @@ -409,7 +409,7 @@ haze_contact_list_accept_publish_request (HazeContactList *self, } static void -haze_contact_list_authorize_publication_async (TpBaseContactList *cl, +haze_contact_list_authorize_publication_async (TpMutableContactList *cl, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) @@ -435,7 +435,7 @@ haze_contact_list_reject_publish_request (HazeContactList *self, PublishRequestData *request_data = g_hash_table_lookup ( self->priv->pending_publish_requests, key); const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, handle); + TP_ENTITY_TYPE_CONTACT, handle); if (request_data == NULL) return; @@ -465,7 +465,7 @@ haze_request_authorize (PurpleAccount *account, HazeConnection *conn = account->ui_data; TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); HazeContactList *self = conn->contact_list; TpHandle remote_handle; PublishRequestData *request_data = publish_request_data_new (); @@ -526,7 +526,7 @@ haze_contact_list_request_subscription (HazeContactList *self, { PurpleAccount *account = self->priv->conn->account; const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, handle); + TP_ENTITY_TYPE_CONTACT, handle); PurpleBuddy *buddy; /* If the buddy already exists, then it should already be on the @@ -546,7 +546,7 @@ haze_contact_list_request_subscription (HazeContactList *self, } static void -haze_contact_list_request_subscription_async (TpBaseContactList *cl, +haze_contact_list_request_subscription_async (TpMutableContactList *cl, TpHandleSet *contacts, const gchar *message, GAsyncReadyCallback callback, @@ -566,7 +566,7 @@ haze_contact_list_request_subscription_async (TpBaseContactList *cl, } static void -haze_contact_list_store_contacts_async (TpBaseContactList *cl, +haze_contact_list_store_contacts_async (TpMutableContactList *cl, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) @@ -581,7 +581,7 @@ haze_contact_list_remove_contact (HazeContactList *self, { PurpleAccount *account = self->priv->conn->account; const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, handle); + TP_ENTITY_TYPE_CONTACT, handle); GSList *buddies, *l; buddies = purple_find_buddies (account, bname); @@ -606,7 +606,7 @@ haze_contact_list_remove_contact (HazeContactList *self, } static void -haze_contact_list_remove_contacts_async (TpBaseContactList *cl, +haze_contact_list_remove_contacts_async (TpMutableContactList *cl, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) @@ -631,14 +631,14 @@ haze_contact_list_add_to_group (HazeContactList *self, { HazeConnection *conn = self->priv->conn; const gchar *bname = - haze_connection_handle_inspect (conn, TP_HANDLE_TYPE_CONTACT, handle); + haze_connection_handle_inspect (conn, TP_ENTITY_TYPE_CONTACT, handle); PurpleBuddy *buddy; /* This actually has "ensure" semantics, and doesn't return a ref */ PurpleGroup *group = purple_group_new (group_name); /* We have to reassure the TpBaseContactList that the group exists, * because libpurple doesn't have a group-added signal */ - tp_base_contact_list_groups_created ((TpBaseContactList *) self, + tp_contact_group_list_groups_created ((TpContactGroupList *) self, &group_name, 1); g_return_if_fail (group != NULL); @@ -666,7 +666,7 @@ haze_contact_list_prep_remove_from_group (HazeContactList *self, HazeConnection *conn = self->priv->conn; TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); PurpleAccount *account = conn->account; PurpleGroup *group = purple_find_group (group_name); TpIntsetFastIter iter; @@ -688,7 +688,7 @@ haze_contact_list_prep_remove_from_group (HazeContactList *self, GSList *buddies; GSList *l; const gchar *bname = - haze_connection_handle_inspect (conn, TP_HANDLE_TYPE_CONTACT, + haze_connection_handle_inspect (conn, TP_ENTITY_TYPE_CONTACT, handle); g_assert (bname != NULL); @@ -721,7 +721,7 @@ haze_contact_list_prep_remove_from_group (HazeContactList *self, /* We might have just created that group; libpurple doesn't have * a group-added signal, so tell TpBaseContactList about it */ - tp_base_contact_list_groups_created ((TpBaseContactList *) self, + tp_contact_group_list_groups_created ((TpContactGroupList *) self, &def_name, 1); if (default_group == group) @@ -737,7 +737,7 @@ haze_contact_list_prep_remove_from_group (HazeContactList *self, while (tp_intset_fast_iter_next (&iter, &handle)) { const gchar *bname = - haze_connection_handle_inspect (conn, TP_HANDLE_TYPE_CONTACT, + haze_connection_handle_inspect (conn, TP_ENTITY_TYPE_CONTACT, handle); PurpleBuddy *copy = purple_buddy_new (conn->account, bname, NULL); @@ -770,7 +770,7 @@ haze_contact_list_remove_many_from_group (HazeContactList *self, GSList *buddies; GSList *l; const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, handle); + TP_ENTITY_TYPE_CONTACT, handle); buddies = purple_find_buddies (account, bname); @@ -797,7 +797,7 @@ haze_contact_list_remove_from_group (HazeContactList *self, { TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); gboolean ok; TpHandleSet *contacts = tp_handle_set_new_containing (contact_repo, handle); @@ -829,7 +829,7 @@ haze_contact_list_mutable_init (TpMutableContactListInterface *vtable) } static GStrv -haze_contact_list_dup_groups (TpBaseContactList *cl G_GNUC_UNUSED) +haze_contact_list_dup_groups (TpContactGroupList *cl G_GNUC_UNUSED) { PurpleBlistNode *node; /* borrowed group name => NULL */ @@ -859,12 +859,12 @@ haze_contact_list_dup_groups (TpBaseContactList *cl G_GNUC_UNUSED) } static GStrv -haze_contact_list_dup_contact_groups (TpBaseContactList *cl, +haze_contact_list_dup_contact_groups (TpContactGroupList *cl, TpHandle contact) { HazeContactList *self = HAZE_CONTACT_LIST (cl); const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, contact); + TP_ENTITY_TYPE_CONTACT, contact); GSList *buddies, *sl_iter; GPtrArray *arr; @@ -887,13 +887,13 @@ haze_contact_list_dup_contact_groups (TpBaseContactList *cl, } static TpHandleSet * -haze_contact_list_dup_group_members (TpBaseContactList *cl, +haze_contact_list_dup_group_members (TpContactGroupList *cl, const gchar *group_name) { HazeContactList *self = HAZE_CONTACT_LIST (cl); TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); PurpleGroup *group = purple_find_group (group_name); PurpleBlistNode *contact, *buddy; TpHandleSet *members = tp_handle_set_new (contact_repo); @@ -940,7 +940,7 @@ haze_contact_list_dup_group_members (TpBaseContactList *cl, } static gchar * -haze_contact_list_normalize_group (TpBaseContactList *cl G_GNUC_UNUSED, +haze_contact_list_normalize_group (TpContactGroupList *cl G_GNUC_UNUSED, const gchar *s) { /* By inspection of blist.c: group names are normalized by stripping @@ -984,7 +984,7 @@ haze_contact_list_groups_init (TpContactGroupListInterface *vtable) } static void -haze_contact_list_set_contact_groups_async (TpBaseContactList *cl, +haze_contact_list_set_contact_groups_async (TpMutableContactGroupList *cl, TpHandle contact, const gchar * const *names, gsize n_names, @@ -995,7 +995,7 @@ haze_contact_list_set_contact_groups_async (TpBaseContactList *cl, PurpleAccount *account = self->priv->conn->account; const gchar *fallback_group; const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, contact); + TP_ENTITY_TYPE_CONTACT, contact); gsize i; GSList *buddies, *l; @@ -1043,7 +1043,7 @@ haze_contact_list_set_contact_groups_async (TpBaseContactList *cl, } static void -haze_contact_list_add_to_group_async (TpBaseContactList *cl, +haze_contact_list_add_to_group_async (TpMutableContactGroupList *cl, const gchar *group_name, TpHandleSet *contacts, GAsyncReadyCallback callback, @@ -1058,7 +1058,7 @@ haze_contact_list_add_to_group_async (TpBaseContactList *cl, /* We have to reassure the TpBaseContactList that the group exists, * because libpurple doesn't have a group-added signal */ g_assert (group != NULL); - tp_base_contact_list_groups_created ((TpBaseContactList *) self, + tp_contact_group_list_groups_created ((TpContactGroupList *) self, &group_name, 1); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); @@ -1071,7 +1071,7 @@ haze_contact_list_add_to_group_async (TpBaseContactList *cl, } static void -haze_contact_list_remove_from_group_async (TpBaseContactList *cl, +haze_contact_list_remove_from_group_async (TpMutableContactGroupList *cl, const gchar *group_name, TpHandleSet *contacts, GAsyncReadyCallback callback, @@ -1096,12 +1096,14 @@ haze_contact_list_remove_from_group_async (TpBaseContactList *cl, } static void -haze_contact_list_remove_group_async (TpBaseContactList *cl, +haze_contact_list_remove_group_async (TpMutableContactGroupList *cl, const gchar *group_name, GAsyncReadyCallback callback, gpointer user_data) { - TpHandleSet *members = haze_contact_list_dup_group_members (cl, group_name); + TpContactGroupList *contact_group = TP_CONTACT_GROUP_LIST (cl); + TpHandleSet *members = haze_contact_list_dup_group_members ( + contact_group, group_name); GError *error = NULL; if (haze_contact_list_prep_remove_from_group (HAZE_CONTACT_LIST (cl), @@ -1112,7 +1114,7 @@ haze_contact_list_remove_group_async (TpBaseContactList *cl, if (group != NULL) purple_blist_remove_group (group); - tp_base_contact_list_groups_removed (cl, &group_name, 1); + tp_contact_group_list_groups_removed (contact_group, &group_name, 1); tp_simple_async_report_success_in_idle ((GObject *) cl, callback, user_data, haze_contact_list_remove_group_async); @@ -1128,14 +1130,16 @@ haze_contact_list_remove_group_async (TpBaseContactList *cl, } static void -haze_contact_list_set_group_members_async (TpBaseContactList *cl, +haze_contact_list_set_group_members_async (TpMutableContactGroupList *cl, const gchar *group_name, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { HazeContactList *self = HAZE_CONTACT_LIST (cl); - TpHandleSet *outcasts = haze_contact_list_dup_group_members (cl, group_name); + TpContactGroupList *contact_group = TP_CONTACT_GROUP_LIST (cl); + TpHandleSet *outcasts = haze_contact_list_dup_group_members (contact_group, + group_name); GError *error = NULL; /* This actually has "ensure" semantics, and doesn't return a ref. * We do this even if there are no contacts, to create the group as a @@ -1145,7 +1149,7 @@ haze_contact_list_set_group_members_async (TpBaseContactList *cl, /* We have to reassure the TpBaseContactList that the group exists, * because libpurple doesn't have a group-added signal */ g_assert (group != NULL); - tp_base_contact_list_groups_created ((TpBaseContactList *) self, + tp_contact_group_list_groups_created ((TpContactGroupList *) self, &group_name, 1); tp_intset_destroy (tp_handle_set_difference_update (outcasts, @@ -1167,7 +1171,7 @@ haze_contact_list_set_group_members_async (TpBaseContactList *cl, } static void -haze_contact_list_rename_group_async (TpBaseContactList *cl, +haze_contact_list_rename_group_async (TpMutableContactGroupList *cl, const gchar *old_name, const gchar *new_name, GAsyncReadyCallback callback, @@ -1193,7 +1197,8 @@ haze_contact_list_rename_group_async (TpBaseContactList *cl, } purple_blist_rename_group (group, new_name); - tp_base_contact_list_group_renamed (cl, old_name, new_name); + tp_contact_group_list_group_renamed (TP_CONTACT_GROUP_LIST (cl), old_name, + new_name); tp_simple_async_report_success_in_idle ((GObject *) cl, callback, user_data, haze_contact_list_rename_group_async); @@ -1214,14 +1219,36 @@ haze_contact_list_mutable_groups_init ( /* assume default: groups are stored persistently */ } +static gboolean +is_blocked (TpBlockableContactList *cl, + TpHandle contact) +{ + HazeContactList *self = HAZE_CONTACT_LIST (cl); + PurpleAccount *account = self->priv->conn->account; + TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn); + TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, + TP_ENTITY_TYPE_CONTACT); + GSList *l; + + for (l = account->deny; l != NULL; l = l->next) + { + TpHandle denied = tp_handle_ensure (contact_repo, l->data, NULL, NULL); + + if (denied == contact) + return TRUE; + } + + return FALSE; +} + static TpHandleSet * -dup_blocked_contacts (TpBaseContactList *cl) +dup_blocked_contacts (TpBlockableContactList *cl) { HazeContactList *self = HAZE_CONTACT_LIST (cl); PurpleAccount *account = self->priv->conn->account; TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); TpHandleSet *blocked = tp_handle_set_new (contact_repo); GSList *l; @@ -1250,7 +1277,7 @@ set_contacts_privacy (TpBaseContactList *cl, while (tp_intset_fast_iter_next (&iter, &handle)) { const gchar *bname = haze_connection_handle_inspect (self->priv->conn, - TP_HANDLE_TYPE_CONTACT, handle); + TP_ENTITY_TYPE_CONTACT, handle); if (block) purple_privacy_deny (account, bname, FALSE, FALSE); @@ -1260,35 +1287,36 @@ set_contacts_privacy (TpBaseContactList *cl, } static void -block_contacts_async(TpBaseContactList *cl, +block_contacts_async(TpBlockableContactList *cl, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { - set_contacts_privacy (cl, contacts, TRUE); + set_contacts_privacy (TP_BASE_CONTACT_LIST (cl), contacts, TRUE); tp_simple_async_report_success_in_idle ((GObject *) cl, callback, user_data, block_contacts_async); } static void -unblock_contacts_async(TpBaseContactList *cl, +unblock_contacts_async(TpBlockableContactList *cl, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { - set_contacts_privacy (cl, contacts, FALSE); + set_contacts_privacy (TP_BASE_CONTACT_LIST (cl), contacts, FALSE); tp_simple_async_report_success_in_idle ((GObject *) cl, callback, user_data, unblock_contacts_async); } static gboolean -can_block (TpBaseContactList *cl) +can_block (TpBlockableContactList *cl) { HazeContactList *self = HAZE_CONTACT_LIST (cl); - return (self->priv->conn->account->gc != NULL && + return (self->priv->conn->account != NULL && + self->priv->conn->account->gc != NULL && HAZE_CONNECTION_GET_PRPL_INFO (self->priv->conn)->add_deny != NULL); } @@ -1296,6 +1324,7 @@ static void haze_contact_list_blockable_init( TpBlockableContactListInterface *vtable) { + vtable->is_blocked = is_blocked; vtable->dup_blocked_contacts = dup_blocked_contacts; vtable->block_contacts_async = block_contacts_async; vtable->unblock_contacts_async = unblock_contacts_async; @@ -1311,7 +1340,7 @@ haze_contact_list_deny_changed ( HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (account); TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); GError *error = NULL; TpHandle handle = tp_handle_ensure (contact_repo, name, NULL, &error); TpHandleSet *set; @@ -1324,8 +1353,8 @@ haze_contact_list_deny_changed ( } set = tp_handle_set_new_containing (contact_repo, handle); - tp_base_contact_list_contact_blocking_changed ( - TP_BASE_CONTACT_LIST (conn->contact_list), + tp_blockable_contact_list_contact_blocking_changed ( + TP_BLOCKABLE_CONTACT_LIST (conn->contact_list), set); g_object_unref (set); } diff --git a/src/im-channel-factory.c b/src/im-channel-factory.c index 7508b25..ac72b94 100644 --- a/src/im-channel-factory.c +++ b/src/im-channel-factory.c @@ -25,6 +25,7 @@ #include <string.h> #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "debug.h" #include "im-channel.h" @@ -53,7 +54,9 @@ enum { }; static HazeIMChannel *get_im_channel (HazeImChannelFactory *self, - TpHandle handle, TpHandle initiator, gpointer request_token, + TpHandle handle, + TpHandle initiator, + TpChannelManagerRequest *request, gboolean *created); static void close_all (HazeImChannelFactory *self); @@ -101,8 +104,8 @@ conversation_updated_cb (PurpleConversation *conv, chan = get_im_channel (im_factory, ui_data->contact_handle, ui_data->contact_handle, NULL, NULL); - tp_svc_channel_interface_chat_state_emit_chat_state_changed ( - (TpSvcChannelInterfaceChatState*)chan, ui_data->contact_handle, state); + tp_svc_channel_interface_chat_state1_emit_chat_state_changed ( + (TpSvcChannelInterfaceChatState1 *)chan, ui_data->contact_handle, state); } static void @@ -229,12 +232,10 @@ static void im_channel_closed_cb (HazeIMChannel *chan, gpointer user_data) { HazeImChannelFactory *self = HAZE_IM_CHANNEL_FACTORY (user_data); + TpBaseChannel *base = TP_BASE_CHANNEL (chan); TpHandle contact_handle; guint really_destroyed; - tp_channel_manager_emit_channel_closed_for_object (self, - TP_EXPORTABLE_CHANNEL (chan)); - if (self->priv->channels) { g_object_get (chan, @@ -247,13 +248,17 @@ im_channel_closed_cb (HazeIMChannel *chan, gpointer user_data) DEBUG ("removing channel with handle %u", contact_handle); g_hash_table_remove (self->priv->channels, GUINT_TO_POINTER (contact_handle)); + tp_channel_manager_emit_channel_closed_for_object ( + TP_CHANNEL_MANAGER (self), base); } else { DEBUG ("reopening channel with handle %u due to pending messages", contact_handle); - tp_channel_manager_emit_new_channel (self, - (TpExportableChannel *) chan, NULL); + tp_channel_manager_emit_channel_closed_for_object ( + TP_CHANNEL_MANAGER (self), base); + tp_channel_manager_emit_new_channel (TP_CHANNEL_MANAGER (self), + base, NULL); } } } @@ -292,8 +297,8 @@ new_im_channel (HazeImChannelFactory *self, if (request_token != NULL) requests = g_slist_prepend (requests, request_token); - tp_channel_manager_emit_new_channel (self, - TP_EXPORTABLE_CHANNEL (chan), requests); + tp_channel_manager_emit_new_channel (TP_CHANNEL_MANAGER (self), + TP_BASE_CHANNEL (chan), requests); g_slist_free (requests); return chan; @@ -301,10 +306,10 @@ new_im_channel (HazeImChannelFactory *self, static HazeIMChannel * get_im_channel (HazeImChannelFactory *self, - TpHandle handle, - TpHandle initiator, - gpointer request_token, - gboolean *created) + TpHandle handle, + TpHandle initiator, + TpChannelManagerRequest *request, + gboolean *created) { HazeIMChannel *chan = g_hash_table_lookup (self->priv->channels, GINT_TO_POINTER (handle)); @@ -316,7 +321,7 @@ get_im_channel (HazeImChannelFactory *self, } else { - chan = new_im_channel (self, handle, initiator, request_token); + chan = new_im_channel (self, handle, initiator, request); if (created) *created = TRUE; } @@ -348,7 +353,7 @@ close_all (HazeImChannelFactory *self) struct _ForeachData { - TpExportableChannelFunc foreach; + TpBaseChannelFunc foreach; gpointer user_data; }; @@ -356,14 +361,14 @@ static void _foreach_slave (gpointer key, gpointer value, gpointer user_data) { struct _ForeachData *data = (struct _ForeachData *) user_data; - TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value); + TpBaseChannel *chan = TP_BASE_CHANNEL (value); data->foreach (chan, data->user_data); } static void haze_im_channel_factory_foreach (TpChannelManager *iface, - TpExportableChannelFunc foreach, + TpBaseChannelFunc foreach, gpointer user_data) { HazeImChannelFactory *self = HAZE_IM_CHANNEL_FACTORY (iface); @@ -421,7 +426,7 @@ haze_create_conversation (PurpleConversation *conv) ACCOUNT_GET_HAZE_CONNECTION (account)->im_factory; TpBaseConnection *base_conn = TP_BASE_CONNECTION (im_factory->priv->conn); TpHandleRepoIface *contact_repo = - tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); + tp_base_connection_get_handles (base_conn, TP_ENTITY_TYPE_CONTACT); const gchar *who = purple_conversation_get_name (conv); @@ -501,7 +506,7 @@ haze_get_conv_ui_ops(void) static const gchar * const fixed_properties[] = { TP_IFACE_CHANNEL ".ChannelType", - TP_IFACE_CHANNEL ".TargetHandleType", + TP_IFACE_CHANNEL ".TargetEntityType", NULL }; static const gchar * const allowed_properties[] = { @@ -524,8 +529,8 @@ haze_im_channel_factory_foreach_channel_class (TpChannelManager *manager, g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType", value); value = tp_g_value_slice_new (G_TYPE_UINT); - g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); - g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType", value); + g_value_set_uint (value, TP_ENTITY_TYPE_CONTACT); + g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetEntityType", value); func (manager, table, allowed_properties, user_data); @@ -534,9 +539,9 @@ haze_im_channel_factory_foreach_channel_class (TpChannelManager *manager, static gboolean haze_im_channel_factory_request (HazeImChannelFactory *self, - gpointer request_token, - GHashTable *request_properties, - gboolean require_new) + TpChannelManagerRequest *request, + GHashTable *request_properties, + gboolean require_new) { TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn); TpHandle handle; @@ -552,7 +557,7 @@ haze_im_channel_factory_request (HazeImChannelFactory *self, } if (tp_asv_get_uint32 (request_properties, - TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT) + TP_IFACE_CHANNEL ".TargetEntityType", NULL) != TP_ENTITY_TYPE_CONTACT) { return FALSE; } @@ -568,7 +573,7 @@ haze_im_channel_factory_request (HazeImChannelFactory *self, } chan = get_im_channel (self, handle, - tp_base_connection_get_self_handle (base_conn), request_token, + tp_base_connection_get_self_handle (base_conn), request, &created); g_assert (chan != NULL); @@ -576,20 +581,22 @@ haze_im_channel_factory_request (HazeImChannelFactory *self, { if (require_new) { - tp_channel_manager_emit_request_failed (self, request_token, - TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Channel already exists"); + tp_channel_manager_emit_request_failed (TP_CHANNEL_MANAGER (self), + request, TP_ERROR, TP_ERROR_NOT_AVAILABLE, + "Channel already exists"); } else { - tp_channel_manager_emit_request_already_satisfied (self, - request_token, TP_EXPORTABLE_CHANNEL (chan)); + tp_channel_manager_emit_request_already_satisfied ( + TP_CHANNEL_MANAGER (self), request, + TP_BASE_CHANNEL (chan)); } } return TRUE; error: - tp_channel_manager_emit_request_failed (self, request_token, + tp_channel_manager_emit_request_failed (TP_CHANNEL_MANAGER (self), request, error->domain, error->code, error->message); g_error_free (error); return TRUE; @@ -597,20 +604,20 @@ error: static gboolean haze_im_channel_factory_create_channel (TpChannelManager *manager, - gpointer request_token, - GHashTable *request_properties) + TpChannelManagerRequest *request, + GHashTable *request_properties) { return haze_im_channel_factory_request (HAZE_IM_CHANNEL_FACTORY (manager), - request_token, request_properties, TRUE); + request, request_properties, TRUE); } static gboolean haze_im_channel_factory_ensure_channel (TpChannelManager *manager, - gpointer request_token, - GHashTable *request_properties) + TpChannelManagerRequest *request, + GHashTable *request_properties) { return haze_im_channel_factory_request (HAZE_IM_CHANNEL_FACTORY (manager), - request_token, request_properties, FALSE); + request, request_properties, FALSE); } static void @@ -624,6 +631,4 @@ channel_manager_iface_init (gpointer g_iface, haze_im_channel_factory_foreach_channel_class; iface->create_channel = haze_im_channel_factory_create_channel; iface->ensure_channel = haze_im_channel_factory_ensure_channel; - /* Request is equivalent to Ensure for this channel class */ - iface->request_channel = haze_im_channel_factory_ensure_channel; } diff --git a/src/im-channel.c b/src/im-channel.c index dd4cf53..da65934 100644 --- a/src/im-channel.c +++ b/src/im-channel.c @@ -23,6 +23,7 @@ #include "im-channel.h" #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "connection.h" #include "debug.h" @@ -38,15 +39,13 @@ static void chat_state_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE(HazeIMChannel, haze_im_channel, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, - tp_message_mixin_text_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MESSAGES, - tp_message_mixin_messages_iface_init); - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DESTROYABLE, + tp_message_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DESTROYABLE1, destroyable_iface_init); /* For some reason we reimplement ChatState rather than having the * TpMessageMixin do it :-( */ - G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CHAT_STATE, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CHAT_STATE1, chat_state_iface_init)) static void @@ -101,10 +100,9 @@ haze_im_channel_get_interfaces (TpBaseChannel *base) haze_im_channel_parent_class)->get_interfaces (base); if (_chat_state_available (self)) - g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE); + g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE1); - g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_MESSAGES); - g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_DESTROYABLE); + g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_DESTROYABLE1); return interfaces; } @@ -113,11 +111,11 @@ haze_im_channel_get_interfaces (TpBaseChannel *base) * haze_im_channel_destroy * * Implements D-Bus method Destroy - * on interface org.freedesktop.Telepathy.Channel.Interface.Destroyable + * on interface im.telepathy.v1.Channel.Interface.Destroyable */ static void -haze_im_channel_destroy (TpSvcChannelInterfaceDestroyable *iface, - DBusGMethodInvocation *context) +haze_im_channel_destroy (TpSvcChannelInterfaceDestroyable1 *iface, + GDBusMethodInvocation *context) { HazeIMChannel *self = HAZE_IM_CHANNEL (iface); @@ -129,16 +127,16 @@ haze_im_channel_destroy (TpSvcChannelInterfaceDestroyable *iface, tp_message_mixin_clear ((GObject *) self); haze_im_channel_close (TP_BASE_CHANNEL (self)); - tp_svc_channel_interface_destroyable_return_from_destroy (context); + tp_svc_channel_interface_destroyable1_return_from_destroy (context); } static void destroyable_iface_init (gpointer g_iface, gpointer iface_data) { - TpSvcChannelInterfaceDestroyableClass *klass = g_iface; + TpSvcChannelInterfaceDestroyable1Class *klass = g_iface; -#define IMPLEMENT(x) tp_svc_channel_interface_destroyable_implement_##x (\ +#define IMPLEMENT(x) tp_svc_channel_interface_destroyable1_implement_##x (\ klass, haze_im_channel_##x) IMPLEMENT(destroy); #undef IMPLEMENT @@ -174,9 +172,9 @@ resend_typing_cb (gpointer data) static void -haze_im_channel_set_chat_state (TpSvcChannelInterfaceChatState *self, +haze_im_channel_set_chat_state (TpSvcChannelInterfaceChatState1 *self, guint state, - DBusGMethodInvocation *context) + GDBusMethodInvocation *context) { HazeIMChannel *chan = HAZE_IM_CHANNEL (self); @@ -223,7 +221,7 @@ haze_im_channel_set_chat_state (TpSvcChannelInterfaceChatState *self, if (error) { - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); g_error_free (error); return; } @@ -246,15 +244,15 @@ haze_im_channel_set_chat_state (TpSvcChannelInterfaceChatState *self, resend_typing_cb, conv); } - tp_svc_channel_interface_chat_state_return_from_set_chat_state (context); + tp_svc_channel_interface_chat_state1_return_from_set_chat_state (context); } static void chat_state_iface_init (gpointer g_iface, gpointer iface_data) { - TpSvcChannelInterfaceChatStateClass *klass = - (TpSvcChannelInterfaceChatStateClass *)g_iface; -#define IMPLEMENT(x) tp_svc_channel_interface_chat_state_implement_##x (\ + TpSvcChannelInterfaceChatState1Class *klass = + (TpSvcChannelInterfaceChatState1Class *)g_iface; +#define IMPLEMENT(x) tp_svc_channel_interface_chat_state1_implement_##x (\ klass, haze_im_channel_##x) IMPLEMENT(set_chat_state); #undef IMPLEMENT @@ -266,7 +264,7 @@ haze_im_channel_send (GObject *obj, TpMessageSendingFlags send_flags) { HazeIMChannel *self = HAZE_IM_CHANNEL (obj); - const GHashTable *header, *body; + GVariant *header = NULL, *body = NULL; const gchar *content_type, *text; guint type = 0; PurpleMessageFlags flags = 0; @@ -280,12 +278,14 @@ haze_im_channel_send (GObject *obj, goto err; } - header = tp_message_peek (message, 0); - body = tp_message_peek (message, 1); + header = tp_message_dup_part (message, 0); + body = tp_message_dup_part (message, 1); - type = tp_asv_get_uint32 (header, "message-type", NULL); - content_type = tp_asv_get_string (body, "content-type"); - text = tp_asv_get_string (body, "content"); + type = tp_vardict_get_uint32 (header, "message-type", NULL); + g_variant_unref (header); + + content_type = tp_vardict_get_string (body, "content-type"); + text = tp_vardict_get_string (body, "content"); if (tp_strdiff (content_type, "text/plain")) { @@ -340,6 +340,7 @@ haze_im_channel_send (GObject *obj, g_free (reapostrophised); g_free (line_broken); g_free (escaped); + g_variant_unref (body); tp_message_mixin_sent (obj, message, 0, "", NULL); return; @@ -348,6 +349,8 @@ err: g_assert (error != NULL); tp_message_mixin_sent (obj, message, 0, NULL, error); g_error_free (error); + if (body != NULL) + g_variant_unref (body); } static void @@ -361,10 +364,10 @@ haze_im_channel_fill_immutable_properties (TpBaseChannel *chan, tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, - TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "MessagePartSupportFlags", - TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "DeliveryReportingSupport", - TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "SupportedContentTypes", - TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "MessageTypes", + TP_IFACE_CHANNEL_TYPE_TEXT, "MessagePartSupportFlags", + TP_IFACE_CHANNEL_TYPE_TEXT, "DeliveryReportingSupport", + TP_IFACE_CHANNEL_TYPE_TEXT, "SupportedContentTypes", + TP_IFACE_CHANNEL_TYPE_TEXT, "MessageTypes", NULL); } @@ -443,7 +446,7 @@ haze_im_channel_class_init (HazeIMChannelClass *klass) base_class->channel_type = TP_IFACE_CHANNEL_TYPE_TEXT; base_class->get_interfaces = haze_im_channel_get_interfaces; - base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; + base_class->target_entity_type = TP_ENTITY_TYPE_CONTACT; base_class->close = haze_im_channel_close; base_class->fill_immutable_properties = haze_im_channel_fill_immutable_properties; @@ -471,7 +474,7 @@ haze_im_channel_start (HazeIMChannel *self) HazeConnection *conn = HAZE_CONNECTION (base_conn); contact_handles = tp_base_connection_get_handles (base_conn, - TP_HANDLE_TYPE_CONTACT); + TP_ENTITY_TYPE_CONTACT); recipient = tp_handle_inspect (contact_handles, tp_base_channel_get_target_handle (base)); priv->conv = purple_conversation_new (PURPLE_CONV_TYPE_IM, diff --git a/src/im-channel.h b/src/im-channel.h index 3486d05..9caadf8 100644 --- a/src/im-channel.h +++ b/src/im-channel.h @@ -36,8 +36,6 @@ typedef struct _HazeIMChannelClass HazeIMChannelClass; struct _HazeIMChannelClass { TpBaseChannelClass parent_class; - - TpDBusPropertiesMixinClass properties_class; }; struct _HazeIMChannel { diff --git a/src/protocol.c b/src/protocol.c index dc2fa64..5216bf1 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -29,6 +29,7 @@ #include <libpurple/accountopt.h> #include <libpurple/prpl.h> #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "connection.h" #include "connection-avatars.h" @@ -203,7 +204,7 @@ static const KnownProtocolInfo known_protocol_info[] = { { "irc", "prpl-irc", irc_mappings, "x-irc" /* ? */ }, { "icq", "prpl-icq", encoding_to_charset, "x-icq" }, { "jabber", "prpl-jabber", jabber_mappings, "x-jabber", jabber_fixup }, - { "local-xmpp", "prpl-bonjour", bonjour_mappings, "" /* ? */ }, + { "local_xmpp", "prpl-bonjour", bonjour_mappings, "" /* ? */ }, { "msn", "prpl-msn", NULL, "x-msn" }, { "qq", "prpl-qq", NULL, "x-qq" /* ? */ }, { "sametime", "prpl-meanwhile", sametime_mappings, "x-sametime" /* ? */ }, @@ -213,8 +214,8 @@ static const KnownProtocolInfo known_protocol_info[] = { { "zephyr", "prpl-zephyr", encoding_to_charset, "x-zephyr" /* ? */ }, { "mxit", "prpl-loubserp-mxit", NULL, "x-mxit" /* ? */ }, { "sip", "prpl-simple", NULL, "x-sip" }, - { "skype-dbus", "prpl-bigbrownchunx-skype-dbus", NULL, "x-skype" }, - { "skype-x11", "prpl-bigbrownchunx-skype", NULL, "x-skype" }, + { "skype_dbus", "prpl-bigbrownchunx-skype-dbus", NULL, "x-skype" }, + { "skype_x11", "prpl-bigbrownchunx-skype", NULL, "x-skype" }, { NULL, NULL, NULL } }; @@ -245,20 +246,36 @@ haze_protocol_build_list (void) if (info == NULL) { + gchar *tmp; const gchar *tp_name; if (g_str_has_prefix (p_info->id, "prpl-")) { - tp_name = (p_info->id + 5); + /* We prepend _ in case the prpl ID starts with a digit. + * We'll skip it later if we don't need it. */ + tmp = g_strdup_printf ("_%s", p_info->id + 5); } else { g_warning ("prpl '%s' has a dumb id; spank its author", p_info->id); - tp_name = p_info->id; + tmp = g_strdup_printf ("_%s", p_info->id); } - DEBUG ("using default behaviour for unknown prpl '%s'", p_info->id); + /* filter out anything odd */ + g_strcanon (tmp, + "abcdefghijklmnopqrstuvwzyz" + "ABCDEFGHIJKLMNOPQRSTUVWZYZ" + "0123456789_", '_'); + + /* see whether we need to prefix with _ or not */ + if (tmp[1] >= '0' && tmp[1] <= '9') + tp_name = tmp; + else + tp_name = tmp + 1; + + DEBUG ("using default behaviour for unknown prpl '%s' " + "(renamed to %s for Telepathy)", p_info->id, tp_name); protocol = g_object_new (HAZE_TYPE_PROTOCOL, "name", tp_name, @@ -266,6 +283,7 @@ haze_protocol_build_list (void) "prpl-id", p_info->id, "prpl-info", prpl_info, NULL); + g_free (tmp); } else { @@ -561,7 +579,7 @@ haze_protocol_get_parameters (TpBaseProtocol *protocol) paramspecs = g_array_new (TRUE, TRUE, sizeof (TpCMParamSpec)); - /* TODO: local-xmpp shouldn't have an account parameter */ + /* TODO: local_xmpp shouldn't have an account parameter */ g_array_append_val (paramspecs, account_spec); /* Translate user splits for protocols that have a mapping */ @@ -615,6 +633,23 @@ haze_protocol_init (HazeProtocol *self) HazeProtocolPrivate); } +static void +haze_protocol_constructed (GObject *object) +{ + void (*constructed) (GObject *) = + G_OBJECT_CLASS (haze_protocol_parent_class)->constructed; + HazeProtocol *self = HAZE_PROTOCOL (object); + + if (constructed != NULL) + constructed (object); + + /* Knock out the Avatars1 interface if we shouldn't support it. */ + if (!haze_connection_protocol_info_supports_avatar (self->priv->prpl_info)) + g_dbus_object_skeleton_remove_interface_by_name ( + G_DBUS_OBJECT_SKELETON (self), + TP_IFACE_CONNECTION_INTERFACE_AVATARS1); +} + static gchar * haze_protocol_get_username (GHashTable *params, PurplePluginProtocolInfo *prpl_info, @@ -883,34 +918,6 @@ haze_protocol_identify_account (TpBaseProtocol *base, return ret; } -static GPtrArray * -haze_protocol_get_interfaces_array (TpBaseProtocol *base) -{ - HazeProtocol *self = HAZE_PROTOCOL (base); - GPtrArray *interfaces; - GPtrArray *tmp; - guint i; - - interfaces = TP_BASE_PROTOCOL_CLASS ( - haze_protocol_parent_class)->get_interfaces_array (base); - - /* Claim to implement Avatars only if we support avatars for this - * protocol. */ - tmp = haze_connection_dup_implemented_interfaces (self->priv->prpl_info); - for (i = 0; i < tmp->len; i++) - { - if (!tp_strdiff (g_ptr_array_index (tmp, i), - TP_IFACE_CONNECTION_INTERFACE_AVATARS)) - { - g_ptr_array_add (interfaces, TP_IFACE_PROTOCOL_INTERFACE_AVATARS); - break; - } - } - g_ptr_array_unref (tmp); - - return interfaces; -} - static void haze_protocol_get_connection_details (TpBaseProtocol *base, GStrv *connection_interfaces, @@ -945,7 +952,6 @@ haze_protocol_get_connection_details (TpBaseProtocol *base, if (channel_manager_types != NULL) { GType types[] = { HAZE_TYPE_IM_CHANNEL_FACTORY, - HAZE_TYPE_CONTACT_LIST, G_TYPE_INVALID }; *channel_manager_types = g_memdup (types, sizeof (types)); @@ -958,6 +964,7 @@ haze_protocol_get_connection_details (TpBaseProtocol *base, { /* guess from the protocol name, like TpProtocol and TpAccount do */ *icon_name = g_strdup_printf ("im-%s", tp_base_protocol_get_name (base)); + g_strdelimit (*icon_name, "_", '-'); } if (vcard_field != NULL) @@ -966,7 +973,7 @@ haze_protocol_get_connection_details (TpBaseProtocol *base, self->priv->known_protocol->vcard_field != NULL) { /* this might be "", for cases where we know that there isn't an - * applicable vCard field, like local-xmpp and facebook */ + * applicable vCard field, like local_xmpp and facebook */ *vcard_field = g_strdup ( self->priv->known_protocol->vcard_field); } @@ -988,14 +995,14 @@ static GStrv haze_protocol_dup_authentication_types (TpBaseProtocol *base) { static const gchar *types[] = { - TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, + TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION1, NULL }; return g_strdupv ((GStrv) types); } -static void +static gboolean haze_protocol_get_avatar_details (TpBaseProtocol *base, GStrv *supported_mime_types, guint *min_height, @@ -1022,12 +1029,14 @@ haze_protocol_get_avatar_details (TpBaseProtocol *base, *max_height = 0; *max_width = 0; *max_bytes = 0; - return; + return FALSE; } haze_connection_get_icon_spec_requirements (icon_spec, supported_mime_types, min_height, min_width, rec_height, rec_width, max_height, max_width, max_bytes); + + return TRUE; } static void @@ -1041,7 +1050,6 @@ haze_protocol_class_init (HazeProtocolClass *cls) base_class->new_connection = haze_protocol_new_connection; base_class->normalize_contact = haze_protocol_normalize_contact; base_class->identify_account = haze_protocol_identify_account; - base_class->get_interfaces_array = haze_protocol_get_interfaces_array; base_class->get_connection_details = haze_protocol_get_connection_details; base_class->dup_authentication_types = haze_protocol_dup_authentication_types; @@ -1050,6 +1058,7 @@ haze_protocol_class_init (HazeProtocolClass *cls) g_type_class_add_private (cls, sizeof (HazeProtocolPrivate)); object_class->get_property = haze_protocol_get_property; object_class->set_property = haze_protocol_set_property; + object_class->constructed = haze_protocol_constructed; object_class->finalize = haze_protocol_finalize; param_spec = g_param_spec_pointer ("plugin", "PurplePlugin", diff --git a/src/telepathy-haze.8.in b/src/telepathy-haze-1.8.in index 8641a11..de5982d 100644 --- a/src/telepathy-haze.8.in +++ b/src/telepathy-haze-1.8.in @@ -1,12 +1,12 @@ -.TH TELEPATHY-HAZE "8" "October 2007" "Telepathy" "D-Bus services" +.TH TELEPATHY-HAZE-1 "8" "October 2007" "Telepathy" "D-Bus services" \" This man page was written by Simon McVittie for the Debian project, \" but may be used by others. \" Copyright © 2007 Collabora Ltd. <http://www.collabora.co.uk/> \" It may be distributed under the same terms as telepathy-haze itself. .SH NAME -telepathy-haze \- Telepathy connection manager using libpurple +telepathy-haze-1 \- Telepathy connection manager using libpurple .SH SYNOPSIS -\fB@libexecdir@/telepathy\-haze\fR +\fB@libexecdir@/telepathy\-haze\-1\fR .SH DESCRIPTION Haze implements the Telepathy D-Bus specification using libpurple, allowing Telepathy clients like diff --git a/tests/Makefile.am b/tests/Makefile.am index af9cb85..efde446 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,5 @@ SUBDIRS = . -if WANT_TWISTED_TESTS SUBDIRS += twisted -endif CLEANFILES = haze-testing.log diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am index f932229..146d128 100644 --- a/tests/twisted/Makefile.am +++ b/tests/twisted/Makefile.am @@ -23,8 +23,9 @@ TWISTED_TESTS = \ text/test-text-no-body.py \ text/test-text.py - +if WANT_TWISTED_TESTS check-local: check-twisted +endif CHECK_TWISTED_SLEEP=0 @@ -35,36 +36,55 @@ check-twisted: $(BUILT_SOURCES) else \ haze_test_sleep=--sleep=$(CHECK_TWISTED_SLEEP); \ fi; \ - HAZE_TEST_UNINSTALLED=1 \ - HAZE_ABS_TOP_SRCDIR=@abs_top_srcdir@ \ - HAZE_ABS_TOP_BUILDDIR=@abs_top_builddir@ \ - HAZE_TEST_SLEEP=$$haze_test_sleep \ + CHECK_TWISTED_UNINSTALLED=1 \ + G_TEST_SRCDIR=@abs_srcdir@ \ + G_TEST_BUILDDIR=@abs_builddir@ \ + CHECK_TWISTED_SLEEP=$$haze_test_sleep \ ./run-test.sh "$(TWISTED_TESTS)" -EXTRA_DIST = \ +dist_test_data = \ $(TWISTED_TESTS) \ constants.py \ gabbletest.py \ hazetest.py \ - run-test.sh.in \ sasl/saslutil.py \ servicetest.py \ - ns.py + ns.py \ + $(NULL) -haze-twisted-tests.list: Makefile +EXTRA_DIST = \ + $(dist_test_data) \ + run-test.sh.in \ + $(NULL) + +twisted-tests.list: Makefile $(AM_V_GEN)echo $(TWISTED_TESTS) > $@ +built_test_data = \ + twisted-tests.list \ + $(NULL) + +built_test_scripts = \ + run-test.sh \ + $(NULL) + BUILT_SOURCES = \ - haze-twisted-tests.list \ - run-test.sh \ - $(NULL) + $(built_test_data) \ + $(built_test_scripts) \ + $(NULL) + +testsdir = ${datadir}/telepathy-haze-1-tests +twistedtestsdir = ${testsdir}/twisted + +if ENABLE_INSTALLED_TESTS +nobase_dist_twistedtests_DATA = $(dist_test_data) +twistedtests_DATA = $(built_test_data) +twistedtests_SCRIPTS = $(built_test_scripts) +endif -# We don't really use hazetestsdir yet - we only support uninstalled testing -# so far - but I'm substituting it to keep the script more similar to Gabble's. -# ${pkglibexecdir}/tests is what GNOME's InstalledTests goal recommends. run-test.sh: run-test.sh.in Makefile $(AM_V_GEN)sed \ - -e 's![@]hazetestsdir[@]!${pkglibexecdir}/tests!' \ + -e 's![@]twistedtestsdir[@]!${twistedtestsdir}!' \ -e 's![@]TEST_PYTHON[@]!$(TEST_PYTHON)!' \ < $< > $@.tmp && \ chmod +x $@.tmp && \ @@ -76,3 +96,19 @@ CLEANFILES = \ *.pyc \ */*.pyc \ $(NULL) + +%.test: Makefile + @$(MKDIR_P) $(dir $*) + $(AM_V_GEN)( echo '[Test]'; \ + echo 'Exec=${twistedtestsdir}/run-test.sh $*.py'; \ + echo 'Type=session'; \ + echo 'Output=TAP' ) > $@.tmp + @mv $@.tmp $@ + +insttestdir = ${datadir}/installed-tests/telepathy-haze-1 + +if ENABLE_INSTALLED_TESTS +nobase_nodist_insttest_DATA = \ + $(patsubst %.py,%.test,$(TWISTED_TESTS)) \ + $(NULL) +endif diff --git a/tests/twisted/avatar-requirements.py b/tests/twisted/avatar-requirements.py index 8cd3d77..a4b59b4 100644 --- a/tests/twisted/avatar-requirements.py +++ b/tests/twisted/avatar-requirements.py @@ -1,27 +1,34 @@ -from servicetest import call_async, EventPattern +from dbus import (DBusException) + +from servicetest import (call_async, EventPattern, assertContains) from hazetest import exec_test import constants as cs def test(q, bus, conn, stream): - props = conn.GetAll(cs.CONN_IFACE_AVATARS, + try: + props = conn.GetAll(cs.CONN_IFACE_AVATARS, dbus_interface=cs.PROPERTIES_IFACE) - types = props['SupportedAvatarMIMETypes'] - minw = props['MinimumAvatarWidth'] - minh = props['MinimumAvatarHeight'] - maxw = props['MaximumAvatarWidth'] - maxh = props['MaximumAvatarHeight'] - maxb = props['MaximumAvatarBytes'] - rech = props['RecommendedAvatarHeight'] - recw = props['RecommendedAvatarWidth'] + except DBusException, e: + assertContains(e.get_dbus_name(), + ['org.freedesktop.DBus.Error.InvalidArgs']) + else: + types = props['SupportedAvatarMIMETypes'] + minw = props['MinimumAvatarWidth'] + minh = props['MinimumAvatarHeight'] + maxw = props['MaximumAvatarWidth'] + maxh = props['MaximumAvatarHeight'] + maxb = props['MaximumAvatarBytes'] + rech = props['RecommendedAvatarHeight'] + recw = props['RecommendedAvatarWidth'] - assert types == [], types - assert minw == 0, minw - assert minh == 0, minh - assert maxw == 0, maxw - assert maxh == 0, maxh - assert maxb == 0, maxb - assert recw == 0, recw - assert rech == 0, rech + assert types == [], types + assert minw == 0, minw + assert minh == 0, minh + assert maxw == 0, maxw + assert maxh == 0, maxh + assert maxb == 0, maxb + assert recw == 0, recw + assert rech == 0, rech conn.Connect() q.expect('dbus-signal', signal='StatusChanged', @@ -49,15 +56,5 @@ def test(q, bus, conn, stream): assert recw == 0, recw assert rech == 0, rech - # deprecated version - types, minw, minh, maxw, maxh, maxb = conn.Avatars.GetAvatarRequirements() - assert types[0] == 'image/png', types - assert minw == 32, minw - assert minh == 32, minh - assert maxw == 96, maxw - assert maxh == 96, maxh - # libpurple currently says there's no max size - #assert maxb == 8192, maxb - if __name__ == '__main__': exec_test(test, do_connect=False) diff --git a/tests/twisted/cm/protocols.py b/tests/twisted/cm/protocols.py index 2bd835b..5f2d60f 100644 --- a/tests/twisted/cm/protocols.py +++ b/tests/twisted/cm/protocols.py @@ -17,27 +17,25 @@ def test(q, bus, conn, stream): cm_props = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = cm_props.Get(cs.CM, 'Protocols') - protocol_names = cm_iface.ListProtocols() - assertEquals(set(protocols.iterkeys()), set(protocol_names)) - for name in protocol_names: - props = protocols[name] + for name, props in protocols.iteritems(): protocol = bus.get_object(cm.bus_name, cm.object_path + '/' + name.replace('-', '_')) protocol_iface = dbus.Interface(protocol, cs.PROTOCOL) protocol_props = dbus.Interface(protocol, cs.PROPERTIES_IFACE) flat_props = protocol_props.GetAll(cs.PROTOCOL) - protocol_avatar_props = protocol_props.GetAll(cs.PROTOCOL_IFACE_AVATARS) # Protocol is supposed to implement Interface.Avatars iff the # connection implements Avatars as well. if cs.CONN_IFACE_AVATARS in flat_props['ConnectionInterfaces']: assertContains(cs.PROTOCOL_IFACE_AVATARS, props[cs.PROTOCOL + '.Interfaces']) + protocol_avatar_props = ( + protocol_props.GetAll(cs.PROTOCOL_IFACE_AVATARS)) else: assertDoesNotContain(cs.PROTOCOL_IFACE_AVATARS, props[cs.PROTOCOL + '.Interfaces']) + protocol_avatar_props = None - parameters = cm_iface.GetParameters(name) - assertEquals(parameters, props[cs.PROTOCOL + '.Parameters']) + parameters = props[cs.PROTOCOL + '.Parameters'] assertEquals(parameters, flat_props['Parameters']) assertEquals(parameters, protocol_props.Get(cs.PROTOCOL, 'Parameters')) @@ -69,7 +67,7 @@ def test(q, bus, conn, stream): assertDoesNotContain('encoding', param_map) assertDoesNotContain('local_charset', param_map) - if name not in ('local-xmpp', 'irc'): + if name not in ('local_xmpp', 'irc'): # it would be more correct for these protocols not to have this # parameter assertEquals((cs.PARAM_REQUIRED, 's', ''), param_map['account']) @@ -108,14 +106,7 @@ def test(q, bus, conn, stream): assertDoesNotContain(cs.CONN_IFACE_MAIL_NOTIFICATION, flat_props['ConnectionInterfaces']) # Avatar not supported - assertEquals(0, protocol_avatar_props['MaximumAvatarBytes']) - assertEquals(0, protocol_avatar_props['MaximumAvatarHeight']) - assertEquals(0, protocol_avatar_props['MaximumAvatarWidth']) - assertEquals(0, protocol_avatar_props['MinimumAvatarHeight']) - assertEquals(0, protocol_avatar_props['MinimumAvatarWidth']) - assertEquals(0, protocol_avatar_props['RecommendedAvatarHeight']) - assertEquals(0, protocol_avatar_props['RecommendedAvatarWidth']) - assertEquals([], protocol_avatar_props['SupportedAvatarMIMETypes']) + assertEquals(None, protocol_avatar_props) elif name == 'myspace': assertEquals('x-myspace', flat_props['VCardField']) assertEquals('im-myspace', flat_props['Icon']) @@ -186,7 +177,7 @@ def test(q, bus, conn, stream): assertEquals('im-zephyr', flat_props['Icon']) assertEquals('s', param_type['realm']) assertEquals('s', param_type['charset']) - elif name == 'local-xmpp': + elif name == 'local_xmpp': # makes very little sense in an address book assertEquals('', flat_props['VCardField']) assertEquals('im-local-xmpp', flat_props['Icon']) diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py index e4235f8..8272a67 100644 --- a/tests/twisted/constants.py +++ b/tests/twisted/constants.py @@ -1,60 +1,71 @@ +# Copyright (C) 2009 Nokia Corporation +# Copyright (C) 2009-2013 Collabora Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + """ Some handy constants for other tests to share and enjoy. """ -from dbus import PROPERTIES_IFACE +from dbus import PROPERTIES_IFACE, INTROSPECTABLE_IFACE + +PREFIX = "im.telepathy.v1" +PATH_PREFIX = '/' + PREFIX.replace('.', '/') -PREFIX = "org.freedesktop.Telepathy" +tp_name_prefix = PREFIX +tp_path_prefix = PATH_PREFIX CM = PREFIX + ".ConnectionManager" HT_NONE = 0 HT_CONTACT = 1 HT_ROOM = 2 -HT_LIST = 3 -HT_GROUP = 4 CHANNEL = PREFIX + ".Channel" -CHANNEL_IFACE_CALL_STATE = CHANNEL + ".Interface.CallState" -CHANNEL_IFACE_CHAT_STATE = CHANNEL + '.Interface.ChatState' -CHANNEL_IFACE_DESTROYABLE = CHANNEL + ".Interface.Destroyable" -CHANNEL_IFACE_DTMF = CHANNEL + ".Interface.DTMF" -CHANNEL_IFACE_GROUP = CHANNEL + ".Interface.Group" -CHANNEL_IFACE_HOLD = CHANNEL + ".Interface.Hold" -CHANNEL_IFACE_MEDIA_SIGNALLING = CHANNEL + ".Interface.MediaSignalling" -CHANNEL_IFACE_MESSAGES = CHANNEL + ".Interface.Messages" -CHANNEL_IFACE_PASSWORD = CHANNEL + ".Interface.Password" -CHANNEL_IFACE_TUBE = CHANNEL + ".Interface.Tube" -CHANNEL_IFACE_SASL_AUTH = CHANNEL + ".Interface.SASLAuthentication" -CHANNEL_IFACE_CONFERENCE = CHANNEL + '.Interface.Conference' -CHANNEL_IFACE_ROOM = CHANNEL + '.Interface.Room2' +CHANNEL_IFACE_CHAT_STATE = CHANNEL + '.Interface.ChatState1' +CHANNEL_IFACE_DESTROYABLE = CHANNEL + ".Interface.Destroyable1" +CHANNEL_IFACE_DTMF = CHANNEL + ".Interface.DTMF1" +CHANNEL_IFACE_GROUP = CHANNEL + ".Interface.Group1" +CHANNEL_IFACE_HOLD = CHANNEL + ".Interface.Hold1" +CHANNEL_IFACE_PASSWORD = CHANNEL + ".Interface.Password1" +CHANNEL_IFACE_TUBE = CHANNEL + ".Interface.Tube1" +CHANNEL_IFACE_SASL_AUTH = CHANNEL + ".Interface.SASLAuthentication1" +CHANNEL_IFACE_CONFERENCE = CHANNEL + '.Interface.Conference1' +CHANNEL_IFACE_ROOM = CHANNEL + '.Interface.Room1' CHANNEL_IFACE_ROOM_CONFIG = CHANNEL + '.Interface.RoomConfig1' -CHANNEL_IFACE_SUBJECT = CHANNEL + '.Interface.Subject2' -CHANNEL_IFACE_FILE_TRANSFER_METADATA = CHANNEL + '.Interface.FileTransfer.Metadata' +CHANNEL_IFACE_SUBJECT = CHANNEL + '.Interface.Subject1' +CHANNEL_IFACE_FILE_TRANSFER_METADATA = CHANNEL + '.Interface.FileTransfer.Metadata1' CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call1" -CHANNEL_TYPE_CONTACT_LIST = CHANNEL + ".Type.ContactList" -CHANNEL_TYPE_CONTACT_SEARCH = CHANNEL + ".Type.ContactSearch" -CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text" -CHANNEL_TYPE_TUBES = CHANNEL + ".Type.Tubes" -CHANNEL_TYPE_STREAM_TUBE = CHANNEL + ".Type.StreamTube" -CHANNEL_TYPE_DBUS_TUBE = CHANNEL + ".Type.DBusTube" +CHANNEL_TYPE_CONTACT_SEARCH = CHANNEL + ".Type.ContactSearch1" CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text" -CHANNEL_TYPE_FILE_TRANSFER = CHANNEL + ".Type.FileTransfer" -CHANNEL_TYPE_ROOM_LIST = CHANNEL + ".Type.RoomList" +CHANNEL_TYPE_STREAM_TUBE = CHANNEL + ".Type.StreamTube1" +CHANNEL_TYPE_DBUS_TUBE = CHANNEL + ".Type.DBusTube1" +CHANNEL_TYPE_FILE_TRANSFER = CHANNEL + ".Type.FileTransfer1" +CHANNEL_TYPE_ROOM_LIST = CHANNEL + ".Type.RoomList1" CHANNEL_TYPE_SERVER_AUTHENTICATION = \ - CHANNEL + ".Type.ServerAuthentication" + CHANNEL + ".Type.ServerAuthentication1" CHANNEL_TYPE_SERVER_TLS_CONNECTION = \ - CHANNEL + ".Type.ServerTLSConnection" - -TP_AWKWARD_PROPERTIES = PREFIX + ".Properties" -PROPERTY_FLAG_READ = 1 -PROPERTY_FLAG_WRITE = 2 -PROPERTY_FLAGS_RW = PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE + CHANNEL + ".Type.ServerTLSConnection1" CHANNEL_TYPE = CHANNEL + '.ChannelType' -TARGET_HANDLE_TYPE = CHANNEL + '.TargetHandleType' +TARGET_ENTITY_TYPE = CHANNEL + '.TargetEntityType' +# let's leave this as a synonym to reduce tests' diff churn in CMs +TARGET_HANDLE_TYPE = CHANNEL + '.TargetEntityType' TARGET_HANDLE = CHANNEL + '.TargetHandle' TARGET_ID = CHANNEL + '.TargetID' REQUESTED = CHANNEL + '.Requested' @@ -62,6 +73,15 @@ INITIATOR_HANDLE = CHANNEL + '.InitiatorHandle' INITIATOR_ID = CHANNEL + '.InitiatorID' INTERFACES = CHANNEL + '.Interfaces' +CALL_CONTENTS = CHANNEL_TYPE_CALL + '.Contents' +CALL_CALL_STATE_DETAILS = CHANNEL_TYPE_CALL + '.CallStateDetails' +CALL_CALL_STATE = CHANNEL_TYPE_CALL + '.CallState' +CALL_CALL_FLAGS = CHANNEL_TYPE_CALL + '.CallFlags' +CALL_CALL_STATE_REASON = CHANNEL_TYPE_CALL + '.CallStateReason' +CALL_HARDWARE_STREAMING = CHANNEL_TYPE_CALL + '.HardwareStreaming' +CALL_CALL_MEMBERS = CHANNEL_TYPE_CALL + '.CallMembers' +CALL_MEMBER_IDENTIFIERS = CHANNEL_TYPE_CALL + '.MemberIdentifiers' +CALL_INITIAL_TRANSPORT = CHANNEL_TYPE_CALL + '.InitialTransport' CALL_INITIAL_AUDIO = CHANNEL_TYPE_CALL + '.InitialAudio' CALL_INITIAL_AUDIO_NAME = CHANNEL_TYPE_CALL + '.InitialAudioName' CALL_INITIAL_VIDEO = CHANNEL_TYPE_CALL + '.InitialVideo' @@ -70,9 +90,9 @@ CALL_MUTABLE_CONTENTS = CHANNEL_TYPE_CALL + '.MutableContents' CALL_CONTENT = PREFIX + '.Call1.Content' CALL_CONTENT_IFACE_MEDIA = CALL_CONTENT + '.Interface.Media' -CALL_CONTENT_IFACE_DTMF = CALL_CONTENT + '.Interface.DTMF' +CALL_CONTENT_IFACE_DTMF = CALL_CONTENT + '.Interface.DTMF1' -CALL_CONTENT_MEDIADESCRIPTION = CALL_CONTENT + '.MediaDescription' +CALL_CONTENT_MEDIA_DESCRIPTION = CALL_CONTENT + '.MediaDescription' CALL_STREAM = PREFIX + '.Call1.Stream' CALL_STREAM_IFACE_MEDIA = CALL_STREAM + '.Interface.Media' @@ -165,31 +185,36 @@ CONTACT_LIST_STATE_FAILURE = 2 CONTACT_LIST_STATE_SUCCESS = 3 CONN = PREFIX + ".Connection" -CONN_IFACE_AVATARS = CONN + '.Interface.Avatars' -CONN_IFACE_ALIASING = CONN + '.Interface.Aliasing' -CONN_IFACE_CAPS = CONN + '.Interface.Capabilities' -CONN_IFACE_CONTACTS = CONN + '.Interface.Contacts' -CONN_IFACE_CONTACT_CAPS = CONN + '.Interface.ContactCapabilities' -CONN_IFACE_CONTACT_INFO = CONN + ".Interface.ContactInfo" -CONN_IFACE_PRESENCE = CONN + '.Interface.Presence' -CONN_IFACE_SIMPLE_PRESENCE = CONN + '.Interface.SimplePresence' +CONN_IFACE_AVATARS = CONN + '.Interface.Avatars1' +CONN_IFACE_ALIASING = CONN + '.Interface.Aliasing1' +CONN_IFACE_CONTACT_CAPS = CONN + '.Interface.ContactCapabilities1' +CONN_IFACE_CONTACT_INFO = CONN + ".Interface.ContactInfo1" +CONN_IFACE_PRESENCE = CONN + '.Interface.Presence1' +CONN_IFACE_RENAMING = CONN + '.Interface.Renaming1' +CONN_IFACE_SIDECARS1 = CONN + '.Interface.Sidecars1' CONN_IFACE_REQUESTS = CONN + '.Interface.Requests' -CONN_IFACE_LOCATION = CONN + '.Interface.Location' +CONN_IFACE_LOCATION = CONN + '.Interface.Location1' CONN_IFACE_GABBLE_DECLOAK = CONN + '.Interface.Gabble.Decloak' -CONN_IFACE_MAIL_NOTIFICATION = CONN + '.Interface.MailNotification' -CONN_IFACE_CONTACT_LIST = CONN + '.Interface.ContactList' -CONN_IFACE_CONTACT_GROUPS = CONN + '.Interface.ContactGroups' -CONN_IFACE_CLIENT_TYPES = CONN + '.Interface.ClientTypes' -CONN_IFACE_POWER_SAVING = CONN + '.Interface.PowerSaving' -CONN_IFACE_CONTACT_BLOCKING = CONN + '.Interface.ContactBlocking' +CONN_IFACE_MAIL_NOTIFICATION = CONN + '.Interface.MailNotification1' +CONN_IFACE_CONTACT_LIST = CONN + '.Interface.ContactList1' +CONN_IFACE_CONTACT_GROUPS = CONN + '.Interface.ContactGroups1' +CONN_IFACE_CLIENT_TYPES = CONN + '.Interface.ClientTypes1' +CONN_IFACE_POWER_SAVING = CONN + '.Interface.PowerSaving1' +CONN_IFACE_CONTACT_BLOCKING = CONN + '.Interface.ContactBlocking1' CONN_IFACE_ADDRESSING = CONN + '.Interface.Addressing1' +CONN_IFACE_SERVICE_POINT = CONN + '.Interface.ServicePoint1' -ATTR_CONTACT_ID = CONN + '/contact-id' +ATTR_ALIAS = CONN_IFACE_ALIASING + '/alias' +ATTR_AVATAR_TOKEN = CONN_IFACE_AVATARS + '/token' +ATTR_CLIENT_TYPES = CONN_IFACE_CLIENT_TYPES + '/client-types' ATTR_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities' -ATTR_PRESENCE = CONN_IFACE_SIMPLE_PRESENCE + '/presence' -ATTR_SUBSCRIBE = CONN_IFACE_CONTACT_LIST + '/subscribe' -ATTR_PUBLISH = CONN_IFACE_CONTACT_LIST + '/publish' +ATTR_CONTACT_ID = CONN + '/contact-id' +ATTR_CONTACT_INFO = CONN_IFACE_CONTACT_INFO + '/info' ATTR_GROUPS = CONN_IFACE_CONTACT_GROUPS + '/groups' +ATTR_LOCATION = CONN_IFACE_LOCATION + '/location' +ATTR_PRESENCE = CONN_IFACE_PRESENCE + '/presence' +ATTR_PUBLISH = CONN_IFACE_CONTACT_LIST + '/publish' +ATTR_SUBSCRIBE = CONN_IFACE_CONTACT_LIST + '/subscribe' STREAM_HANDLER = PREFIX + '.Media.StreamHandler' @@ -204,6 +229,7 @@ CONNECTION_REFUSED = ERROR + '.ConnectionRefused' CONNECTION_FAILED = ERROR + '.ConnectionFailed' CONNECTION_LOST = ERROR + '.ConnectionLost' CANCELLED = ERROR + '.Cancelled' +NOT_YOURS = ERROR + '.NotYours' DISCONNECTED = ERROR + '.Disconnected' REGISTRATION_EXISTS = ERROR + '.RegistrationExists' AUTHENTICATION_FAILED = ERROR + '.AuthenticationFailed' @@ -215,10 +241,12 @@ INVALID_HANDLE = ERROR + '.InvalidHandle' CERT_UNTRUSTED = ERROR + '.Cert.Untrusted' SERVICE_BUSY = ERROR + '.ServiceBusy' SERVICE_CONFUSED = ERROR + '.ServiceConfused' +SOFTWARE_UPGRADE_REQUIRED = ERROR + '.SoftwareUpgradeRequired' BANNED = ERROR + '.Channel.Banned' -UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod' +DBUS_ERROR_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod' +DBUS_ERROR_NO_REPLY = 'org.freedesktop.DBus.Error.NoReply' TUBE_PARAMETERS = CHANNEL_IFACE_TUBE + '.Parameters' TUBE_STATE = CHANNEL_IFACE_TUBE + '.State' @@ -264,17 +292,13 @@ SOCKET_ADDRESS_TYPE_IPV6 = 3 SOCKET_ACCESS_CONTROL_LOCALHOST = 0 SOCKET_ACCESS_CONTROL_PORT = 1 -SOCKET_ACCESS_CONTROL_NETMASK = 2 -SOCKET_ACCESS_CONTROL_CREDENTIALS = 3 +SOCKET_ACCESS_CONTROL_CREDENTIALS = 2 TUBE_STATE_LOCAL_PENDING = 0 TUBE_STATE_REMOTE_PENDING = 1 TUBE_STATE_OPEN = 2 TUBE_STATE_NOT_OFFERED = 3 -TUBE_TYPE_DBUS = 0 -TUBE_TYPE_STREAM = 1 - MEDIA_STREAM_DIRECTION_NONE = 0 MEDIA_STREAM_DIRECTION_SEND = 1 MEDIA_STREAM_DIRECTION_RECEIVE = 2 @@ -286,15 +310,6 @@ MEDIA_STREAM_PENDING_REMOTE_SEND = 2 MEDIA_STREAM_TYPE_AUDIO = 0 MEDIA_STREAM_TYPE_VIDEO = 1 -MEDIA_STREAM_STATE_DISCONNECTED = 0 -MEDIA_STREAM_STATE_CONNECTING = 1 -MEDIA_STREAM_STATE_CONNECTED = 2 - -MEDIA_STREAM_DIRECTION_NONE = 0 -MEDIA_STREAM_DIRECTION_SEND = 1 -MEDIA_STREAM_DIRECTION_RECEIVE = 2 -MEDIA_STREAM_DIRECTION_BIDIRECTIONAL = 3 - FT_STATE_NONE = 0 FT_STATE_PENDING = 1 FT_STATE_ACCEPTED = 2 @@ -325,7 +340,7 @@ FT_DATE = CHANNEL_TYPE_FILE_TRANSFER + '.Date' FT_AVAILABLE_SOCKET_TYPES = CHANNEL_TYPE_FILE_TRANSFER + '.AvailableSocketTypes' FT_TRANSFERRED_BYTES = CHANNEL_TYPE_FILE_TRANSFER + '.TransferredBytes' FT_INITIAL_OFFSET = CHANNEL_TYPE_FILE_TRANSFER + '.InitialOffset' -FT_FILE_COLLECTION = CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE.FileCollection' +FT_FILE_COLLECTION = CHANNEL_TYPE_FILE_TRANSFER + '.FileCollection' FT_URI = CHANNEL_TYPE_FILE_TRANSFER + '.URI' FT_SERVICE_NAME = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.ServiceName' FT_METADATA = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.Metadata' @@ -341,8 +356,7 @@ GF_MESSAGE_RESCIND = 128 GF_CHANNEL_SPECIFIC_HANDLES = 256 GF_ONLY_ONE_GROUP = 512 GF_HANDLE_OWNERS_NOT_AVAILABLE = 1024 -GF_PROPERTIES = 2048 -GF_MEMBERS_CHANGED_DETAILED = 4096 +GF_MESSAGE_DEPART = 2048 GC_REASON_NONE = 0 GC_REASON_OFFLINE = 1 @@ -404,6 +418,7 @@ MEDIA_CAP_IMMUTABLE_STREAMS = 32 CLIENT = PREFIX + '.Client' +PRESENCE_UNSET = 0 PRESENCE_OFFLINE = 1 PRESENCE_AVAILABLE = 2 PRESENCE_AWAY = 3 @@ -473,9 +488,9 @@ class SendError(object): NOT_IMPLEMENTED = 5 PROTOCOL = PREFIX + '.Protocol' -PROTOCOL_IFACE_PRESENCES = PROTOCOL + '.Interface.Presence' -PROTOCOL_IFACE_ADDRESSING = PROTOCOL + '.Interface.Addressing' -PROTOCOL_IFACE_AVATARS = PROTOCOL + '.Interface.Avatars' +PROTOCOL_IFACE_PRESENCES = PROTOCOL + '.Interface.Presence1' +PROTOCOL_IFACE_ADDRESSING = PROTOCOL + '.Interface.Addressing1' +PROTOCOL_IFACE_AVATARS = PROTOCOL + '.Interface.Avatars1' PARAM_REQUIRED = 1 PARAM_REGISTER = 2 @@ -495,9 +510,9 @@ TLS_REJECT_REASON_UNTRUSTED = 1 # Channel.Interface.Messages -MESSAGE_PART_SUPPORT_FLAGS = CHANNEL_IFACE_MESSAGES + '.MessagePartSupportFlags' -DELIVERY_REPORTING_SUPPORT = CHANNEL_IFACE_MESSAGES + '.DeliveryReportingSupport' -SUPPORTED_CONTENT_TYPES = CHANNEL_IFACE_MESSAGES + '.SupportedContentTypes' +MESSAGE_PART_SUPPORT_FLAGS = CHANNEL_TYPE_TEXT + '.MessagePartSupportFlags' +DELIVERY_REPORTING_SUPPORT = CHANNEL_TYPE_TEXT + '.DeliveryReportingSupport' +SUPPORTED_CONTENT_TYPES = CHANNEL_TYPE_TEXT + '.SupportedContentTypes' MSG_SENDING_FLAGS_REPORT_DELIVERY = 1 MSG_SENDING_FLAGS_REPORT_READ = 2 @@ -516,15 +531,7 @@ DELIVERY_STATUS_ACCEPTED = 4 DELIVERY_STATUS_READ = 5 DELIVERY_STATUS_DELETED = 6 -MEDIA_STREAM_ERROR_UNKNOWN = 0 -MEDIA_STREAM_ERROR_EOS = 1 -MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED = 2 -MEDIA_STREAM_ERROR_CONNECTION_FAILED = 3 -MEDIA_STREAM_ERROR_NETWORK_ERROR = 4 -MEDIA_STREAM_ERROR_NO_CODECS = 5 -MEDIA_STREAM_ERROR_INVALID_CM_BEHAVIOR = 6 -MEDIA_STREAM_ERROR_MEDIA_ERROR = 7 - +PASSWORD_FLAG_HINT = 4 PASSWORD_FLAG_PROVIDE = 8 # Channel.Interface.Room @@ -536,5 +543,58 @@ SUBJECT = CHANNEL_IFACE_ROOM + '.Subject' SUBJECT_PRESENT = 1 SUBJECT_CAN_SET = 2 -DEBUG_IFACE = PREFIX + '.Debug' -DEBUG_PATH = '/' + PREFIX.replace('.', '/') + '/debug' +DEBUG_IFACE = PREFIX + '.Debug1' +DEBUG_PATH = PATH_PREFIX + '/debug' + +SERVICE_POINT_TYPE_NONE = 0 +SERVICE_POINT_TYPE_EMERGENCY = 1 +SERVICE_POINT_TYPE_COUNSELING = 2 + +CLIENT = PREFIX + '.Client' +CLIENT_PATH = PATH_PREFIX + '/Client' +OBSERVER = PREFIX + '.Client.Observer' +APPROVER = PREFIX + '.Client.Approver' +HANDLER = PREFIX + '.Client.Handler' +CLIENT_IFACE_REQUESTS = CLIENT + '.Interface.Requests' + +ACCOUNT = PREFIX + '.Account' +ACCOUNT_IFACE_AVATAR = ACCOUNT + '.Interface.Avatar1' +ACCOUNT_IFACE_ADDRESSING = ACCOUNT + '.Interface.Addressing1' +ACCOUNT_IFACE_HIDDEN = ACCOUNT + '.Interface.Hidden1' +ACCOUNT_IFACE_NOKIA_CONDITIONS = 'com.nokia.Account.Interface.Conditions' +ACCOUNT_PATH_PREFIX = PATH_PREFIX + '/Account/' + +AM = PREFIX + '.AccountManager' +AM_IFACE_HIDDEN = AM + '.Interface.Hidden1' +AM_PATH = PATH_PREFIX + '/AccountManager' + +CR = PREFIX + '.ChannelRequest' +CDO = PREFIX + '.ChannelDispatchOperation' + +CD = PREFIX + '.ChannelDispatcher' +CD_IFACE_MESSAGES1 = PREFIX + '.ChannelDispatcher.Interface.Messages1' +CD_IFACE_OP_LIST = PREFIX + '.ChannelDispatcher.Interface.OperationList1' +CD_PATH = PATH_PREFIX + '/ChannelDispatcher' + +MC = PREFIX + '.MissionControl6' +MC_PATH = PATH_PREFIX + '/MissionControl6' +DTMF_CURRENTLY_SENDING_TONES = CHANNEL_IFACE_DTMF + '.CurrentlySendingTones' +DTMF_INITIAL_TONES = CHANNEL_IFACE_DTMF + '.InitialTones' +DTMF_DEFERRED_TONES = CHANNEL_IFACE_DTMF + '.DeferredTones' + +TESTS = PREFIX + ".Tests" +TESTDOT = PREFIX + ".Test." +TESTSLASH = PATH_PREFIX + "/Test/" + +TEST_DBUS_ACCOUNT_SERVICE = TESTDOT + "DBusAccountService" +TEST_DBUS_ACCOUNT_SERVICE_PATH = TESTSLASH + "DBusAccountService" +TEST_DBUS_ACCOUNT_SERVICE_IFACE = TEST_DBUS_ACCOUNT_SERVICE + +TEST_DBUS_ACCOUNT_PLUGIN_PATH = TESTSLASH + "DBusAccountPlugin" +TEST_DBUS_ACCOUNT_PLUGIN_IFACE = TESTDOT + "DBusAccountPlugin" + +class StorageRestrictionFlags(object): + CANNOT_SET_PARAMETERS = 1 + CANNOT_SET_ENABLED = 2 + CANNOT_SET_PRESENCE = 4 + CANNOT_SET_SERVICE = 8 diff --git a/tests/twisted/presence/presence.py b/tests/twisted/presence/presence.py index c91ddfd..d722890 100644 --- a/tests/twisted/presence/presence.py +++ b/tests/twisted/presence/presence.py @@ -49,11 +49,11 @@ def test(q, bus, conn, stream): assert event.args[0] == { amy_handle: (2, 'available', 'I may have been drinking') } amy_handle, asv = conn.Contacts.GetContactByID('amy@foo.com', - [cs.CONN_IFACE_SIMPLE_PRESENCE]) + [cs.CONN_IFACE_PRESENCE]) assertEquals(event.args[0][amy_handle], asv.get(cs.ATTR_PRESENCE)) bob_handle, asv = conn.Contacts.GetContactByID('bob@foo.com', - [cs.CONN_IFACE_SIMPLE_PRESENCE]) + [cs.CONN_IFACE_PRESENCE]) assertEquals((cs.PRESENCE_UNKNOWN, 'unknown', ''), asv.get(cs.ATTR_PRESENCE)) diff --git a/tests/twisted/roster/groups.py b/tests/twisted/roster/groups.py index 0ded827..ab74c2a 100644 --- a/tests/twisted/roster/groups.py +++ b/tests/twisted/roster/groups.py @@ -13,6 +13,9 @@ from hazetest import acknowledge_iq, exec_test, sync_stream import constants as cs import ns +# TODO: this needs porting to ContactList +raise SystemExit(77) + def test(q, bus, conn, stream): self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") diff --git a/tests/twisted/roster/initial-roster.py b/tests/twisted/roster/initial-roster.py index 18169fc..7fa9c96 100644 --- a/tests/twisted/roster/initial-roster.py +++ b/tests/twisted/roster/initial-roster.py @@ -67,7 +67,13 @@ def test(q, bus, conn, stream): amy: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_UNKNOWN, ''), bob: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_UNKNOWN, ''), chris: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_UNKNOWN, ''), - }, []], s.args) + }, + { + amy: 'amy@foo.com', + bob: 'bob@foo.com', + chris: 'chris@foo.com', + }, + {}], s.args) # the XMPP prpl puts people into some sort of group, probably called # Buddies @@ -85,7 +91,7 @@ def test(q, bus, conn, stream): default_group = group call_async(q, conn.ContactList, 'GetContactListAttributes', - [cs.CONN_IFACE_CONTACT_GROUPS], False) + [cs.CONN_IFACE_CONTACT_GROUPS]) r = q.expect('dbus-return', method='GetContactListAttributes') assertEquals(cs.SUBSCRIPTION_STATE_YES, r.value[0][amy][cs.ATTR_SUBSCRIBE]) diff --git a/tests/twisted/roster/publish.py b/tests/twisted/roster/publish.py index df88ce2..3b83e18 100644 --- a/tests/twisted/roster/publish.py +++ b/tests/twisted/roster/publish.py @@ -13,6 +13,9 @@ from hazetest import acknowledge_iq, exec_test, sync_stream import constants as cs import ns +# TODO: this needs porting to ContactList +raise SystemExit(77) + def test(q, bus, conn, stream): call_async(q, conn.ContactList, 'GetContactListAttributes', [cs.CONN_IFACE_CONTACT_GROUPS], False) @@ -30,7 +33,7 @@ def test(q, bus, conn, stream): # it seems either libpurple or haze doesn't pass the message through q.expect_many( - EventPattern('dbus-signal', signal='ContactsChangedWithID', + EventPattern('dbus-signal', signal='ContactsChanged', args=[{ alice: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_ASK, @@ -47,7 +50,7 @@ def test(q, bus, conn, stream): q.expect_many( EventPattern('stream-presence', presence_type='subscribed', to='alice@wonderland.lit'), - EventPattern('dbus-signal', signal='ContactsChangedWithID', + EventPattern('dbus-signal', signal='ContactsChanged', args=[{ alice: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_YES, @@ -72,7 +75,7 @@ def test(q, bus, conn, stream): predicate=lambda e: e.stanza['id'] == 'roster-push'), # She's not really on our subscribe list, but this is the closest # we can guess from libpurple - EventPattern('dbus-signal', signal='ContactsChangedWithID', + EventPattern('dbus-signal', signal='ContactsChanged', args=[{ alice: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, @@ -100,7 +103,7 @@ def test(q, bus, conn, stream): # it seems either libpurple or haze doesn't pass the message through q.expect_many( - EventPattern('dbus-signal', signal='ContactsChangedWithID', + EventPattern('dbus-signal', signal='ContactsChanged', args=[{ queen: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_ASK, @@ -121,7 +124,7 @@ def test(q, bus, conn, stream): q.expect_many( EventPattern('stream-presence', presence_type='unsubscribed', to='queen.of.hearts@wonderland.lit'), - EventPattern('dbus-signal', signal='ContactsChangedWithID', + EventPattern('dbus-signal', signal='ContactsChanged', args=[{ queen: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_NO, @@ -147,7 +150,7 @@ def test(q, bus, conn, stream): stream.send(presence) q.expect_many( - EventPattern('dbus-signal', signal='ContactsChangedWithID', + EventPattern('dbus-signal', signal='ContactsChanged', args=[{ queen: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_ASK, diff --git a/tests/twisted/roster/removed-from-rp-subscribe.py b/tests/twisted/roster/removed-from-rp-subscribe.py index 4b1a0db..e48ae41 100644 --- a/tests/twisted/roster/removed-from-rp-subscribe.py +++ b/tests/twisted/roster/removed-from-rp-subscribe.py @@ -10,6 +10,9 @@ from hazetest import exec_test import constants as cs import ns +# TODO: this needs porting to ContactList +raise SystemExit(77) + jid = 'marco@barisione.lit' def test(q, bus, conn, stream, remove, local): @@ -37,7 +40,7 @@ def test(q, bus, conn, stream, remove, local): # In response, Haze adds Marco to the roster, which we guess (wrongly, # in this case) also means subscribe - q.expect('dbus-signal', signal='ContactsChangedWithID', + q.expect('dbus-signal', signal='ContactsChanged', args=[{ h: (cs.SUBSCRIPTION_STATE_YES, @@ -90,7 +93,7 @@ def test(q, bus, conn, stream, remove, local): # In response, Haze should announce that Marco has been removed from # the roster - q.expect('dbus-signal', signal='ContactsChangedWithID', + q.expect('dbus-signal', signal='ContactsChanged', args=[{}, {}, {h: jid}]) else: # ...rescinds the subscription request... diff --git a/tests/twisted/roster/subscribe.py b/tests/twisted/roster/subscribe.py index b39f86e..ebd325b 100644 --- a/tests/twisted/roster/subscribe.py +++ b/tests/twisted/roster/subscribe.py @@ -12,6 +12,9 @@ from hazetest import acknowledge_iq, exec_test, sync_stream import constants as cs import ns +# TODO: this needs porting to ContactList +raise SystemExit(77) + def test(q, bus, conn, stream): self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") @@ -35,7 +38,7 @@ def test(q, bus, conn, stream): EventPattern('stream-presence', presence_type='subscribe', to='suggs@night.boat.cairo'), EventPattern('dbus-return', method='RequestSubscription', value=()), - EventPattern('dbus-signal', signal='ContactsChangedWithID', + EventPattern('dbus-signal', signal='ContactsChanged', args=[{ handle: (cs.SUBSCRIPTION_STATE_YES, @@ -76,7 +79,7 @@ def test(q, bus, conn, stream): EventPattern('stream-presence', presence_type='subscribe', to='ayria@revenge.world'), EventPattern('dbus-return', method='AddToGroup', value=()), - EventPattern('dbus-signal', signal='ContactsChangedWithID', + EventPattern('dbus-signal', signal='ContactsChanged', args=[{ handle: (cs.SUBSCRIPTION_STATE_YES, diff --git a/tests/twisted/run-test.sh.in b/tests/twisted/run-test.sh.in index 11bbaf9..c0a3284 100644 --- a/tests/twisted/run-test.sh.in +++ b/tests/twisted/run-test.sh.in @@ -1,69 +1,159 @@ #!/bin/sh -if test "x$HAZE_TEST_UNINSTALLED" = x; then - script_fullname=`readlink -e "@hazetestsdir@/twisted/run-test.sh"` +# This script assumes that it is run in a temporary directory where it can +# create and delete subdirectories for files, logs, etc., but other users +# cannot write (for instance, /tmp is unsuitable, but +# the directory created by `mktemp -d /tmp/test.XXXXXXXXXX` is fine). +# +# During "make check" or "make installcheck" it runs in +# ${top_builddir}/tests/twisted. +# +# During installed testing, the test environment must run it in a +# suitable location. + +set -e + +CHECK_TWISTED_CURDIR="`pwd`" +export CHECK_TWISTED_CURDIR + +if test "x$CHECK_TWISTED_UNINSTALLED" = x; then + script_fullname=`readlink -e "@twistedtestsdir@/run-test.sh"` if [ `readlink -e "$0"` != "$script_fullname" ] ; then - echo "This script is meant to be installed at $script_fullname" >&2 + echo "Bail out! This script is meant to be installed at $script_fullname" exit 1 fi - test_src="@hazetestsdir@" - test_build="@hazetestsdir@" - config_file="@hazetestsdir@/twisted/tools/servicedir/tmp-session-bus.conf" + G_TEST_SRCDIR="@twistedtestsdir@" + export G_TEST_SRCDIR + G_TEST_BUILDDIR="@twistedtestsdir@" + export G_TEST_BUILDDIR - PYTHONPATH="@hazetestsdir@/twisted" + PYTHONPATH="${G_TEST_SRCDIR}" export PYTHONPATH - - HAZE_TWISTED_PATH="@hazetestsdir@/twisted" - export HAZE_TWISTED_PATH else - if test -z "$HAZE_ABS_TOP_SRCDIR"; then - echo "HAZE_ABS_TOP_SRCDIR must be set" >&2 + if ! test -d "$G_TEST_SRCDIR"; then + echo "Bail out! G_TEST_SRCDIR must be set and absolute" exit 1 fi - if test -z "$HAZE_ABS_TOP_BUILDDIR"; then - echo "HAZE_ABS_TOP_BUILDDIR must be set" >&2 + if ! test -d "$G_TEST_BUILDDIR"; then + echo "Bail out! G_TEST_BUILDDIR must be set and absolute" exit 1 fi - test_src="${HAZE_ABS_TOP_SRCDIR}/tests" - test_build="${HAZE_ABS_TOP_BUILDDIR}/tests" - config_file="${test_build}/twisted/tools/tmp-session-bus.conf" - - PYTHONPATH="${test_src}/twisted:${test_build}/twisted" + PYTHONPATH="${G_TEST_SRCDIR}:${G_TEST_BUILDDIR}" export PYTHONPATH - - HAZE_TWISTED_PATH="${test_src}/twisted" - export HAZE_TWISTED_PATH fi +config_file="${G_TEST_BUILDDIR}/tools/tmp-session-bus.conf" + +# Use international English messages for testing +LC_ALL=C +export LC_ALL + +# Avoid using a non-trivial GSettings backend +GSETTINGS_BACKEND=memory +export GSETTINGS_BACKEND + +# Avoid libpurple doing "clever" things +unset KDE_FULL_SESSION +unset KDEDIR +unset KDEDIRS +unset GNOME_DESKTOP_SESSION_ID + +HAZE_DEBUG=all +export HAZE_DEBUG + +G_MESSAGES_DEBUG=all +export G_MESSAGES_DEBUG + +XDG_CONFIG_DIRS="${G_TEST_SRCDIR}" +export XDG_CONFIG_DIRS + if [ -n "$1" ] ; then list="$1" else - list=$(cat "${test_build}"/twisted/haze-twisted-tests.list) + list=$(cat "${G_TEST_BUILDDIR}"/twisted-tests.list) fi -any_failed=0 +n=0 for i in $list ; do - echo "Testing $i ..." - sh "${test_src}/twisted/tools/with-session-bus.sh" \ - ${HAZE_TEST_SLEEP} \ + n=$(( $n + 1 )) +done + +echo "1..$n" + +i=0 +n_failed=0 +for t in $list ; do + i=$(( $i + 1 )) + echo "# Testing $i/$n: $t ..." + + tmp="${CHECK_TWISTED_CURDIR}/tmp-`echo $t | tr ./ __`" + rm -fr "$tmp" + mkdir "$tmp" + + CHECK_TWISTED_LOG_DIR="${tmp}" + export CHECK_TWISTED_LOG_DIR + XDG_CONFIG_HOME="${tmp}/config" + export XDG_CONFIG_HOME + XDG_DATA_HOME="${tmp}/localshare" + export XDG_DATA_HOME + XDG_DATA_DIRS="${tmp}/share:${G_TEST_SRCDIR}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}" + export XDG_DATA_DIRS + XDG_CACHE_HOME="${tmp}/cache" + export XDG_CACHE_HOME + XDG_CACHE_DIR="${tmp}/cache" + export XDG_CACHE_DIR + HAZE_LOGFILE="${tmp}/cm.log" + export HAZE_LOGFILE + + CHECK_TWISTED_VERBOSE=1 + export CHECK_TWISTED_VERBOSE + + e=0 + sh "${G_TEST_SRCDIR}/tools/with-session-bus.sh" \ + ${CHECK_TWISTED_SLEEP} \ --config-file="${config_file}" \ -- \ - @TEST_PYTHON@ -u "${test_src}/twisted/$i" - e=$? + @TEST_PYTHON@ -u "${G_TEST_SRCDIR}/$t" \ + > "$tmp"/test.log 2>&1 || e=$? case "$e" in (0) - echo "PASS: $i" + echo "ok $i - $t" + if test -z "$CHECK_TWISTED_KEEP_TEMP"; then + rm -fr "$tmp" + fi ;; (77) - echo "SKIP: $i" + echo "ok $i # SKIP $t" + ( + cd $tmp && for x in *.log; do + echo "# ===== log file: $x =====" + sed 's/^/# /' "$x" + done + echo "# ===== end of log files for $t =====" + ) + if test -z "$CHECK_TWISTED_KEEP_TEMP"; then + rm -fr "$tmp" + fi ;; (*) - any_failed=1 - echo "FAIL: $i ($e)" + n_failed=$(( $n_failed + 1 )) + echo "not ok $i - $t ($e)" + ( + cd $tmp && for x in *.log; do + echo "# ===== log file: $x =====" + sed 's/^/# /' "$x" + done + echo "# ===== end of log files for $t =====" + ) ;; esac done -exit $any_failed +if test $n_failed != 0; then + echo "# Tests run: $n; tests failed: $n_failed" + exit 1 +else + exit 0 +fi diff --git a/tests/twisted/sasl/saslutil.py b/tests/twisted/sasl/saslutil.py index 83afe2b..2912f95 100644 --- a/tests/twisted/sasl/saslutil.py +++ b/tests/twisted/sasl/saslutil.py @@ -89,17 +89,15 @@ def connect_and_get_sasl_channel(q, bus, conn): return expect_sasl_channel(q, bus, conn) def expect_sasl_channel(q, bus, conn): - signal, = q.expect_many( - EventPattern('dbus-signal', signal='NewChannels', - predicate=lambda e: - e.args[0][0][1].get(cs.CHANNEL_TYPE) == - cs.CHANNEL_TYPE_SERVER_AUTHENTICATION), - ) - path = signal.args[0][0][0] + signal = q.expect('dbus-signal', signal='NewChannel', + predicate=lambda e: + e.args[1].get(cs.CHANNEL_TYPE) == + cs.CHANNEL_TYPE_SERVER_AUTHENTICATION) + + path = signal.args[0] chan = SaslChannelWrapper(bus.get_object(conn.bus_name, path)) - assertLength(1, signal.args[0]) - props = signal.args[0][0][1] + props = signal.args[1] assertEquals(cs.CHANNEL_IFACE_SASL_AUTH, props.get(cs.AUTH_METHOD)) return chan, props diff --git a/tests/twisted/servicetest.py b/tests/twisted/servicetest.py index fcba708..0902b55 100644 --- a/tests/twisted/servicetest.py +++ b/tests/twisted/servicetest.py @@ -1,6 +1,23 @@ +# Copyright (C) 2009 Nokia Corporation +# Copyright (C) 2009-2013 Collabora Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA """ -Infrastructure code for testing connection managers. +Infrastructure code for testing Telepathy services. """ from twisted.internet import glib2reactor @@ -14,6 +31,7 @@ import pprint import unittest import dbus +import dbus.lowlevel from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) @@ -22,7 +40,7 @@ from twisted.internet import reactor import constants as cs tp_name_prefix = cs.PREFIX -tp_path_prefix = '/' + cs.PREFIX.replace('.', '/') +tp_path_prefix = cs.PATH_PREFIX class DictionarySupersetOf (object): """Utility class for expecting "a dictionary with at least these keys".""" @@ -179,7 +197,14 @@ class BaseEventQueue: t = time.time() while True: - event = self.wait([pattern.subqueue]) + try: + event = self.wait([pattern.subqueue]) + except TimeoutError: + self.log('timeout') + self.log('still expecting:') + self.log(' - %r' % pattern) + raise + self._check_forbidden(event) if pattern.match(event): @@ -291,6 +316,11 @@ class IteratingEventQueue(BaseEventQueue): def __init__(self, timeout=None): BaseEventQueue.__init__(self, timeout) + self._dbus_method_impls = [] + self._buses = [] + # a message filter which will claim we handled everything + self._dbus_dev_null = \ + lambda bus, message: dbus.lowlevel.HANDLER_RESULT_HANDLED def wait(self, queues=None): stop = [False] @@ -315,6 +345,127 @@ class IteratingEventQueue(BaseEventQueue): else: raise TimeoutError + def add_dbus_method_impl(self, cb, bus=None, **kwargs): + if bus is None: + bus = self._buses[0] + + self._dbus_method_impls.append( + (EventPattern('dbus-method-call', **kwargs), cb)) + + def dbus_emit(self, path, iface, name, *a, **k): + bus = k.pop('bus', self._buses[0]) + assert 'signature' in k, k + message = dbus.lowlevel.SignalMessage(path, iface, name) + message.append(*a, **k) + bus.send_message(message) + + def dbus_return(self, in_reply_to, *a, **k): + bus = k.pop('bus', self._buses[0]) + assert 'signature' in k, k + reply = dbus.lowlevel.MethodReturnMessage(in_reply_to) + reply.append(*a, **k) + bus.send_message(reply) + + def dbus_raise(self, in_reply_to, name, message=None, bus=None): + if bus is None: + bus = self._buses[0] + + reply = dbus.lowlevel.ErrorMessage(in_reply_to, name, message) + bus.send_message(reply) + + def attach_to_bus(self, bus): + if not self._buses: + # first-time setup + self._dbus_filter_bound_method = self._dbus_filter + + self._buses.append(bus) + + # Only subscribe to messages on the first bus connection (assumed to + # be the shared session bus connection used by the simulated connection + # manager and most of the test suite), not on subsequent bus + # connections (assumed to represent extra clients). + # + # When we receive a method call on the other bus connections, ignore + # it - the eavesdropping filter installed on the first bus connection + # will see it too. + # + # This is highly counter-intuitive, but it means our messages are in + # a guaranteed order (we don't have races between messages arriving on + # various connections). + if len(self._buses) > 1: + bus.add_message_filter(self._dbus_dev_null) + return + + try: + # for dbus > 1.5 + bus.add_match_string("eavesdrop=true,type='signal'") + except dbus.DBusException: + bus.add_match_string("type='signal'") + bus.add_match_string("type='method_call'") + else: + bus.add_match_string("eavesdrop=true,type='method_call'") + + bus.add_message_filter(self._dbus_filter_bound_method) + + bus.add_signal_receiver( + lambda *args, **kw: + self.append( + Event('dbus-signal', + path=unwrap(kw['path']), + signal=kw['member'], + args=map(unwrap, args), + interface=kw['interface'])), + None, + None, + None, + path_keyword='path', + member_keyword='member', + interface_keyword='interface', + byte_arrays=True, + ) + + def cleanup(self): + if self._buses: + self._buses[0].remove_message_filter(self._dbus_filter_bound_method) + for bus in self._buses[1:]: + bus.remove_message_filter(self._dbus_dev_null) + + self._buses = [] + self._dbus_method_impls = [] + + def _dbus_filter(self, bus, message): + if isinstance(message, dbus.lowlevel.MethodCallMessage): + + destination = message.get_destination() + sender = message.get_sender() + + if (destination == 'org.freedesktop.DBus' or + sender == self._buses[0].get_unique_name()): + # suppress reply and don't make an Event + return dbus.lowlevel.HANDLER_RESULT_HANDLED + + e = Event('dbus-method-call', message=message, + interface=message.get_interface(), path=message.get_path(), + raw_args=message.get_args_list(byte_arrays=True), + args=map(unwrap, message.get_args_list(byte_arrays=True)), + destination=str(destination), + method=message.get_member(), + sender=message.get_sender(), + handled=False) + + for pair in self._dbus_method_impls: + pattern, cb = pair + if pattern.match(e): + cb(e) + e.handled = True + break + + self.append(e) + + return dbus.lowlevel.HANDLER_RESULT_HANDLED + + return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED + class TestEventQueue(BaseEventQueue): def __init__(self, events): BaseEventQueue.__init__(self) @@ -425,19 +576,33 @@ def call_async(test, proxy, method, *args, **kw): kw.update({'reply_handler': reply_func, 'error_handler': error_func}) method_proxy(*args, **kw) -def sync_dbus(bus, q, conn): - # Dummy D-Bus method call. We can't use DBus.Peer.Ping() because libdbus - # replies to that message immediately, rather than handing it up to - # dbus-glib and thence Gabble, which means that Ping()ing Gabble doesn't - # ensure that it's processed all D-Bus messages prior to our ping. - # - # This won't do the right thing unless the proxy has a unique name. - assert conn.object.bus_name.startswith(':') - root_object = bus.get_object(conn.object.bus_name, '/', introspect=False) - call_async(q, - dbus.Interface(root_object, cs.PREFIX + '.Tests'), - 'DummySyncDBus') - q.expect('dbus-error', method='DummySyncDBus') +def sync_dbus(bus, q, proxy): + # We need to use functionality that is actually implemented by tp-glib, + # because unimplemented and built-in functionality in GDBus can jump + # the queue. <https://bugzilla.gnome.org/show_bug.cgi?id=726259> + + if proxy.object_path == cs.AM_PATH: + call_async(q, dbus.Interface(proxy, cs.PROPERTIES_IFACE), + 'Get', cs.AM, 'Interfaces') + q.expect('dbus-return', method='Get') + elif proxy.object_path.startswith(cs.ACCOUNT_PATH_PREFIX): + call_async(q, dbus.Interface(proxy, cs.PROPERTIES_IFACE), + 'Get', cs.ACCOUNT, 'Enabled') + q.expect('dbus-return', method='Get') + elif proxy.object_path.startswith('/' + cs.CONN.replace('.', '/') + '/'): + # It could be a Connection or a Channel. Assume it's a Connection + # for now, that's what all the CM tests use in practice + call_async(q, dbus.Interface(proxy, cs.PROPERTIES_IFACE), + 'Get', cs.CONN, 'Status') + q.expect('dbus-return', method='Get') + elif proxy.object_path.startswith('/' + cs.CM.replace('.', '/') + '/'): + # It could be a ConnectionManager or a Protocol. Assume it's a + # ConnectionManager for now + call_async(q, dbus.Interface(proxy, cs.PROPERTIES_IFACE), + 'Get', cs.CM, 'Protocols') + q.expect('dbus-return', method='Get') + else: + raise AssertionError("don't know how to sync %s" % proxy.object_path) class ProxyWrapper: def __init__(self, object, default, others={}): @@ -464,7 +629,7 @@ class ConnWrapper(ProxyWrapper): return self.inspect_contacts_sync([handle])[0] def inspect_contacts_sync(self, handles): - h2asv = self.Contacts.GetContactAttributes(handles, [], True) + h2asv = self.Contacts.GetContactAttributes(handles, []) ret = [] for h in handles: ret.append(h2asv[h][cs.ATTR_CONTACT_ID]) @@ -478,26 +643,46 @@ class ConnWrapper(ProxyWrapper): def wrap_connection(conn): return ConnWrapper(conn, tp_name_prefix + '.Connection', - dict([ - (name, tp_name_prefix + '.Connection.Interface.' + name) - for name in ['Aliasing', 'Avatars', 'Capabilities', 'Contacts', - 'SimplePresence', 'Requests']] + + dict( [('Peer', 'org.freedesktop.DBus.Peer'), + ('Contacts', cs.CONN), # backwards compat with Telepathy 0 + ('Aliasing', cs.CONN_IFACE_ALIASING), + ('Avatars', cs.CONN_IFACE_AVATARS), ('ContactCapabilities', cs.CONN_IFACE_CONTACT_CAPS), ('ContactInfo', cs.CONN_IFACE_CONTACT_INFO), ('Location', cs.CONN_IFACE_LOCATION), - ('Future', tp_name_prefix + '.Connection.FUTURE'), + ('Presence', cs.CONN_IFACE_PRESENCE), + ('Requests', cs.CONN_IFACE_REQUESTS), ('MailNotification', cs.CONN_IFACE_MAIL_NOTIFICATION), ('ContactList', cs.CONN_IFACE_CONTACT_LIST), ('ContactGroups', cs.CONN_IFACE_CONTACT_GROUPS), + ('ContactBlocking', cs.CONN_IFACE_CONTACT_BLOCKING), ('PowerSaving', cs.CONN_IFACE_POWER_SAVING), ('Addressing', cs.CONN_IFACE_ADDRESSING), + ('ClientTypes', cs.CONN_IFACE_CLIENT_TYPES), + ('Renaming', cs.CONN_IFACE_RENAMING), + ('Sidecars1', cs.CONN_IFACE_SIDECARS1), ])) +class ChannelWrapper(ProxyWrapper): + def send_msg_sync(self, txt): + message = [ + { 'message-type': cs.MT_NORMAL, }, + { 'content-type': 'text/plain', + 'content': txt + }] + self.Text.SendMessage(message, 0) + def wrap_channel(chan, type_, extra=None): interfaces = { type_: tp_name_prefix + '.Channel.Type.' + type_, - 'Group': tp_name_prefix + '.Channel.Interface.Group', + 'Channel': cs.CHANNEL, + 'Group': cs.CHANNEL_IFACE_GROUP, + 'Hold': cs.CHANNEL_IFACE_HOLD, + 'RoomConfig1': cs.CHANNEL_IFACE_ROOM_CONFIG, + 'ChatState': cs.CHANNEL_IFACE_CHAT_STATE, + 'Destroyable': cs.CHANNEL_IFACE_DESTROYABLE, + 'Password': cs.CHANNEL_IFACE_PASSWORD, } if extra: @@ -505,11 +690,14 @@ def wrap_channel(chan, type_, extra=None): (name, tp_name_prefix + '.Channel.Interface.' + name) for name in extra])) - return ProxyWrapper(chan, tp_name_prefix + '.Channel', interfaces) + return ChannelWrapper(chan, tp_name_prefix + '.Channel', interfaces) def wrap_content(chan, extra=None): - interfaces = { } + interfaces = { + 'DTMF': cs.CALL_CONTENT_IFACE_DTMF, + 'Media': cs.CALL_CONTENT_IFACE_MEDIA, + } if extra: interfaces.update(dict([ diff --git a/tests/twisted/simple-caps.py b/tests/twisted/simple-caps.py index c1dff88..d1657b9 100644 --- a/tests/twisted/simple-caps.py +++ b/tests/twisted/simple-caps.py @@ -21,8 +21,7 @@ def check_text_only(rccs): # assert just text caps def check_rccs(conn, handle): attrs = conn.Contacts.GetContactAttributes([handle], - [cs.CONN_IFACE_CONTACT_CAPS], - False) + [cs.CONN_IFACE_CONTACT_CAPS]) rccs = attrs[handle][cs.CONN_IFACE_CONTACT_CAPS + '/capabilities'] check_text_only(rccs) diff --git a/tests/twisted/text/destroy.py b/tests/twisted/text/destroy.py index 9e0a03c..c7d2350 100644 --- a/tests/twisted/text/destroy.py +++ b/tests/twisted/text/destroy.py @@ -8,8 +8,7 @@ import dbus from twisted.words.xish import domish from hazetest import exec_test -from servicetest import (call_async, EventPattern, assertEquals, assertLength, - assertContains) +from servicetest import call_async, EventPattern, assertEquals, assertLength import constants as cs def test(q, bus, conn, stream): @@ -26,20 +25,16 @@ def test(q, bus, conn, stream): ret, sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), - EventPattern('dbus-signal', signal='NewChannels'), + EventPattern('dbus-signal', signal='NewChannel'), ) text_chan = bus.get_object(conn.bus_name, ret.value[0]) chan_iface = dbus.Interface(text_chan, cs.CHANNEL) text_iface = dbus.Interface(text_chan, cs.CHANNEL_TYPE_TEXT) - messages_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_MESSAGES) destroyable_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_DESTROYABLE) - assertLength(1, sig.args) - assertLength(1, sig.args[0]) # one channel - assertLength(2, sig.args[0][0]) # two struct members - assertEquals(ret.value, sig.args[0][0]) - emitted_props = sig.args[0][0][1] + assertEquals(ret.value, (sig.args[0], sig.args[1])) + emitted_props = sig.args[1] assertEquals(cs.CHANNEL_TYPE_TEXT, emitted_props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_CONTACT, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(foo_handle, emitted_props[cs.TARGET_HANDLE]) @@ -47,8 +42,6 @@ def test(q, bus, conn, stream): assertEquals(True, emitted_props[cs.REQUESTED]) assertEquals(self_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals('test@localhost', emitted_props[cs.INITIATOR_ID]) - assertContains(cs.CHANNEL_IFACE_MESSAGES, emitted_props[cs.INTERFACES]) - assertContains(cs.CHANNEL_IFACE_DESTROYABLE, emitted_props[cs.INTERFACES]) channel_props = text_chan.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) @@ -60,7 +53,7 @@ def test(q, bus, conn, stream): assert channel_props['InitiatorID'] == 'test@localhost',\ channel_props['InitiatorID'] - messages_iface.SendMessage([{}, { + text_iface.SendMessage([{}, { 'content-type': 'text/plain', 'content': 'hey', }], 0) @@ -98,7 +91,7 @@ def test(q, bus, conn, stream): assertEquals('text/plain', message[1]['content-type']) assertEquals('hello', message[1]['content']) - messages = text_chan.Get(cs.CHANNEL_IFACE_MESSAGES, 'PendingMessages', + messages = text_chan.Get(cs.CHANNEL_TYPE_TEXT, 'PendingMessages', dbus_interface=cs.PROPERTIES_IFACE) assertEquals([message], messages) diff --git a/tests/twisted/text/ensure.py b/tests/twisted/text/ensure.py index 6896408..58521f0 100644 --- a/tests/twisted/text/ensure.py +++ b/tests/twisted/text/ensure.py @@ -28,6 +28,8 @@ def test(q, bus, conn, stream): if c[1][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT ] assert text_channels == [], text_channels + + properties = conn.GetAll(cs.CONN, dbus_interface=dbus.PROPERTIES_IFACE) assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, }, @@ -53,7 +55,7 @@ def test_ensure_ensure(q, conn, self_handle, jid, handle): ret, sig = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), - EventPattern('dbus-signal', signal='NewChannels'), + EventPattern('dbus-signal', signal='NewChannel'), ) assert len(ret.value) == 3 @@ -65,16 +67,13 @@ def test_ensure_ensure(q, conn, self_handle, jid, handle): check_props(emitted_props, self_handle, handle, jid) - assertLength(1, sig.args) - assertLength(1, sig.args[0]) # one channel - assertLength(2, sig.args[0][0]) # two struct members - assertEquals(path, sig.args[0][0][0]) - assertEquals(emitted_props, sig.args[0][0][1]) + assertEquals(path, sig.args[0]) + assertEquals(emitted_props, sig.args[1]) properties = conn.GetAll(cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE) - assertContains(sig.args[0][0], properties['Channels']) + assertContains((sig.args[0], sig.args[1]), properties['Channels']) # Now try Ensuring a channel which already exists call_async(q, conn.Requests, 'EnsureChannel', request_props (handle)) @@ -100,7 +99,7 @@ def test_request_ensure(q, conn, self_handle, jid, handle): ret, sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), - EventPattern('dbus-signal', signal='NewChannels'), + EventPattern('dbus-signal', signal='NewChannel'), ) assert len(ret.value) == 2 @@ -108,16 +107,13 @@ def test_request_ensure(q, conn, self_handle, jid, handle): check_props(emitted_props, self_handle, handle, jid) - assertLength(1, sig.args) - assertLength(1, sig.args[0]) # one channel - assertLength(2, sig.args[0][0]) # two struct members - assertEquals(path, sig.args[0][0][0]) - assertEquals(emitted_props, sig.args[0][0][1]) + assertEquals(path, sig.args[0]) + assertEquals(emitted_props, sig.args[1]) properties = conn.GetAll(cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE) - assertContains(sig.args[0][0], properties['Channels']) + assertContains((sig.args[0], sig.args[1]), properties['Channels']) # Now try Ensuring that same channel. call_async(q, conn.Requests, 'EnsureChannel', request_props (handle)) diff --git a/tests/twisted/text/initiate-requestotron.py b/tests/twisted/text/initiate-requestotron.py index c76dd36..2120436 100644 --- a/tests/twisted/text/initiate-requestotron.py +++ b/tests/twisted/text/initiate-requestotron.py @@ -28,6 +28,9 @@ def test(q, bus, conn, stream): if c[1][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT ] assert text_channels == [], text_channels + + properties = conn.GetAll(cs.CONN, + dbus_interface=dbus.PROPERTIES_IFACE) assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, }, @@ -43,7 +46,7 @@ def test(q, bus, conn, stream): ret, sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), - EventPattern('dbus-signal', signal='NewChannels'), + EventPattern('dbus-signal', signal='NewChannel'), ) assert len(ret.value) == 2 @@ -56,16 +59,13 @@ def test(q, bus, conn, stream): assertEquals(self_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals('test@localhost', emitted_props[cs.INITIATOR_ID]) - assertLength(1, sig.args) - assertLength(1, sig.args[0]) # one channel - assertLength(2, sig.args[0][0]) # two struct members - assertEquals(ret.value[0], sig.args[0][0][0]) - assertEquals(ret.value[1], sig.args[0][0][1]) + assertEquals(ret.value[0], sig.args[0]) + assertEquals(ret.value[1], sig.args[1]) properties = conn.GetAll(cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE) - assertContains(sig.args[0][0], properties['Channels']) + assertContains((sig.args[0], sig.args[1]), properties['Channels']) conn.Disconnect() q.expect('dbus-signal', signal='StatusChanged', args=[2, 1]) diff --git a/tests/twisted/text/respawn.py b/tests/twisted/text/respawn.py index e86b6c4..e3dbb9c 100644 --- a/tests/twisted/text/respawn.py +++ b/tests/twisted/text/respawn.py @@ -7,8 +7,7 @@ import dbus from twisted.words.xish import domish from hazetest import exec_test -from servicetest import (call_async, EventPattern, assertEquals, assertLength, - assertContains) +from servicetest import call_async, EventPattern, assertEquals, assertLength import constants as cs def test(q, bus, conn, stream): @@ -25,20 +24,15 @@ def test(q, bus, conn, stream): ret, sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), - EventPattern('dbus-signal', signal='NewChannels'), + EventPattern('dbus-signal', signal='NewChannel'), ) text_chan = bus.get_object(conn.bus_name, ret.value[0]) chan_iface = dbus.Interface(text_chan, cs.CHANNEL) text_iface = dbus.Interface(text_chan, cs.CHANNEL_TYPE_TEXT) - messages_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_MESSAGES) - destroyable_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_DESTROYABLE) - - assertLength(1, sig.args) - assertLength(1, sig.args[0]) # one channel - assertLength(2, sig.args[0][0]) # two struct members - assertEquals(ret.value, sig.args[0][0]) - emitted_props = sig.args[0][0][1] + + assertEquals(ret.value, ( sig.args[0], sig.args[1] )) + emitted_props = sig.args[1] assertEquals(cs.CHANNEL_TYPE_TEXT, emitted_props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_CONTACT, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(foo_handle, emitted_props[cs.TARGET_HANDLE]) @@ -46,8 +40,6 @@ def test(q, bus, conn, stream): assertEquals(True, emitted_props[cs.REQUESTED]) assertEquals(self_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals('test@localhost', emitted_props[cs.INITIATOR_ID]) - assertContains(cs.CHANNEL_IFACE_MESSAGES, emitted_props[cs.INTERFACES]) - assertContains(cs.CHANNEL_IFACE_DESTROYABLE, emitted_props[cs.INTERFACES]) channel_props = text_chan.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) @@ -59,7 +51,7 @@ def test(q, bus, conn, stream): assert channel_props['InitiatorID'] == 'test@localhost',\ channel_props['InitiatorID'] - messages_iface.SendMessage([{}, { + text_iface.SendMessage([{}, { 'content-type': 'text/plain', 'content': 'hey', }], 0) @@ -97,7 +89,7 @@ def test(q, bus, conn, stream): assertEquals('text/plain', message[1]['content-type']) assertEquals('hello', message[1]['content']) - messages = text_chan.Get(cs.CHANNEL_IFACE_MESSAGES, 'PendingMessages', + messages = text_chan.Get(cs.CHANNEL_TYPE_TEXT, 'PendingMessages', dbus_interface=cs.PROPERTIES_IFACE) assertEquals([message], messages) @@ -120,9 +112,9 @@ def test(q, bus, conn, stream): new_props[cs.INITIATOR_ID] = 'foo@bar.com' new_props[cs.REQUESTED] = False - event = q.expect('dbus-signal', signal='NewChannels') - assertEquals(text_chan.object_path, event.args[0][0][0]) - assertEquals(new_props, event.args[0][0][1]) + event = q.expect('dbus-signal', signal='NewChannel') + assertEquals(text_chan.object_path, event.args[0]) + assertEquals(new_props, event.args[1]) event = q.expect('dbus-return', method='Close') @@ -139,7 +131,7 @@ def test(q, bus, conn, stream): # the message is still there, but is marked as rescued now message[0]['rescued'] = True - messages = text_chan.Get(cs.CHANNEL_IFACE_MESSAGES, 'PendingMessages', + messages = text_chan.Get(cs.CHANNEL_TYPE_TEXT, 'PendingMessages', dbus_interface=cs.PROPERTIES_IFACE) assertEquals([message], messages) @@ -148,7 +140,7 @@ def test(q, bus, conn, stream): text_chan.AcknowledgePendingMessages([hello_message_id], dbus_interface=cs.CHANNEL_TYPE_TEXT) - messages = text_chan.Get(cs.CHANNEL_IFACE_MESSAGES, 'PendingMessages', + messages = text_chan.Get(cs.CHANNEL_TYPE_TEXT, 'PendingMessages', dbus_interface=cs.PROPERTIES_IFACE) assertEquals([], messages) diff --git a/tests/twisted/text/test-text-delayed.py b/tests/twisted/text/test-text-delayed.py index 59e73d0..bb9695e 100644 --- a/tests/twisted/text/test-text-delayed.py +++ b/tests/twisted/text/test-text-delayed.py @@ -23,10 +23,10 @@ def test(q, bus, conn, stream): stream.send(m) - event = q.expect('dbus-signal', signal='NewChannels') - assertEquals(cs.CHANNEL_TYPE_TEXT, event.args[0][0][1][cs.CHANNEL_TYPE]) - assertEquals(cs.HT_CONTACT, event.args[0][0][1][cs.TARGET_HANDLE_TYPE]) - assertEquals('foo@bar.com', event.args[0][0][1][cs.TARGET_ID]) + event = q.expect('dbus-signal', signal='NewChannel') + assertEquals(cs.CHANNEL_TYPE_TEXT, event.args[1][cs.CHANNEL_TYPE]) + assertEquals(cs.HT_CONTACT, event.args[1][cs.TARGET_HANDLE_TYPE]) + assertEquals('foo@bar.com', event.args[1][cs.TARGET_ID]) message_received = q.expect('dbus-signal', signal='MessageReceived') diff --git a/tests/twisted/text/test-text-no-body.py b/tests/twisted/text/test-text-no-body.py index c8aacd7..c5e32cc 100644 --- a/tests/twisted/text/test-text-no-body.py +++ b/tests/twisted/text/test-text-no-body.py @@ -29,10 +29,10 @@ def test(q, bus, conn, stream): stream.send(m) # first message should be from Bob, not Alice - event = q.expect('dbus-signal', signal='NewChannels') - assertEquals(cs.CHANNEL_TYPE_TEXT, event.args[0][0][1][cs.CHANNEL_TYPE]) - assertEquals(cs.HT_CONTACT, event.args[0][0][1][cs.TARGET_HANDLE_TYPE]) - assertEquals('bob@foo.com', event.args[0][0][1][cs.TARGET_ID]) + event = q.expect('dbus-signal', signal='NewChannel') + assertEquals(cs.CHANNEL_TYPE_TEXT, event.args[1][cs.CHANNEL_TYPE]) + assertEquals(cs.HT_CONTACT, event.args[1][cs.TARGET_HANDLE_TYPE]) + assertEquals('bob@foo.com', event.args[1][cs.TARGET_ID]) conn.Disconnect() q.expect('dbus-signal', signal='StatusChanged', args=[2, 1]) diff --git a/tests/twisted/text/test-text.py b/tests/twisted/text/test-text.py index b1916ed..2639465 100644 --- a/tests/twisted/text/test-text.py +++ b/tests/twisted/text/test-text.py @@ -21,25 +21,23 @@ def test(q, bus, conn, stream): m.addElement('body', content='hello') stream.send(m) - event = q.expect('dbus-signal', signal='NewChannels') - assertEquals(cs.CHANNEL_TYPE_TEXT, event.args[0][0][1][cs.CHANNEL_TYPE]) - assertEquals(cs.HT_CONTACT, event.args[0][0][1][cs.TARGET_HANDLE_TYPE]) - assertEquals(jid, event.args[0][0][1][cs.TARGET_ID]) - foo_at_bar_dot_com_handle = event.args[0][0][1][cs.TARGET_HANDLE] + event = q.expect('dbus-signal', signal='NewChannel') + assertEquals(cs.CHANNEL_TYPE_TEXT, event.args[1][cs.CHANNEL_TYPE]) + assertEquals(cs.HT_CONTACT, event.args[1][cs.TARGET_HANDLE_TYPE]) + assertEquals(jid, event.args[1][cs.TARGET_ID]) + foo_at_bar_dot_com_handle = event.args[1][cs.TARGET_HANDLE] - text_chan = bus.get_object(conn.bus_name, event.args[0][0][0]) + text_chan = bus.get_object(conn.bus_name, event.args[0]) # Exercise basic Channel Properties from spec 0.17.7 channel_props = text_chan.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(foo_at_bar_dot_com_handle, channel_props.get('TargetHandle')) - assert channel_props.get('TargetHandleType') == 1,\ - channel_props.get('TargetHandleType') + assert channel_props.get('TargetEntityType') == 1,\ + channel_props.get('TargetEntityType') assertEquals(cs.CHANNEL_TYPE_TEXT, channel_props.get('ChannelType')) assertContains(cs.CHANNEL_IFACE_CHAT_STATE, channel_props.get('Interfaces', ())) - assertContains(cs.CHANNEL_IFACE_MESSAGES, - channel_props.get('Interfaces', ())) assert channel_props['TargetID'] == jid,\ (channel_props['TargetID'], jid) assert channel_props['Requested'] == False @@ -86,7 +84,7 @@ def test(q, bus, conn, stream): } ] - dbus.Interface(text_chan, cs.CHANNEL_IFACE_MESSAGES + dbus.Interface(text_chan, cs.CHANNEL_TYPE_TEXT ).SendMessage(greeting, dbus.UInt32(0)) stream_message, message_sent = q.expect_many( @@ -114,7 +112,8 @@ def test(q, bus, conn, stream): assert body['content-type'] == 'text/plain', body assert body['content'] == u'waves', body - dbus.Interface(text_chan, cs.CHANNEL_IFACE_MESSAGES + # Send a message using Channel.Type.Text API + dbus.Interface(text_chan, cs.CHANNEL_TYPE_TEXT ).SendMessage([{}, { 'content-type': 'text/plain', 'content': 'goodbye', diff --git a/tests/twisted/tools/Makefile.am b/tests/twisted/tools/Makefile.am index a8b34c1..b4eca52 100644 --- a/tests/twisted/tools/Makefile.am +++ b/tests/twisted/tools/Makefile.am @@ -1,31 +1,63 @@ -%.conf: %.conf.in - $(AM_V_GEN)sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@ +%.conf: %.conf.in Makefile + $(AM_V_GEN)sed -e "s|[@]servicedir[@]|@abs_top_builddir@/tests/twisted/tools|g" $< > $@ + +servicedir = $(datadir)/dbus-1/services + +installed/%.conf: %.conf.in Makefile + @$(MKDIR_P) installed + $(AM_V_GEN)sed -e "s|[@]servicedir[@]|$(servicedir)|g" $< > $@ # We don't use the full filename for the .in because > 99 character filenames # in tarballs are non-portable (and automake 1.8 doesn't let us build # non-archaic tarballs) -org.freedesktop.Telepathy.ConnectionManager.%.service: %.service.in +im.telepathy.v1.ConnectionManager.%.service: %.service.in $(AM_V_GEN)sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" \ -e "s|[@]abs_top_srcdir[@]|@abs_top_srcdir@|g" $< > $@ # D-Bus service file for testing service_in_files = haze.service.in -service_files = org.freedesktop.Telepathy.ConnectionManager.haze.service +service_files = im.telepathy.v1.ConnectionManager.haze.service # D-Bus config file for testing conf_in_files = tmp-session-bus.conf.in conf_files = $(conf_in_files:.conf.in=.conf) -BUILT_SOURCES = $(service_files) $(conf_files) +BUILT_SOURCES = \ + $(built_test_data) \ + $(conf_files) \ + $(service_files) \ + $(NULL) + +dist_test_scripts = \ + with-session-bus.sh \ + $(NULL) + +dist_test_data = \ + $(NULL) + +built_test_data = \ + installed/tmp-session-bus.conf \ + $(NULL) EXTRA_DIST = \ + $(dist_test_data) \ + $(dist_test_scripts) \ $(service_in_files) \ $(conf_in_files) \ exec-with-log.sh \ - with-session-bus.sh \ $(NULL) CLEANFILES = \ $(BUILT_SOURCES) \ haze-testing.log \ $(NULL) + +testsdir = ${datadir}/telepathy-haze-1-tests +twistedtestsdir = ${testsdir}/twisted +twistedtoolsdir = ${twistedtestsdir}/tools + +if ENABLE_INSTALLED_TESTS +dist_twistedtools_SCRIPTS = ${dist_test_scripts} +dist_twistedtools_DATA = ${dist_test_data} +twistedtools_DATA = ${built_test_data} +endif diff --git a/tests/twisted/tools/exec-with-log.sh b/tests/twisted/tools/exec-with-log.sh index e6e9379..b77e5c2 100755 --- a/tests/twisted/tools/exec-with-log.sh +++ b/tests/twisted/tools/exec-with-log.sh @@ -45,4 +45,4 @@ fi # not suitable for haze: #export G_DEBUG=fatal-warnings" ${G_DEBUG}" exec "${abs_top_builddir}/libtool" --mode=execute $HAZE_WRAPPER \ - "${abs_top_builddir}/src/telepathy-haze" + "${abs_top_builddir}/src/telepathy-haze-1" diff --git a/tests/twisted/tools/haze.service.in b/tests/twisted/tools/haze.service.in index 8ee3f3a..d106060 100644 --- a/tests/twisted/tools/haze.service.in +++ b/tests/twisted/tools/haze.service.in @@ -1,3 +1,3 @@ [D-BUS Service] -Name=org.freedesktop.Telepathy.ConnectionManager.haze +Name=im.telepathy.v1.ConnectionManager.haze Exec=@abs_top_srcdir@/tests/twisted/tools/exec-with-log.sh @abs_top_srcdir@ @abs_top_builddir@ diff --git a/tests/twisted/tools/tmp-session-bus.conf.in b/tests/twisted/tools/tmp-session-bus.conf.in index 84d8d65..1cde692 100644 --- a/tests/twisted/tools/tmp-session-bus.conf.in +++ b/tests/twisted/tools/tmp-session-bus.conf.in @@ -10,7 +10,7 @@ <listen>unix:tmpdir=/tmp</listen> - <servicedir>@abs_top_builddir@/tests/twisted/tools</servicedir> + <servicedir>@servicedir@</servicedir> <policy context="default"> <!-- Allow everything to be sent --> diff --git a/tools/Makefile.am b/tools/Makefile.am index 715d792..f1e455d 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,29 +1,9 @@ EXTRA_DIST = \ - c-constants-gen.py \ - doc-generator.xsl \ - glib-ginterface-gen.py \ - glib-gtypes-generator.py \ - glib-interfaces-gen.py \ - glib-signals-marshal-gen.py \ - identity.xsl \ - libglibcodegen.py \ - libtpcodegen.py \ make-release-mail.py \ telepathy.am -CLEANFILES = *.pyc *.pyo - all: $(EXTRA_DIST) -libglibcodegen.py: libtpcodegen.py - test -e $< - $(AM_V_GEN)touch $@ - -glib-ginterface-gen.py glib-gtypes-generator.py glib-interfaces-gen.py \ -glib-signals-marshal-gen.py c-constants-gen.py: %: libglibcodegen.py - test -e $< - $(AM_V_GEN)touch $@ - TELEPATHY_GLIB_SRCDIR = $(top_srcdir)/../telepathy-glib maintainer-update-from-telepathy-glib: set -e && cd $(srcdir) && \ diff --git a/tools/c-constants-gen.py b/tools/c-constants-gen.py deleted file mode 100644 index 8969ffd..0000000 --- a/tools/c-constants-gen.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/python - -from sys import argv, stdout, stderr -import xml.dom.minidom - -from libglibcodegen import NS_TP, get_docstring, \ - get_descendant_text, get_by_path - -class Generator(object): - def __init__(self, prefix, dom): - self.prefix = prefix + '_' - self.spec = get_by_path(dom, "spec")[0] - - def __call__(self): - self.do_header() - self.do_body() - self.do_footer() - - def write(self, code): - stdout.write(code.encode('utf-8')) - - # Header - def do_header(self): - self.write('/* Generated from ') - self.write(get_descendant_text(get_by_path(self.spec, 'title'))) - version = get_by_path(self.spec, "version") - if version: - self.write(', version ' + get_descendant_text(version)) - self.write('\n\n') - for copyright in get_by_path(self.spec, 'copyright'): - self.write(get_descendant_text(copyright)) - self.write('\n') - self.write(get_descendant_text(get_by_path(self.spec, 'license'))) - self.write('\n') - self.write(get_descendant_text(get_by_path(self.spec, 'docstring'))) - self.write(""" - */ - -#ifdef __cplusplus -extern "C" { -#endif -\n""") - - # Body - def do_body(self): - for elem in self.spec.getElementsByTagNameNS(NS_TP, '*'): - if elem.localName == 'flags': - self.do_flags(elem) - elif elem.localName == 'enum': - self.do_enum(elem) - - def do_flags(self, flags): - name = flags.getAttribute('plural') or flags.getAttribute('name') - value_prefix = flags.getAttribute('singular') or \ - flags.getAttribute('value-prefix') or \ - flags.getAttribute('name') - self.write("""\ -/** - * -%s: -""" % (self.prefix + name).replace('_', '')) - for flag in get_by_path(flags, 'flag'): - self.do_gtkdoc(flag, value_prefix) - self.write(' *\n') - docstrings = get_by_path(flags, 'docstring') - if docstrings: - self.write("""\ - * <![CDATA[%s]]> - * -""" % get_descendant_text(docstrings).replace('\n', ' ')) - self.write("""\ - * Bitfield/set of flags generated from the Telepathy specification. - */ -typedef enum { -""") - for flag in get_by_path(flags, 'flag'): - self.do_val(flag, value_prefix) - self.write("""\ -} %s; - -""" % (self.prefix + name).replace('_', '')) - - def do_enum(self, enum): - name = enum.getAttribute('singular') or enum.getAttribute('name') - value_prefix = enum.getAttribute('singular') or \ - enum.getAttribute('value-prefix') or \ - enum.getAttribute('name') - name_plural = enum.getAttribute('plural') or \ - enum.getAttribute('name') + 's' - self.write("""\ -/** - * -%s: -""" % (self.prefix + name).replace('_', '')) - vals = get_by_path(enum, 'enumvalue') - for val in vals: - self.do_gtkdoc(val, value_prefix) - self.write(' *\n') - docstrings = get_by_path(enum, 'docstring') - if docstrings: - self.write("""\ - * <![CDATA[%s]]> - * -""" % get_descendant_text(docstrings).replace('\n', ' ')) - self.write("""\ - * Bitfield/set of flags generated from the Telepathy specification. - */ -typedef enum { -""") - for val in vals: - self.do_val(val, value_prefix) - self.write("""\ -} %(mixed-name)s; - -/** - * NUM_%(upper-plural)s: - * - * 1 higher than the highest valid value of #%(mixed-name)s. - */ -#define NUM_%(upper-plural)s (%(last-val)s+1) - -""" % {'mixed-name' : (self.prefix + name).replace('_', ''), - 'upper-plural' : (self.prefix + name_plural).upper(), - 'last-val' : vals[-1].getAttribute('value')}) - - def do_val(self, val, value_prefix): - name = val.getAttribute('name') - suffix = val.getAttribute('suffix') - use_name = (self.prefix + value_prefix + '_' + \ - (suffix or name)).upper() - assert not (name and suffix) or name == suffix, \ - 'Flag/enumvalue name %s != suffix %s' % (name, suffix) - self.write(' %s = %s,\n' % (use_name, val.getAttribute('value'))) - - def do_gtkdoc(self, node, value_prefix): - self.write(' * @') - self.write((self.prefix + value_prefix + '_' + - node.getAttribute('suffix')).upper()) - self.write(': <![CDATA[') - docstring = get_by_path(node, 'docstring') - self.write(get_descendant_text(docstring).replace('\n', ' ')) - self.write(']]>\n') - - # Footer - def do_footer(self): - self.write(""" -#ifdef __cplusplus -} -#endif -""") - -if __name__ == '__main__': - argv = argv[1:] - Generator(argv[0], xml.dom.minidom.parse(argv[1]))() diff --git a/tools/doc-generator.xsl b/tools/doc-generator.xsl deleted file mode 100644 index 76fc969..0000000 --- a/tools/doc-generator.xsl +++ /dev/null @@ -1,1199 +0,0 @@ -<!-- Generate HTML documentation from the Telepathy specification. -The master copy of this stylesheet is in the Telepathy spec repository - -please make any changes there. - -Copyright (C) 2006-2008 Collabora Limited - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ---> - -<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" - xmlns:html="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="tp html"> - <!--Don't move the declaration of the HTML namespace up here — XMLNSs - don't work ideally in the presence of two things that want to use the - absence of a prefix, sadly. --> - - <xsl:param name="allow-undefined-interfaces" select="false()"/> - - <xsl:template match="html:* | @*" mode="html"> - <xsl:copy> - <xsl:apply-templates mode="html"/> - </xsl:copy> - </xsl:template> - - <xsl:template match="tp:type" mode="html"> - <xsl:call-template name="tp-type"> - <xsl:with-param name="tp-type" select="string(.)"/> - </xsl:call-template> - </xsl:template> - - <!-- tp:dbus-ref: reference a D-Bus interface, signal, method or property --> - <xsl:template match="tp:dbus-ref" mode="html"> - <xsl:variable name="name"> - <xsl:choose> - <xsl:when test="@namespace"> - <xsl:value-of select="@namespace"/> - <xsl:text>.</xsl:text> - </xsl:when> - </xsl:choose> - <xsl:value-of select="string(.)"/> - </xsl:variable> - - <xsl:choose> - <xsl:when test="//interface[@name=$name] - or //interface/method[concat(../@name, '.', @name)=$name] - or //interface/signal[concat(../@name, '.', @name)=$name] - or //interface/property[concat(../@name, '.', @name)=$name] - or //interface[@name=concat($name, '.DRAFT')] - or //interface/method[ - concat(../@name, '.', @name)=concat($name, '.DRAFT')] - or //interface/signal[ - concat(../@name, '.', @name)=concat($name, '.DRAFT')] - or //interface/property[ - concat(../@name, '.', @name)=concat($name, '.DRAFT')] - "> - <a xmlns="http://www.w3.org/1999/xhtml" href="#{$name}"> - <xsl:value-of select="string(.)"/> - </a> - </xsl:when> - - <xsl:when test="$allow-undefined-interfaces"> - <span xmlns="http://www.w3.org/1999/xhtml" title="defined elsewhere"> - <xsl:value-of select="string(.)"/> - </span> - </xsl:when> - - <xsl:otherwise> - <xsl:message terminate="yes"> - <xsl:text>ERR: cannot find D-Bus interface, method, </xsl:text> - <xsl:text>signal or property called '</xsl:text> - <xsl:value-of select="$name"/> - <xsl:text>' </xsl:text> - </xsl:message> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - - <!-- tp:member-ref: reference a property of the current interface --> - <xsl:template match="tp:member-ref" mode="html"> - <xsl:variable name="prefix" select="concat(ancestor::interface/@name, - '.')"/> - <xsl:variable name="name" select="string(.)"/> - - <xsl:if test="not(ancestor::interface)"> - <xsl:message terminate="yes"> - <xsl:text>ERR: Cannot use tp:member-ref when not in an</xsl:text> - <xsl:text> <interface> </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:choose> - <xsl:when test="ancestor::interface/signal[@name=$name]"/> - <xsl:when test="ancestor::interface/method[@name=$name]"/> - <xsl:when test="ancestor::interface/property[@name=$name]"/> - <xsl:otherwise> - <xsl:message terminate="yes"> - <xsl:text>ERR: interface </xsl:text> - <xsl:value-of select="ancestor::interface/@name"/> - <xsl:text> has no signal/method/property called </xsl:text> - <xsl:value-of select="$name"/> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:otherwise> - </xsl:choose> - - <a xmlns="http://www.w3.org/1999/xhtml" href="#{$prefix}{$name}"> - <xsl:value-of select="$name"/> - </a> - </xsl:template> - - <xsl:template match="*" mode="identity"> - <xsl:copy> - <xsl:apply-templates mode="identity"/> - </xsl:copy> - </xsl:template> - - <xsl:template match="tp:docstring"> - <xsl:apply-templates mode="html"/> - </xsl:template> - - <xsl:template match="tp:added"> - <p class="added" xmlns="http://www.w3.org/1999/xhtml">Added in - version <xsl:value-of select="@version"/>. - <xsl:apply-templates select="node()" mode="html"/></p> - </xsl:template> - - <xsl:template match="tp:changed"> - <xsl:choose> - <xsl:when test="node()"> - <p class="changed" xmlns="http://www.w3.org/1999/xhtml">Changed in - version <xsl:value-of select="@version"/>: - <xsl:apply-templates select="node()" mode="html"/></p> - </xsl:when> - <xsl:otherwise> - <p class="changed">Changed in version - <xsl:value-of select="@version"/></p> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - - <xsl:template match="tp:deprecated"> - <p class="deprecated" xmlns="http://www.w3.org/1999/xhtml">Deprecated - since version <xsl:value-of select="@version"/>. - <xsl:apply-templates select="node()" mode="html"/></p> - </xsl:template> - - <xsl:template match="tp:rationale" mode="html"> - <div xmlns="http://www.w3.org/1999/xhtml" class="rationale"> - <xsl:apply-templates select="node()" mode="html"/> - </div> - </xsl:template> - - <xsl:template match="tp:errors"> - <h1 xmlns="http://www.w3.org/1999/xhtml">Errors</h1> - <xsl:apply-templates/> - </xsl:template> - - <xsl:template match="tp:generic-types"> - <h1 xmlns="http://www.w3.org/1999/xhtml">Generic types</h1> - <xsl:call-template name="do-types"/> - </xsl:template> - - <xsl:template name="do-types"> - <xsl:if test="tp:simple-type"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Simple types</h2> - <xsl:apply-templates select="tp:simple-type"/> - </xsl:if> - - <xsl:if test="tp:enum"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Enumerated types:</h2> - <xsl:apply-templates select="tp:enum"/> - </xsl:if> - - <xsl:if test="tp:flags"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Sets of flags:</h2> - <xsl:apply-templates select="tp:flags"/> - </xsl:if> - - <xsl:if test="tp:struct"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Structure types</h2> - <xsl:apply-templates select="tp:struct"/> - </xsl:if> - - <xsl:if test="tp:mapping"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Mapping types</h2> - <xsl:apply-templates select="tp:mapping"/> - </xsl:if> - - <xsl:if test="tp:external-type"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Types defined elsewhere</h2> - <dl><xsl:apply-templates select="tp:external-type"/></dl> - </xsl:if> - </xsl:template> - - <xsl:template match="tp:error"> - <h2 xmlns="http://www.w3.org/1999/xhtml"><a name="{concat(../@namespace, '.', translate(@name, ' ', ''))}"></a><xsl:value-of select="concat(../@namespace, '.', translate(@name, ' ', ''))"/></h2> - <xsl:apply-templates select="tp:docstring"/> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </xsl:template> - - <xsl:template match="/tp:spec/tp:copyright"> - <div xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates mode="text"/> - </div> - </xsl:template> - <xsl:template match="/tp:spec/tp:license"> - <div xmlns="http://www.w3.org/1999/xhtml" class="license"> - <xsl:apply-templates mode="html"/> - </div> - </xsl:template> - - <xsl:template match="tp:copyright"/> - <xsl:template match="tp:license"/> - - <xsl:template match="interface"> - <h1 xmlns="http://www.w3.org/1999/xhtml"><a name="{@name}"></a><xsl:value-of select="@name"/></h1> - - <xsl:if test="@tp:causes-havoc"> - <p xmlns="http://www.w3.org/1999/xhtml" class="causes-havoc"> - This interface is <xsl:value-of select="@tp:causes-havoc"/> - and is likely to cause havoc to your API/ABI if bindings are generated. - Don't include it in libraries that care about compatibility. - </p> - </xsl:if> - - <xsl:if test="tp:requires"> - <p>Implementations of this interface must also implement:</p> - <ul xmlns="http://www.w3.org/1999/xhtml"> - <xsl:for-each select="tp:requires"> - <li><code><a href="#{@interface}"><xsl:value-of select="@interface"/></a></code></li> - </xsl:for-each> - </ul> - </xsl:if> - - <xsl:apply-templates select="tp:docstring" /> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - - <xsl:choose> - <xsl:when test="method"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Methods:</h2> - <xsl:apply-templates select="method"/> - </xsl:when> - <xsl:otherwise> - <p xmlns="http://www.w3.org/1999/xhtml">Interface has no methods.</p> - </xsl:otherwise> - </xsl:choose> - - <xsl:choose> - <xsl:when test="signal"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Signals:</h2> - <xsl:apply-templates select="signal"/> - </xsl:when> - <xsl:otherwise> - <p xmlns="http://www.w3.org/1999/xhtml">Interface has no signals.</p> - </xsl:otherwise> - </xsl:choose> - - <xsl:choose> - <xsl:when test="tp:property"> - <h2 xmlns="http://www.w3.org/1999/xhtml">Telepathy Properties:</h2> - <p xmlns="http://www.w3.org/1999/xhtml">Accessed using the - <a href="#org.freedesktop.Telepathy.Properties">Telepathy - Properties</a> interface.</p> - <dl xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="tp:property"/> - </dl> - </xsl:when> - <xsl:otherwise> - <p xmlns="http://www.w3.org/1999/xhtml">Interface has no Telepathy - properties.</p> - </xsl:otherwise> - </xsl:choose> - - <xsl:choose> - <xsl:when test="property"> - <h2 xmlns="http://www.w3.org/1999/xhtml">D-Bus core Properties:</h2> - <p xmlns="http://www.w3.org/1999/xhtml">Accessed using the - org.freedesktop.DBus.Properties interface.</p> - <dl xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="property"/> - </dl> - </xsl:when> - <xsl:otherwise> - <p xmlns="http://www.w3.org/1999/xhtml">Interface has no D-Bus core - properties.</p> - </xsl:otherwise> - </xsl:choose> - - <xsl:call-template name="do-types"/> - - </xsl:template> - - <xsl:template match="tp:flags"> - - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @name on a tp:flags type </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:if test="not(@type) or @type = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @type on tp:flags type</xsl:text> - <xsl:value-of select="@name"/> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:if> - - <h3> - <a name="type-{@name}"> - <xsl:value-of select="@name"/> - </a> - </h3> - <xsl:apply-templates select="tp:docstring" /> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - <dl xmlns="http://www.w3.org/1999/xhtml"> - <xsl:variable name="value-prefix"> - <xsl:choose> - <xsl:when test="@value-prefix"> - <xsl:value-of select="@value-prefix"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="@name"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - <xsl:for-each select="tp:flag"> - <dt xmlns="http://www.w3.org/1999/xhtml"><code><xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/></code></dt> - <xsl:choose> - <xsl:when test="tp:docstring"> - <dd xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="tp:docstring" /> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </dd> - </xsl:when> - <xsl:otherwise> - <dd xmlns="http://www.w3.org/1999/xhtml">(Undocumented)</dd> - </xsl:otherwise> - </xsl:choose> - </xsl:for-each> - </dl> - </xsl:template> - - <xsl:template match="tp:enum"> - - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @name on a tp:enum type </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:if test="not(@type) or @type = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @type on tp:enum type</xsl:text> - <xsl:value-of select="@name"/> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:if> - - <h3 xmlns="http://www.w3.org/1999/xhtml"> - <a name="type-{@name}"> - <xsl:value-of select="@name"/> - </a> - </h3> - <xsl:apply-templates select="tp:docstring" /> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - <dl xmlns="http://www.w3.org/1999/xhtml"> - <xsl:variable name="value-prefix"> - <xsl:choose> - <xsl:when test="@value-prefix"> - <xsl:value-of select="@value-prefix"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="@name"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - <xsl:for-each select="tp:enumvalue"> - <dt xmlns="http://www.w3.org/1999/xhtml"><code><xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/></code></dt> - <xsl:choose> - <xsl:when test="tp:docstring"> - <dd xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="tp:docstring" /> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </dd> - </xsl:when> - <xsl:otherwise> - <dd xmlns="http://www.w3.org/1999/xhtml">(Undocumented)</dd> - </xsl:otherwise> - </xsl:choose> - </xsl:for-each> - </dl> - </xsl:template> - - <xsl:template match="property"> - - <xsl:if test="not(parent::interface)"> - <xsl:message terminate="yes"> - <xsl:text>ERR: property </xsl:text> - <xsl:value-of select="@name"/> - <xsl:text> does not have an interface as parent </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @name on a property of </xsl:text> - <xsl:value-of select="../@name"/> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:if test="not(@type) or @type = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @type on property </xsl:text> - <xsl:value-of select="concat(../@name, '.', @name)"/> - <xsl:text>: '</xsl:text> - <xsl:value-of select="@access"/> - <xsl:text>' </xsl:text> - </xsl:message> - </xsl:if> - - <dt xmlns="http://www.w3.org/1999/xhtml"> - <a name="{concat(../@name, '.', @name)}"> - <code><xsl:value-of select="@name"/></code> - </a> - <xsl:text> − </xsl:text> - <code><xsl:value-of select="@type"/></code> - <xsl:call-template name="parenthesized-tp-type"/> - <xsl:text>, </xsl:text> - <xsl:choose> - <xsl:when test="@access = 'read'"> - <xsl:text>read-only</xsl:text> - </xsl:when> - <xsl:when test="@access = 'write'"> - <xsl:text>write-only</xsl:text> - </xsl:when> - <xsl:when test="@access = 'readwrite'"> - <xsl:text>read/write</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:message terminate="yes"> - <xsl:text>ERR: unknown or missing value for </xsl:text> - <xsl:text>@access on property </xsl:text> - <xsl:value-of select="concat(../@name, '.', @name)"/> - <xsl:text>: '</xsl:text> - <xsl:value-of select="@access"/> - <xsl:text>' </xsl:text> - </xsl:message> - </xsl:otherwise> - </xsl:choose> - </dt> - <dd xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="tp:docstring"/> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </dd> - </xsl:template> - - <xsl:template match="tp:property"> - <dt xmlns="http://www.w3.org/1999/xhtml"> - <xsl:if test="@name"> - <code><xsl:value-of select="@name"/></code> − - </xsl:if> - <code><xsl:value-of select="@type"/></code> - </dt> - <dd xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="tp:docstring"/> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </dd> - </xsl:template> - - <xsl:template match="tp:mapping"> - <div xmlns="http://www.w3.org/1999/xhtml" class="struct"> - <h3> - <a name="type-{@name}"> - <xsl:value-of select="@name"/> - </a> − a{ - <xsl:for-each select="tp:member"> - <xsl:value-of select="@type"/> - <xsl:text>: </xsl:text> - <xsl:value-of select="@name"/> - <xsl:if test="position() != last()"> → </xsl:if> - </xsl:for-each> - } - </h3> - <div class="docstring"> - <xsl:apply-templates select="tp:docstring"/> - <xsl:if test="string(@array-name) != ''"> - <p>In bindings that need a separate name, arrays of - <xsl:value-of select="@name"/> should be called - <xsl:value-of select="@array-name"/>.</p> - </xsl:if> - </div> - <div> - <h4>Members</h4> - <dl> - <xsl:apply-templates select="tp:member" mode="members-in-docstring"/> - </dl> - </div> - </div> - </xsl:template> - - <xsl:template match="tp:docstring" mode="in-index"/> - - <xsl:template match="tp:simple-type | tp:enum | tp:flags | tp:external-type" - mode="in-index"> - − <xsl:value-of select="@type"/> - </xsl:template> - - <xsl:template match="tp:simple-type"> - - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @name on a tp:simple-type </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:if test="not(@type) or @type = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @type on tp:simple-type</xsl:text> - <xsl:value-of select="@name"/> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:if> - - <div xmlns="http://www.w3.org/1999/xhtml" class="simple-type"> - <h3> - <a name="type-{@name}"> - <xsl:value-of select="@name"/> - </a> − <xsl:value-of select="@type"/> - </h3> - <div class="docstring"> - <xsl:apply-templates select="tp:docstring"/> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </div> - </div> - </xsl:template> - - <xsl:template match="tp:external-type"> - - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @name on a tp:external-type </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:if test="not(@type) or @type = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @type on tp:external-type</xsl:text> - <xsl:value-of select="@name"/> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:if> - - <div xmlns="http://www.w3.org/1999/xhtml" class="external-type"> - <dt> - <a name="type-{@name}"> - <xsl:value-of select="@name"/> - </a> − <xsl:value-of select="@type"/> - </dt> - <dd>Defined by: <xsl:value-of select="@from"/></dd> - </div> - </xsl:template> - - <xsl:template match="tp:struct" mode="in-index"> - − ( <xsl:for-each select="tp:member"> - <xsl:value-of select="@type"/> - <xsl:if test="position() != last()">, </xsl:if> - </xsl:for-each> ) - </xsl:template> - - <xsl:template match="tp:mapping" mode="in-index"> - − a{ <xsl:for-each select="tp:member"> - <xsl:value-of select="@type"/> - <xsl:if test="position() != last()"> → </xsl:if> - </xsl:for-each> } - </xsl:template> - - <xsl:template match="tp:struct"> - <div xmlns="http://www.w3.org/1999/xhtml" class="struct"> - <h3> - <a name="type-{@name}"> - <xsl:value-of select="@name"/> - </a> − ( - <xsl:for-each select="tp:member"> - <xsl:value-of select="@type"/> - <xsl:text>: </xsl:text> - <xsl:value-of select="@name"/> - <xsl:if test="position() != last()">, </xsl:if> - </xsl:for-each> - ) - </h3> - <div class="docstring"> - <xsl:apply-templates select="tp:docstring"/> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </div> - <xsl:choose> - <xsl:when test="string(@array-name) != ''"> - <p>In bindings that need a separate name, arrays of - <xsl:value-of select="@name"/> should be called - <xsl:value-of select="@array-name"/>.</p> - </xsl:when> - <xsl:otherwise> - <p>Arrays of <xsl:value-of select="@name"/> don't generally - make sense.</p> - </xsl:otherwise> - </xsl:choose> - <div> - <h4>Members</h4> - <dl> - <xsl:apply-templates select="tp:member" mode="members-in-docstring"/> - </dl> - </div> - </div> - </xsl:template> - - <xsl:template match="method"> - - <xsl:if test="not(parent::interface)"> - <xsl:message terminate="yes"> - <xsl:text>ERR: method </xsl:text> - <xsl:value-of select="@name"/> - <xsl:text> does not have an interface as parent </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @name on a method of </xsl:text> - <xsl:value-of select="../@name"/> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:for-each select="arg"> - <xsl:if test="not(@type) or @type = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: an arg of method </xsl:text> - <xsl:value-of select="concat(../../@name, '.', ../@name)"/> - <xsl:text> has no type</xsl:text> - </xsl:message> - </xsl:if> - <xsl:choose> - <xsl:when test="@direction='in'"> - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: an 'in' arg of method </xsl:text> - <xsl:value-of select="concat(../../@name, '.', ../@name)"/> - <xsl:text> has no name</xsl:text> - </xsl:message> - </xsl:if> - </xsl:when> - <xsl:when test="@direction='out'"> - <!-- FIXME: This is commented out until someone with a lot of time - on their hands goes through the spec adding names to all the "out" - arguments - - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="no"> - <xsl:text>INFO: an 'out' arg of method </xsl:text> - <xsl:value-of select="concat(../../@name, '.', ../@name)"/> - <xsl:text> has no name</xsl:text> - </xsl:message> - </xsl:if>--> - </xsl:when> - <xsl:otherwise> - <xsl:message terminate="yes"> - <xsl:text>ERR: an arg of method </xsl:text> - <xsl:value-of select="concat(../../@name, '.', ../@name)"/> - <xsl:text> has direction neither 'in' nor 'out'</xsl:text> - </xsl:message> - </xsl:otherwise> - </xsl:choose> - </xsl:for-each> - - <div xmlns="http://www.w3.org/1999/xhtml" class="method"> - <h3 xmlns="http://www.w3.org/1999/xhtml"> - <a name="{concat(../@name, concat('.', @name))}"> - <xsl:value-of select="@name"/> - </a> ( - <xsl:for-each xmlns="" select="arg[@direction='in']"> - <xsl:value-of select="@type"/>: <xsl:value-of select="@name"/> - <xsl:if test="position() != last()">, </xsl:if> - </xsl:for-each> - ) → - <xsl:choose> - <xsl:when test="arg[@direction='out']"> - <xsl:for-each xmlns="" select="arg[@direction='out']"> - <xsl:value-of select="@type"/> - <xsl:if test="position() != last()">, </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:otherwise>nothing</xsl:otherwise> - </xsl:choose> - </h3> - <div xmlns="http://www.w3.org/1999/xhtml" class="docstring"> - <xsl:apply-templates select="tp:docstring" /> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </div> - - <xsl:if test="arg[@direction='in']"> - <div xmlns="http://www.w3.org/1999/xhtml"> - <h4>Parameters</h4> - <dl xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="arg[@direction='in']" - mode="parameters-in-docstring"/> - </dl> - </div> - </xsl:if> - - <xsl:if test="arg[@direction='out']"> - <div xmlns="http://www.w3.org/1999/xhtml"> - <h4>Returns</h4> - <dl xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="arg[@direction='out']" - mode="returns-in-docstring"/> - </dl> - </div> - </xsl:if> - - <xsl:if test="tp:possible-errors"> - <div xmlns="http://www.w3.org/1999/xhtml"> - <h4>Possible errors</h4> - <dl xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="tp:possible-errors/tp:error"/> - </dl> - </div> - </xsl:if> - - </div> - </xsl:template> - - <xsl:template name="tp-type"> - <xsl:param name="tp-type"/> - <xsl:param name="type"/> - - <xsl:variable name="single-type"> - <xsl:choose> - <xsl:when test="contains($tp-type, '[]')"> - <xsl:value-of select="substring-before($tp-type, '[]')"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="$tp-type"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:variable name="type-of-tp-type"> - <xsl:if test="contains($tp-type, '[]')"> - <!-- one 'a', plus one for each [ after the [], and delete all ] --> - <xsl:value-of select="concat('a', - translate(substring-after($tp-type, '[]'), '[]', 'a'))"/> - </xsl:if> - - <xsl:choose> - <xsl:when test="//tp:simple-type[@name=$single-type]"> - <xsl:value-of select="string(//tp:simple-type[@name=$single-type]/@type)"/> - </xsl:when> - <xsl:when test="//tp:struct[@name=$single-type]"> - <xsl:text>(</xsl:text> - <xsl:for-each select="//tp:struct[@name=$single-type]/tp:member"> - <xsl:value-of select="@type"/> - </xsl:for-each> - <xsl:text>)</xsl:text> - </xsl:when> - <xsl:when test="//tp:enum[@name=$single-type]"> - <xsl:value-of select="string(//tp:enum[@name=$single-type]/@type)"/> - </xsl:when> - <xsl:when test="//tp:flags[@name=$single-type]"> - <xsl:value-of select="string(//tp:flags[@name=$single-type]/@type)"/> - </xsl:when> - <xsl:when test="//tp:mapping[@name=$single-type]"> - <xsl:text>a{</xsl:text> - <xsl:for-each select="//tp:mapping[@name=$single-type]/tp:member"> - <xsl:value-of select="@type"/> - </xsl:for-each> - <xsl:text>}</xsl:text> - </xsl:when> - <xsl:when test="//tp:external-type[@name=$single-type]"> - <xsl:value-of select="string(//tp:external-type[@name=$single-type]/@type)"/> - </xsl:when> - <xsl:otherwise> - <xsl:message terminate="yes"> - <xsl:text>ERR: Unable to find type '</xsl:text> - <xsl:value-of select="$tp-type"/> - <xsl:text>' </xsl:text> - </xsl:message> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:if test="string($type) != '' and - string($type-of-tp-type) != string($type)"> - <xsl:message terminate="yes"> - <xsl:text>ERR: tp:type '</xsl:text> - <xsl:value-of select="$tp-type"/> - <xsl:text>' has D-Bus type '</xsl:text> - <xsl:value-of select="$type-of-tp-type"/> - <xsl:text>' but has been used with type='</xsl:text> - <xsl:value-of select="$type"/> - <xsl:text>' </xsl:text> - </xsl:message> - </xsl:if> - - <a href="#type-{$single-type}"><xsl:value-of select="$tp-type"/></a> - - </xsl:template> - - <xsl:template name="parenthesized-tp-type"> - <xsl:if test="@tp:type"> - <xsl:text> (</xsl:text> - <xsl:call-template name="tp-type"> - <xsl:with-param name="tp-type" select="@tp:type"/> - <xsl:with-param name="type" select="@type"/> - </xsl:call-template> - <xsl:text>)</xsl:text> - </xsl:if> - </xsl:template> - - <xsl:template match="tp:member" mode="members-in-docstring"> - <dt xmlns="http://www.w3.org/1999/xhtml"> - <code><xsl:value-of select="@name"/></code> − - <code><xsl:value-of select="@type"/></code> - <xsl:call-template name="parenthesized-tp-type"/> - </dt> - <dd xmlns="http://www.w3.org/1999/xhtml"> - <xsl:choose> - <xsl:when test="tp:docstring"> - <xsl:apply-templates select="tp:docstring" /> - </xsl:when> - <xsl:otherwise> - <em>(undocumented)</em> - </xsl:otherwise> - </xsl:choose> - </dd> - </xsl:template> - - <xsl:template match="arg" mode="parameters-in-docstring"> - <dt xmlns="http://www.w3.org/1999/xhtml"> - <code><xsl:value-of select="@name"/></code> − - <code><xsl:value-of select="@type"/></code> - <xsl:call-template name="parenthesized-tp-type"/> - </dt> - <dd xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="tp:docstring" /> - </dd> - </xsl:template> - - <xsl:template match="arg" mode="returns-in-docstring"> - <dt xmlns="http://www.w3.org/1999/xhtml"> - <xsl:if test="@name"> - <code><xsl:value-of select="@name"/></code> − - </xsl:if> - <code><xsl:value-of select="@type"/></code> - <xsl:call-template name="parenthesized-tp-type"/> - </dt> - <dd xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="tp:docstring"/> - </dd> - </xsl:template> - - <xsl:template match="tp:possible-errors/tp:error"> - <dt xmlns="http://www.w3.org/1999/xhtml"> - <code><xsl:value-of select="@name"/></code> - </dt> - <dd xmlns="http://www.w3.org/1999/xhtml"> - <xsl:variable name="name" select="@name"/> - <xsl:choose> - <xsl:when test="tp:docstring"> - <xsl:apply-templates select="tp:docstring"/> - </xsl:when> - <xsl:when test="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"> - <xsl:apply-templates select="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"/> <em xmlns="http://www.w3.org/1999/xhtml">(generic description)</em> - </xsl:when> - <xsl:otherwise> - (Undocumented.) - </xsl:otherwise> - </xsl:choose> - </dd> - </xsl:template> - - <xsl:template match="signal"> - - <xsl:if test="not(parent::interface)"> - <xsl:message terminate="yes"> - <xsl:text>ERR: signal </xsl:text> - <xsl:value-of select="@name"/> - <xsl:text> does not have an interface as parent </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: missing @name on a signal of </xsl:text> - <xsl:value-of select="../@name"/> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:if> - - <xsl:for-each select="arg"> - <xsl:if test="not(@type) or @type = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: an arg of signal </xsl:text> - <xsl:value-of select="concat(../../@name, '.', ../@name)"/> - <xsl:text> has no type</xsl:text> - </xsl:message> - </xsl:if> - <xsl:if test="not(@name) or @name = ''"> - <xsl:message terminate="yes"> - <xsl:text>ERR: an arg of signal </xsl:text> - <xsl:value-of select="concat(../../@name, '.', ../@name)"/> - <xsl:text> has no name</xsl:text> - </xsl:message> - </xsl:if> - <xsl:choose> - <xsl:when test="not(@direction)"/> - <xsl:when test="@direction='in'"> - <xsl:message terminate="no"> - <xsl:text>INFO: an arg of signal </xsl:text> - <xsl:value-of select="concat(../../@name, '.', ../@name)"/> - <xsl:text> has unnecessary direction 'in'</xsl:text> - </xsl:message> - </xsl:when> - <xsl:otherwise> - <xsl:message terminate="yes"> - <xsl:text>ERR: an arg of signal </xsl:text> - <xsl:value-of select="concat(../../@name, '.', ../@name)"/> - <xsl:text> has direction other than 'in'</xsl:text> - </xsl:message> - </xsl:otherwise> - </xsl:choose> - </xsl:for-each> - - <div xmlns="http://www.w3.org/1999/xhtml" class="signal"> - <h3 xmlns="http://www.w3.org/1999/xhtml"> - <a name="{concat(../@name, concat('.', @name))}"> - <xsl:value-of select="@name"/> - </a> ( - <xsl:for-each xmlns="" select="arg"> - <xsl:value-of select="@type"/>: <xsl:value-of select="@name"/> - <xsl:if test="position() != last()">, </xsl:if> - </xsl:for-each> - )</h3> - - <div xmlns="http://www.w3.org/1999/xhtml" class="docstring"> - <xsl:apply-templates select="tp:docstring"/> - <xsl:apply-templates select="tp:added"/> - <xsl:apply-templates select="tp:changed"/> - <xsl:apply-templates select="tp:deprecated"/> - </div> - - <xsl:if test="arg"> - <div xmlns="http://www.w3.org/1999/xhtml"> - <h4>Parameters</h4> - <dl xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates select="arg" mode="parameters-in-docstring"/> - </dl> - </div> - </xsl:if> - </div> - </xsl:template> - - <xsl:output method="xml" indent="no" encoding="ascii" - omit-xml-declaration="yes" - doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" - doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" /> - - <xsl:template match="/tp:spec"> - <html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <title> - <xsl:value-of select="tp:title"/> - <xsl:if test="tp:version"> - <xsl:text> version </xsl:text> - <xsl:value-of select="tp:version"/> - </xsl:if> - </title> - <style type="text/css"> - - body { - font-family: sans-serif; - margin: 2em; - height: 100%; - font-size: 1.2em; - } - h1 { - padding-top: 5px; - padding-bottom: 5px; - font-size: 1.6em; - background: #dadae2; - } - h2 { - font-size: 1.3em; - } - h3 { - font-size: 1.2em; - } - a:link, a:visited, a:link:hover, a:visited:hover { - font-weight: bold; - } - .topbox { - padding-top: 10px; - padding-left: 10px; - border-bottom: black solid 1px; - padding-bottom: 10px; - background: #dadae2; - font-size: 2em; - font-weight: bold; - color: #5c5c5c; - } - .topnavbox { - padding-left: 10px; - padding-top: 5px; - padding-bottom: 5px; - background: #abacba; - border-bottom: black solid 1px; - font-size: 1.2em; - } - .topnavbox a{ - color: black; - font-weight: normal; - } - .sidebar { - float: left; - /* width:9em; - border-right:#abacba solid 1px; - border-left: #abacba solid 1px; - height:100%; */ - border: #abacba solid 1px; - padding-left: 10px; - margin-left: 10px; - padding-right: 10px; - margin-right: 10px; - color: #5d5d5d; - background: #dadae2; - } - .sidebar a { - text-decoration: none; - border-bottom: #e29625 dotted 1px; - color: #e29625; - font-weight: normal; - } - .sidebar h1 { - font-size: 1.2em; - color: black; - } - .sidebar ul { - padding-left: 25px; - padding-bottom: 10px; - border-bottom: #abacba solid 1px; - } - .sidebar li { - padding-top: 2px; - padding-bottom: 2px; - } - .sidebar h2 { - font-style:italic; - font-size: 0.81em; - padding-left: 5px; - padding-right: 5px; - font-weight: normal; - } - .date { - font-size: 0.6em; - float: right; - font-style: italic; - } - .method, .signal, .property { - margin-left: 1em; - margin-right: 4em; - } - .rationale { - font-style: italic; - border-left: 0.25em solid #808080; - padding-left: 0.5em; - } - - .added { - color: #006600; - background: #ffffff; - } - .deprecated { - color: #ff0000; - background: #ffffff; - } - table, tr, td, th { - border: 1px solid #666; - } - - </style> - </head> - <body> - <h1 class="topbox"> - <xsl:value-of select="tp:title" /> - </h1> - <xsl:if test="tp:version"> - <h2>Version <xsl:value-of select="string(tp:version)"/></h2> - </xsl:if> - <xsl:apply-templates select="tp:copyright"/> - <xsl:apply-templates select="tp:license"/> - <xsl:apply-templates select="tp:docstring"/> - - <h2>Interfaces</h2> - <ul> - <xsl:for-each select="//node/interface"> - <li><code><a href="#{@name}"><xsl:value-of select="@name"/></a></code></li> - </xsl:for-each> - </ul> - - <xsl:apply-templates select="//node"/> - <xsl:apply-templates select="tp:generic-types"/> - <xsl:apply-templates select="tp:errors"/> - - <h1>Index</h1> - <h2>Index of interfaces</h2> - <ul> - <xsl:for-each select="//node/interface"> - <li><code><a href="#{@name}"><xsl:value-of select="@name"/></a></code></li> - </xsl:for-each> - </ul> - <h2>Index of types</h2> - <ul> - <xsl:for-each select="//tp:simple-type | //tp:enum | //tp:flags | //tp:mapping | //tp:struct | //tp:external-type"> - <xsl:sort select="@name"/> - <li> - <code> - <a href="#type-{@name}"> - <xsl:value-of select="@name"/> - </a> - </code> - <xsl:apply-templates mode="in-index" select="."/> - </li> - </xsl:for-each> - </ul> - </body> - </html> - </xsl:template> - - <xsl:template match="node"> - <xsl:apply-templates /> - </xsl:template> - - <xsl:template match="text()"> - <xsl:if test="normalize-space(.) != ''"> - <xsl:message terminate="yes"> - <xsl:text>Stray text: {{{</xsl:text> - <xsl:value-of select="." /> - <xsl:text>}}} </xsl:text> - </xsl:message> - </xsl:if> - </xsl:template> - - <xsl:template match="*"> - <xsl:message terminate="yes"> - <xsl:text>Unrecognised element: {</xsl:text> - <xsl:value-of select="namespace-uri(.)" /> - <xsl:text>}</xsl:text> - <xsl:value-of select="local-name(.)" /> - <xsl:text> </xsl:text> - </xsl:message> - </xsl:template> -</xsl:stylesheet> - -<!-- vim:set sw=2 sts=2 et: --> diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py deleted file mode 100644 index 6543146..0000000 --- a/tools/glib-ginterface-gen.py +++ /dev/null @@ -1,802 +0,0 @@ -#!/usr/bin/python - -# glib-ginterface-gen.py: service-side interface generator -# -# Generate dbus-glib 0.x service GInterfaces from the Telepathy specification. -# The master copy of this program is in the telepathy-glib repository - -# please make any changes there. -# -# Copyright (C) 2006, 2007 Collabora Limited -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import sys -import os.path -import xml.dom.minidom - -from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ - NS_TP, dbus_gutils_wincaps_to_uscore, \ - signal_to_marshal_name, method_to_glue_marshal_name - - -NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" - -class Generator(object): - - def __init__(self, dom, prefix, basename, signal_marshal_prefix, - headers, end_headers, not_implemented_func, - allow_havoc): - self.dom = dom - self.__header = [] - self.__body = [] - - assert prefix.endswith('_') - assert not signal_marshal_prefix.endswith('_') - - # The main_prefix, sub_prefix thing is to get: - # FOO_ -> (FOO_, _) - # FOO_SVC_ -> (FOO_, _SVC_) - # but - # FOO_BAR/ -> (FOO_BAR_, _) - # FOO_BAR/SVC_ -> (FOO_BAR_, _SVC_) - - if '/' in prefix: - main_prefix, sub_prefix = prefix.upper().split('/', 1) - prefix = prefix.replace('/', '_') - else: - main_prefix, sub_prefix = prefix.upper().split('_', 1) - - self.MAIN_PREFIX_ = main_prefix + '_' - self._SUB_PREFIX_ = '_' + sub_prefix - - self.Prefix_ = prefix - self.Prefix = prefix.replace('_', '') - self.prefix_ = prefix.lower() - self.PREFIX_ = prefix.upper() - - self.basename = basename - self.signal_marshal_prefix = signal_marshal_prefix - self.headers = headers - self.end_headers = end_headers - self.not_implemented_func = not_implemented_func - self.allow_havoc = allow_havoc - - def h(self, s): - self.__header.append(s) - - def b(self, s): - self.__body.append(s) - - def do_node(self, node): - node_name = node.getAttribute('name').replace('/', '') - node_name_mixed = self.node_name_mixed = node_name.replace('_', '') - node_name_lc = self.node_name_lc = node_name.lower() - node_name_uc = self.node_name_uc = node_name.upper() - - interfaces = node.getElementsByTagName('interface') - assert len(interfaces) == 1, interfaces - interface = interfaces[0] - self.iface_name = interface.getAttribute('name') - - tmp = interface.getAttribute('tp:implement-service') - if tmp == "no": - return - - tmp = interface.getAttribute('tp:causes-havoc') - if tmp and not self.allow_havoc: - raise AssertionError('%s is %s' % (self.iface_name, tmp)) - - self.b('static const DBusGObjectInfo _%s%s_object_info;' - % (self.prefix_, node_name_lc)) - self.b('') - - methods = interface.getElementsByTagName('method') - signals = interface.getElementsByTagName('signal') - properties = interface.getElementsByTagName('property') - # Don't put properties in dbus-glib glue - glue_properties = [] - - self.b('struct _%s%sClass {' % (self.Prefix, node_name_mixed)) - self.b(' GTypeInterface parent_class;') - for method in methods: - self.b(' %s %s;' % self.get_method_impl_names(method)) - self.b('};') - self.b('') - - if signals: - self.b('enum {') - for signal in signals: - self.b(' %s,' % self.get_signal_const_entry(signal)) - self.b(' N_%s_SIGNALS' % node_name_uc) - self.b('};') - self.b('static guint %s_signals[N_%s_SIGNALS] = {0};' - % (node_name_lc, node_name_uc)) - self.b('') - - self.b('static void %s%s_base_init (gpointer klass);' - % (self.prefix_, node_name_lc)) - self.b('') - - self.b('GType') - self.b('%s%s_get_type (void)' - % (self.prefix_, node_name_lc)) - self.b('{') - self.b(' static GType type = 0;') - self.b('') - self.b(' if (G_UNLIKELY (type == 0))') - self.b(' {') - self.b(' static const GTypeInfo info = {') - self.b(' sizeof (%s%sClass),' % (self.Prefix, node_name_mixed)) - self.b(' %s%s_base_init, /* base_init */' - % (self.prefix_, node_name_lc)) - self.b(' NULL, /* base_finalize */') - self.b(' NULL, /* class_init */') - self.b(' NULL, /* class_finalize */') - self.b(' NULL, /* class_data */') - self.b(' 0,') - self.b(' 0, /* n_preallocs */') - self.b(' NULL /* instance_init */') - self.b(' };') - self.b('') - self.b(' type = g_type_register_static (G_TYPE_INTERFACE,') - self.b(' "%s%s", &info, 0);' % (self.Prefix, node_name_mixed)) - self.b(' }') - self.b('') - self.b(' return type;') - self.b('}') - self.b('') - - self.h('/**') - self.h(' * %s%s:' % (self.Prefix, node_name_mixed)) - self.h(' *') - self.h(' * Dummy typedef representing any implementation of this ' - 'interface.') - self.h(' */') - self.h('typedef struct _%s%s %s%s;' - % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed)) - self.h('') - self.h('/**') - self.h(' * %s%sClass:' % (self.Prefix, node_name_mixed)) - self.h(' *') - self.h(' * The class of %s%s.' % (self.Prefix, node_name_mixed)) - - if methods: - self.h(' *') - self.h(' * In a full implementation of this interface (i.e. all') - self.h(' * methods implemented), the interface initialization') - self.h(' * function used in G_IMPLEMENT_INTERFACE() would') - self.h(' * typically look like this:') - self.h(' *') - self.h(' * <programlisting>') - self.h(' * static void') - self.h(' * implement_%s (gpointer klass,' % self.node_name_lc) - self.h(' * gpointer unused G_GNUC_UNUSED)') - self.h(' * {') - # "#" is special to gtkdoc under some circumstances; it appears - # that escaping "##" as "#<!---->#" or "##" doesn't work, - # but adding an extra hash symbol does. Thanks, gtkdoc :-( - self.h(' * #define IMPLEMENT(x) %s%s_implement_###x (\\' - % (self.prefix_, self.node_name_lc)) - self.h(' * klass, my_object_###x)') - - for method in methods: - class_member_name = method.getAttribute('tp:name-for-bindings') - class_member_name = class_member_name.lower() - self.h(' * IMPLEMENT (%s);' % class_member_name) - - self.h(' * #undef IMPLEMENT') - self.h(' * }') - self.h(' * </programlisting>') - else: - self.h(' * This interface has no D-Bus methods, so an') - self.h(' * implementation can typically pass %NULL to') - self.h(' * G_IMPLEMENT_INTERFACE() as the interface') - self.h(' * initialization function.') - - self.h(' */') - - self.h('typedef struct _%s%sClass %s%sClass;' - % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed)) - self.h('') - self.h('GType %s%s_get_type (void);' - % (self.prefix_, node_name_lc)) - - gtype = self.current_gtype = \ - self.MAIN_PREFIX_ + 'TYPE' + self._SUB_PREFIX_ + node_name_uc - classname = self.Prefix + node_name_mixed - - self.h('#define %s \\\n (%s%s_get_type ())' - % (gtype, self.prefix_, node_name_lc)) - self.h('#define %s%s(obj) \\\n' - ' (G_TYPE_CHECK_INSTANCE_CAST((obj), %s, %s))' - % (self.PREFIX_, node_name_uc, gtype, classname)) - self.h('#define %sIS%s%s(obj) \\\n' - ' (G_TYPE_CHECK_INSTANCE_TYPE((obj), %s))' - % (self.MAIN_PREFIX_, self._SUB_PREFIX_, node_name_uc, gtype)) - self.h('#define %s%s_GET_CLASS(obj) \\\n' - ' (G_TYPE_INSTANCE_GET_INTERFACE((obj), %s, %sClass))' - % (self.PREFIX_, node_name_uc, gtype, classname)) - self.h('') - self.h('') - - base_init_code = [] - - for method in methods: - self.do_method(method) - - for signal in signals: - base_init_code.extend(self.do_signal(signal)) - - self.b('static inline void') - self.b('%s%s_base_init_once (gpointer klass G_GNUC_UNUSED)' - % (self.prefix_, node_name_lc)) - self.b('{') - - if properties: - self.b(' static TpDBusPropertiesMixinPropInfo properties[%d] = {' - % (len(properties) + 1)) - - for m in properties: - access = m.getAttribute('access') - assert access in ('read', 'write', 'readwrite') - - if access == 'read': - flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_READ' - elif access == 'write': - flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE' - else: - flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | ' - 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE') - - self.b(' { 0, %s, "%s", 0, NULL, NULL }, /* %s */' - % (flags, m.getAttribute('type'), m.getAttribute('name'))) - - self.b(' { 0, 0, NULL, 0, NULL, NULL }') - self.b(' };') - self.b(' static TpDBusPropertiesMixinIfaceInfo interface =') - self.b(' { 0, properties, NULL, NULL };') - self.b('') - - - self.b(' dbus_g_object_type_install_info (%s%s_get_type (),' - % (self.prefix_, node_name_lc)) - self.b(' &_%s%s_object_info);' - % (self.prefix_, node_name_lc)) - self.b('') - - if properties: - self.b(' interface.dbus_interface = g_quark_from_static_string ' - '("%s");' % self.iface_name) - - for i, m in enumerate(properties): - self.b(' properties[%d].name = g_quark_from_static_string ("%s");' - % (i, m.getAttribute('name'))) - self.b(' properties[%d].type = %s;' - % (i, type_to_gtype(m.getAttribute('type'))[1])) - - self.b(' tp_svc_interface_set_dbus_properties_info (%s, &interface);' - % self.current_gtype) - - self.b('') - - for s in base_init_code: - self.b(s) - self.b('}') - - self.b('static void') - self.b('%s%s_base_init (gpointer klass)' - % (self.prefix_, node_name_lc)) - self.b('{') - self.b(' static gboolean initialized = FALSE;') - self.b('') - self.b(' if (!initialized)') - self.b(' {') - self.b(' initialized = TRUE;') - self.b(' %s%s_base_init_once (klass);' - % (self.prefix_, node_name_lc)) - self.b(' }') - # insert anything we need to do per implementation here - self.b('}') - - self.h('') - - self.b('static const DBusGMethodInfo _%s%s_methods[] = {' - % (self.prefix_, node_name_lc)) - - method_blob, offsets = self.get_method_glue(methods) - - for method, offset in zip(methods, offsets): - self.do_method_glue(method, offset) - - if len(methods) == 0: - # empty arrays are a gcc extension, so put in a dummy member - self.b(" { NULL, NULL, 0 }") - - self.b('};') - self.b('') - - self.b('static const DBusGObjectInfo _%s%s_object_info = {' - % (self.prefix_, node_name_lc)) - self.b(' 0,') # version - self.b(' _%s%s_methods,' % (self.prefix_, node_name_lc)) - self.b(' %d,' % len(methods)) - self.b('"' + method_blob.replace('\0', '\\0') + '",') - self.b('"' + self.get_signal_glue(signals).replace('\0', '\\0') + '",') - self.b('"' + - self.get_property_glue(glue_properties).replace('\0', '\\0') + - '",') - self.b('};') - self.b('') - - self.node_name_mixed = None - self.node_name_lc = None - self.node_name_uc = None - - def get_method_glue(self, methods): - info = [] - offsets = [] - - for method in methods: - offsets.append(len(''.join(info))) - - info.append(self.iface_name + '\0') - info.append(method.getAttribute('name') + '\0') - - info.append('A\0') # async - - counter = 0 - for arg in method.getElementsByTagName('arg'): - out = arg.getAttribute('direction') == 'out' - - name = arg.getAttribute('name') - if not name: - assert out - name = 'arg%u' % counter - counter += 1 - - info.append(name + '\0') - - if out: - info.append('O\0') - else: - info.append('I\0') - - if out: - info.append('F\0') # not const - info.append('N\0') # not error or return - info.append(arg.getAttribute('type') + '\0') - - info.append('\0') - - return ''.join(info) + '\0', offsets - - def do_method_glue(self, method, offset): - lc_name = method.getAttribute('tp:name-for-bindings') - if method.getAttribute('name') != lc_name.replace('_', ''): - raise AssertionError('Method %s tp:name-for-bindings (%s) does ' - 'not match' % (method.getAttribute('name'), lc_name)) - lc_name = lc_name.lower() - - marshaller = method_to_glue_marshal_name(method, - self.signal_marshal_prefix) - wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name - - self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset)) - - def get_signal_glue(self, signals): - info = [] - - for signal in signals: - info.append(self.iface_name) - info.append(signal.getAttribute('name')) - - return '\0'.join(info) + '\0\0' - - # the implementation can be the same - get_property_glue = get_signal_glue - - def get_method_impl_names(self, method): - dbus_method_name = method.getAttribute('name') - - class_member_name = method.getAttribute('tp:name-for-bindings') - if dbus_method_name != class_member_name.replace('_', ''): - raise AssertionError('Method %s tp:name-for-bindings (%s) does ' - 'not match' % (dbus_method_name, class_member_name)) - class_member_name = class_member_name.lower() - - stub_name = (self.prefix_ + self.node_name_lc + '_' + - class_member_name) - return (stub_name + '_impl', class_member_name) - - def do_method(self, method): - assert self.node_name_mixed is not None - - in_class = [] - - # Examples refer to Thing.DoStuff (su) -> ii - - # DoStuff - dbus_method_name = method.getAttribute('name') - # do_stuff - class_member_name = method.getAttribute('tp:name-for-bindings') - if dbus_method_name != class_member_name.replace('_', ''): - raise AssertionError('Method %s tp:name-for-bindings (%s) does ' - 'not match' % (dbus_method_name, class_member_name)) - class_member_name = class_member_name.lower() - - # void tp_svc_thing_do_stuff (TpSvcThing *, const char *, guint, - # DBusGMethodInvocation *); - stub_name = (self.prefix_ + self.node_name_lc + '_' + - class_member_name) - # typedef void (*tp_svc_thing_do_stuff_impl) (TpSvcThing *, - # const char *, guint, DBusGMethodInvocation); - impl_name = stub_name + '_impl' - # void tp_svc_thing_return_from_do_stuff (DBusGMethodInvocation *, - # gint, gint); - ret_name = (self.prefix_ + self.node_name_lc + '_return_from_' + - class_member_name) - - # Gather arguments - in_args = [] - out_args = [] - for i in method.getElementsByTagName('arg'): - name = i.getAttribute('name') - direction = i.getAttribute('direction') or 'in' - dtype = i.getAttribute('type') - - assert direction in ('in', 'out') - - if name: - name = direction + '_' + name - elif direction == 'in': - name = direction + str(len(in_args)) - else: - name = direction + str(len(out_args)) - - ctype, gtype, marshaller, pointer = type_to_gtype(dtype) - - if pointer: - ctype = 'const ' + ctype - - struct = (ctype, name) - - if direction == 'in': - in_args.append(struct) - else: - out_args.append(struct) - - # Implementation type declaration (in header, docs in body) - self.b('/**') - self.b(' * %s:' % impl_name) - self.b(' * @self: The object implementing this interface') - for (ctype, name) in in_args: - self.b(' * @%s: %s (FIXME, generate documentation)' - % (name, ctype)) - self.b(' * @context: Used to return values or throw an error') - self.b(' *') - self.b(' * The signature of an implementation of the D-Bus method') - self.b(' * %s on interface %s.' % (dbus_method_name, self.iface_name)) - self.b(' */') - self.h('typedef void (*%s) (%s%s *self,' - % (impl_name, self.Prefix, self.node_name_mixed)) - for (ctype, name) in in_args: - self.h(' %s%s,' % (ctype, name)) - self.h(' DBusGMethodInvocation *context);') - - # Class member (in class definition) - in_class.append(' %s %s;' % (impl_name, class_member_name)) - - # Stub definition (in body only - it's static) - self.b('static void') - self.b('%s (%s%s *self,' - % (stub_name, self.Prefix, self.node_name_mixed)) - for (ctype, name) in in_args: - self.b(' %s%s,' % (ctype, name)) - self.b(' DBusGMethodInvocation *context)') - self.b('{') - self.b(' %s impl = (%s%s_GET_CLASS (self)->%s);' - % (impl_name, self.PREFIX_, self.node_name_uc, class_member_name)) - self.b('') - self.b(' if (impl != NULL)') - tmp = ['self'] + [name for (ctype, name) in in_args] + ['context'] - self.b(' {') - self.b(' (impl) (%s);' % ',\n '.join(tmp)) - self.b(' }') - self.b(' else') - self.b(' {') - if self.not_implemented_func: - self.b(' %s (context);' % self.not_implemented_func) - else: - self.b(' GError e = { DBUS_GERROR, ') - self.b(' DBUS_GERROR_UNKNOWN_METHOD,') - self.b(' "Method not implemented" };') - self.b('') - self.b(' dbus_g_method_return_error (context, &e);') - self.b(' }') - self.b('}') - self.b('') - - # Implementation registration (in both header and body) - self.h('void %s%s_implement_%s (%s%sClass *klass, %s impl);' - % (self.prefix_, self.node_name_lc, class_member_name, - self.Prefix, self.node_name_mixed, impl_name)) - - self.b('/**') - self.b(' * %s%s_implement_%s:' - % (self.prefix_, self.node_name_lc, class_member_name)) - self.b(' * @klass: A class whose instances implement this interface') - self.b(' * @impl: A callback used to implement the %s D-Bus method' - % dbus_method_name) - self.b(' *') - self.b(' * Register an implementation for the %s method in the vtable' - % dbus_method_name) - self.b(' * of an implementation of this interface. To be called from') - self.b(' * the interface init function.') - self.b(' */') - self.b('void') - self.b('%s%s_implement_%s (%s%sClass *klass, %s impl)' - % (self.prefix_, self.node_name_lc, class_member_name, - self.Prefix, self.node_name_mixed, impl_name)) - self.b('{') - self.b(' klass->%s = impl;' % class_member_name) - self.b('}') - self.b('') - - # Return convenience function (static inline, in header) - self.h('/**') - self.h(' * %s:' % ret_name) - self.h(' * @context: The D-Bus method invocation context') - for (ctype, name) in out_args: - self.h(' * @%s: %s (FIXME, generate documentation)' - % (name, ctype)) - self.h(' *') - self.h(' * Return successfully by calling dbus_g_method_return().') - self.h(' * This inline function exists only to provide type-safety.') - self.h(' */') - tmp = (['DBusGMethodInvocation *context'] + - [ctype + name for (ctype, name) in out_args]) - self.h('static inline') - self.h('/* this comment is to stop gtkdoc realising this is static */') - self.h(('void %s (' % ret_name) + (',\n '.join(tmp)) + ');') - self.h('static inline void') - self.h(('%s (' % ret_name) + (',\n '.join(tmp)) + ')') - self.h('{') - tmp = ['context'] + [name for (ctype, name) in out_args] - self.h(' dbus_g_method_return (' + ',\n '.join(tmp) + ');') - self.h('}') - self.h('') - - return in_class - - def get_signal_const_entry(self, signal): - assert self.node_name_uc is not None - return ('SIGNAL_%s_%s' - % (self.node_name_uc, signal.getAttribute('name'))) - - def do_signal(self, signal): - assert self.node_name_mixed is not None - - in_base_init = [] - - # for signal: Thing::StuffHappened (s, u) - # we want to emit: - # void tp_svc_thing_emit_stuff_happened (gpointer instance, - # const char *arg0, guint arg1); - - dbus_name = signal.getAttribute('name') - - ugly_name = signal.getAttribute('tp:name-for-bindings') - if dbus_name != ugly_name.replace('_', ''): - raise AssertionError('Signal %s tp:name-for-bindings (%s) does ' - 'not match' % (dbus_name, ugly_name)) - - stub_name = (self.prefix_ + self.node_name_lc + '_emit_' + - ugly_name.lower()) - - const_name = self.get_signal_const_entry(signal) - - # Gather arguments - args = [] - for i in signal.getElementsByTagName('arg'): - name = i.getAttribute('name') - dtype = i.getAttribute('type') - tp_type = i.getAttribute('tp:type') - - if name: - name = 'arg_' + name - else: - name = 'arg' + str(len(args)) - - ctype, gtype, marshaller, pointer = type_to_gtype(dtype) - - if pointer: - ctype = 'const ' + ctype - - struct = (ctype, name, gtype) - args.append(struct) - - tmp = (['gpointer instance'] + - [ctype + name for (ctype, name, gtype) in args]) - - self.h(('void %s (' % stub_name) + (',\n '.join(tmp)) + ');') - - # FIXME: emit docs - - self.b('/**') - self.b(' * %s:' % stub_name) - self.b(' * @instance: The object implementing this interface') - for (ctype, name, gtype) in args: - self.b(' * @%s: %s (FIXME, generate documentation)' - % (name, ctype)) - self.b(' *') - self.b(' * Type-safe wrapper around g_signal_emit to emit the') - self.b(' * %s signal on interface %s.' - % (dbus_name, self.iface_name)) - self.b(' */') - - self.b('void') - self.b(('%s (' % stub_name) + (',\n '.join(tmp)) + ')') - self.b('{') - self.b(' g_assert (instance != NULL);') - self.b(' g_assert (G_TYPE_CHECK_INSTANCE_TYPE (instance, %s));' - % (self.current_gtype)) - tmp = (['instance', '%s_signals[%s]' % (self.node_name_lc, const_name), - '0'] + [name for (ctype, name, gtype) in args]) - self.b(' g_signal_emit (' + ',\n '.join(tmp) + ');') - self.b('}') - self.b('') - - signal_name = dbus_gutils_wincaps_to_uscore(dbus_name).replace('_', - '-') - in_base_init.append(' /**') - in_base_init.append(' * %s%s::%s:' - % (self.Prefix, self.node_name_mixed, signal_name)) - for (ctype, name, gtype) in args: - in_base_init.append(' * @%s: %s (FIXME, generate documentation)' - % (name, ctype)) - in_base_init.append(' *') - in_base_init.append(' * The %s D-Bus signal is emitted whenever ' - 'this GObject signal is.' % dbus_name) - in_base_init.append(' */') - in_base_init.append(' %s_signals[%s] =' - % (self.node_name_lc, const_name)) - in_base_init.append(' g_signal_new ("%s",' % signal_name) - in_base_init.append(' G_OBJECT_CLASS_TYPE (klass),') - in_base_init.append(' G_SIGNAL_RUN_LAST|G_SIGNAL_DETAILED,') - in_base_init.append(' 0,') - in_base_init.append(' NULL, NULL,') - in_base_init.append(' %s,' - % signal_to_marshal_name(signal, self.signal_marshal_prefix)) - in_base_init.append(' G_TYPE_NONE,') - tmp = ['%d' % len(args)] + [gtype for (ctype, name, gtype) in args] - in_base_init.append(' %s);' % ',\n '.join(tmp)) - in_base_init.append('') - - return in_base_init - - def have_properties(self, nodes): - for node in nodes: - interface = node.getElementsByTagName('interface')[0] - if interface.getElementsByTagName('property'): - return True - return False - - def __call__(self): - nodes = self.dom.getElementsByTagName('node') - nodes.sort(cmp_by_name) - - self.h('#include <glib-object.h>') - self.h('#include <dbus/dbus-glib.h>') - - if self.have_properties(nodes): - self.h('#include <telepathy-glib/telepathy-glib.h>') - - self.h('') - self.h('G_BEGIN_DECLS') - self.h('') - - self.b('#include "%s.h"' % self.basename) - self.b('') - for header in self.headers: - self.b('#include %s' % header) - self.b('') - - for node in nodes: - self.do_node(node) - - self.h('') - self.h('G_END_DECLS') - - self.b('') - for header in self.end_headers: - self.b('#include %s' % header) - - self.h('') - self.b('') - open(self.basename + '.h', 'w').write('\n'.join(self.__header)) - open(self.basename + '.c', 'w').write('\n'.join(self.__body)) - - -def cmdline_error(): - print """\ -usage: - gen-ginterface [OPTIONS] xmlfile Prefix_ -options: - --include='<header.h>' (may be repeated) - --include='"header.h"' (ditto) - --include-end='"header.h"' (ditto) - Include extra headers in the generated .c file - --signal-marshal-prefix='prefix' - Use the given prefix on generated signal marshallers (default is - prefix.lower()). - --filename='BASENAME' - Set the basename for the output files (default is prefix.lower() - + 'ginterfaces') - --not-implemented-func='symbol' - Set action when methods not implemented in the interface vtable are - called. symbol must have signature - void symbol (DBusGMethodInvocation *context) - and return some sort of "not implemented" error via - dbus_g_method_return_error (context, ...) -""" - sys.exit(1) - - -if __name__ == '__main__': - from getopt import gnu_getopt - - options, argv = gnu_getopt(sys.argv[1:], '', - ['filename=', 'signal-marshal-prefix=', - 'include=', 'include-end=', - 'allow-unstable', - 'not-implemented-func=']) - - try: - prefix = argv[1] - except IndexError: - cmdline_error() - - basename = prefix.lower() + 'ginterfaces' - signal_marshal_prefix = prefix.lower().rstrip('_') - headers = [] - end_headers = [] - not_implemented_func = '' - allow_havoc = False - - for option, value in options: - if option == '--filename': - basename = value - elif option == '--signal-marshal-prefix': - signal_marshal_prefix = value - elif option == '--include': - if value[0] not in '<"': - value = '"%s"' % value - headers.append(value) - elif option == '--include-end': - if value[0] not in '<"': - value = '"%s"' % value - end_headers.append(value) - elif option == '--not-implemented-func': - not_implemented_func = value - elif option == '--allow-unstable': - allow_havoc = True - - try: - dom = xml.dom.minidom.parse(argv[0]) - except IndexError: - cmdline_error() - - Generator(dom, prefix, basename, signal_marshal_prefix, headers, - end_headers, not_implemented_func, allow_havoc)() diff --git a/tools/glib-gtypes-generator.py b/tools/glib-gtypes-generator.py deleted file mode 100644 index ebc2ad4..0000000 --- a/tools/glib-gtypes-generator.py +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/python - -# Generate GLib GInterfaces from the Telepathy specification. -# The master copy of this program is in the telepathy-glib repository - -# please make any changes there. -# -# Copyright (C) 2006, 2007 Collabora Limited -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import sys -import xml.dom.minidom - -from libglibcodegen import escape_as_identifier, \ - get_docstring, \ - NS_TP, \ - Signature, \ - type_to_gtype, \ - xml_escape - - -def types_to_gtypes(types): - return [type_to_gtype(t)[1] for t in types] - - -class GTypesGenerator(object): - def __init__(self, dom, output, mixed_case_prefix): - self.dom = dom - self.Prefix = mixed_case_prefix - self.PREFIX_ = self.Prefix.upper() + '_' - self.prefix_ = self.Prefix.lower() + '_' - - self.header = open(output + '.h', 'w') - self.body = open(output + '-body.h', 'w') - - for f in (self.header, self.body): - f.write('/* Auto-generated, do not edit.\n *\n' - ' * This file may be distributed under the same terms\n' - ' * as the specification from which it was generated.\n' - ' */\n\n') - - # keys are e.g. 'sv', values are the key escaped - self.need_mappings = {} - # keys are the contents of the struct (e.g. 'sssu'), values are the - # key escaped - self.need_structs = {} - # keys are the contents of the struct (e.g. 'sssu'), values are the - # key escaped - self.need_struct_arrays = {} - - # keys are the contents of the array (unlike need_struct_arrays!), - # values are the key escaped - self.need_other_arrays = {} - - def h(self, code): - self.header.write(code.encode("utf-8")) - - def c(self, code): - self.body.write(code.encode("utf-8")) - - def do_mapping_header(self, mapping): - members = mapping.getElementsByTagNameNS(NS_TP, 'member') - assert len(members) == 2 - - impl_sig = ''.join([elt.getAttribute('type') - for elt in members]) - - esc_impl_sig = escape_as_identifier(impl_sig) - - name = (self.PREFIX_ + 'HASH_TYPE_' + - mapping.getAttribute('name').upper()) - impl = self.prefix_ + 'type_dbus_hash_' + esc_impl_sig - - docstring = get_docstring(mapping) or '(Undocumented)' - - self.h('/**\n * %s:\n *\n' % name) - self.h(' * %s\n' % xml_escape(docstring)) - self.h(' *\n') - self.h(' * This macro expands to a call to a function\n') - self.h(' * that returns the #GType of a #GHashTable\n') - self.h(' * appropriate for representing a D-Bus\n') - self.h(' * dictionary of signature\n') - self.h(' * <literal>a{%s}</literal>.\n' % impl_sig) - self.h(' *\n') - - key, value = members - - self.h(' * Keys (D-Bus type <literal>%s</literal>,\n' - % key.getAttribute('type')) - tp_type = key.getAttributeNS(NS_TP, 'type') - if tp_type: - self.h(' * type <literal>%s</literal>,\n' % tp_type) - self.h(' * named <literal>%s</literal>):\n' - % key.getAttribute('name')) - docstring = get_docstring(key) or '(Undocumented)' - self.h(' * %s\n' % xml_escape(docstring)) - self.h(' *\n') - - self.h(' * Values (D-Bus type <literal>%s</literal>,\n' - % value.getAttribute('type')) - tp_type = value.getAttributeNS(NS_TP, 'type') - if tp_type: - self.h(' * type <literal>%s</literal>,\n' % tp_type) - self.h(' * named <literal>%s</literal>):\n' - % value.getAttribute('name')) - docstring = get_docstring(value) or '(Undocumented)' - self.h(' * %s\n' % xml_escape(docstring)) - self.h(' *\n') - - self.h(' */\n') - - self.h('#define %s (%s ())\n\n' % (name, impl)) - self.need_mappings[impl_sig] = esc_impl_sig - - array_name = mapping.getAttribute('array-name') - if array_name: - gtype_name = self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper() - contents_sig = 'a{' + impl_sig + '}' - esc_contents_sig = escape_as_identifier(contents_sig) - impl = self.prefix_ + 'type_dbus_array_of_' + esc_contents_sig - self.h('/**\n * %s:\n\n' % gtype_name) - self.h(' * Expands to a call to a function\n') - self.h(' * that returns the #GType of a #GPtrArray\n') - self.h(' * of #%s.\n' % name) - self.h(' */\n') - self.h('#define %s (%s ())\n\n' % (gtype_name, impl)) - self.need_other_arrays[contents_sig] = esc_contents_sig - - def do_struct_header(self, struct): - members = struct.getElementsByTagNameNS(NS_TP, 'member') - impl_sig = ''.join([elt.getAttribute('type') for elt in members]) - esc_impl_sig = escape_as_identifier(impl_sig) - - name = (self.PREFIX_ + 'STRUCT_TYPE_' + - struct.getAttribute('name').upper()) - impl = self.prefix_ + 'type_dbus_struct_' + esc_impl_sig - docstring = struct.getElementsByTagNameNS(NS_TP, 'docstring') - if docstring: - docstring = docstring[0].toprettyxml() - if docstring.startswith('<tp:docstring>'): - docstring = docstring[14:] - if docstring.endswith('</tp:docstring>\n'): - docstring = docstring[:-16] - if docstring.strip() in ('<tp:docstring/>', ''): - docstring = '(Undocumented)' - else: - docstring = '(Undocumented)' - self.h('/**\n * %s:\n\n' % name) - self.h(' * %s\n' % xml_escape(docstring)) - self.h(' *\n') - self.h(' * This macro expands to a call to a function\n') - self.h(' * that returns the #GType of a #GValueArray\n') - self.h(' * appropriate for representing a D-Bus struct\n') - self.h(' * with signature <literal>(%s)</literal>.\n' - % impl_sig) - self.h(' *\n') - - for i, member in enumerate(members): - self.h(' * Member %d (D-Bus type ' - '<literal>%s</literal>,\n' - % (i, member.getAttribute('type'))) - tp_type = member.getAttributeNS(NS_TP, 'type') - if tp_type: - self.h(' * type <literal>%s</literal>,\n' % tp_type) - self.h(' * named <literal>%s</literal>):\n' - % member.getAttribute('name')) - docstring = get_docstring(member) or '(Undocumented)' - self.h(' * %s\n' % xml_escape(docstring)) - self.h(' *\n') - - self.h(' */\n') - self.h('#define %s (%s ())\n\n' % (name, impl)) - - array_name = struct.getAttribute('array-name') - if array_name != '': - array_name = (self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper()) - impl = self.prefix_ + 'type_dbus_array_' + esc_impl_sig - self.h('/**\n * %s:\n\n' % array_name) - self.h(' * Expands to a call to a function\n') - self.h(' * that returns the #GType of a #GPtrArray\n') - self.h(' * of #%s.\n' % name) - self.h(' */\n') - self.h('#define %s (%s ())\n\n' % (array_name, impl)) - self.need_struct_arrays[impl_sig] = esc_impl_sig - - self.need_structs[impl_sig] = esc_impl_sig - - def __call__(self): - mappings = self.dom.getElementsByTagNameNS(NS_TP, 'mapping') - structs = self.dom.getElementsByTagNameNS(NS_TP, 'struct') - - for mapping in mappings: - self.do_mapping_header(mapping) - - for sig in self.need_mappings: - self.h('GType %stype_dbus_hash_%s (void);\n\n' % - (self.prefix_, self.need_mappings[sig])) - self.c('GType\n%stype_dbus_hash_%s (void)\n{\n' % - (self.prefix_, self.need_mappings[sig])) - self.c(' static GType t = 0;\n\n') - self.c(' if (G_UNLIKELY (t == 0))\n') - # FIXME: translate sig into two GTypes - items = tuple(Signature(sig)) - gtypes = types_to_gtypes(items) - self.c(' t = dbus_g_type_get_map ("GHashTable", ' - '%s, %s);\n' % (gtypes[0], gtypes[1])) - self.c(' return t;\n') - self.c('}\n\n') - - for struct in structs: - self.do_struct_header(struct) - - for sig in self.need_structs: - self.h('GType %stype_dbus_struct_%s (void);\n\n' % - (self.prefix_, self.need_structs[sig])) - self.c('GType\n%stype_dbus_struct_%s (void)\n{\n' % - (self.prefix_, self.need_structs[sig])) - self.c(' static GType t = 0;\n\n') - self.c(' if (G_UNLIKELY (t == 0))\n') - self.c(' t = dbus_g_type_get_struct ("GValueArray",\n') - items = tuple(Signature(sig)) - gtypes = types_to_gtypes(items) - for gtype in gtypes: - self.c(' %s,\n' % gtype) - self.c(' G_TYPE_INVALID);\n') - self.c(' return t;\n') - self.c('}\n\n') - - for sig in self.need_struct_arrays: - self.h('GType %stype_dbus_array_%s (void);\n\n' % - (self.prefix_, self.need_struct_arrays[sig])) - self.c('GType\n%stype_dbus_array_%s (void)\n{\n' % - (self.prefix_, self.need_struct_arrays[sig])) - self.c(' static GType t = 0;\n\n') - self.c(' if (G_UNLIKELY (t == 0))\n') - self.c(' t = dbus_g_type_get_collection ("GPtrArray", ' - '%stype_dbus_struct_%s ());\n' % - (self.prefix_, self.need_struct_arrays[sig])) - self.c(' return t;\n') - self.c('}\n\n') - - for sig in self.need_other_arrays: - self.h('GType %stype_dbus_array_of_%s (void);\n\n' % - (self.prefix_, self.need_other_arrays[sig])) - self.c('GType\n%stype_dbus_array_of_%s (void)\n{\n' % - (self.prefix_, self.need_other_arrays[sig])) - self.c(' static GType t = 0;\n\n') - self.c(' if (G_UNLIKELY (t == 0))\n') - - if sig[:2] == 'a{' and sig[-1:] == '}': - # array of mappings - self.c(' t = dbus_g_type_get_collection (' - '"GPtrArray", ' - '%stype_dbus_hash_%s ());\n' % - (self.prefix_, escape_as_identifier(sig[2:-1]))) - elif sig[:2] == 'a(' and sig[-1:] == ')': - # array of arrays of struct - self.c(' t = dbus_g_type_get_collection (' - '"GPtrArray", ' - '%stype_dbus_array_%s ());\n' % - (self.prefix_, escape_as_identifier(sig[2:-1]))) - elif sig[:1] == 'a': - # array of arrays of non-struct - self.c(' t = dbus_g_type_get_collection (' - '"GPtrArray", ' - '%stype_dbus_array_of_%s ());\n' % - (self.prefix_, escape_as_identifier(sig[1:]))) - else: - raise AssertionError("array of '%s' not supported" % sig) - - self.c(' return t;\n') - self.c('}\n\n') - -if __name__ == '__main__': - argv = sys.argv[1:] - - dom = xml.dom.minidom.parse(argv[0]) - - GTypesGenerator(dom, argv[1], argv[2])() diff --git a/tools/glib-interfaces-gen.py b/tools/glib-interfaces-gen.py deleted file mode 100644 index 9543968..0000000 --- a/tools/glib-interfaces-gen.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/python - -from sys import argv, stdout, stderr -import xml.dom.minidom - -from libglibcodegen import NS_TP, get_docstring, \ - get_descendant_text, get_by_path - -class Generator(object): - def __init__(self, prefix, implfile, declfile, dom): - self.prefix = prefix + '_' - self.impls = open(implfile, 'w') - self.decls = open(declfile, 'w') - self.spec = get_by_path(dom, "spec")[0] - - def h(self, code): - self.decls.write(code.encode('utf-8')) - - def c(self, code): - self.impls.write(code.encode('utf-8')) - - def __call__(self): - for f in self.h, self.c: - self.do_header(f) - self.do_body() - - # Header - def do_header(self, f): - f('/* Generated from: ') - f(get_descendant_text(get_by_path(self.spec, 'title'))) - version = get_by_path(self.spec, "version") - if version: - f(' version ' + get_descendant_text(version)) - f('\n\n') - for copyright in get_by_path(self.spec, 'copyright'): - f(get_descendant_text(copyright)) - f('\n') - f('\n') - f(get_descendant_text(get_by_path(self.spec, 'license'))) - f(get_descendant_text(get_by_path(self.spec, 'docstring'))) - f(""" - */ - -""") - - # Body - def do_body(self): - for iface in self.spec.getElementsByTagName('interface'): - self.do_iface(iface) - - def do_iface(self, iface): - parent_name = get_by_path(iface, '../@name') - self.h("""\ -/** - * %(IFACE_DEFINE)s: - * - * The interface name "%(name)s" - */ -#define %(IFACE_DEFINE)s \\ -"%(name)s" -""" % {'IFACE_DEFINE' : (self.prefix + 'IFACE_' + \ - parent_name).upper().replace('/', ''), - 'name' : iface.getAttribute('name')}) - - self.h(""" -/** - * %(IFACE_QUARK_DEFINE)s: - * - * Expands to a call to a function that returns a quark for the interface \ -name "%(name)s" - */ -#define %(IFACE_QUARK_DEFINE)s \\ - (%(iface_quark_func)s ()) - -GQuark %(iface_quark_func)s (void); - -""" % {'IFACE_QUARK_DEFINE' : (self.prefix + 'IFACE_QUARK_' + \ - parent_name).upper().replace('/', ''), - 'iface_quark_func' : (self.prefix + 'iface_quark_' + \ - parent_name).lower().replace('/', ''), - 'name' : iface.getAttribute('name')}) - - self.c("""\ -GQuark -%(iface_quark_func)s (void) -{ - static GQuark quark = 0; - - if (G_UNLIKELY (quark == 0)) - { - quark = g_quark_from_static_string ("%(name)s"); - } - - return quark; -} - -""" % {'iface_quark_func' : (self.prefix + 'iface_quark_' + \ - parent_name).lower().replace('/', ''), - 'name' : iface.getAttribute('name')}) - - for prop in iface.getElementsByTagNameNS(None, 'property'): - self.decls.write(""" -/** - * %(IFACE_PREFIX)s_%(PROP_UC)s: - * - * The fully-qualified property name "%(name)s.%(prop)s" - */ -#define %(IFACE_PREFIX)s_%(PROP_UC)s \\ -"%(name)s.%(prop)s" -""" % {'IFACE_PREFIX' : (self.prefix + 'PROP_' + \ - parent_name).upper().replace('/', ''), - 'PROP_UC': prop.getAttributeNS(NS_TP, "name-for-bindings").upper(), - 'name' : iface.getAttribute('name'), - 'prop' : prop.getAttribute('name'), - }) - -if __name__ == '__main__': - argv = argv[1:] - Generator(argv[0], argv[1], argv[2], xml.dom.minidom.parse(argv[3]))() diff --git a/tools/glib-signals-marshal-gen.py b/tools/glib-signals-marshal-gen.py deleted file mode 100644 index 0d02c13..0000000 --- a/tools/glib-signals-marshal-gen.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/python - -import sys -import xml.dom.minidom -from string import ascii_letters, digits - - -from libglibcodegen import signal_to_marshal_name, method_to_glue_marshal_name - - -class Generator(object): - - def __init__(self, dom): - self.dom = dom - self.marshallers = {} - - def do_method(self, method): - marshaller = method_to_glue_marshal_name(method, 'PREFIX') - - assert '__' in marshaller - rhs = marshaller.split('__', 1)[1].split('_') - - self.marshallers[marshaller] = rhs - - def do_signal(self, signal): - marshaller = signal_to_marshal_name(signal, 'PREFIX') - - assert '__' in marshaller - rhs = marshaller.split('__', 1)[1].split('_') - - self.marshallers[marshaller] = rhs - - def __call__(self): - methods = self.dom.getElementsByTagName('method') - - for method in methods: - self.do_method(method) - - signals = self.dom.getElementsByTagName('signal') - - for signal in signals: - self.do_signal(signal) - - all = self.marshallers.keys() - all.sort() - for marshaller in all: - rhs = self.marshallers[marshaller] - if not marshaller.startswith('g_cclosure'): - print 'VOID:' + ','.join(rhs) - -if __name__ == '__main__': - argv = sys.argv[1:] - dom = xml.dom.minidom.parse(argv[0]) - - Generator(dom)() diff --git a/tools/identity.xsl b/tools/identity.xsl deleted file mode 100644 index 6630f84..0000000 --- a/tools/identity.xsl +++ /dev/null @@ -1,7 +0,0 @@ -<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> - <xsl:template match="@*|node()"> - <xsl:copy> - <xsl:apply-templates select="@*|node()"/> - </xsl:copy> - </xsl:template> -</xsl:stylesheet> diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py deleted file mode 100644 index 6a9d214..0000000 --- a/tools/libglibcodegen.py +++ /dev/null @@ -1,172 +0,0 @@ -"""Library code for GLib/D-Bus-related code generation. - -The master copy of this library is in the telepathy-glib repository - -please make any changes there. -""" - -# Copyright (C) 2006-2008 Collabora Limited -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -from libtpcodegen import NS_TP, \ - Signature, \ - cmp_by_name, \ - escape_as_identifier, \ - get_by_path, \ - get_descendant_text, \ - get_docstring, \ - xml_escape, \ - get_deprecated - -def dbus_gutils_wincaps_to_uscore(s): - """Bug-for-bug compatible Python port of _dbus_gutils_wincaps_to_uscore - which gets sequences of capital letters wrong in the same way. - (e.g. in Telepathy, SendDTMF -> send_dt_mf) - """ - ret = '' - for c in s: - if c >= 'A' and c <= 'Z': - length = len(ret) - if length > 0 and (length < 2 or ret[length-2] != '_'): - ret += '_' - ret += c.lower() - else: - ret += c - return ret - - -def signal_to_marshal_type(signal): - """ - return a list of strings indicating the marshalling type for this signal. - """ - - mtype=[] - for i in signal.getElementsByTagName("arg"): - name =i.getAttribute("name") - type = i.getAttribute("type") - mtype.append(type_to_gtype(type)[2]) - - return mtype - - -_glib_marshallers = ['VOID', 'BOOLEAN', 'CHAR', 'UCHAR', 'INT', - 'STRING', 'UINT', 'LONG', 'ULONG', 'ENUM', 'FLAGS', 'FLOAT', - 'DOUBLE', 'STRING', 'PARAM', 'BOXED', 'POINTER', 'OBJECT', - 'UINT_POINTER'] - - -def signal_to_marshal_name(signal, prefix): - - mtype = signal_to_marshal_type(signal) - if len(mtype): - name = '_'.join(mtype) - else: - name = 'VOID' - - if name in _glib_marshallers: - return 'g_cclosure_marshal_VOID__' + name - else: - return prefix + '_marshal_VOID__' + name - - -def method_to_glue_marshal_name(method, prefix): - - mtype = [] - for i in method.getElementsByTagName("arg"): - if i.getAttribute("direction") != "out": - type = i.getAttribute("type") - mtype.append(type_to_gtype(type)[2]) - - mtype.append('POINTER') - - name = '_'.join(mtype) - - if name in _glib_marshallers: - return 'g_cclosure_marshal_VOID__' + name - else: - return prefix + '_marshal_VOID__' + name - - -def type_to_gtype(s): - if s == 'y': #byte - return ("guchar ", "G_TYPE_UCHAR","UCHAR", False) - elif s == 'b': #boolean - return ("gboolean ", "G_TYPE_BOOLEAN","BOOLEAN", False) - elif s == 'n': #int16 - return ("gint ", "G_TYPE_INT","INT", False) - elif s == 'q': #uint16 - return ("guint ", "G_TYPE_UINT","UINT", False) - elif s == 'i': #int32 - return ("gint ", "G_TYPE_INT","INT", False) - elif s == 'u': #uint32 - return ("guint ", "G_TYPE_UINT","UINT", False) - elif s == 'x': #int64 - return ("gint64 ", "G_TYPE_INT64","INT64", False) - elif s == 't': #uint64 - return ("guint64 ", "G_TYPE_UINT64","UINT64", False) - elif s == 'd': #double - return ("gdouble ", "G_TYPE_DOUBLE","DOUBLE", False) - elif s == 's': #string - return ("gchar *", "G_TYPE_STRING", "STRING", True) - elif s == 'g': #signature - FIXME - return ("gchar *", "DBUS_TYPE_G_SIGNATURE", "STRING", True) - elif s == 'o': #object path - return ("gchar *", "DBUS_TYPE_G_OBJECT_PATH", "BOXED", True) - elif s == 'v': #variant - return ("GValue *", "G_TYPE_VALUE", "BOXED", True) - elif s == 'as': #array of strings - return ("gchar **", "G_TYPE_STRV", "BOXED", True) - elif s == 'ay': #byte array - return ("GArray *", - "dbus_g_type_get_collection (\"GArray\", G_TYPE_UCHAR)", "BOXED", - True) - elif s == 'au': #uint array - return ("GArray *", "DBUS_TYPE_G_UINT_ARRAY", "BOXED", True) - elif s == 'ai': #int array - return ("GArray *", "DBUS_TYPE_G_INT_ARRAY", "BOXED", True) - elif s == 'ax': #int64 array - return ("GArray *", "DBUS_TYPE_G_INT64_ARRAY", "BOXED", True) - elif s == 'at': #uint64 array - return ("GArray *", "DBUS_TYPE_G_UINT64_ARRAY", "BOXED", True) - elif s == 'ad': #double array - return ("GArray *", "DBUS_TYPE_G_DOUBLE_ARRAY", "BOXED", True) - elif s == 'ab': #boolean array - return ("GArray *", "DBUS_TYPE_G_BOOLEAN_ARRAY", "BOXED", True) - elif s == 'ao': #object path array - return ("GPtrArray *", - 'dbus_g_type_get_collection ("GPtrArray",' - ' DBUS_TYPE_G_OBJECT_PATH)', - "BOXED", True) - elif s == 'a{ss}': #hash table of string to string - return ("GHashTable *", "DBUS_TYPE_G_STRING_STRING_HASHTABLE", "BOXED", False) - elif s[:2] == 'a{': #some arbitrary hash tables - if s[2] not in ('y', 'b', 'n', 'q', 'i', 'u', 's', 'o', 'g'): - raise Exception, "can't index a hashtable off non-basic type " + s - first = type_to_gtype(s[2]) - second = type_to_gtype(s[3:-1]) - return ("GHashTable *", "(dbus_g_type_get_map (\"GHashTable\", " + first[1] + ", " + second[1] + "))", "BOXED", False) - elif s[:2] in ('a(', 'aa'): # array of structs or arrays, recurse - gtype = type_to_gtype(s[1:])[1] - return ("GPtrArray *", "(dbus_g_type_get_collection (\"GPtrArray\", "+gtype+"))", "BOXED", True) - elif s[:1] == '(': #struct - gtype = "(dbus_g_type_get_struct (\"GValueArray\", " - for subsig in Signature(s[1:-1]): - gtype = gtype + type_to_gtype(subsig)[1] + ", " - gtype = gtype + "G_TYPE_INVALID))" - return ("GValueArray *", gtype, "BOXED", True) - - # we just don't know .. - raise Exception, "don't know the GType for " + s diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py deleted file mode 100644 index 837ff2f..0000000 --- a/tools/libtpcodegen.py +++ /dev/null @@ -1,215 +0,0 @@ -"""Library code for language-independent D-Bus-related code generation. - -The master copy of this library is in the telepathy-glib repository - -please make any changes there. -""" - -# Copyright (C) 2006-2008 Collabora Limited -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -from string import ascii_letters, digits - - -NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" - -_ASCII_ALNUM = ascii_letters + digits - - -def cmp_by_name(node1, node2): - return cmp(node1.getAttributeNode("name").nodeValue, - node2.getAttributeNode("name").nodeValue) - - -def escape_as_identifier(identifier): - """Escape the given string to be a valid D-Bus object path or service - name component, using a reversible encoding to ensure uniqueness. - - The reversible encoding is as follows: - - * The empty string becomes '_' - * Otherwise, each non-alphanumeric character is replaced by '_' plus - two lower-case hex digits; the same replacement is carried out on - the first character, if it's a digit - """ - # '' -> '_' - if not identifier: - return '_' - - # A bit of a fast path for strings which are already OK. - # We deliberately omit '_' because, for reversibility, that must also - # be escaped. - if (identifier.strip(_ASCII_ALNUM) == '' and - identifier[0] in ascii_letters): - return identifier - - # The first character may not be a digit - if identifier[0] not in ascii_letters: - ret = ['_%02x' % ord(identifier[0])] - else: - ret = [identifier[0]] - - # Subsequent characters may be digits or ASCII letters - for c in identifier[1:]: - if c in _ASCII_ALNUM: - ret.append(c) - else: - ret.append('_%02x' % ord(c)) - - return ''.join(ret) - - -def get_by_path(element, path): - branches = path.split('/') - branch = branches[0] - - # Is the current branch an attribute, if so, return the attribute value - if branch[0] == '@': - return element.getAttribute(branch[1:]) - - # Find matching children for the branch - children = [] - if branch == '..': - children.append(element.parentNode) - else: - for x in element.childNodes: - if x.localName == branch: - children.append(x) - - ret = [] - # If this is not the last path element, recursively gather results from - # children - if len(branches) > 1: - for x in children: - add = get_by_path(x, '/'.join(branches[1:])) - if isinstance(add, list): - ret += add - else: - return add - else: - ret = children - - return ret - - -def get_docstring(element): - docstring = None - for x in element.childNodes: - if x.namespaceURI == NS_TP and x.localName == 'docstring': - docstring = x - if docstring is not None: - docstring = docstring.toxml().replace('\n', ' ').strip() - if docstring.startswith('<tp:docstring>'): - docstring = docstring[14:].lstrip() - if docstring.endswith('</tp:docstring>'): - docstring = docstring[:-15].rstrip() - if docstring in ('<tp:docstring/>', ''): - docstring = '' - return docstring - -def get_deprecated(element): - text = [] - for x in element.childNodes: - if hasattr(x, 'data'): - text.append(x.data.replace('\n', ' ').strip()) - else: - # This caters for tp:dbus-ref elements, but little else. - if x.childNodes and hasattr(x.childNodes[0], 'data'): - text.append(x.childNodes[0].data.replace('\n', ' ').strip()) - return ' '.join(text) - -def get_descendant_text(element_or_elements): - if not element_or_elements: - return '' - if isinstance(element_or_elements, list): - return ''.join(map(get_descendant_text, element_or_elements)) - parts = [] - for x in element_or_elements.childNodes: - if x.nodeType == x.TEXT_NODE: - parts.append(x.nodeValue) - elif x.nodeType == x.ELEMENT_NODE: - parts.append(get_descendant_text(x)) - else: - pass - return ''.join(parts) - - -class _SignatureIter: - """Iterator over a D-Bus signature. Copied from dbus-python 0.71 so we - can run genginterface in a limited environment with only Python - (like Scratchbox). - """ - def __init__(self, string): - self.remaining = string - - def next(self): - if self.remaining == '': - raise StopIteration - - signature = self.remaining - block_depth = 0 - block_type = None - end = len(signature) - - for marker in range(0, end): - cur_sig = signature[marker] - - if cur_sig == 'a': - pass - elif cur_sig == '{' or cur_sig == '(': - if block_type == None: - block_type = cur_sig - - if block_type == cur_sig: - block_depth = block_depth + 1 - - elif cur_sig == '}': - if block_type == '{': - block_depth = block_depth - 1 - - if block_depth == 0: - end = marker - break - - elif cur_sig == ')': - if block_type == '(': - block_depth = block_depth - 1 - - if block_depth == 0: - end = marker - break - - else: - if block_depth == 0: - end = marker - break - - end = end + 1 - self.remaining = signature[end:] - return Signature(signature[0:end]) - - -class Signature(str): - """A string, iteration over which is by D-Bus single complete types - rather than characters. - """ - def __iter__(self): - return _SignatureIter(self) - - -def xml_escape(s): - s = s.replace('&', '&').replace("'", ''').replace('"', '"') - return s.replace('<', '<').replace('>', '>') diff --git a/tools/telepathy.am b/tools/telepathy.am index 2b6c430..e6defea 100644 --- a/tools/telepathy.am +++ b/tools/telepathy.am @@ -50,7 +50,7 @@ maintainer-prepare-release: $(MAKE) all $(MAKE) distcheck $(MAKE) release-mail - git tag -s @PACKAGE@-@VERSION@ -m @PACKAGE@' '@VERSION@ + cd $(srcdir) && git tag -s @PACKAGE@-@VERSION@ -m @PACKAGE@' '@VERSION@ gpg --detach-sign --armor @PACKAGE@-@VERSION@.tar.gz release-mail: NEWS |