diff options
-rw-r--r-- | docs/reference/Makefile.am | 1 | ||||
-rw-r--r-- | docs/reference/telepathy-glib-docs.sgml | 1 | ||||
-rw-r--r-- | docs/reference/telepathy-glib-sections.txt | 35 | ||||
-rw-r--r-- | telepathy-glib/Makefile.am | 3 | ||||
-rw-r--r-- | telepathy-glib/account-manager.c | 9 | ||||
-rw-r--r-- | telepathy-glib/account.c | 11 | ||||
-rw-r--r-- | telepathy-glib/channel-dispatch-operation.c | 13 | ||||
-rw-r--r-- | telepathy-glib/channel-request.c | 24 | ||||
-rw-r--r-- | telepathy-glib/channel.c | 13 | ||||
-rw-r--r-- | telepathy-glib/connection.c | 13 | ||||
-rw-r--r-- | telepathy-glib/introspection.am | 1 | ||||
-rw-r--r-- | telepathy-glib/proxy.c | 45 | ||||
-rw-r--r-- | telepathy-glib/proxy.h | 4 | ||||
-rw-r--r-- | telepathy-glib/simple-client-factory-internal.h | 82 | ||||
-rw-r--r-- | telepathy-glib/simple-client-factory.c | 1031 | ||||
-rw-r--r-- | telepathy-glib/simple-client-factory.h | 174 | ||||
-rw-r--r-- | telepathy-glib/telepathy-glib.h | 1 |
17 files changed, 1461 insertions, 0 deletions
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 5631bf684..4180c1e79 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -84,6 +84,7 @@ IGNORE_HFILES=\ proxy-internal.h \ proxy-introspectable.h \ signalled-message-internal.h \ + simple-client-factory-internal.h \ util-internal.h # Images to copy into HTML directory. diff --git a/docs/reference/telepathy-glib-docs.sgml b/docs/reference/telepathy-glib-docs.sgml index dd7621064..006e11c45 100644 --- a/docs/reference/telepathy-glib-docs.sgml +++ b/docs/reference/telepathy-glib-docs.sgml @@ -81,6 +81,7 @@ <xi:include href="xml/client-channel-factory.xml"/> <xi:include href="xml/basic-proxy-factory.xml"/> <xi:include href="xml/automatic-proxy-factory.xml"/> + <xi:include href="xml/simple-client-factory.xml"/> <xi:include href="xml/client-message.xml"/> <xi:include href="xml/signalled-message.xml"/> <xi:include href="xml/text-channel.xml"/> diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt index 7e2d85c9c..3f4e698bd 100644 --- a/docs/reference/telepathy-glib-sections.txt +++ b/docs/reference/telepathy-glib-sections.txt @@ -2958,6 +2958,7 @@ TpProxyPendingCall tp_proxy_pending_call_cancel TpProxySignalConnection tp_proxy_signal_connection_disconnect +tp_proxy_get_factory tp_proxy_get_dbus_daemon tp_proxy_get_dbus_connection tp_proxy_get_bus_name @@ -5716,3 +5717,37 @@ TP_TYPE_FILE_TRANSFER_CHANNEL TpFileTransferChannelPrivate tp_file_transfer_channel_get_feature_quark_core </SECTION> + +<SECTION> +<FILE>simple-client-factory</FILE> +<TITLE>simple-client-factory</TITLE> +<INCLUDE>telepathy-glib/telepathy-glib.h</INCLUDE> +TpSimpleClientFactory +TpSimpleClientFactoryClass +tp_simple_client_factory_new +tp_simple_client_factory_get_dbus_daemon +tp_simple_client_factory_ensure_account_manager +tp_simple_client_factory_dup_account_manager_features +tp_simple_client_factory_add_account_manager_features +tp_simple_client_factory_ensure_account +tp_simple_client_factory_dup_account_features +tp_simple_client_factory_add_account_features +tp_simple_client_factory_ensure_connection +tp_simple_client_factory_dup_connection_features +tp_simple_client_factory_add_connection_features +tp_simple_client_factory_ensure_channel +tp_simple_client_factory_dup_channel_features +tp_simple_client_factory_add_channel_features +tp_simple_client_factory_ensure_contact +tp_simple_client_factory_dup_contact_features +tp_simple_client_factory_add_contact_features +<SUBSECTION Standard> +TP_IS_SIMPLE_CLIENT_FACTORY +TP_IS_SIMPLE_CLIENT_FACTORY_CLASS +TP_SIMPLE_CLIENT_FACTORY +TP_SIMPLE_CLIENT_FACTORY_CLASS +TP_SIMPLE_CLIENT_FACTORY_GET_CLASS +TP_TYPE_SIMPLE_CLIENT_FACTORY +tp_simple_client_factory_get_type +TpSimpleClientFactoryPrivate +</SECTION> diff --git a/telepathy-glib/Makefile.am b/telepathy-glib/Makefile.am index b63f03f83..da1309da7 100644 --- a/telepathy-glib/Makefile.am +++ b/telepathy-glib/Makefile.am @@ -91,6 +91,7 @@ our_headers = \ run.h \ signalled-message.h \ simple-approver.h \ + simple-client-factory.h \ simple-handler.h \ simple-observer.h \ simple-password-manager.h \ @@ -239,6 +240,8 @@ libtelepathy_glib_internal_la_SOURCES = \ signalled-message.c \ signalled-message-internal.h \ simple-approver.c \ + simple-client-factory.c \ + simple-client-factory-internal.h \ simple-handler.c \ simple-observer.c \ simple-password-manager.c \ diff --git a/telepathy-glib/account-manager.c b/telepathy-glib/account-manager.c index 1e3802f05..458da97c2 100644 --- a/telepathy-glib/account-manager.c +++ b/telepathy-glib/account-manager.c @@ -35,6 +35,7 @@ #define DEBUG_FLAG TP_DEBUG_ACCOUNTS #include "telepathy-glib/debug-internal.h" #include "telepathy-glib/proxy-internal.h" +#include "telepathy-glib/simple-client-factory-internal.h" #include "telepathy-glib/_gen/tp-cli-account-manager-body.h" @@ -681,6 +682,13 @@ tp_account_manager_init_known_interfaces (void) TpAccountManager * tp_account_manager_new (TpDBusDaemon *bus_daemon) { + return _tp_account_manager_new_with_factory (NULL, bus_daemon); +} + +TpAccountManager * +_tp_account_manager_new_with_factory (TpSimpleClientFactory *factory, + TpDBusDaemon *bus_daemon) +{ TpAccountManager *self; g_return_val_if_fail (TP_IS_DBUS_DAEMON (bus_daemon), NULL); @@ -690,6 +698,7 @@ tp_account_manager_new (TpDBusDaemon *bus_daemon) "dbus-connection", ((TpProxy *) bus_daemon)->dbus_connection, "bus-name", TP_ACCOUNT_MANAGER_BUS_NAME, "object-path", TP_ACCOUNT_MANAGER_OBJECT_PATH, + "factory", factory, NULL)); return self; diff --git a/telepathy-glib/account.c b/telepathy-glib/account.c index b097e1ebc..275dfd2c8 100644 --- a/telepathy-glib/account.c +++ b/telepathy-glib/account.c @@ -36,6 +36,7 @@ #include "telepathy-glib/connection-internal.h" #include "telepathy-glib/debug-internal.h" #include "telepathy-glib/proxy-internal.h" +#include "telepathy-glib/simple-client-factory-internal.h" #include <telepathy-glib/util-internal.h> #include "telepathy-glib/_gen/signals-marshal.h" @@ -1838,6 +1839,15 @@ tp_account_new (TpDBusDaemon *bus_daemon, const gchar *object_path, GError **error) { + return _tp_account_new_with_factory (NULL, bus_daemon, object_path, error); +} + +TpAccount * +_tp_account_new_with_factory (TpSimpleClientFactory *factory, + TpDBusDaemon *bus_daemon, + const gchar *object_path, + GError **error) +{ TpAccount *self; g_return_val_if_fail (TP_IS_DBUS_DAEMON (bus_daemon), NULL); @@ -1852,6 +1862,7 @@ tp_account_new (TpDBusDaemon *bus_daemon, "dbus-connection", ((TpProxy *) bus_daemon)->dbus_connection, "bus-name", TP_ACCOUNT_MANAGER_BUS_NAME, "object-path", object_path, + "factory", factory, NULL)); return self; diff --git a/telepathy-glib/channel-dispatch-operation.c b/telepathy-glib/channel-dispatch-operation.c index 8ccb65260..1c560a5e0 100644 --- a/telepathy-glib/channel-dispatch-operation.c +++ b/telepathy-glib/channel-dispatch-operation.c @@ -36,6 +36,7 @@ #define DEBUG_FLAG TP_DEBUG_DISPATCHER #include "telepathy-glib/dbus-internal.h" #include "telepathy-glib/debug-internal.h" +#include "telepathy-glib/simple-client-factory-internal.h" #include "telepathy-glib/_gen/signals-marshal.h" #include "telepathy-glib/_gen/tp-cli-channel-dispatch-operation-body.h" @@ -912,6 +913,17 @@ tp_channel_dispatch_operation_new (TpDBusDaemon *bus_daemon, GHashTable *immutable_properties, GError **error) { + return _tp_channel_dispatch_operation_new_with_factory (NULL, bus_daemon, + object_path, immutable_properties, error); +} + +TpChannelDispatchOperation * +_tp_channel_dispatch_operation_new_with_factory (TpSimpleClientFactory *factory, + TpDBusDaemon *bus_daemon, + const gchar *object_path, + GHashTable *immutable_properties, + GError **error) +{ TpChannelDispatchOperation *self; gchar *unique_name; @@ -932,6 +944,7 @@ tp_channel_dispatch_operation_new (TpDBusDaemon *bus_daemon, "bus-name", unique_name, "object-path", object_path, "cdo-properties", immutable_properties, + "factory", factory, NULL)); g_free (unique_name); diff --git a/telepathy-glib/channel-request.c b/telepathy-glib/channel-request.c index 693b22100..99b44af5e 100644 --- a/telepathy-glib/channel-request.c +++ b/telepathy-glib/channel-request.c @@ -35,6 +35,7 @@ #define DEBUG_FLAG TP_DEBUG_DISPATCHER #include "telepathy-glib/dbus-internal.h" #include "telepathy-glib/debug-internal.h" +#include "telepathy-glib/simple-client-factory-internal.h" #include "telepathy-glib/_gen/tp-cli-channel-request-body.h" @@ -573,6 +574,17 @@ tp_channel_request_new (TpDBusDaemon *bus_daemon, GHashTable *immutable_properties, GError **error) { + return _tp_channel_request_new_with_factory (NULL, bus_daemon, object_path, + immutable_properties, error); +} + +TpChannelRequest * +_tp_channel_request_new_with_factory (TpSimpleClientFactory *factory, + TpDBusDaemon *bus_daemon, + const gchar *object_path, + GHashTable *immutable_properties, + GError **error) +{ TpChannelRequest *self; gchar *unique_name; @@ -593,6 +605,7 @@ tp_channel_request_new (TpDBusDaemon *bus_daemon, "bus-name", unique_name, "object-path", object_path, "immutable-properties", immutable_properties, + "factory", factory, NULL)); g_free (unique_name); @@ -638,6 +651,17 @@ tp_channel_request_get_immutable_properties (TpChannelRequest *self) return self->priv->immutable_properties; } +void +_tp_channel_request_ensure_immutable_properties (TpChannelRequest *self, + GHashTable *immutable_properties) +{ + if (self->priv->immutable_properties == NULL && immutable_properties != NULL) + { + self->priv->immutable_properties = g_hash_table_ref (immutable_properties); + g_object_notify ((GObject *) self, "immutable-properties"); + } +} + /** * tp_channel_request_get_account: * @self: a #tpchannelrequest diff --git a/telepathy-glib/channel.c b/telepathy-glib/channel.c index a42cd45ba..011456c7b 100644 --- a/telepathy-glib/channel.c +++ b/telepathy-glib/channel.c @@ -32,6 +32,7 @@ #define DEBUG_FLAG TP_DEBUG_CHANNEL #include "telepathy-glib/debug-internal.h" #include "telepathy-glib/proxy-internal.h" +#include "telepathy-glib/simple-client-factory-internal.h" #include "telepathy-glib/_gen/signals-marshal.h" #include "_gen/tp-cli-channel-body.h" @@ -1787,6 +1788,17 @@ tp_channel_new_from_properties (TpConnection *conn, const GHashTable *immutable_properties, GError **error) { + return _tp_channel_new_with_factory (NULL, conn, object_path, + immutable_properties, error); +} + +TpChannel * +_tp_channel_new_with_factory (TpSimpleClientFactory *factory, + TpConnection *conn, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error) +{ TpProxy *conn_proxy = (TpProxy *) conn; TpChannel *ret = NULL; @@ -1809,6 +1821,7 @@ tp_channel_new_from_properties (TpConnection *conn, "object-path", object_path, "handle-type", (guint) TP_UNKNOWN_HANDLE_TYPE, "channel-properties", immutable_properties, + "factory", factory, NULL)); finally: diff --git a/telepathy-glib/connection.c b/telepathy-glib/connection.c index dd49ed344..b11ddcb11 100644 --- a/telepathy-glib/connection.c +++ b/telepathy-glib/connection.c @@ -42,6 +42,7 @@ #include "telepathy-glib/dbus-internal.h" #include "telepathy-glib/debug-internal.h" #include "telepathy-glib/proxy-internal.h" +#include "telepathy-glib/simple-client-factory-internal.h" #include "telepathy-glib/util-internal.h" #include "telepathy-glib/_gen/signals-marshal.h" @@ -1786,6 +1787,17 @@ tp_connection_new (TpDBusDaemon *dbus, const gchar *object_path, GError **error) { + return _tp_connection_new_with_factory (NULL, dbus, bus_name, object_path, + error); +} + +TpConnection * +_tp_connection_new_with_factory (TpSimpleClientFactory *factory, + TpDBusDaemon *dbus, + const gchar *bus_name, + const gchar *object_path, + GError **error) +{ gchar *dup_path = NULL; gchar *dup_name = NULL; gchar *dup_unique_name = NULL; @@ -1831,6 +1843,7 @@ tp_connection_new (TpDBusDaemon *dbus, "dbus-daemon", dbus, "bus-name", bus_name, "object-path", object_path, + "factory", factory, NULL)); finally: diff --git a/telepathy-glib/introspection.am b/telepathy-glib/introspection.am index 4dc6d9e46..de9bbcc94 100644 --- a/telepathy-glib/introspection.am +++ b/telepathy-glib/introspection.am @@ -38,6 +38,7 @@ INTROSPECTION_FILES = \ $(srcdir)/debug.c $(srcdir)/debug.h \ $(srcdir)/base-client.c $(srcdir)/base-client.h \ $(srcdir)/simple-approver.c $(srcdir)/simple-approver.h \ + $(srcdir)/simple-client-factory.c $(srcdir)/simple-client-factory.h \ $(srcdir)/simple-handler.c $(srcdir)/simple-handler.h \ $(srcdir)/simple-observer.c $(srcdir)/simple-observer.h \ $(srcdir)/dbus-properties-mixin.c $(srcdir)/dbus-properties-mixin.h \ diff --git a/telepathy-glib/proxy.c b/telepathy-glib/proxy.c index b64e9190d..f4e648a34 100644 --- a/telepathy-glib/proxy.c +++ b/telepathy-glib/proxy.c @@ -386,6 +386,8 @@ struct _TpProxyPrivate { guint pending_will_announce_calls; gboolean dispose_has_run; + + TpSimpleClientFactory *factory; }; G_DEFINE_TYPE (TpProxy, tp_proxy, G_TYPE_OBJECT) @@ -397,6 +399,7 @@ enum PROP_BUS_NAME, PROP_OBJECT_PATH, PROP_INTERFACES, + PROP_FACTORY, N_PROPS }; @@ -876,6 +879,9 @@ tp_proxy_get_property (GObject *object, g_value_take_boxed (value, g_ptr_array_free (strings, FALSE)); } break; + case PROP_FACTORY: + g_value_set_object (value, self->priv->factory); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -941,6 +947,10 @@ tp_proxy_set_property (GObject *object, g_assert (self->object_path == NULL); self->object_path = g_value_dup_string (value); break; + case PROP_FACTORY: + g_assert (self->priv->factory == NULL); + self->priv->factory = g_value_dup_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -1119,6 +1129,7 @@ tp_proxy_dispose (GObject *object) tp_proxy_invalidate (self, &e); tp_clear_object (&self->dbus_daemon); + tp_clear_object (&self->priv->factory); G_OBJECT_CLASS (tp_proxy_parent_class)->dispose (object); } @@ -1324,6 +1335,20 @@ tp_proxy_class_init (TpProxyClass *klass) param_spec); /** + * TpProxy:factory: + * + * The #TpSimpleClientFactory that has been used to create this proxy, + * or %NULL if proxy was not created through a factory. + */ + param_spec = g_param_spec_object ("factory", "Simple Client Factory", + "The TpSimpleClientFactory used to create this proxy", + TP_TYPE_SIMPLE_CLIENT_FACTORY, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); + g_object_class_install_property (object_class, PROP_FACTORY, + param_spec); + + /** * TpProxy::interface-added: (skip) * @self: the proxy object * @id: the GQuark representing the interface @@ -1366,6 +1391,26 @@ tp_proxy_class_init (TpProxyClass *klass) } /** + * tp_proxy_get_factory: + * @self: a #TpProxy or subclass + * + * <!-- --> + * + * Returns: (transfer none): the same value as #TpProxy:factory property + * + * Since: 0.UNRELEASED + */ +TpSimpleClientFactory * +tp_proxy_get_factory (gpointer self) +{ + TpProxy *proxy = self; + + g_return_val_if_fail (TP_IS_PROXY (self), NULL); + + return proxy->priv->factory; +} + +/** * tp_proxy_get_dbus_daemon: * @self: a #TpProxy or subclass * diff --git a/telepathy-glib/proxy.h b/telepathy-glib/proxy.h index 8b0cdfb3f..c170c4a86 100644 --- a/telepathy-glib/proxy.h +++ b/telepathy-glib/proxy.h @@ -32,6 +32,8 @@ G_BEGIN_DECLS /* Forward declaration of a subclass - from dbus.h */ typedef struct _TpDBusDaemon TpDBusDaemon; +/* Forward declaration - from simple-client-factory.h */ +typedef struct _TpSimpleClientFactory TpSimpleClientFactory; typedef struct _TpProxyPrivate TpProxyPrivate; @@ -154,6 +156,8 @@ GType tp_proxy_get_type (void); gboolean tp_proxy_has_interface_by_id (gpointer self, GQuark iface); gboolean tp_proxy_has_interface (gpointer self, const gchar *iface); +TpSimpleClientFactory *tp_proxy_get_factory (gpointer self); + TpDBusDaemon *tp_proxy_get_dbus_daemon (gpointer self); DBusGConnection *tp_proxy_get_dbus_connection (gpointer self); diff --git a/telepathy-glib/simple-client-factory-internal.h b/telepathy-glib/simple-client-factory-internal.h new file mode 100644 index 000000000..8facf8940 --- /dev/null +++ b/telepathy-glib/simple-client-factory-internal.h @@ -0,0 +1,82 @@ +/* + * Simple client factory internal + * + * Copyright © 2011 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 + */ + +#ifndef __TP_SIMPLE_CLIENT_FACTORY_INTERNAL_H__ +#define __TP_SIMPLE_CLIENT_FACTORY_INTERNAL_H__ + +#include <telepathy-glib/simple-client-factory.h> + +G_BEGIN_DECLS + +void _tp_simple_client_factory_insert_proxy (TpSimpleClientFactory *self, + gpointer proxy); + +TpChannelRequest *_tp_simple_client_factory_ensure_channel_request ( + TpSimpleClientFactory *self, + const gchar *object_path, + GHashTable *immutable_properties, + GError **error); + +TpChannelDispatchOperation * +_tp_simple_client_factory_ensure_channel_dispatch_operation ( + TpSimpleClientFactory *self, + const gchar *object_path, + GHashTable *immutable_properties, + GError **error); + +TpAccountManager *_tp_account_manager_new_with_factory ( + TpSimpleClientFactory *factory, TpDBusDaemon *bus_daemon); + +TpAccount *_tp_account_new_with_factory (TpSimpleClientFactory *factory, + TpDBusDaemon *bus_daemon, + const gchar *object_path, + GError **error); + +TpConnection *_tp_connection_new_with_factory (TpSimpleClientFactory *factory, + TpDBusDaemon *dbus, + const gchar *bus_name, + const gchar *object_path, + GError **error); + +TpChannel *_tp_channel_new_with_factory (TpSimpleClientFactory *factory, + TpConnection *conn, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error); + +TpChannelRequest *_tp_channel_request_new_with_factory ( + TpSimpleClientFactory *factory, + TpDBusDaemon *bus_daemon, + const gchar *object_path, + GHashTable *immutable_properties, + GError **error); +void _tp_channel_request_ensure_immutable_properties (TpChannelRequest *self, + GHashTable *immutable_properties); + +TpChannelDispatchOperation *_tp_channel_dispatch_operation_new_with_factory ( + TpSimpleClientFactory *factory, + TpDBusDaemon *bus_daemon, + const gchar *object_path, + GHashTable *immutable_properties, + GError **error); + +G_END_DECLS + +#endif diff --git a/telepathy-glib/simple-client-factory.c b/telepathy-glib/simple-client-factory.c new file mode 100644 index 000000000..4bf6b1eab --- /dev/null +++ b/telepathy-glib/simple-client-factory.c @@ -0,0 +1,1031 @@ +/* + * Simple client factory + * + * Copyright © 2011 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 + */ + +/** + * SECTION:simple-client-factory + * @title: TpSimpleClientFactory + * @short_description: simple client factory + * @see_also: #TpAutomaticClientFactory + * + * This factory constructs various #TpProxy subclasses as well as #TpContact. It + * guarantees uniqueness of those objects. It is also used to describe the + * features desired for each of those object classes. + * + * Note that the factory will not prepare the desired features, it is caller's + * responsibility to do so. By default only core features are requested. + * + * Currently supported classes are #TpAccountManager, #TpAccount, #TpConnection, + * #TpChannel and #TpContact. Those objects should always be acquired through a + * factory and not created directly. + * + * One can subclass #TpSimpleClientFactory and override some of its virtual + * methods to construct more specialized objects. See #TpAutomaticClientFactory + * for more specialized factory. + * + * Since: 0.UNRELEASED + */ + +/** + * TpSimpleClientFactory: + * + * Data structure representing a #TpSimpleClientFactory + * + * Since: 0.UNRELEASED + */ + +/** + * TpSimpleClientFactoryClass: + * @parent_class: the parent class + * + * The class of a #TpSimpleClientFactory. + * + * Since: 0.UNRELEASED + */ + +/** + * TpSimpleClientFactoryClass: + * @parent_class: the parent + * @create_account_manager: virtual method used to create a #TpAccountManager; + * see tp_simple_client_factory_ensure_account_manager() + * @dup_account_manager_features: virtual method returning account manager + * features that have to be prepared on newly created account manager; + * see tp_simple_client_factory_dup_account_features() + * @create_account: virtual method used to create a #TpAccount; + * see tp_simple_client_factory_ensure_account() + * @dup_account_features: virtual method returning account features that + * have to be prepared on newly created accounts; + * see tp_simple_client_factory_dup_account_features() + * @create_connection: virtual method used to create a #TpConnection; + * see tp_simple_client_factory_ensure_connection() + * @dup_connection_features: virtual method returning connection features that + * have to be prepared on newly created connections; + * see tp_simple_client_factory_dup_connection_features() + * @create_channel: virtual method used to create a #TpChannel; + * see tp_simple_client_factory_ensure_channel() + * @dup_channel_features: virtual method returning connection features that + * have to be prepared on newly created channel; + * see tp_simple_client_factory_dup_channel_features() + * @create_contact: virtual method used to create a #TpContact; + * see tp_simple_client_factory_ensure_contact() + * @dup_contact_features: virtual method returning contact features that + * have to be prepared on newly created contacts; + * see tp_simple_client_factory_dup_contact_features() + * + * V-Table for #TpSimpleClientFactory sub-classing + * + * Since: 0.UNRELEASED + */ + +#include "telepathy-glib/simple-client-factory.h" + +#include <telepathy-glib/util.h> + +#define DEBUG_FLAG TP_DEBUG_CLIENT +#include "telepathy-glib/connection-internal.h" +#include "telepathy-glib/contact-internal.h" +#include "telepathy-glib/debug-internal.h" +#include "telepathy-glib/simple-client-factory-internal.h" +#include "telepathy-glib/util-internal.h" + +struct _TpSimpleClientFactoryPrivate +{ + TpDBusDaemon *dbus; + /* Owned object-path -> weakref to TpProxy */ + GHashTable *proxy_cache; + GArray *desired_account_manager_features; + GArray *desired_account_features; + GArray *desired_connection_features; + GArray *desired_channel_features; + GArray *desired_contact_features; +}; + +enum +{ + PROP_DBUS_DAEMON = 1, + N_PROPS +}; + +G_DEFINE_TYPE (TpSimpleClientFactory, tp_simple_client_factory, G_TYPE_OBJECT) + +static void +proxy_invalidated_cb (TpProxy *proxy, + guint domain, + gint code, + gchar *message, + TpSimpleClientFactory *self) +{ + g_hash_table_remove (self->priv->proxy_cache, + tp_proxy_get_object_path (proxy)); +} + +static void +insert_proxy (TpSimpleClientFactory *self, + gpointer proxy) +{ + if (proxy == NULL) + return; + + g_hash_table_insert (self->priv->proxy_cache, + (gpointer) tp_proxy_get_object_path (proxy), proxy); + + /* This assume that invalidated signal is emitted from TpProxy dispose. May + * change in a future API break? */ + tp_g_signal_connect_object (proxy, "invalidated", + G_CALLBACK (proxy_invalidated_cb), self, 0); +} + +static gpointer +lookup_proxy (TpSimpleClientFactory *self, + const gchar *object_path) +{ + return g_hash_table_lookup (self->priv->proxy_cache, object_path); +} + +void +_tp_simple_client_factory_insert_proxy (TpSimpleClientFactory *self, + gpointer proxy) +{ + g_return_if_fail (lookup_proxy (self, + tp_proxy_get_object_path (proxy)) == NULL); + + insert_proxy (self, proxy); +} + +static TpAccountManager * +create_account_manager_impl (TpSimpleClientFactory *self) +{ + return _tp_account_manager_new_with_factory (self, self->priv->dbus); +} + +static GArray * +dup_account_manager_features_impl (TpSimpleClientFactory *self, + TpAccountManager *manager) +{ + return _tp_quark_array_copy ( + (GQuark *) self->priv->desired_account_manager_features->data); +} + +static TpAccount * +create_account_impl (TpSimpleClientFactory *self, + const gchar *object_path, + const GHashTable *immutable_properties G_GNUC_UNUSED, + GError **error) +{ + return _tp_account_new_with_factory (self, self->priv->dbus, object_path, + error); +} + +static GArray * +dup_account_features_impl (TpSimpleClientFactory *self, + TpAccount *account) +{ + return _tp_quark_array_copy ( + (GQuark *) self->priv->desired_account_features->data); +} + +static TpConnection * +create_connection_impl (TpSimpleClientFactory *self, + const gchar *object_path, + const GHashTable *immutable_properties G_GNUC_UNUSED, + GError **error) +{ + return _tp_connection_new_with_factory (self, self->priv->dbus, NULL, + object_path, error); +} + +static GArray * +dup_connection_features_impl (TpSimpleClientFactory *self, + TpConnection *connection) +{ + return _tp_quark_array_copy ( + (GQuark *) self->priv->desired_connection_features->data); +} + +static TpChannel * +create_channel_impl (TpSimpleClientFactory *self, + TpConnection *conn, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error) +{ + return _tp_channel_new_with_factory (self, conn, object_path, + immutable_properties, error); +} + +static GArray * +dup_channel_features_impl (TpSimpleClientFactory *self, + TpChannel *channel) +{ + return _tp_quark_array_copy ( + (GQuark *) self->priv->desired_channel_features->data); +} + +static TpContact * +create_contact_impl (TpSimpleClientFactory *self, + TpConnection *connection, + TpHandle handle, + const gchar *identifier) +{ + return _tp_contact_new (connection, handle, identifier); +} + +static GArray * +dup_contact_features_impl (TpSimpleClientFactory *self, + TpConnection *connection) +{ + GArray *array; + + array = g_array_sized_new (FALSE, FALSE, sizeof (TpContactFeature), + self->priv->desired_contact_features->len); + g_array_append_vals (array, self->priv->desired_contact_features->data, + self->priv->desired_contact_features->len); + + return array; +} + +static void +tp_simple_client_factory_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TpSimpleClientFactory *self = (TpSimpleClientFactory *) object; + + switch (property_id) + { + case PROP_DBUS_DAEMON: + g_value_set_object (value, self->priv->dbus); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tp_simple_client_factory_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + TpSimpleClientFactory *self = (TpSimpleClientFactory *) object; + + switch (property_id) + { + case PROP_DBUS_DAEMON: + g_assert (self->priv->dbus == NULL); /* construct only */ + self->priv->dbus = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tp_simple_client_factory_constructed (GObject *object) +{ + TpSimpleClientFactory *self = (TpSimpleClientFactory *) object; + + g_assert (TP_IS_DBUS_DAEMON (self->priv->dbus)); + + G_OBJECT_CLASS (tp_simple_client_factory_parent_class)->constructed (object); +} + +static void +tp_simple_client_factory_finalize (GObject *object) +{ + TpSimpleClientFactory *self = (TpSimpleClientFactory *) object; + + g_clear_object (&self->priv->dbus); + tp_clear_pointer (&self->priv->proxy_cache, g_hash_table_unref); + tp_clear_pointer (&self->priv->desired_account_manager_features, + g_array_unref); + tp_clear_pointer (&self->priv->desired_account_features, g_array_unref); + tp_clear_pointer (&self->priv->desired_connection_features, g_array_unref); + tp_clear_pointer (&self->priv->desired_channel_features, g_array_unref); + tp_clear_pointer (&self->priv->desired_contact_features, g_array_unref); + + G_OBJECT_CLASS (tp_simple_client_factory_parent_class)->finalize (object); +} + +static void +tp_simple_client_factory_init (TpSimpleClientFactory *self) +{ + GQuark feature; + + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TYPE_SIMPLE_CLIENT_FACTORY, + TpSimpleClientFactoryPrivate); + + self->priv->proxy_cache = g_hash_table_new (g_str_hash, g_str_equal); + + self->priv->desired_account_manager_features = g_array_new (TRUE, FALSE, + sizeof (GQuark)); + feature = TP_ACCOUNT_MANAGER_FEATURE_CORE; + g_array_append_val (self->priv->desired_account_manager_features, feature); + + self->priv->desired_account_features = g_array_new (TRUE, FALSE, + sizeof (GQuark)); + feature = TP_ACCOUNT_FEATURE_CORE; + g_array_append_val (self->priv->desired_account_features, feature); + + self->priv->desired_connection_features = g_array_new (TRUE, FALSE, + sizeof (GQuark)); + feature = TP_CONNECTION_FEATURE_CORE; + g_array_append_val (self->priv->desired_connection_features, feature); + + self->priv->desired_channel_features = g_array_new (TRUE, FALSE, + sizeof (GQuark)); + feature = TP_CHANNEL_FEATURE_CORE; + g_array_append_val (self->priv->desired_channel_features, feature); + + self->priv->desired_contact_features = g_array_new (FALSE, FALSE, + sizeof (TpContactFeature)); +} + +static void +tp_simple_client_factory_class_init (TpSimpleClientFactoryClass *klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + GParamSpec *param_spec; + + g_type_class_add_private (klass, sizeof (TpSimpleClientFactoryPrivate)); + + object_class->get_property = tp_simple_client_factory_get_property; + object_class->set_property = tp_simple_client_factory_set_property; + object_class->constructed = tp_simple_client_factory_constructed; + object_class->finalize = tp_simple_client_factory_finalize; + + klass->create_account_manager = create_account_manager_impl; + klass->dup_account_manager_features = dup_account_manager_features_impl; + klass->create_account = create_account_impl; + klass->dup_account_features = dup_account_features_impl; + klass->create_connection = create_connection_impl; + klass->dup_connection_features = dup_connection_features_impl; + klass->create_channel = create_channel_impl; + klass->dup_channel_features = dup_channel_features_impl; + klass->create_contact = create_contact_impl; + klass->dup_contact_features = dup_contact_features_impl; + + /** + * TpSimpleClientFactory:dbus-daemon: + * + * The D-Bus daemon for this object. + */ + param_spec = g_param_spec_object ("dbus-daemon", "D-Bus daemon", + "The D-Bus daemon used by this object", + TP_TYPE_DBUS_DAEMON, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | + G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK); + g_object_class_install_property (object_class, PROP_DBUS_DAEMON, + param_spec); +} + +/** + * tp_simple_client_factory_new: + * @dbus: a #TpDBusDaemon + * + * Convenient function to create a new #TpSimpleClientFactory instance. + * + * Returns: a new #TpSimpleClientFactory + * + * Since: 0.UNRELEASED + */ +TpSimpleClientFactory * +tp_simple_client_factory_new (TpDBusDaemon *dbus) +{ + return g_object_new (TP_TYPE_SIMPLE_CLIENT_FACTORY, + "dbus-daemon", dbus, + NULL); +} + +/** + * tp_simple_client_factory_get_dbus_daemon: + * @self: a #TpSimpleClientFactory object + * + * <!-- --> + * + * Returns: (transfer none): same value as #TpSimpleClientFactory:dbus-daemon + * property + * + * Since: 0.UNRELEASED + */ +TpDBusDaemon * +tp_simple_client_factory_get_dbus_daemon (TpSimpleClientFactory *self) +{ + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + + return self->priv->dbus; +} + +/** + * tp_simple_client_factory_ensure_account_manager: + * @self: a #TpSimpleClientFactory object + * + * The returned #TpAccountManager is cached; the same #TpAccountManager object + * will be returned by this function repeatedly, as long as at least one + * reference exists. Note that the returned #TpAccountManager is not guaranteed + * to be ready on return. + * + * Returns: (transfer full): a reference on a new or existing #TpAccountManager; + * see tp_account_manager_new(). + * + * Since: 0.UNRELEASED + */ +TpAccountManager * +tp_simple_client_factory_ensure_account_manager (TpSimpleClientFactory *self) +{ + TpAccountManager *manager; + + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + + manager = lookup_proxy (self, TP_ACCOUNT_MANAGER_OBJECT_PATH); + if (manager != NULL) + return g_object_ref (manager); + + manager = TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->create_account_manager ( + self); + insert_proxy (self, manager); + + return manager; +} + +/** + * tp_simple_client_factory_dup_account_manager_features: + * @self: a #TpSimpleClientFactory object + * @manager: a #TpAccountManager + * + * Return a zero terminated #GArray containing the #TpAccountManager features + * that should be prepared on @manager. + * + * Returns: (transfer full) (element-type GLib.Quark): a newly allocated + * #GArray + * + * Since: 0.UNRELEASED + */ +GArray * +tp_simple_client_factory_dup_account_manager_features ( + TpSimpleClientFactory *self, + TpAccountManager *manager) +{ + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (TP_IS_ACCOUNT_MANAGER (manager), NULL); + g_return_val_if_fail (tp_proxy_get_factory (manager) == self, NULL); + + return TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->dup_account_manager_features + (self, manager); +} + +/** + * tp_simple_client_factory_add_account_manager_features: + * @self: a #TpSimpleClientFactory object + * @features: (transfer none) (array zero-terminated=1) (allow-none): an array + * of desired features, ending with 0; %NULL is equivalent to an array + * containing only 0 + * + * Add @features to the desired features to be prepared on #TpAccountManager + * object. Those features will be added to the features already returned be + * tp_simple_client_factory_dup_account_manager_features(). + * + * It is not necessary to add %TP_ACCOUNT_MANAGER_FEATURE_CORE as it is already + * included by default. + * + * Note that existing proxy won't be upgraded unless done manually using + * tp_proxy_prepare_async(). + * + * Since: 0.UNRELEASED + */ +void +tp_simple_client_factory_add_account_manager_features ( + TpSimpleClientFactory *self, + const GQuark *features) +{ + g_return_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self)); + + _tp_quark_array_merge (self->priv->desired_account_manager_features, features, + -1); +} + +/** + * tp_simple_client_factory_ensure_account: + * @self: a #TpSimpleClientFactory object + * @object_path: the non-NULL object path of this account + * @immutable_properties: (transfer none) (element-type utf8 GObject.Value): + * the immutable properties of the account. Currently unused. + * @error: Used to raise an error if @object_path is not valid + * + * The returned #TpAccount is cached; the same #TpAccount object + * will be returned by this function repeatedly, as long as at least one + * reference exists. Note that the returned #TpAccount is not guaranteed + * to be ready on return. + * + * Caller is responsible to call tp_proxy_prepare_async() with the desired + * features as given by tp_simple_client_factory_dup_account_features(). + * + * Returns: (transfer full): a reference on a new or existing #TpAccount; + * see tp_account_new(). + * + * Since: 0.UNRELEASED + */ +TpAccount * +tp_simple_client_factory_ensure_account (TpSimpleClientFactory *self, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error) +{ + TpAccount *account; + + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (g_variant_is_object_path (object_path), NULL); + + account = lookup_proxy (self, object_path); + if (account != NULL) + return g_object_ref (account); + + account = TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->create_account (self, + object_path, immutable_properties, error); + insert_proxy (self, account); + + return account; +} + +/** + * tp_simple_client_factory_dup_account_features: + * @self: a #TpSimpleClientFactory object + * @account: a #TpAccount + * + * Return a zero terminated #GArray containing the #TpAccount features that + * should be prepared on @account. + * + * Returns: (transfer full) (element-type GLib.Quark): a newly allocated + * #GArray + * + * Since: 0.UNRELEASED + */ +GArray * +tp_simple_client_factory_dup_account_features (TpSimpleClientFactory *self, + TpAccount *account) +{ + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL); + g_return_val_if_fail (tp_proxy_get_factory (account) == self, NULL); + + return TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->dup_account_features (self, + account); +} + +/** + * tp_simple_client_factory_add_account_features: + * @self: a #TpSimpleClientFactory object + * @features: (transfer none) (array zero-terminated=1) (allow-none): an array + * of desired features, ending with 0; %NULL is equivalent to an array + * containing only 0 + * + * Add @features to the desired features to be prepared on #TpAccount + * objects. Those features will be added to the features already returned be + * tp_simple_client_factory_dup_account_features(). + * + * It is not necessary to add %TP_ACCOUNT_FEATURE_CORE as it is already + * included by default. + * + * Note that existing proxies won't be upgraded unless done manually using + * tp_proxy_prepare_async(). + * + * Since: 0.UNRELEASED + */ +void +tp_simple_client_factory_add_account_features ( + TpSimpleClientFactory *self, + const GQuark *features) +{ + g_return_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self)); + + _tp_quark_array_merge (self->priv->desired_account_features, features, -1); +} + +/** + * tp_simple_client_factory_ensure_connection: + * @self: a #TpSimpleClientFactory object + * @object_path: the non-NULL object path of this connection + * @immutable_properties: (transfer none) (element-type utf8 GObject.Value): + * the immutable properties of the connection. Currently unused. + * @error: Used to raise an error if @object_path is not valid + * + * The returned #TpConnection is cached; the same #TpConnection object + * will be returned by this function repeatedly, as long as at least one + * reference exists. Note that the returned #TpConnection is not guaranteed + * to be ready on return. + * + * Caller is responsible to call tp_proxy_prepare_async() with the desired + * features as given by tp_simple_client_factory_dup_connection_features(). + * + * Returns: (transfer full): a reference on a new or existing #TpConnection; + * see tp_connection_new(). + * + * Since: 0.UNRELEASED + */ +TpConnection * +tp_simple_client_factory_ensure_connection (TpSimpleClientFactory *self, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error) +{ + TpConnection *connection; + + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (g_variant_is_object_path (object_path), NULL); + + connection = lookup_proxy (self, object_path); + if (connection != NULL) + return g_object_ref (connection); + + connection = TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->create_connection ( + self, object_path, immutable_properties, error); + insert_proxy (self, connection); + + return connection; +} + +/** + * tp_simple_client_factory_dup_connection_features: + * @self: a #TpSimpleClientFactory object + * @connection: a #TpConnection + * + * Return a zero terminated #GArray containing the #TpConnection features that + * should be prepared on @connection. + * + * Returns: (transfer full) (element-type GLib.Quark): a newly allocated + * #GArray + * + * Since: 0.UNRELEASED + */ +GArray * +tp_simple_client_factory_dup_connection_features (TpSimpleClientFactory *self, + TpConnection *connection) +{ + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (TP_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (tp_proxy_get_factory (connection) == self, NULL); + + return TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->dup_connection_features ( + self, connection); +} + +/** + * tp_simple_client_factory_add_connection_features: + * @self: a #TpSimpleClientFactory object + * @features: (transfer none) (array zero-terminated=1) (allow-none): an array + * of desired features, ending with 0; %NULL is equivalent to an array + * containing only 0 + * + * Add @features to the desired features to be prepared on #TpConnection + * objects. Those features will be added to the features already returned be + * tp_simple_client_factory_dup_connection_features(). + * + * It is not necessary to add %TP_CONNECTION_FEATURE_CORE as it is already + * included by default. + * + * Note that existing proxies won't be upgraded unless done manually using + * tp_proxy_prepare_async(). + * + * Since: 0.UNRELEASED + */ +void +tp_simple_client_factory_add_connection_features ( + TpSimpleClientFactory *self, + const GQuark *features) +{ + g_return_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self)); + + _tp_quark_array_merge (self->priv->desired_connection_features, features, -1); +} + +/** + * tp_simple_client_factory_ensure_channel: + * @self: a #TpSimpleClientFactory object + * @connection: a #TpConnection + * @object_path: the non-NULL object path of this connection + * @immutable_properties: (transfer none) (element-type utf8 GObject.Value): + * the immutable properties of the channel + * @error: Used to raise an error if @object_path is not valid + * + * The returned #TpChannel is cached; the same #TpChannel object + * will be returned by this function repeatedly, as long as at least one + * reference exists. Note that the returned #TpChannel is not guaranteed + * to be ready on return. + * + * Caller is responsible to call tp_proxy_prepare_async() with the desired + * features as given by tp_simple_client_factory_dup_channel_features(). + * + * Returns: (transfer full): a reference on a new or existing #TpChannel; + * see tp_channel_new_with_properties(). + * + * Since: 0.UNRELEASED + */ +TpChannel * +tp_simple_client_factory_ensure_channel (TpSimpleClientFactory *self, + TpConnection *connection, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error) +{ + TpChannel *channel; + + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (TP_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (tp_proxy_get_factory (connection) == self, NULL); + g_return_val_if_fail (g_variant_is_object_path (object_path), NULL); + + channel = lookup_proxy (self, object_path); + if (channel != NULL) + return g_object_ref (channel); + + channel = TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->create_channel (self, + connection, object_path, immutable_properties, error); + insert_proxy (self, channel); + + return channel; +} + +/** + * tp_simple_client_factory_dup_channel_features: + * @self: a #TpSimpleClientFactory object + * @channel: a #TpChannel + * + * Return a zero terminated #GArray containing the #TpChannel features that + * should be prepared on @channel. + * + * Returns: (transfer full) (element-type GLib.Quark): a newly allocated + * #GArray + * + * Since: 0.UNRELEASED + */ +GArray * +tp_simple_client_factory_dup_channel_features (TpSimpleClientFactory *self, + TpChannel *channel) +{ + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL); + g_return_val_if_fail (tp_proxy_get_factory (channel) == self, NULL); + + return TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->dup_channel_features ( + self, channel); +} + +/** + * tp_simple_client_factory_add_channel_features: + * @self: a #TpSimpleClientFactory object + * @features: (transfer none) (array zero-terminated=1) (allow-none): an array + * of desired features, ending with 0; %NULL is equivalent to an array + * containing only 0 + * + * Add @features to the desired features to be prepared on #TpChannel + * objects. Those features will be added to the features already returned be + * tp_simple_client_factory_dup_channel_features(). + * + * It is not necessary to add %TP_CHANNEL_FEATURE_CORE as it is already + * included by default. + * + * Note that existing proxies won't be upgraded unless done manually using + * tp_proxy_prepare_async(). + * + * Since: 0.UNRELEASED + */ +void +tp_simple_client_factory_add_channel_features ( + TpSimpleClientFactory *self, + const GQuark *features) +{ + g_return_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self)); + + _tp_quark_array_merge (self->priv->desired_channel_features, features, -1); +} + +/** + * tp_simple_client_factory_ensure_contact: + * @self: a #TpSimpleClientFactory object + * @connection: a #TpConnection + * @handle: a #TpHandle + * @identifier: a string representing the contact's identifier + * + * The returned #TpContact is cached; the same #TpContact object + * will be returned by this function repeatedly, as long as at least one + * reference exists. Note that the returned #TpContact is not guaranteed + * to be ready on return. + * + * Caller is responsible to call tp_connection_upgrade_contacts() with the + * desired features as given by tp_simple_client_factory_dup_contact_features(). + * + * For this to work properly tp_connection_has_immortal_handles() has to return + * %TRUE for @connection. + * + * Returns: (transfer full): a reference on a new or existing #TpContact. + * + * Since: 0.UNRELEASED + */ +TpContact * +tp_simple_client_factory_ensure_contact (TpSimpleClientFactory *self, + TpConnection *connection, + TpHandle handle, + const gchar *identifier) +{ + TpContact *contact; + + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (TP_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (tp_proxy_get_factory (connection) == self, NULL); + g_return_val_if_fail (tp_connection_has_immortal_handles (connection), NULL); + g_return_val_if_fail (handle != 0, NULL); + g_return_val_if_fail (identifier != NULL, NULL); + + contact = _tp_connection_lookup_contact (connection, handle); + if (contact != NULL) + return g_object_ref (contact); + + contact = TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->create_contact (self, + connection, handle, identifier); + _tp_connection_add_contact (connection, handle, contact); + + return contact; +} + +/** + * tp_simple_client_factory_dup_contact_features: + * @self: a #TpSimpleClientFactory object + * @connection: a #TpConnection + * + * Return a #GArray containing the #TpContactFeature that should be prepared on + * all contacts of @connection. + * + * Returns: (transfer full) (element-type TelepathyGLib.ContactFeature): a newly + * allocated #GArray + * + * Since: 0.UNRELEASED + */ +GArray * +tp_simple_client_factory_dup_contact_features (TpSimpleClientFactory *self, + TpConnection *connection) +{ + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (TP_IS_CONNECTION (connection), NULL); + g_return_val_if_fail (tp_proxy_get_factory (connection) == self, NULL); + + return TP_SIMPLE_CLIENT_FACTORY_GET_CLASS (self)->dup_contact_features ( + self, connection); +} + +/** + * tp_simple_client_factory_add_contact_features: + * @self: a #TpSimpleClientFactory object + * @n_features: The number of features in @features (may be 0) + * @features: (array length=n_features) (allow-none): an array of desired + * features (may be %NULL if @n_features is 0) + * + * Add @features to the desired features to be prepared on #TpContact + * objects. Those features will be added to the features already returned be + * tp_simple_client_factory_dup_contact_features(). + * + * Note that existing contacts won't be upgraded unless done manually using + * tp_connection_upgrade_contacts(). + * + * Since: 0.UNRELEASED + */ +void +tp_simple_client_factory_add_contact_features (TpSimpleClientFactory *self, + guint n_features, const TpContactFeature *features) +{ + guint i; + + g_return_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self)); + + /* Add features into desired_contact_features avoiding dups */ + for (i = 0; i < n_features; i++) + { + guint j; + gboolean found = FALSE; + + for (j = 0; j < self->priv->desired_contact_features->len; j++) + { + if (features[i] == g_array_index ( + self->priv->desired_contact_features, TpContactFeature, j)) + { + found = TRUE; + break; + } + } + + if (!found) + g_array_append_val (self->priv->desired_contact_features, features[i]); + } +} + +/** + * tp_simple_client_factory_ensure_channel_request: + * @self: a #TpSimpleClientFactory object + * @object_path: the non-NULL object path of this connection + * @immutable_properties: (transfer none) (element-type utf8 GObject.Value): + * the immutable properties of the channel request + * @error: Used to raise an error if @object_path is not valid + * + * The returned #TpChannelRequest is cached; the same #TpChannelRequest object + * will be returned by this function repeatedly, as long as at least one + * reference exists. Note that the returned #TpChannelRequest is not guaranteed + * to be ready on return. + * + * Caller is responsible to call tp_proxy_prepare_async(). + * + * Returns: (transfer full): a reference on a new or existing #TpChannelRequest; + * see tp_channel_request_new(). + * + * Since: 0.UNRELEASED + */ +TpChannelRequest * +_tp_simple_client_factory_ensure_channel_request (TpSimpleClientFactory *self, + const gchar *object_path, + GHashTable *immutable_properties, + GError **error) +{ + TpChannelRequest *request; + + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (g_variant_is_object_path (object_path), NULL); + + request = lookup_proxy (self, object_path); + if (request != NULL) + { + /* A common usage is request_and_handle, in that case EnsureChannel + * returns only the object-path of the ChannelRequest but not properties. + * The TpChannelRequest will be created with no properties, then when + * handling we get the properties and we reuse the same TpChannelRequest + * object, and we can give it the immutable-properties. */ + _tp_channel_request_ensure_immutable_properties (request, + immutable_properties); + return g_object_ref (request); + } + + request = _tp_channel_request_new_with_factory (self, self->priv->dbus, + object_path, immutable_properties, error); + insert_proxy (self, request); + + return request; +} + +/** + * tp_simple_client_factory_ensure_channel_dispatch_operation: + * @self: a #TpSimpleClientFactory object + * @object_path: the non-NULL object path of this connection + * @immutable_properties: (transfer none) (element-type utf8 GObject.Value): + * the immutable properties of the channel dispatch operation + * @error: Used to raise an error if @object_path is not valid + * + * The returned #TpChannelDispatchOperation is cached; the same + * #TpChannelDispatchOperation object will be returned by this function + * repeatedly, as long as at least one reference exists. Note that the returned + * #TpChannelDispatchOperation is not guaranteed to be ready on return. + * + * Caller is responsible to call tp_proxy_prepare_async(). + * + * Returns: (transfer full): a reference on a new or existing + * #TpChannelDispatchOperation; see tp_channel_dispatch_operation_new(). + * + * Since: 0.UNRELEASED + */ +TpChannelDispatchOperation * +_tp_simple_client_factory_ensure_channel_dispatch_operation ( + TpSimpleClientFactory *self, + const gchar *object_path, + GHashTable *immutable_properties, + GError **error) +{ + TpChannelDispatchOperation *dispatch; + + g_return_val_if_fail (TP_IS_SIMPLE_CLIENT_FACTORY (self), NULL); + g_return_val_if_fail (g_variant_is_object_path (object_path), NULL); + + dispatch = lookup_proxy (self, object_path); + if (dispatch != NULL) + return g_object_ref (dispatch); + + dispatch = _tp_channel_dispatch_operation_new_with_factory (self, + self->priv->dbus, object_path, immutable_properties, error); + insert_proxy (self, dispatch); + + return dispatch; +} diff --git a/telepathy-glib/simple-client-factory.h b/telepathy-glib/simple-client-factory.h new file mode 100644 index 000000000..36cb5c830 --- /dev/null +++ b/telepathy-glib/simple-client-factory.h @@ -0,0 +1,174 @@ +/* + * Simple client factory + * + * Copyright © 2011 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 + */ + +#ifndef __TP_SIMPLE_CLIENT_FACTORY_H__ +#define __TP_SIMPLE_CLIENT_FACTORY_H__ + +#include <telepathy-glib/account-manager.h> +#include <telepathy-glib/account.h> +#include <telepathy-glib/channel.h> +#include <telepathy-glib/channel-dispatch-operation.h> +#include <telepathy-glib/channel-request.h> +#include <telepathy-glib/connection.h> +#include <telepathy-glib/contact.h> +#include <telepathy-glib/dbus-daemon.h> + +G_BEGIN_DECLS + +/* TpSimpleClientFactory is typedef'd in proxy.h */ +typedef struct _TpSimpleClientFactoryPrivate TpSimpleClientFactoryPrivate; +typedef struct _TpSimpleClientFactoryClass TpSimpleClientFactoryClass; + +struct _TpSimpleClientFactoryClass { + /*<public>*/ + GObjectClass parent_class; + + /* TpAccountManager */ + TpAccountManager * (*create_account_manager) (TpSimpleClientFactory *self); + GArray * (*dup_account_manager_features) (TpSimpleClientFactory *self, + TpAccountManager *manager); + + /* TpAccount */ + TpAccount * (*create_account) (TpSimpleClientFactory *self, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error); + GArray * (*dup_account_features) (TpSimpleClientFactory *self, + TpAccount *account); + + /* TpConnection */ + TpConnection * (*create_connection) (TpSimpleClientFactory *self, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error); + GArray * (*dup_connection_features) (TpSimpleClientFactory *self, + TpConnection *connection); + + /* TpChannel */ + TpChannel * (*create_channel) (TpSimpleClientFactory *self, + TpConnection *conn, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error); + GArray * (*dup_channel_features) (TpSimpleClientFactory *self, + TpChannel *channel); + + /* TpContact */ + TpContact * (*create_contact) (TpSimpleClientFactory *self, + TpConnection *connection, + TpHandle handle, + const gchar *identifier); + GArray * (*dup_contact_features) (TpSimpleClientFactory *self, + TpConnection *connection); + + /*<private>*/ + GCallback padding[20]; +}; + +struct _TpSimpleClientFactory { + /*<private>*/ + GObject parent; + TpSimpleClientFactoryPrivate *priv; +}; + +GType tp_simple_client_factory_get_type (void); + +#define TP_TYPE_SIMPLE_CLIENT_FACTORY \ + (tp_simple_client_factory_get_type ()) +#define TP_SIMPLE_CLIENT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TP_TYPE_SIMPLE_CLIENT_FACTORY, \ + TpSimpleClientFactory)) +#define TP_SIMPLE_CLIENT_FACTORY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TP_TYPE_SIMPLE_CLIENT_FACTORY, \ + TpSimpleClientFactoryClass)) +#define TP_IS_SIMPLE_CLIENT_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TP_TYPE_SIMPLE_CLIENT_FACTORY)) +#define TP_IS_SIMPLE_CLIENT_FACTORY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TP_TYPE_SIMPLE_CLIENT_FACTORY)) +#define TP_SIMPLE_CLIENT_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TP_TYPE_SIMPLE_CLIENT_FACTORY, \ + TpSimpleClientFactoryClass)) + +TpSimpleClientFactory * tp_simple_client_factory_new (TpDBusDaemon *dbus); + +TpDBusDaemon *tp_simple_client_factory_get_dbus_daemon ( + TpSimpleClientFactory *self); + +/* TpAccountManager */ +TpAccountManager *tp_simple_client_factory_ensure_account_manager ( + TpSimpleClientFactory *self); +GArray *tp_simple_client_factory_dup_account_manager_features ( + TpSimpleClientFactory *self, + TpAccountManager *manager); +void tp_simple_client_factory_add_account_manager_features ( + TpSimpleClientFactory *self, + const GQuark *features); + +/* TpAccount */ +TpAccount *tp_simple_client_factory_ensure_account (TpSimpleClientFactory *self, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error); +GArray *tp_simple_client_factory_dup_account_features ( + TpSimpleClientFactory *self, + TpAccount *account); +void tp_simple_client_factory_add_account_features (TpSimpleClientFactory *self, + const GQuark *features); + +/* TpConnection */ +TpConnection *tp_simple_client_factory_ensure_connection ( + TpSimpleClientFactory *self, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error); +GArray *tp_simple_client_factory_dup_connection_features ( + TpSimpleClientFactory *self, + TpConnection *connection); +void tp_simple_client_factory_add_connection_features ( + TpSimpleClientFactory *self, + const GQuark *features); + +/* TpChannel */ +TpChannel *tp_simple_client_factory_ensure_channel (TpSimpleClientFactory *self, + TpConnection *connection, + const gchar *object_path, + const GHashTable *immutable_properties, + GError **error); +GArray *tp_simple_client_factory_dup_channel_features ( + TpSimpleClientFactory *self, + TpChannel *channel); +void tp_simple_client_factory_add_channel_features (TpSimpleClientFactory *self, + const GQuark *features); + +/* TpContact */ +TpContact *tp_simple_client_factory_ensure_contact (TpSimpleClientFactory *self, + TpConnection *connection, + TpHandle handle, + const gchar *identifier); +GArray *tp_simple_client_factory_dup_contact_features ( + TpSimpleClientFactory *self, + TpConnection *connection); +void tp_simple_client_factory_add_contact_features (TpSimpleClientFactory *self, + guint n_features, + const TpContactFeature *features); + +G_END_DECLS + +#endif diff --git a/telepathy-glib/telepathy-glib.h b/telepathy-glib/telepathy-glib.h index e93c370d5..6409d3921 100644 --- a/telepathy-glib/telepathy-glib.h +++ b/telepathy-glib/telepathy-glib.h @@ -58,6 +58,7 @@ #include <telepathy-glib/proxy.h> #include <telepathy-glib/signalled-message.h> #include <telepathy-glib/simple-approver.h> +#include <telepathy-glib/simple-client-factory.h> #include <telepathy-glib/simple-handler.h> #include <telepathy-glib/simple-observer.h> #include <telepathy-glib/stream-tube-channel.h> |