Mercurial > pidgin
diff libpurple/disco.c @ 26974:c2cd559e034f
propagate from branch 'im.pidgin.pidgin' (head 97fbf033d9afea69a6eabaac94698b3c051584cf)
to branch 'im.pidgin.cpw.darkrain42.xmpp.disco' (head d1274de628e3e7c76742ebf0941b7d104e19dceb)
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sat, 23 May 2009 22:46:28 +0000 |
parents | ba99ee519926 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/disco.c Sat May 23 22:46:28 2009 +0000 @@ -0,0 +1,411 @@ +/** + * @file disco.c Service Discovery API + * @ingroup core + */ + +/* purple + * + * Purple is the legal property of its developers, whose names are too numerous + * to list here. Please refer to the COPYRIGHT file distributed with this + * source distribution. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "internal.h" +#include "debug.h" + +#include "disco.h" + +/**************************************************************************/ +/* Main structures, members and constants */ +/**************************************************************************/ + +/** + * Represents a list of services for a given connection on a given protocol. + */ +struct _PurpleDiscoList { + PurpleAccount *account; /**< The account this list belongs to. */ + GList *services; /**< The list of services. */ + + gboolean in_progress; + + gpointer ui_data; /**< UI private data. */ + gpointer proto_data; /**< Prpl private data. */ + guint ref; /**< The reference count. */ + + struct { + PurpleDiscoCancelFunc cancel_cb; + PurpleDiscoCloseFunc close_cb; /**< Callback to free the prpl data */ + PurpleDiscoServiceCloseFunc service_close_cb; + PurpleDiscoServiceExpandFunc expand_cb; /**< Expand a service (iteratively + look for things that are + "sub-elements" in the tree */ + PurpleDiscoRegisterFunc register_cb; + } ops; +}; + +/** + * Represents a list of services for a given connection on a given protocol. + */ +struct _PurpleDiscoService { + PurpleDiscoList *list; + gchar *name; /**< The name of the service. */ + gchar *description; /**< The name of the service. */ + + gpointer proto_data; + + gchar *gateway_type; /**< The type of the gateway service. */ + PurpleDiscoServiceType type; /**< The type of service. */ + PurpleDiscoServiceFlags flags; +}; + +static PurpleDiscoUiOps *ops = NULL; + +PurpleDiscoList *purple_disco_list_new(PurpleAccount *account) +{ + PurpleDiscoList *list; + + g_return_val_if_fail(account != NULL, NULL); + + list = g_new0(PurpleDiscoList, 1); + list->account = account; + list->ref = 1; + + if (ops && ops->create) + ops->create(list); + + return list; +} + +PurpleDiscoList *purple_disco_list_ref(PurpleDiscoList *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + list->ref++; + purple_debug_misc("disco", "reffing list, ref count now %d\n", list->ref); + + return list; +} + +static void purple_disco_list_service_destroy(PurpleDiscoList *list, PurpleDiscoService *r) +{ + if (list->ops.service_close_cb) + list->ops.service_close_cb(r); + + g_free(r->name); + g_free(r->description); + g_free(r->gateway_type); + g_free(r); +} + +static void purple_disco_list_destroy(PurpleDiscoList *list) +{ + GList *l; + + purple_debug_misc("disco", "destroying list %p\n", list); + + if (ops && ops->destroy) + ops->destroy(list); + + if (list->ops.close_cb) + list->ops.close_cb(list); + + for (l = list->services; l; l = l->next) { + PurpleDiscoService *s = l->data; + purple_disco_list_service_destroy(list, s); + } + g_list_free(list->services); + + g_free(list); +} + +void purple_disco_list_unref(PurpleDiscoList *list) +{ + g_return_if_fail(list != NULL); + g_return_if_fail(list->ref > 0); + + list->ref--; + + purple_debug_misc("disco", "unreffing list, ref count now %d\n", list->ref); + if (list->ref == 0) + purple_disco_list_destroy(list); +} + +void purple_disco_list_service_add(PurpleDiscoList *list, + PurpleDiscoService *service, + PurpleDiscoService *parent) +{ + g_return_if_fail(list != NULL); + g_return_if_fail(service != NULL); + + list->services = g_list_append(list->services, service); + service->list = list; + + if (ops && ops->add_service) + ops->add_service(list, service, parent); +} + +PurpleDiscoService *purple_disco_list_service_new(PurpleDiscoServiceType type, + const gchar *name, const gchar *description, + PurpleDiscoServiceFlags flags, gpointer proto_data) +{ + PurpleDiscoService *s; + + g_return_val_if_fail(name != NULL, NULL); + g_return_val_if_fail(type != PURPLE_DISCO_SERVICE_TYPE_UNSET, NULL); + + s = g_new0(PurpleDiscoService, 1); + s->name = g_strdup(name); + s->type = type; + s->description = g_strdup(description); + s->flags = flags; + s->proto_data = proto_data; + + return s; +} + +PurpleDiscoList *purple_disco_get_list(PurpleConnection *pc) +{ + PurplePlugin *prpl = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + + g_return_val_if_fail(pc != NULL, NULL); + + prpl = purple_connection_get_prpl(pc); + if (prpl != NULL) + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + + if (prpl_info && PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, disco_get_list)) + return prpl_info->disco_get_list(pc); + + return NULL; +} + +void purple_disco_cancel_get_list(PurpleDiscoList *list) +{ + PurpleConnection *pc; + + g_return_if_fail(list != NULL); + + pc = purple_account_get_connection(list->account); + + g_return_if_fail(pc != NULL); + + if (list->ops.cancel_cb) + list->ops.cancel_cb(list); + + purple_disco_list_set_in_progress(list, FALSE); +} + +void purple_disco_service_expand(PurpleDiscoService *service) +{ + PurpleDiscoList *list; + PurpleConnection *pc; + + g_return_if_fail(service != NULL); + g_return_if_fail((service->flags & PURPLE_DISCO_BROWSE)); + + list = service->list; + pc = purple_account_get_connection(list->account); + + g_return_if_fail(pc != NULL); + + purple_disco_list_set_in_progress(list, TRUE); + + if (list->ops.expand_cb) + list->ops.expand_cb(list, service); + else + purple_debug_warning("disco", "Cannot expand %s for account %s, " + "protocol did not provide expand op.\n", + service->name, + purple_account_get_username(list->account)); +} + +void purple_disco_service_register(PurpleDiscoService *service) +{ + PurpleDiscoList *list; + PurpleConnection *pc; + + g_return_if_fail(service != NULL); + + list = service->list; + pc = purple_account_get_connection(list->account); + + g_return_if_fail(pc != NULL); + + if (list->ops.register_cb) + list->ops.register_cb(pc, service); + else + purple_debug_warning("disco", "Cannot register to %s for account %s, " + "protocol did not provide register op.\n", + service->name, + purple_account_get_username(list->account)); +} + +const gchar *purple_disco_service_get_name(PurpleDiscoService *service) +{ + g_return_val_if_fail(service != NULL, NULL); + + return service->name; +} + +const gchar *purple_disco_service_get_description(PurpleDiscoService *service) +{ + g_return_val_if_fail(service != NULL, NULL); + + return service->description; +} + +gpointer +purple_disco_service_get_protocol_data(PurpleDiscoService *service) +{ + g_return_val_if_fail(service != NULL, NULL); + + return service->proto_data; +} + +PurpleDiscoServiceType +purple_disco_service_get_type(PurpleDiscoService *service) +{ + g_return_val_if_fail(service != NULL, PURPLE_DISCO_SERVICE_TYPE_UNSET); + + return service->type; +} + +PurpleDiscoServiceFlags +purple_disco_service_get_flags(PurpleDiscoService *service) +{ + g_return_val_if_fail(service != NULL, PURPLE_DISCO_NONE); + + return service->flags; +} + +void purple_disco_service_set_gateway_type(PurpleDiscoService *service, const gchar *type) +{ + g_return_if_fail(service != NULL); + + g_free(service->gateway_type); + service->gateway_type = g_strdup(type); +} + +const gchar *purple_disco_service_get_gateway_type(PurpleDiscoService *service) +{ + g_return_val_if_fail(service != NULL, NULL); + + return service->gateway_type; +} + +PurpleAccount* purple_disco_list_get_account(PurpleDiscoList *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->account; +} + +GList* purple_disco_list_get_services(PurpleDiscoList *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->services; +} + +void purple_disco_list_set_ui_data(PurpleDiscoList *list, gpointer ui_data) +{ + g_return_if_fail(list != NULL); + + list->ui_data = ui_data; +} + +gpointer purple_disco_list_get_ui_data(PurpleDiscoList *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->ui_data; +} + +void purple_disco_list_set_in_progress(PurpleDiscoList *list, + gboolean in_progress) +{ + g_return_if_fail(list != NULL); + + list->in_progress = in_progress; + + if (ops && ops->in_progress) + ops->in_progress(list, in_progress); +} + +gboolean purple_disco_list_get_in_progress(PurpleDiscoList *list) +{ + g_return_val_if_fail(list != NULL, FALSE); + + return list->in_progress; +} + +void purple_disco_list_set_protocol_data(PurpleDiscoList *list, + gpointer proto_data, + PurpleDiscoCloseFunc cb) +{ + g_return_if_fail(list != NULL); + + list->proto_data = proto_data; + list->ops.close_cb = cb; +} + +gpointer purple_disco_list_get_protocol_data(PurpleDiscoList *list) +{ + g_return_val_if_fail(list != NULL, NULL); + + return list->proto_data; +} + +void purple_disco_list_set_service_close_func(PurpleDiscoList *list, + PurpleDiscoServiceCloseFunc cb) +{ + g_return_if_fail(list != NULL); + + list->ops.service_close_cb = cb; +} + +void purple_disco_list_set_cancel_func(PurpleDiscoList *list, PurpleDiscoCancelFunc cb) +{ + g_return_if_fail(list != NULL); + + list->ops.cancel_cb = cb; +} + +void purple_disco_list_set_expand_func(PurpleDiscoList *list, PurpleDiscoServiceExpandFunc cb) +{ + g_return_if_fail(list != NULL); + + list->ops.expand_cb = cb; +} + +void purple_disco_list_set_register_func(PurpleDiscoList *list, PurpleDiscoRegisterFunc cb) +{ + g_return_if_fail(list != NULL); + + list->ops.register_cb = cb; +} + +void purple_disco_set_ui_ops(PurpleDiscoUiOps *ui_ops) +{ + ops = ui_ops; +} + +PurpleDiscoUiOps *purple_disco_get_ui_ops(void) +{ + return ops; +}