key-file \
$(NULL)
+if ENABLE_LIBSOCIALWEB
+SUBDIRS += libsocialweb
+endif
+
if ENABLE_TRACKER
SUBDIRS += tracker
endif
telepathy \
key-file \
tracker \
+ libsocialweb \
$(NULL)
-include $(top_srcdir)/git.mk
--- /dev/null
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/folks \
+ -include $(CONFIG_HEADER) \
+ -DPACKAGE_DATADIR=\"$(pkgdatadir)\" \
+ -DG_LOG_DOMAIN=\"LibSocialWebBackend\" \
+ $(NULL)
+
+VALAFLAGS += \
+ --vapidir=. \
+ --vapidir=$(top_srcdir)/folks \
+ $(addprefix --pkg ,$(folks_backend_libsocialweb_deps)) \
+ $(NULL)
+
+backenddir = $(BACKEND_DIR)/libsocialweb
+backend_LTLIBRARIES = libfolks-backend-libsocialweb.la
+
+libfolks_backend_libsocialweb_la_SOURCES = \
+ sw-backend.vala \
+ sw-backend-factory.vala \
+ sw-persona-store.vala \
+ sw-persona.vala \
+ $(NULL)
+
+folks_backend_libsocialweb_deps = \
+ folks \
+ gee-1.0 \
+ gio-2.0 \
+ gobject-2.0 \
+ libsocialweb-client \
+ $(NULL)
+
+libfolks_backend_libsocialweb_la_CFLAGS = \
+ $(GIO_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GEE_CFLAGS) \
+ $(SW_CLIENT_CFLAGS) \
+ $(NULL)
+
+libfolks_backend_libsocialweb_la_LIBADD = \
+ $(GIO_LIBS) \
+ $(GLIB_LIBS) \
+ $(GEE_LIBS) \
+ $(top_builddir)/folks/libfolks.la \
+ $(SW_CLIENT_LIBS) \
+ $(NULL)
+
+libfolks_backend_libsocialweb_la_LDFLAGS = -shared -fPIC -module -avoid-version
+
+GITIGNOREFILES = \
+ folks-backend-libsocialweb.vapi \
+ $(libfolks_backend_libsocialweb_la_SOURCES:.vala=.c) \
+ libfolks_backend_libsocialweb_la_vala.stamp \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
--- /dev/null
+/*
+ * Copyright (C) 2009 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>.
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2010 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ * Travis Reitter <travis.reitter@collabora.co.uk>
+ * Marco Barisione <marco.barisione@collabora.co.uk>
+ *
+ * This file was originally part of Rygel.
+ */
+
+using Folks;
+using Folks.Backends.Sw;
+
+private BackendFactory backend_factory = null;
+
+/**
+ * The libsocialweb backend module entry point.
+ */
+public void module_init (BackendStore backend_store)
+{
+ backend_factory = new BackendFactory (backend_store);
+}
+
+/**
+ * The libsocialweb backend module exit point.
+ */
+public void module_finalize (BackendStore backend_store)
+{
+ backend_factory = null;
+}
+
+/**
+ * A backend factory to create a single {@link Backend}.
+ */
+public class Folks.Backends.Sw.BackendFactory : Object
+{
+ /**
+ * {@inheritDoc}
+ */
+ public BackendFactory (BackendStore backend_store)
+ {
+ backend_store.add_backend (new Backend ());
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2010 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Travis Reitter <travis.reitter@collabora.co.uk>
+ * Marco Barisione <marco.barisione@collabora.co.uk>
+ */
+
+using GLib;
+using Folks;
+using Folks.Backends.Sw;
+using SocialWebClient;
+
+extern const string BACKEND_NAME;
+
+/**
+ * A backend which connects to libsocialweb and creates a {@link PersonaStore}
+ * for each service.
+ */
+public class Folks.Backends.Sw.Backend : Folks.Backend
+{
+ private bool _is_prepared = false;
+ private Client _client;
+ private HashTable<string, PersonaStore> _persona_stores =
+ new HashTable<string, PersonaStore> (str_hash, str_equal);
+
+ /**
+ * {@inheritDoc}
+ */
+ public override string name { get { return BACKEND_NAME; } }
+
+ /**
+ * {@inheritDoc}
+ */
+ public override HashTable<string, PersonaStore> persona_stores
+ {
+ get { return this._persona_stores; }
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Backend ()
+ {
+ }
+
+ /**
+ * Whether this Backend has been prepared.
+ *
+ * See {@link Folks.Backend.is_prepared}.
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public override async void prepare () throws GLib.Error
+ {
+ lock (this._is_prepared)
+ {
+ if (!this._is_prepared)
+ {
+ this._client = new Client();
+ this._client.get_services((client, services) =>
+ {
+ foreach (var service_name in services)
+ this.add_service (service_name);
+
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+ });
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public override async void unprepare () throws GLib.Error
+ {
+ this._persona_stores.foreach ((k, v) =>
+ {
+ PersonaStore store = v;
+ store.removed.disconnect (this.store_removed_cb);
+ this.persona_store_removed (store);
+ });
+
+ this._client = null;
+
+ this._persona_stores.remove_all ();
+ this.notify_property ("persona-stores");
+
+ this._is_prepared = false;
+ this.notify_property ("is-prepared");
+ }
+
+ private void add_service (string service_name)
+ {
+ if (this._persona_stores.lookup (service_name) != null)
+ return;
+
+ var store = new PersonaStore (this._client.get_service (service_name));
+ this._persona_stores.insert (store.id, store);
+ store.removed.connect (this.store_removed_cb);
+ this.persona_store_added (store);
+ }
+
+ private void store_removed_cb (Folks.PersonaStore store)
+ {
+ this.persona_store_removed (store);
+ this._persona_stores.remove (store.id);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2010 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Travis Reitter <travis.reitter@collabora.co.uk>
+ * Philip Withnall <philip.withnall@collabora.co.uk>
+ * Marco Barisione <marco.barisione@collabora.co.uk>
+ */
+
+using GLib;
+using Folks;
+using SocialWebClient;
+
+/**
+ * A persona store which is associated with a single libsocialweb service.
+ * It will create {@link Persona}s for each of the contacts known to that
+ * service.
+ */
+public class Folks.Backends.Sw.PersonaStore : Folks.PersonaStore
+{
+ private HashTable<string, Persona> _personas;
+ private bool _is_prepared = false;
+ private ClientService _service;
+ private ClientItemView _item_view;
+
+ /**
+ * The type of persona store this is.
+ *
+ * See {@link Folks.PersonaStore.type_id}.
+ */
+ public override string type_id { get { return "libsocialweb"; } }
+
+ /**
+ * Whether this PersonaStore can add {@link Folks.Persona}s.
+ *
+ * See {@link Folks.PersonaStore.can_add_personas}.
+ *
+ * @since 0.3.1
+ */
+ public override MaybeBool can_add_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore can set the alias of {@link Folks.Persona}s.
+ *
+ * See {@link Folks.PersonaStore.can_alias_personas}.
+ *
+ * @since 0.3.1
+ */
+ public override MaybeBool can_alias_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore can set the groups of {@link Folks.Persona}s.
+ *
+ * See {@link Folks.PersonaStore.can_group_personas}.
+ *
+ * @since 0.3.1
+ */
+ public override MaybeBool can_group_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore can remove {@link Folks.Persona}s.
+ *
+ * See {@link Folks.PersonaStore.can_remove_personas}.
+ *
+ * @since 0.3.1
+ */
+ public override MaybeBool can_remove_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * Whether this PersonaStore has been prepared.
+ *
+ * See {@link Folks.PersonaStore.is_prepared}.
+ *
+ * @since 0.3.0
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
+ * The {@link Persona}s exposed by this PersonaStore.
+ *
+ * See {@link Folks.PersonaStore.personas}.
+ */
+ public override HashTable<string, Persona> personas
+ {
+ get { return this._personas; }
+ }
+
+ /**
+ * Create a new PersonaStore.
+ *
+ * Create a new persona store to store the {@link Persona}s for the contacts
+ * provided by the `service`.
+ */
+ public PersonaStore (ClientService service)
+ {
+ Object (display_name: service.get_display_name(),
+ id: service.get_name ());
+
+ this.trust_level = PersonaStoreTrust.PARTIAL;
+ this._service = service;
+ this._personas = new HashTable<string, Persona> (str_hash, str_equal);
+ }
+
+ /**
+ * Add a new {@link Persona} to the PersonaStore.
+ *
+ * See {@link Folks.PersonaStore.add_persona_from_details}.
+ */
+ public override async Folks.Persona? add_persona_from_details (
+ HashTable<string, Value?> details) throws Folks.PersonaStoreError
+ {
+ // FIXME: There is no better error for this.
+ throw new PersonaStoreError.UNSUPPORTED_ON_USER (
+ "Personas cannot be added to this store.");
+ }
+
+ /**
+ * Remove a {@link Persona} from the PersonaStore.
+ *
+ * See {@link Folks.PersonaStore.remove_persona}.
+ */
+ public override async void remove_persona (Folks.Persona persona)
+ throws Folks.PersonaStoreError
+ {
+ // FIXME: There is no better error for this.
+ throw new PersonaStoreError.UNSUPPORTED_ON_USER (
+ "Personas cannot be removed from this store.");
+ }
+
+ /**
+ * Prepare the PersonaStore for use.
+ *
+ * See {@link Folks.PersonaStore.prepare}.
+ */
+ public override async void prepare ()
+ {
+ lock (this._is_prepared)
+ {
+ if (!this._is_prepared)
+ {
+ var parameters = new HashTable<weak string, weak string> (
+ str_hash, str_equal);
+ this._service.query_open_view("people", parameters,
+ (query, item_view) =>
+ {
+ item_view.items_added.connect (this.items_added_cb);
+ item_view.items_changed.connect (this.items_changed_cb);
+ item_view.items_removed.connect (this.items_removed_cb);
+
+ this._item_view = item_view;
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+
+ this._item_view.start ();
+ });
+ }
+ }
+ }
+
+ private void items_added_cb (List<unowned Item> items)
+ {
+ var added_personas = new Queue<Persona> ();
+ foreach (var item in items)
+ {
+ var persona = new Persona(this, item);
+ _personas.insert(persona.iid, persona);
+ added_personas.push_tail(persona);
+ }
+
+ if (added_personas.length > 0)
+ this.personas_changed (added_personas.head, null, null, null, 0);
+ }
+
+ private void items_changed_cb (List<unowned Item> items)
+ {
+ foreach (var item in items)
+ {
+ var persona = _personas.lookup(Persona.get_item_id (item));
+ if (persona != null)
+ persona.update (item);
+ }
+ }
+
+ private void items_removed_cb (List<unowned Item> items)
+ {
+ var removed_personas = new Queue<Persona> ();
+ foreach (var item in items)
+ {
+ var persona = _personas.lookup(Persona.get_item_id (item));
+ if (persona != null)
+ {
+ removed_personas.push_tail(persona);
+ _personas.remove(persona.iid);
+ }
+ }
+
+ if (removed_personas.length > 0)
+ this.personas_changed (null, removed_personas.head, null, null, 0);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2010 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Travis Reitter <travis.reitter@collabora.co.uk>
+ * Marco Barisione <marco.barisione@collabora.co.uk>
+ */
+
+using GLib;
+using Folks;
+using SocialWebClient;
+
+/**
+ * A persona subclass which represents a single libsocialweb contact.
+ */
+internal class Folks.Backends.Sw.Persona : Folks.Persona,
+ Aliasable,
+ AvatarDetails
+{
+ private const string[] _linkable_properties = {};
+
+ /**
+ * The names of the Persona's linkable properties.
+ *
+ * See {@link Folks.Persona.linkable_properties}.
+ */
+ public override string[] linkable_properties
+ {
+ get { return this._linkable_properties; }
+ }
+
+ /**
+ * An avatar for the Persona.
+ *
+ * See {@link Folks.HasAvatar.avatar}.
+ */
+ public File avatar { get; set; }
+
+ /**
+ * An alias for the Persona.
+ *
+ * See {@link Folks.Aliasable.alias}.
+ */
+ public string alias { get; private set; }
+
+ /**
+ * Create a new persona.
+ *
+ * Create a new persona for the {@link PersonaStore} `store`, representing
+ * the libsocialweb contact given by `item`.
+ */
+ public Persona (PersonaStore store, Item item)
+ {
+ var id = get_item_id (item);
+ var uid = this.build_uid ("folks", store.id, id);
+ debug ("Creating new Sw.Persona '%s' for %s UID '%s': %p",
+ uid, store.display_name, id, this);
+ Object (alias: item.get_value ("name"),
+ display_id: id,
+ uid: uid,
+ iid: store.id + ":" + id,
+ store: store,
+ is_user: false);
+ update (item);
+ }
+
+ ~Persona ()
+ {
+ debug ("Destroying Sw.Persona '%s': %p", this.uid, this);
+ }
+
+ public static string? get_item_id (Item item)
+ {
+ return item.get_value ("id");
+ }
+
+ public void update (Item item)
+ {
+ var name = item.get_value ("name");
+ if (name != null && name != alias)
+ alias = name;
+
+ var avatar_path = item.get_value ("icon");
+ if (avatar_path != null)
+ {
+ var avatar_file = File.new_for_path (avatar_path);
+ if (avatar != avatar_file)
+ avatar = avatar_file;
+ }
+ }
+}
VALADOC_REQUIRED=0.2.1
TRACKER_SPARQL_REQUIRED=0.10
GCONF2_REQUIRED=2.31
+SW_CLIENT_REQUIRED=0.25
PKG_CHECK_MODULES([GLIB],
[glib-2.0 >= $GLIB_REQUIRED
[tracker-sparql-0.10 >= $TRACKER_SPARQL_REQUIRED])
fi
+PKG_CHECK_MODULES([SW_CLIENT], [libsocialweb-client >= $SW_CLIENT_REQUIRED])
+VALA_CHECK_PACKAGES([telepathy-glib
+ dbus-glib-1
+ gio-2.0
+ gee-1.0
+ libsocialweb-client])
+
#
# Vala building options -- allows tarball builds without installing Vala
#
Makefile
backends/Makefile
backends/key-file/Makefile
+ backends/libsocialweb/Makefile
backends/telepathy/Makefile
backends/telepathy/lib/Makefile
backends/tracker/Makefile