[folks] ofono: Added new Ofono backend to read contacts from SIM cards.
- From: Jeremy Whiting <jpwhiting src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] ofono: Added new Ofono backend to read contacts from SIM cards.
- Date: Wed, 10 Oct 2012 22:30:03 +0000 (UTC)
commit e82b632f96ea49bd55f28228de4729bc64fb57b9
Author: Jeremy Whiting <jpwhiting kde org>
Date: Fri Sep 28 15:13:39 2012 -0600
ofono: Added new Ofono backend to read contacts from SIM cards.
backends/Makefile.am | 4 +
backends/ofono/Makefile.am | 73 ++++++
backends/ofono/ofono-backend-factory.vala | 71 ++++++
backends/ofono/ofono-backend.vala | 338 +++++++++++++++++++++++++++++
backends/ofono/ofono-persona-store.vala | 291 +++++++++++++++++++++++++
backends/ofono/ofono-persona.vala | 230 ++++++++++++++++++++
backends/ofono/org-ofono.vala | 59 +++++
configure.ac | 33 +++
8 files changed, 1099 insertions(+), 0 deletions(-)
---
diff --git a/backends/Makefile.am b/backends/Makefile.am
index a81ed00..ec9659a 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -18,6 +18,10 @@ if ENABLE_EDS
SUBDIRS += eds
endif
+if ENABLE_OFONO
+SUBDIRS += ofono
+endif
+
DIST_SUBDIRS = \
telepathy \
key-file \
diff --git a/backends/ofono/Makefile.am b/backends/ofono/Makefile.am
new file mode 100644
index 0000000..966e5f4
--- /dev/null
+++ b/backends/ofono/Makefile.am
@@ -0,0 +1,73 @@
+BACKEND_NAME = "ofono"
+
+backenddir = $(BACKEND_DIR)/ofono
+backend_LTLIBRARIES = ofono.la
+
+ofono_la_SOURCES = \
+ ofono-backend.vala \
+ ofono-backend-factory.vala \
+ ofono-persona.vala \
+ ofono-persona-store.vala \
+ org-ofono.vala \
+ $(NULL)
+
+ofono_la_VALAFLAGS = \
+ $(AM_VALAFLAGS) \
+ $(ERROR_VALAFLAGS) \
+ --vapidir=. \
+ --vapidir=$(top_srcdir)/folks \
+ --pkg folks \
+ --pkg folks-internal \
+ --pkg gee-1.0 \
+ --pkg gio-2.0 \
+ --pkg gobject-2.0 \
+ --pkg libebook-1.2 \
+ --pkg libedataserver-1.2 \
+ $(NULL)
+
+# FIXME: libedataserver-1.2 doesn't need to be explicitly mentioned
+# once we depend on libebook version that includes libedataserver-1.2
+# in libebook-1.2.deps.
+
+ofono_la_CPPFLAGS = \
+ -I$(top_srcdir)/folks \
+ -include $(CONFIG_HEADER) \
+ -DPACKAGE_DATADIR=\"$(pkgdatadir)\" \
+ -DBACKEND_NAME=\"$(BACKEND_NAME)\" \
+ -DG_LOG_DOMAIN=\"$(BACKEND_NAME)\" \
+ $(NULL)
+
+ofono_la_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(CODE_COVERAGE_CFLAGS) \
+ $(GIO_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GEE_CFLAGS) \
+ $(EBOOK_CFLAGS) \
+ $(NULL)
+
+ofono_la_LIBADD = \
+ $(AM_LIBADD) \
+ $(GIO_LIBS) \
+ $(GLIB_LIBS) \
+ $(GEE_LIBS) \
+ $(EBOOK_LIBS) \
+ $(top_builddir)/folks/libfolks.la \
+ $(top_builddir)/folks/libfolks-internal.la \
+ $(NULL)
+
+ofono_la_LDFLAGS = \
+ $(AM_LDFLAGS) \
+ $(CODE_COVERAGE_LDFLAGS) \
+ -shared \
+ -fPIC \
+ -module \
+ -avoid-version \
+ $(NULL)
+
+GITIGNOREFILES = \
+ $(ofono_la_SOURCES:.vala=.c) \
+ ofono_la_vala.stamp \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/backends/ofono/ofono-backend-factory.vala b/backends/ofono/ofono-backend-factory.vala
new file mode 100644
index 0000000..5a8aa33
--- /dev/null
+++ b/backends/ofono/ofono-backend-factory.vala
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2012 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:
+ * Jeremy Whiting <jeremy whiting collabora co uk>
+ *
+ * Based on kf-backend-factory.vala by:
+ * Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ * Travis Reitter <travis reitter collabora co uk>
+ * Philip Withnall <philip withnall collabora co uk>
+ */
+
+using Folks;
+using Folks.Backends.Ofono;
+
+private BackendFactory? _backend_factory = null;
+
+/**
+ * The backend module entry point.
+ *
+ * @param backend_store the { link BackendStore} to use in this factory.
+ *
+ * @since UNRELEASED
+ */
+public void module_init (BackendStore backend_store)
+{
+ _backend_factory = new BackendFactory (backend_store);
+}
+
+/**
+ * The backend module exit point.
+ *
+ * @param backend_store the { link BackendStore} used in this factory.
+ *
+ * @since UNRELEASED
+ */
+public void module_finalize (BackendStore backend_store)
+{
+ _backend_factory = null;
+}
+
+/**
+ * A backend factory to create a single { link Backend}.
+ *
+ * @since UNRELEASED
+ */
+public class Folks.Backends.Ofono.BackendFactory : Object
+{
+ /**
+ * { inheritDoc}
+ */
+ public BackendFactory (BackendStore backend_store)
+ {
+ backend_store.add_backend (new Backend ());
+ }
+}
diff --git a/backends/ofono/ofono-backend.vala b/backends/ofono/ofono-backend.vala
new file mode 100644
index 0000000..404b098
--- /dev/null
+++ b/backends/ofono/ofono-backend.vala
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2012 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:
+ * Jeremy Whiting <jeremy whiting collabora co uk>
+ *
+ * Based on kf-backend.vala by:
+ * Philip Withnall <philip withnall collabora co uk>
+ */
+
+using GLib;
+using Gee;
+using Folks;
+using Folks.Backends.Ofono;
+using org.ofono;
+
+extern const string BACKEND_NAME;
+
+/**
+ * A backend which loads { link Persona}s from Modem
+ * devices using the Ofono Phonebook D-Bus API and presents them
+ * using one { link PersonaStore} per device.
+ *
+ * @since UNRELEASED
+ */
+public class Folks.Backends.Ofono.Backend : Folks.Backend
+{
+ private bool _is_prepared = false;
+ private bool _prepare_pending = false; /* used for unprepare() too */
+ private bool _is_quiescent = false;
+ private HashMap<string, PersonaStore> _persona_stores;
+ private Map<string, PersonaStore> _persona_stores_ro;
+ private ModemProperties[] _modems;
+
+ /**
+ * { inheritDoc}
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override bool is_quiescent
+ {
+ get { return this._is_quiescent; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override string name { get { return BACKEND_NAME; } }
+
+ /**
+ * { inheritDoc}
+ */
+ public override Map<string, PersonaStore> persona_stores
+ {
+ get { return this._persona_stores_ro; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override void disable_persona_store (Folks.PersonaStore store)
+ {
+ if (this._persona_stores.has_key (store.id))
+ {
+ this._store_removed_cb (store);
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override void enable_persona_store (Folks.PersonaStore store)
+ {
+ if (this._persona_stores.has_key (store.id) == false)
+ {
+ this._add_store ((Ofono.PersonaStore) store);
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override void set_persona_stores (Set<string>? storeids)
+ {
+ bool added_stores = false;
+ PersonaStore[] removed_stores = {};
+
+ /* First handle adding any missing persona stores. */
+ foreach (ModemProperties modem in this._modems)
+ {
+ if (modem.path in storeids &&
+ this._persona_stores.has_key (modem.path) == false)
+ {
+ string alias = this._modem_alias (modem.properties);
+ PersonaStore store = new Ofono.PersonaStore (modem.path, alias);
+ this._add_store (store, false);
+ added_stores = true;
+ }
+ }
+
+ foreach (PersonaStore store in this._persona_stores.values)
+ {
+ if (!storeids.contains (store.id))
+ {
+ removed_stores += store;
+ }
+ }
+
+ for (int i = 0; i < removed_stores.length; ++i)
+ {
+ this._remove_store ((Ofono.PersonaStore) removed_stores[i], false);
+ }
+
+ /* Finally, if anything changed, emit the persona-stores notification. */
+ if (added_stores || removed_stores.length > 0)
+ {
+ this.notify_property ("persona-stores");
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public Backend ()
+ {
+ Object ();
+ }
+
+ construct
+ {
+ this._persona_stores = new HashMap<string, PersonaStore> ();
+ this._persona_stores_ro = this._persona_stores.read_only_view;
+ }
+
+ private void _add_modem (ObjectPath path, string alias)
+ {
+ PersonaStore store =
+ new Ofono.PersonaStore (path, alias);
+
+ this._add_store (store);
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override async void prepare () throws GLib.Error
+ {
+ Internal.profiling_start ("preparing Ofono.Backend");
+
+ if (this._is_prepared || this._prepare_pending)
+ {
+ return;
+ }
+
+ try
+ {
+ this._prepare_pending = true;
+
+ /* New modem devices can be caught in notifications */
+ Manager manager = yield Bus.get_proxy (BusType.SYSTEM,
+ "org.ofono",
+ "/");
+ manager.ModemAdded.connect (this._modem_added);
+ manager.ModemRemoved.connect (this._modem_removed);
+
+ this._modems = manager.GetModems ();
+
+ foreach (ModemProperties modem in this._modems)
+ {
+ this._modem_added (modem.path, modem.properties);
+ }
+
+ this.freeze_notify ();
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+
+ this._is_quiescent = true;
+ this.notify_property ("is-quiescent");
+ this.thaw_notify ();
+ }
+ finally
+ {
+ this._prepare_pending = false;
+ }
+
+ Internal.profiling_end ("preparing Ofono.Backend");
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override async void unprepare () throws GLib.Error
+ {
+ if (!this._is_prepared || this._prepare_pending == true)
+ {
+ return;
+ }
+
+ try
+ {
+ this._prepare_pending = true;
+
+ foreach (var persona_store in this._persona_stores.values)
+ {
+ this.persona_store_removed (persona_store);
+ }
+
+ this.freeze_notify ();
+ this._persona_stores.clear ();
+ this.notify_property ("persona-stores");
+
+ this._is_quiescent = false;
+ this.notify_property ("is-quiescent");
+
+ this._is_prepared = false;
+ this.notify_property ("is-prepared");
+ this.thaw_notify ();
+ }
+ finally
+ {
+ this._prepare_pending = false;
+ }
+ }
+
+ /**
+ * Utility function to extract a modem's alias from its properties.
+ *
+ * @param properties, the properties of the modem.
+ * @returns the alias to use for this modem.
+ */
+ private string _modem_alias (HashTable<string, Variant> properties)
+ {
+ string alias = "";
+
+ /* Name is more user friendly than Manufacturer, but both are optional,
+ * so use Name if it's there, otherwise Manufacturer, otherwise leave
+ * it blank. */
+ Variant? name_variant = properties.get ("Name");
+ Variant? manufacturer_variant = properties.get ("Manufacturer");
+ if (name_variant != null)
+ {
+ alias = name_variant.get_string ();
+ }
+ else if (manufacturer_variant != null)
+ {
+ alias = manufacturer_variant.get_string ();
+ }
+ return alias;
+ }
+
+ private void _modem_added (ObjectPath path, HashTable<string, Variant> properties)
+ {
+ Variant? features_variant = properties.get ("Features");
+ if (features_variant != null)
+ {
+ string alias = this._modem_alias (properties);
+ string[] features = features_variant.get_strv ();
+
+ foreach (string feature in features)
+ {
+ if (feature == "sim")
+ {
+ /* This modem has a sim card, so add a persona store for it */
+ this._add_modem (path, alias);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Utility function to add a persona store.
+ *
+ * @param store the store to add.
+ * @param notify whether or not to emit notification signals.
+ */
+ private void _add_store (PersonaStore store, bool notify = true)
+ {
+ this._persona_stores.set (store.id, store);
+ store.removed.connect (this._store_removed_cb);
+ this.persona_store_added (store);
+ if (notify)
+ {
+ this.notify_property ("persona-stores");
+ }
+ }
+
+ /**
+ * Utility function to remove a persona store.
+ *
+ * @param store the store to remove.
+ * @param notify whether or not to emit notification signals.
+ */
+ private void _remove_store (PersonaStore store, bool notify = true)
+ {
+ store.removed.disconnect (this._store_removed_cb);
+ this._persona_stores.unset (store.id);
+ this.persona_store_removed (store);
+
+ if (notify)
+ {
+ this.notify_property ("persona-stores");
+ }
+ }
+
+
+ private void _modem_removed (ObjectPath path)
+ {
+ if (this._persona_stores.has_key (path))
+ {
+ this._store_removed_cb (this._persona_stores.get (path));
+ }
+ }
+
+ private void _store_removed_cb (Folks.PersonaStore store)
+ {
+ this._remove_store ((Ofono.PersonaStore) store);
+ }
+}
diff --git a/backends/ofono/ofono-persona-store.vala b/backends/ofono/ofono-persona-store.vala
new file mode 100644
index 0000000..05a2dad
--- /dev/null
+++ b/backends/ofono/ofono-persona-store.vala
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2012 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:
+ * Jeremy Whiting <jeremy whiting collabora co uk>
+ *
+ * Based on kf-persona-store.vala by:
+ * Travis Reitter <travis reitter collabora co uk>
+ * Philip Withnall <philip withnall collabora co uk>
+ */
+
+using GLib;
+using Gee;
+using Folks;
+using Folks.Backends.Ofono;
+
+/**
+ * A persona store which is associated with a single Ofono device. It will
+ * create a { link Persona} for each contact on the SIM card phonebook.
+ *
+ * @since UNRELEASED
+ */
+public class Folks.Backends.Ofono.PersonaStore : Folks.PersonaStore
+{
+ private HashMap<string, Persona> _personas;
+ private Map<string, Persona> _personas_ro;
+ private bool _is_prepared = false;
+ private bool _prepare_pending = false;
+ private bool _is_quiescent = false;
+
+ private static string[] _always_writeable_properties = {};
+ private ObjectPath? _path = null;
+
+ private org.ofono.Phonebook? _ofono_phonebook = null;
+
+ /**
+ * { inheritDoc}
+ */
+ public override string type_id { get { return BACKEND_NAME; } }
+
+ /**
+ * { inheritDoc}
+ */
+ public override MaybeBool can_add_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override MaybeBool can_alias_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override MaybeBool can_group_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override MaybeBool can_remove_personas
+ {
+ get { return MaybeBool.FALSE; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override bool is_quiescent
+ {
+ get { return this._is_quiescent; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override string[] always_writeable_properties
+ {
+ get { return Ofono.PersonaStore._always_writeable_properties; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override Map<string, Persona> personas
+ {
+ get { return this._personas_ro; }
+ }
+
+ /**
+ * Create a new PersonaStore.
+ *
+ * Create a new persona store to expose the { link Persona}s provided by the
+ * modem with the given address.
+ *
+ * @param path the D-Bus object path of this modem
+ * @param alias the name this modem should display to users
+ *
+ * @since UNRELEASED
+ */
+ public PersonaStore (ObjectPath path, string alias)
+ {
+ Object (id: path,
+ display_name: alias);
+
+ this.trust_level = PersonaStoreTrust.FULL;
+ this._personas = new HashMap<string, Persona> ();
+ this._personas_ro = this._personas.read_only_view;
+ this._path = path;
+ }
+
+ private void _property_changed (string property, Variant value)
+ {
+ if (property == "Present" && value.get_boolean () == false)
+ {
+ this._remove_self ();
+ }
+ }
+
+ private void _remove_self ()
+ {
+ /* Marshal the personas from a Collection to a Set. */
+ var removed_personas = new HashSet<Persona> ();
+ var iter = this._personas.map_iterator ();
+
+ while (iter.next () == true)
+ {
+ removed_personas.add (iter.get_value ());
+ }
+
+ this._emit_personas_changed (null, removed_personas);
+ this.removed ();
+ }
+
+ private string[] _split_all_vcards (string all_vcards)
+ {
+ /* Ofono vcards are in vcard 3.0 format and can include the following:
+ * FN, CATEGORIES, EMAIL and IMPP fields. */
+ string[] lines = all_vcards.split ("\n");
+ string[] vcards = {};
+ string vcard = "";
+
+ foreach (string line in lines)
+ {
+ vcard += line;
+ vcard += "\n";
+
+ if (line.strip () == "END:VCARD")
+ {
+ vcards += vcard;
+ vcard = "";
+ }
+ }
+
+ return vcards;
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override async void prepare () throws IOError, DBusError
+ {
+ Internal.profiling_start ("preparing Ofono.PersonaStore (ID: %s)",
+ this.id);
+
+ if (this._is_prepared || this._prepare_pending)
+ {
+ return;
+ }
+
+ try
+ {
+ this._prepare_pending = true;
+ this._ofono_phonebook = yield Bus.get_proxy (BusType.SYSTEM,
+ "org.ofono",
+ this._path);
+
+ org.ofono.SimManager sim_manager = yield Bus.get_proxy (BusType.SYSTEM,
+ "org.ofono",
+ this._path);
+ sim_manager.PropertyChanged.connect (this._property_changed);
+
+ string all_vcards = this._ofono_phonebook.Import ();
+
+ string[] vcards = this._split_all_vcards (all_vcards);
+
+ HashSet<Persona> added_personas = new HashSet<Persona> ();
+
+ foreach (string vcard in vcards)
+ {
+ Persona persona = new Persona (vcard, this);
+ this._personas.set (persona.iid, persona);
+ added_personas.add (persona);
+ }
+
+ if (this._personas.size > 0)
+ {
+ this._emit_personas_changed (added_personas, null);
+ }
+ }
+ catch (GLib.DBusError e)
+ {
+ warning ("DBus Error has occurred when fetching ofono phonebook, %s", e.message);
+ this._remove_self ();
+ }
+ catch (GLib.IOError e)
+ {
+ warning ("IO Error has occurred when fetching ofono phonebook, %s", e.message);
+ this._remove_self ();
+ }
+ finally
+ {
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+
+ /* We've finished loading all the personas we know about */
+ this._is_quiescent = true;
+ this.notify_property ("is-quiescent");
+
+ this._prepare_pending = false;
+ }
+
+ Internal.profiling_end ("preparing Ofono.PersonaStore (ID: %s)", this.id);
+ }
+
+ /**
+ * Remove a { link Persona} from the PersonaStore.
+ *
+ * See { link Folks.PersonaStore.remove_persona}.
+ *
+ * @throws Folks.PersonaStoreError.READ_ONLY every time since the
+ * Ofono backend is read-only.
+ *
+ * @param persona the { link Persona} to remove.
+ *
+ * @since UNRELEASED
+ */
+ public override async void remove_persona (Folks.Persona persona)
+ throws Folks.PersonaStoreError
+ {
+ throw new PersonaStoreError.READ_ONLY (
+ "Personas cannot be removed from this store.");
+ }
+
+ /**
+ * Add a new { link Persona} to the PersonaStore.
+ *
+ * See { link Folks.PersonaStore.add_persona_from_details}.
+ *
+ * @throws Folks.PersonaStoreError.READ_ONLY every time since the
+ * Ofono backend is read-only.
+ *
+ * @param details the details of the { link Persona} to add.
+ *
+ * @since UNRELEASED
+ */
+ public override async Folks.Persona? add_persona_from_details (
+ HashTable<string, Value?> details) throws Folks.PersonaStoreError
+ {
+ throw new PersonaStoreError.READ_ONLY (
+ "Personas cannot be added to this store.");
+ }
+}
diff --git a/backends/ofono/ofono-persona.vala b/backends/ofono/ofono-persona.vala
new file mode 100644
index 0000000..79a91ed
--- /dev/null
+++ b/backends/ofono/ofono-persona.vala
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2012 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:
+ * Jeremy Whiting <jeremy whiting collabora co uk>
+ *
+ * Based on kf-persona.vala by:
+ * Philip Withnall <philip withnall collabora co uk>
+ */
+
+using GLib;
+using Gee;
+using Folks;
+using Folks.Backends.Ofono;
+
+/**
+ * A persona subclass which represents a single persona from a simple key file.
+ *
+ * @since UNRELEASED
+ */
+public class Folks.Backends.Ofono.Persona : Folks.Persona,
+ EmailDetails,
+ NameDetails,
+ PhoneDetails
+{
+ private StructuredName? _structured_name = null;
+ private string _full_name = "";
+ private string _nickname = "";
+ private HashSet<PhoneFieldDetails> _phone_numbers;
+ private Set<PhoneFieldDetails> _phone_numbers_ro;
+ private HashSet<EmailFieldDetails> _email_addresses;
+ private Set<EmailFieldDetails> _email_addresses_ro;
+
+ private const string[] _linkable_properties =
+ {
+ "phone-numbers",
+ "email-addresses"
+ };
+ private static string[] _writeable_properties = {};
+
+ /**
+ * { inheritDoc}
+ */
+ public override string[] linkable_properties
+ {
+ get { return Ofono.Persona._linkable_properties; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override string[] writeable_properties
+ {
+ get { return Ofono.Persona._writeable_properties; }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ [CCode (notify = false)]
+ public Set<PhoneFieldDetails> phone_numbers
+ {
+ get { return this._phone_numbers_ro; }
+ set { this.change_phone_numbers.begin (value); } /* not writeable */
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ [CCode (notify = false)]
+ public StructuredName? structured_name
+ {
+ get { return this._structured_name; }
+ set { this.change_structured_name.begin (value); } /* not writeable */
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ [CCode (notify = false)]
+ public string full_name
+ {
+ get { return this._full_name; }
+ set { this.change_full_name.begin (value); } /* not writeable */
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ [CCode (notify = false)]
+ public string nickname
+ {
+ get { return this._nickname; }
+ set { this.change_nickname.begin (value); } /* not writeable */
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ [CCode (notify = false)]
+ public Set<EmailFieldDetails> email_addresses
+ {
+ get { return this._email_addresses_ro; }
+ set { this.change_email_addresses.begin (value); } /* not writeable */
+ }
+
+ /**
+ * Create a new persona.
+ *
+ * Create a new persona for the given vCard contents.
+ *
+ * @param vcard the vCard data to use for this { link Persona}.
+ * @param store the { link PersonaStore} this { link Persona} belongs to.
+ *
+ * @since UNRELEASED
+ */
+ public Persona (string vcard, Folks.PersonaStore store)
+ {
+ var iid = Checksum.compute_for_string (ChecksumType.SHA1, vcard);
+ var uid = Folks.Persona.build_uid ("ofono", store.id, iid);
+
+ Object (display_id: uid,
+ iid: iid,
+ uid: uid,
+ store: store,
+ is_user: false);
+ this._set_vcard (vcard);
+ }
+
+ construct
+ {
+ debug ("Adding Ofono Persona '%s' (IID '%s', group '%s')", this.uid,
+ this.iid, this.display_id);
+
+ this._phone_numbers = new HashSet<PhoneFieldDetails> ();
+ this._phone_numbers_ro = this._phone_numbers.read_only_view;
+
+ this._email_addresses = new HashSet<EmailFieldDetails> ();
+ this._email_addresses_ro = this._email_addresses.read_only_view;
+ }
+
+ private void _set_vcard (string vcard)
+ {
+ E.VCard card = new E.VCard.from_string (vcard);
+
+ E.VCardAttribute? attribute = card.get_attribute ("TEL");
+ if (attribute != null)
+ {
+ this._phone_numbers.add (new PhoneFieldDetails (attribute.get_value_decoded ().str) );
+ }
+
+ attribute = card.get_attribute ("FN");
+ if (attribute != null)
+ {
+ this._full_name = attribute.get_value_decoded ().str;
+ }
+
+ attribute = card.get_attribute ("NICKNAME");
+ if (attribute != null)
+ {
+ this._nickname = attribute.get_value_decoded ().str;
+ }
+
+ attribute = card.get_attribute ("N");
+ if (attribute != null)
+ {
+ unowned GLib.List<StringBuilder> values = attribute.get_values_decoded ();
+ if (values.length () >= 5)
+ {
+ this._structured_name = new StructuredName (values.nth_data (0).str,
+ values.nth_data (1).str,
+ values.nth_data (2).str,
+ values.nth_data (3).str,
+ values.nth_data (4).str);
+ }
+ else
+ {
+ warning ("Expected 5 components to N value of vcard, got %u", values.length ());
+ }
+ }
+
+ attribute = card.get_attribute ("EMAIL");
+ if (attribute != null)
+ {
+ this._email_addresses.add (new EmailFieldDetails (attribute.get_value_decoded ().str) );
+ }
+ }
+
+ /**
+ * { inheritDoc}
+ */
+ public override void linkable_property_to_links (string prop_name,
+ Folks.Persona.LinkablePropertyCallback callback)
+ {
+ if (prop_name == "phone-numbers")
+ {
+ foreach (var phone_number in this._phone_numbers)
+ {
+ if (phone_number.value != null)
+ callback (phone_number.value);
+ }
+ }
+ else if (prop_name == "email-addresses")
+ {
+ foreach (var email_address in this._email_addresses)
+ {
+ if (email_address.value != null)
+ callback (email_address.value);
+ }
+ }
+ else
+ {
+ /* Chain up */
+ base.linkable_property_to_links (prop_name, callback);
+ }
+ }
+}
diff --git a/backends/ofono/org-ofono.vala b/backends/ofono/org-ofono.vala
new file mode 100644
index 0000000..cc069bd
--- /dev/null
+++ b/backends/ofono/org-ofono.vala
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 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:
+ * Jeremy Whiting <jeremy whiting collabora co uk>
+ */
+
+using GLib;
+
+namespace org
+ {
+ namespace ofono
+ {
+ public struct ModemProperties
+ {
+ ObjectPath path;
+ HashTable<string, Variant> properties;
+ }
+
+ [DBus (name = "org.ofono.Manager")]
+ public interface Manager : Object
+ {
+ [DBus (name = "GetModems")]
+ public abstract ModemProperties[] GetModems() throws DBusError, IOError;
+
+ public signal void ModemAdded (ObjectPath path, HashTable<string, Variant> properties);
+ public signal void ModemRemoved (ObjectPath path);
+ }
+
+ [DBus (name = "org.ofono.Phonebook")]
+ public interface Phonebook : Object
+ {
+ [DBus (name = "Import")]
+ public abstract string Import() throws DBusError, IOError;
+ }
+
+ [DBus (name = "org.ofono.SimManager")]
+ public interface SimManager : Object
+ {
+ [DBus (name = "GetProperties")]
+ public abstract HashTable<string, Variant> GetProperties() throws DBusError, IOError;
+
+ public signal void PropertyChanged (string property, Variant value);
+ }
+ }
+ }
diff --git a/configure.ac b/configure.ac
index 8337642..9c460c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -100,6 +100,20 @@ AS_IF([test "x$enable_eds_backend" = "xyes"], [
AM_CONDITIONAL([ENABLE_EDS], [test "x$enable_eds_backend" = "xyes"])
+AC_ARG_ENABLE(ofono-backend,
+ AC_HELP_STRING([--enable-ofono-backend],
+ [ build the ofono backend]),
+ enable_ofono_backend=$enableval,
+ enable_ofono_backend=yes )
+
+AS_IF([test "x$enable_ofono_backend" = "xyes"], [
+ AC_DEFINE(HAVE_OFONO, [1], [Define as 1 if you have the ofono backend])
+], [
+ AC_DEFINE(HAVE_OFONO, [0], [Define as 1 if you have the ofono backend])
+])
+
+AM_CONDITIONAL([ENABLE_OFONO], [test "x$enable_ofono_backend" = "xyes"])
+
AC_ARG_ENABLE(telepathy-backend,
AC_HELP_STRING([--enable-telepathy-backend],
[ build the Telepathy backend]),
@@ -211,6 +225,10 @@ AS_IF([test x$enable_eds_backend = xyes], [
PKG_CHECK_MODULES([EDATASERVER], [libedataserver-1.2 >= $EDATASERVER_REQUIRED])
])
+AS_IF([test x$enable_ofono_backend = xyes], [
+ PKG_CHECK_MODULES([EBOOK], [libebook-1.2 >= $EBOOK_REQUIRED])
+])
+
#
# Vala building options -- allows tarball builds without installing Vala
#
@@ -297,6 +315,10 @@ AS_IF([test "x$enable_vala" = "xyes"], [
AS_IF([test x$enable_eds_backend = xyes], [
VALA_CHECK_PACKAGES([libebook-1.2 libedataserver-1.2 libxml-2.0])
])
+
+ AS_IF([test x$enable_ofono_backend = xyes], [
+ VALA_CHECK_PACKAGES([libebook-1.2])
+ ])
])
# this will set HAVE_INTROSPECTION
@@ -341,6 +363,11 @@ AS_IF([test x$enable_eds_backend = xyes], [
AC_SUBST([BACKEND_EDS])
])
+if test x$enable_ofono_backend = xyes; then
+ BACKEND_OFONO='$(top_builddir)/backends/ofono/.libs/ofono.so'
+ AC_SUBST([BACKEND_OFONO])
+fi
+
# All of the backend libraries in our tree; to be used by the tests
BACKEND_UNINST_PATH='$(BACKEND_KF):$(BACKEND_TP)'
AS_IF([test x$have_libsocialweb_backend = xyes], [
@@ -355,6 +382,10 @@ AS_IF([test x$enable_eds_backend = xyes], [
EDS_BACKEND_UNINST_PATH='$(BACKEND_EDS)'
BACKEND_UNINST_PATH="$BACKEND_UNINST_PATH:$EDS_BACKEND_UNINST_PATH"
])
+AS_IF([test x$enable_ofono_backend = xyes],
+ OFONO_BACKEND_UNINST_PATH='$(BACKEND_OFONO)'
+ BACKEND_UNINST_PATH="$BACKEND_UNINST_PATH:$OFONO_BACKEND_UNINST_PATH"
+])
AC_SUBST([BACKEND_UNINST_PATH])
# -----------------------------------------------------------
@@ -605,6 +636,7 @@ AC_CONFIG_FILES([
backends/tracker/lib/Makefile
backends/eds/Makefile
backends/eds/lib/Makefile
+ backends/ofono/Makefile
folks/Makefile
docs/Makefile
po/Makefile.in
@@ -649,5 +681,6 @@ Configure summary:
Tracker backend.............: ${enable_tracker_backend}
Libsocialweb backend........: ${have_libsocialweb_backend}
E-D-S backend...............: ${enable_eds_backend}
+ Ofono backend...............: ${enable_ofono_backend}
Build tests.................: ${enable_tests}
"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]