diff options
Diffstat (limited to 'src/avahi-olpc-activity-manager.c')
-rw-r--r-- | src/avahi-olpc-activity-manager.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/src/avahi-olpc-activity-manager.c b/src/avahi-olpc-activity-manager.c new file mode 100644 index 00000000..f7ae90fd --- /dev/null +++ b/src/avahi-olpc-activity-manager.c @@ -0,0 +1,376 @@ +/* + * avahi-avahi_olpc-activity-manager.c - Source for + * SalutAvahiOlpcActivityManager + * Copyright (C) 2008 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 + */ + +#include "config.h" +#include "avahi-olpc-activity-manager.h" + +#include <dbus/dbus-glib.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <avahi-gobject/ga-service-browser.h> + +#include "avahi-olpc-activity.h" +#include "avahi-discovery-client.h" +#include "olpc-activity.h" + +#define DEBUG_FLAG DEBUG_OLPC_ACTIVITY +#include "debug.h" + +G_DEFINE_TYPE (SalutAvahiOlpcActivityManager, salut_avahi_olpc_activity_manager, + SALUT_TYPE_OLPC_ACTIVITY_MANAGER); + +/* properties */ +enum { + PROP_CLIENT = 1, + LAST_PROP +}; + +/* private structure */ +typedef struct _SalutAvahiOlpcActivityManagerPrivate SalutAvahiOlpcActivityManagerPrivate; + +struct _SalutAvahiOlpcActivityManagerPrivate +{ + SalutAvahiDiscoveryClient *discovery_client; + GaServiceBrowser *browser; + + gboolean dispose_has_run; +}; + +#define SALUT_AVAHI_OLPC_ACTIVITY_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SALUT_TYPE_AVAHI_OLPC_ACTIVITY_MANAGER, SalutAvahiOlpcActivityManagerPrivate)) + +static void +salut_avahi_olpc_activity_manager_init (SalutAvahiOlpcActivityManager *self) +{ + SalutAvahiOlpcActivityManagerPrivate *priv = + SALUT_AVAHI_OLPC_ACTIVITY_MANAGER_GET_PRIVATE (self); + + priv->browser = ga_service_browser_new (SALUT_DNSSD_OLPC_ACTIVITY); +} + +static void +salut_avahi_olpc_activity_manager_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + SalutAvahiOlpcActivityManager *self = SALUT_AVAHI_OLPC_ACTIVITY_MANAGER (object); + SalutAvahiOlpcActivityManagerPrivate *priv = SALUT_AVAHI_OLPC_ACTIVITY_MANAGER_GET_PRIVATE (self); + + switch (property_id) + { + case PROP_CLIENT: + g_value_set_object (value, priv->discovery_client); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +salut_avahi_olpc_activity_manager_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + SalutAvahiOlpcActivityManager *self = SALUT_AVAHI_OLPC_ACTIVITY_MANAGER (object); + SalutAvahiOlpcActivityManagerPrivate *priv = SALUT_AVAHI_OLPC_ACTIVITY_MANAGER_GET_PRIVATE (self); + + switch (property_id) + { + case PROP_CLIENT: + priv->discovery_client = g_value_get_object (value); + g_object_ref (priv->discovery_client); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gboolean +split_activity_name (const gchar *name, + gchar **room_name, + gchar **contact_name) +{ + gchar **tmp; + + tmp = g_strsplit (name, ":", 2); + if (tmp[0] == NULL || tmp[1] == NULL) + { + DEBUG ("Ignoring invalid OLPC activity DNS-SD with no ':': %s", name); + return FALSE; + } + + if (room_name != NULL) + *room_name = g_strdup (tmp[0]); + if (contact_name != NULL) + *contact_name = g_strdup (tmp[1]); + + g_strfreev (tmp); + return TRUE; +} + +static void +browser_found (GaServiceBrowser *browser, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *name, + const char *type, + const char *domain, + GaLookupResultFlags flags, + SalutAvahiOlpcActivityManager *self) +{ + SalutOlpcActivityManager *mgr = SALUT_OLPC_ACTIVITY_MANAGER (self); + SalutOlpcActivity *activity; + gchar *room_name = NULL; + gchar *contact_name = NULL; + TpBaseConnection *base_conn = (TpBaseConnection *) mgr->connection; + TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( + base_conn, TP_HANDLE_TYPE_ROOM); + TpHandle room; + GError *error = NULL; + SalutContactManager *contact_manager; + SalutContact *contact; + + if (flags & AVAHI_LOOKUP_RESULT_OUR_OWN) + return; + + if (tp_base_connection_is_destroyed (base_conn)) + return; + + if (!split_activity_name (name, &room_name, &contact_name)) + return; + + room = tp_handle_ensure (room_repo, room_name, NULL, &error); + if (room == 0) + { + DEBUG ("invalid room name %s: %s", room_name, error->message); + g_free (room_name); + g_free (contact_name); + return; + } + + activity = salut_olpc_activity_manager_ensure_activity_by_room (mgr, + room); + + salut_avahi_olpc_activity_add_service (SALUT_AVAHI_OLPC_ACTIVITY (activity), + interface, protocol, name, type, domain); + + g_object_get (mgr->connection, + "contact-manager", &contact_manager, NULL); + g_assert (contact_manager != NULL); + + contact = salut_contact_manager_ensure_contact (contact_manager, + contact_name); + salut_olpc_activity_manager_contact_joined (mgr, contact, activity); + + g_object_unref (activity); + g_free (contact_name); + g_free (room_name); + g_object_unref (contact); + g_object_unref (contact_manager); +} + +static void +browser_removed (GaServiceBrowser *browser, + AvahiIfIndex interface, + AvahiProtocol protocol, + const char *name, + const char *type, + const char *domain, + GaLookupResultFlags flags, + SalutAvahiOlpcActivityManager *self) +{ + SalutOlpcActivityManager *mgr = SALUT_OLPC_ACTIVITY_MANAGER (self); + SalutOlpcActivity *activity; + gchar *room_name = NULL; + gchar *contact_name = NULL; + TpHandleRepoIface *room_repo = tp_base_connection_get_handles + ((TpBaseConnection *) mgr->connection, TP_HANDLE_TYPE_ROOM); + TpHandleRepoIface *contact_repo = tp_base_connection_get_handles + ((TpBaseConnection *) mgr->connection, TP_HANDLE_TYPE_CONTACT); + TpHandle room; + TpHandle contact_handle; + GError *error = NULL; + SalutContactManager *contact_manager; + SalutContact *contact; + + if (!split_activity_name (name, &room_name, &contact_name)) + return; + + room = tp_handle_ensure (room_repo, room_name, NULL, &error); + g_free (room_name); + if (room == 0) + { + DEBUG ("invalid room name %s: %s", room_name, error->message); + g_free (contact_name); + g_error_free (error); + return; + } + + contact_handle = tp_handle_ensure (contact_repo, contact_name, NULL, &error); + if (contact_handle == 0) + { + DEBUG ("Invalid contact name %s: %s", contact_name, error->message); + g_error_free (error); + g_free (contact_name); + return; + } + g_free (contact_name); + + activity = salut_olpc_activity_manager_get_activity_by_room (mgr, room); + if (activity == NULL) + return; + + salut_avahi_olpc_activity_remove_service (SALUT_AVAHI_OLPC_ACTIVITY (activity), + interface, protocol, name, type, domain); + + g_object_get (mgr->connection, + "contact-manager", &contact_manager, NULL); + g_assert (contact_manager != NULL); + + contact = salut_contact_manager_get_contact (contact_manager, + contact_handle); + g_object_unref (contact_manager); + if (contact == NULL) + return; + + salut_olpc_activity_manager_contact_left (mgr, contact, activity); + g_object_unref (contact); +} + +static void +browser_failed (GaServiceBrowser *browser, + GError *error, + SalutAvahiOlpcActivityManager *self) +{ + g_warning ("browser failed -> %s", error->message); +} + +static gboolean +salut_avahi_olpc_activity_manager_start (SalutOlpcActivityManager *mgr, + GError **error) +{ + SalutAvahiOlpcActivityManager *self = SALUT_AVAHI_OLPC_ACTIVITY_MANAGER (mgr); + SalutAvahiOlpcActivityManagerPrivate *priv = + SALUT_AVAHI_OLPC_ACTIVITY_MANAGER_GET_PRIVATE (self); + + g_signal_connect (priv->browser, "new-service", + G_CALLBACK (browser_found), self); + g_signal_connect (priv->browser, "removed-service", + G_CALLBACK (browser_removed), self); + g_signal_connect (priv->browser, "failure", + G_CALLBACK (browser_failed), self); + + if (!ga_service_browser_attach (priv->browser, + priv->discovery_client->avahi_client, error)) + { + DEBUG ("browser attach failed"); + return FALSE; + } + + return TRUE; +} + +static SalutOlpcActivity * +salut_avahi_olpc_activity_manager_create_activity ( + SalutOlpcActivityManager *mgr) +{ + SalutAvahiOlpcActivityManager *self = SALUT_AVAHI_OLPC_ACTIVITY_MANAGER (mgr); + SalutAvahiOlpcActivityManagerPrivate *priv = + SALUT_AVAHI_OLPC_ACTIVITY_MANAGER_GET_PRIVATE (self); + + return SALUT_OLPC_ACTIVITY (salut_avahi_olpc_activity_new ( + mgr->connection, priv->discovery_client)); +} + +static void salut_avahi_olpc_activity_manager_dispose (GObject *object); + +static void +salut_avahi_olpc_activity_manager_class_init (SalutAvahiOlpcActivityManagerClass *salut_avahi_olpc_activity_manager_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (salut_avahi_olpc_activity_manager_class); + SalutOlpcActivityManagerClass *activity_manager_class = SALUT_OLPC_ACTIVITY_MANAGER_CLASS ( + salut_avahi_olpc_activity_manager_class); + + GParamSpec *param_spec; + + g_type_class_add_private (salut_avahi_olpc_activity_manager_class, + sizeof (SalutAvahiOlpcActivityManagerPrivate)); + + object_class->get_property = salut_avahi_olpc_activity_manager_get_property; + object_class->set_property = salut_avahi_olpc_activity_manager_set_property; + + object_class->dispose = salut_avahi_olpc_activity_manager_dispose; + + activity_manager_class->start = salut_avahi_olpc_activity_manager_start; + activity_manager_class->create_activity = + salut_avahi_olpc_activity_manager_create_activity; + + param_spec = g_param_spec_object ( + "discovery-client", + "SalutAvahiDiscoveryClient object", + "The Salut Avahi Discovery client associated with this manager", + SALUT_TYPE_AVAHI_DISCOVERY_CLIENT, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_CLIENT, + param_spec); +} + +static void +salut_avahi_olpc_activity_manager_dispose (GObject *object) +{ + SalutAvahiOlpcActivityManager *self = SALUT_AVAHI_OLPC_ACTIVITY_MANAGER (object); + SalutAvahiOlpcActivityManagerPrivate *priv = SALUT_AVAHI_OLPC_ACTIVITY_MANAGER_GET_PRIVATE (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + if (priv->discovery_client != NULL) + { + g_object_unref (priv->discovery_client); + priv->discovery_client = NULL; + } + + if (priv->browser != NULL) + { + g_object_unref (priv->browser); + priv->browser = NULL; + } + + if (G_OBJECT_CLASS (salut_avahi_olpc_activity_manager_parent_class)->dispose) + G_OBJECT_CLASS (salut_avahi_olpc_activity_manager_parent_class)->dispose (object); +} + +SalutAvahiOlpcActivityManager * +salut_avahi_olpc_activity_manager_new (SalutConnection *connection, + SalutAvahiDiscoveryClient *discovery_client) +{ + return g_object_new (SALUT_TYPE_AVAHI_OLPC_ACTIVITY_MANAGER, + "connection", connection, + "discovery-client", discovery_client, + NULL); +} |