...
 
Commits (2)
  • Bob Ham's avatar
    Turn providers into plugins courtesy of libpeas · 460c0c6c
    Bob Ham authored
    This is an initial, static implementation of plugins.  The
    CallsApplication has a plugin name which can be changed with a new
    --provider command line option.  This plugin name is used to
    instantiate the appropriate plugin when the application is activated.
    From then on, the plugin cannot change.
    
    In future, we can expand this support to include loading multiple
    plugins at once, configurable through some UI.  This will have
    far-reaching implications though, and complicate things like
    enumerating the provider hierarchy.  There is also no practical
    benefit right now; the mm and ofono plugins can't be used at the same
    time because ModemManager and oFono don't play nice together, and the
    whole raison d'être of the dummy plugin is undermined if you can make
    use of one of the others.  So for now, we just implement one static
    plugin.
    460c0c6c
  • Bob Ham's avatar
    Merge branch 'plugins' into 'master' · 2d4ac90f
    Bob Ham authored
    Turn providers into plugins courtesy of libpeas
    
    See merge request Librem5/calls!35
    2d4ac90f
......@@ -9,6 +9,7 @@ Build-Depends:
modemmanager-dev,
libmm-glib-dev,
libgsound-dev,
libpeas-dev,
meson,
pkg-config,
# to run the tests
......
gnome = import('gnome')
dbus_interfaces = ['manager', 'modem', 'call']
gdbus_src = []
foreach iface: dbus_interfaces
gdbus_src += gnome.gdbus_codegen('gdbo-' + iface,
iface + '.xml',
interface_prefix: 'org.ofono.',
namespace: 'GDBO')
endforeach
deps = [ dependency('gio-2.0'),
dependency('gio-unix-2.0'),
]
gdbofono_lib = static_library('gdbofono',
gdbus_src,
include_directories : include_directories('..'),
dependencies : deps )
......@@ -19,11 +19,17 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
project('call', 'c',
version: '0.0.0',
license: 'GPLv3+',
meson_version: '>= 0.42.0',
default_options: [ 'warning_level=1', 'buildtype=debugoptimized', 'c_std=gnu11' ],
project(
'calls',
'c',
version: '0.0.0',
license: 'GPLv3+',
meson_version: '>= 0.46.0',
default_options: [
'warning_level=1',
'buildtype=debugoptimized',
'c_std=gnu11'
]
)
calls_id = 'sm.puri.Calls'
......@@ -31,9 +37,26 @@ calls_homepage = 'https://source.puri.sm/Librem5/calls'
calls_name = meson.project_name()
calls_version = meson.project_version()
subdir('libgdbofono')
top_include = include_directories('.')
prefix = get_option('prefix')
libdir = get_option('libdir')
localedir = get_option('localedir')
full_localedir = join_paths(prefix, localedir)
full_calls_plugin_libdir = join_paths(prefix, libdir, calls_name, 'plugins')
config_data = configuration_data()
config_data.set_quoted('APP_ID', calls_id)
config_data.set_quoted('GETTEXT_PACKAGE', calls_name)
config_data.set_quoted('LOCALEDIR', full_localedir)
config_data.set_quoted('PLUGIN_LIBDIR', full_calls_plugin_libdir)
config_data.set_quoted('PACKAGE_URL', calls_homepage)
config_data.set_quoted('PACKAGE_VERSION', calls_version)
config_data.set('PACKAGE_URL_RAW', calls_homepage)
subdir('po')
subdir('src')
subdir('plugins')
subdir('doc')
subdir('data')
subdir('tests')
......@@ -27,6 +27,9 @@
#include "calls-provider.h"
#include "calls-dummy-origin.h"
#include <libpeas/peas.h>
struct _CallsDummyProvider
{
GObject parent_instance;
......@@ -37,12 +40,26 @@ struct _CallsDummyProvider
static void calls_dummy_provider_message_source_interface_init (CallsProviderInterface *iface);
static void calls_dummy_provider_provider_interface_init (CallsProviderInterface *iface);
G_DEFINE_TYPE_WITH_CODE (CallsDummyProvider, calls_dummy_provider, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CALLS_TYPE_MESSAGE_SOURCE,
calls_dummy_provider_message_source_interface_init)
G_IMPLEMENT_INTERFACE (CALLS_TYPE_PROVIDER,
calls_dummy_provider_provider_interface_init))
#ifdef FOR_TESTING
G_DEFINE_TYPE_WITH_CODE
(CallsDummyProvider, calls_dummy_provider, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CALLS_TYPE_MESSAGE_SOURCE,
calls_dummy_provider_message_source_interface_init)
G_IMPLEMENT_INTERFACE (CALLS_TYPE_PROVIDER,
calls_dummy_provider_provider_interface_init))
#else
G_DEFINE_DYNAMIC_TYPE_EXTENDED
(CallsDummyProvider, calls_dummy_provider, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE_DYNAMIC (CALLS_TYPE_MESSAGE_SOURCE,
calls_dummy_provider_message_source_interface_init)
G_IMPLEMENT_INTERFACE_DYNAMIC (CALLS_TYPE_PROVIDER,
calls_dummy_provider_provider_interface_init))
#endif /* FOR_TESTING */
enum {
PROP_0,
......@@ -65,10 +82,15 @@ get_origins (CallsProvider *iface)
}
CallsDummyProvider *
calls_dummy_provider_new ()
static void
constructed (GObject *object)
{
return g_object_new (CALLS_TYPE_DUMMY_PROVIDER, NULL);
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
CallsDummyProvider *self = CALLS_DUMMY_PROVIDER (object);
calls_dummy_provider_add_origin (self, "Dummy origin");
parent_class->constructed (object);
}
......@@ -108,8 +130,9 @@ calls_dummy_provider_class_init (CallsDummyProviderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = dispose;
object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->dispose = dispose;
g_object_class_override_property (object_class, PROP_STATUS, "status");
}
......@@ -142,3 +165,31 @@ calls_dummy_provider_add_origin (CallsDummyProvider *self,
self->origins = g_list_append (self->origins,
calls_dummy_origin_new (name));
}
CallsDummyProvider *
calls_dummy_provider_new ()
{
return g_object_new (CALLS_TYPE_DUMMY_PROVIDER, NULL);
}
#ifndef FOR_TESTING
static void
calls_dummy_provider_class_finalize (CallsDummyProviderClass *klass)
{
}
G_MODULE_EXPORT void
peas_register_types (PeasObjectModule *module)
{
calls_dummy_provider_register_type (G_TYPE_MODULE (module));
peas_object_module_register_extension_type (module,
CALLS_TYPE_PROVIDER,
CALLS_TYPE_DUMMY_PROVIDER);
}
#endif /* FOR_TESTING */
[Plugin]
Module=dummy
Name=Dummy
Description=Dummy calls provider
Authors=Bob Ham <rah@settrans.net>
Copyright=Copyright (C) 2018 Purism SPC
Website=@PACKAGE_URL_RAW@
#
# Copyright (C) 2018 Purism SPC
#
# This file is part of Calls.
#
# Calls 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 3 of the License, or
# (at your option) any later version.
#
# Calls 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 Calls. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Bob Ham <bob.ham@puri.sm>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
dummy_include = include_directories('.')
dummy_install_dir = join_paths(full_calls_plugin_libdir, 'dummy')
dummy_plugin = configure_file(
input: 'dummy.plugin.in',
output: 'dummy.plugin',
configuration: config_data,
install_dir: dummy_install_dir
)
dummy_deps = [
dependency('gobject-2.0'),
dependency('gtk+-3.0'),
dependency('libpeas-1.0'),
]
dummy_sources = files(
[
'calls-dummy-call.c', 'calls-dummy-call.h',
'calls-dummy-origin.c', 'calls-dummy-origin.h',
'calls-dummy-provider.c', 'calls-dummy-provider.h'
]
)
shared_module(
'dummy',
dummy_sources,
dependencies: dummy_deps,
include_directories: src_include,
install: true,
install_dir: dummy_install_dir
)
subdir('mm')
subdir('dummy')
subdir('ofono')
......@@ -29,6 +29,7 @@
#include "calls-origin.h"
#include <libmm-glib.h>
#include <libpeas/peas.h>
#include <glib/gi18n.h>
struct _CallsMMProvider
......@@ -48,11 +49,13 @@ struct _CallsMMProvider
static void calls_mm_provider_message_source_interface_init (CallsProviderInterface *iface);
static void calls_mm_provider_provider_interface_init (CallsProviderInterface *iface);
G_DEFINE_TYPE_WITH_CODE (CallsMMProvider, calls_mm_provider, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CALLS_TYPE_MESSAGE_SOURCE,
calls_mm_provider_message_source_interface_init)
G_IMPLEMENT_INTERFACE (CALLS_TYPE_PROVIDER,
calls_mm_provider_provider_interface_init))
G_DEFINE_DYNAMIC_TYPE_EXTENDED
(CallsMMProvider, calls_mm_provider, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE_DYNAMIC (CALLS_TYPE_MESSAGE_SOURCE,
calls_mm_provider_message_source_interface_init)
G_IMPLEMENT_INTERFACE_DYNAMIC (CALLS_TYPE_PROVIDER,
calls_mm_provider_provider_interface_init))
enum {
PROP_0,
......@@ -436,6 +439,11 @@ calls_mm_provider_class_init (CallsMMProviderClass *klass)
}
static void
calls_mm_provider_class_finalize (CallsMMProviderClass *klass)
{
}
static void
calls_mm_provider_message_source_interface_init (CallsProviderInterface *iface)
{
......@@ -459,8 +467,12 @@ calls_mm_provider_init (CallsMMProvider *self)
}
CallsMMProvider *
calls_mm_provider_new ()
G_MODULE_EXPORT void
peas_register_types (PeasObjectModule *module)
{
return g_object_new (CALLS_TYPE_MM_PROVIDER, NULL);
calls_mm_provider_register_type (G_TYPE_MODULE (module));
peas_object_module_register_extension_type (module,
CALLS_TYPE_PROVIDER,
CALLS_TYPE_MM_PROVIDER);
}
......@@ -34,8 +34,6 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CallsMMProvider, calls_mm_provider, CALLS, MM_PROVIDER, GObject);
CallsMMProvider *calls_mm_provider_new ();
G_END_DECLS
#endif /* CALLS_MM_PROVIDER_H__ */
#
# Copyright (C) 2018 Purism SPC
#
# This file is part of Calls.
#
# Calls 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 3 of the License, or
# (at your option) any later version.
#
# Calls 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 Calls. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Bob Ham <bob.ham@puri.sm>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
mm_install_dir = join_paths(full_calls_plugin_libdir, 'mm')
mm_plugin = configure_file(
input: 'mm.plugin.in',
output: 'mm.plugin',
configuration: config_data,
install_dir: mm_install_dir
)
mm_deps = [
dependency('gobject-2.0'),
dependency('gtk+-3.0'),
dependency('ModemManager'),
dependency('mm-glib'),
dependency('libpeas-1.0'),
]
mm_sources = files(
[
'calls-mm-call.c', 'calls-mm-call.h',
'calls-mm-origin.c', 'calls-mm-origin.h',
'calls-mm-provider.c', 'calls-mm-provider.h'
]
)
shared_module(
'mm',
mm_sources,
dependencies: mm_deps,
include_directories: src_include,
install: true,
install_dir: mm_install_dir
)
[Plugin]
Module=mm
Name=ModemManager
Description=ModemManager calls provider
Authors=Bob Ham <rah@settrans.net>
Copyright=Copyright (C) 2018 Purism SPC
Website=@PACKAGE_URL_RAW@
......@@ -32,6 +32,8 @@
#include <libgdbofono/gdbo-modem.h>
#include <glib/gi18n.h>
#include <libpeas/peas.h>
struct _CallsOfonoProvider
{
......@@ -47,21 +49,17 @@ struct _CallsOfonoProvider
GHashTable *origins;
};
static void calls_ofono_provider_message_source_interface_init (CallsProviderInterface *iface);
static void calls_ofono_provider_provider_interface_init (CallsProviderInterface *iface);
G_DEFINE_TYPE_WITH_CODE (CallsOfonoProvider, calls_ofono_provider, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CALLS_TYPE_MESSAGE_SOURCE,
calls_ofono_provider_message_source_interface_init)
G_IMPLEMENT_INTERFACE (CALLS_TYPE_PROVIDER,
calls_ofono_provider_provider_interface_init))
enum {
PROP_0,
PROP_CONNECTION,
PROP_LAST_PROP,
};
static GParamSpec *props[PROP_LAST_PROP];
G_DEFINE_DYNAMIC_TYPE_EXTENDED
(CallsOfonoProvider, calls_ofono_provider, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE_DYNAMIC (CALLS_TYPE_MESSAGE_SOURCE,
calls_ofono_provider_message_source_interface_init)
G_IMPLEMENT_INTERFACE_DYNAMIC (CALLS_TYPE_PROVIDER,
calls_ofono_provider_provider_interface_init))
static const gchar *
......@@ -70,6 +68,7 @@ get_name (CallsProvider *iface)
return "oFono";
}
static void
add_origin_to_list (const gchar *path,
CallsOfonoOrigin *origin,
......@@ -78,6 +77,7 @@ add_origin_to_list (const gchar *path,
*list = g_list_prepend (*list, origin);
}
static GList *
get_origins (CallsProvider *iface)
{
......@@ -90,36 +90,6 @@ get_origins (CallsProvider *iface)
return g_list_reverse (list);
}
CallsOfonoProvider *
calls_ofono_provider_new (GDBusConnection *connection)
{
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
return g_object_new (CALLS_TYPE_OFONO_PROVIDER,
"connection", connection,
NULL);
}
static void
set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
CallsOfonoProvider *self = CALLS_OFONO_PROVIDER (object);
switch (property_id) {
case PROP_CONNECTION:
g_set_object (&self->connection,
g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
add_origin (CallsOfonoProvider *self,
......@@ -137,6 +107,7 @@ add_origin (CallsOfonoProvider *self,
"origin-added", origin);
}
static void
remove_origin (CallsOfonoProvider *self,
const gchar *path,
......@@ -151,6 +122,7 @@ remove_origin (CallsOfonoProvider *self,
g_object_unref (origin);
}
static gboolean
object_array_includes (GVariantIter *iter,
const gchar *needle)
......@@ -170,6 +142,7 @@ object_array_includes (GVariantIter *iter,
return found;
}
static void
modem_check_ifaces (CallsOfonoProvider *self,
GDBOModem *modem,
......@@ -199,6 +172,7 @@ modem_check_ifaces (CallsOfonoProvider *self,
}
}
static void
modem_property_changed_cb (GDBOModem *modem,
const gchar *name,
......@@ -220,6 +194,7 @@ modem_property_changed_cb (GDBOModem *modem,
modem_check_ifaces (self, modem, modem_name, value);
}
struct CallsModemProxyNewData
{
CallsOfonoProvider *self;
......@@ -227,6 +202,7 @@ struct CallsModemProxyNewData
GVariant *ifaces;
};
static void
modem_proxy_new_cb (GDBusConnection *connection,
GAsyncResult *res,
......@@ -274,6 +250,7 @@ modem_proxy_new_cb (GDBusConnection *connection,
g_debug ("Modem `%s' added", path);
}
static gchar *
modem_properties_get_name (GVariant *properties)
{
......@@ -297,6 +274,7 @@ modem_properties_get_name (GVariant *properties)
return NULL;
}
static void
modem_added_cb (GDBOManager *manager,
const gchar *path,
......@@ -336,6 +314,7 @@ modem_added_cb (GDBOManager *manager,
g_debug ("Modem `%s' addition in progress", path);
}
static void
modem_removed_cb (GDBOManager *manager,
const gchar *path,
......@@ -405,6 +384,13 @@ constructed (GObject *object)
CallsOfonoProvider *self = CALLS_OFONO_PROVIDER (object);
GError *error = NULL;
self->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
if (!self->connection)
{
g_error ("Error creating D-Bus connection: %s",
error->message);
}
self->manager = gdbo_manager_proxy_new_sync
(self->connection,
G_DBUS_PROXY_FLAGS_NONE,
......@@ -416,7 +402,6 @@ constructed (GObject *object)
{
g_error ("Error creating ModemManager object manager proxy: %s",
error->message);
return;
}
g_signal_connect (self->manager, "modem-added",
......@@ -440,14 +425,13 @@ dispose (GObject *object)
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
CallsOfonoProvider *self = CALLS_OFONO_PROVIDER (object);
// FIXME
g_clear_object (&self->manager);
g_clear_object (&self->connection);
parent_class->dispose (object);
}
static void
finalize (GObject *object)
{
......@@ -466,26 +450,24 @@ calls_ofono_provider_class_init (CallsOfonoProviderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = set_property;
object_class->constructed = constructed;
object_class->dispose = dispose;
object_class->finalize = finalize;
}
props[PROP_CONNECTION] =
g_param_spec_object ("connection",
_("Connection"),
_("The D-Bus connection to use for communication with oFono"),
G_TYPE_DBUS_CONNECTION,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, PROP_LAST_PROP, props);
static void
calls_ofono_provider_class_finalize (CallsOfonoProviderClass *klass)
{
}
static void
calls_ofono_provider_message_source_interface_init (CallsProviderInterface *iface)
{
}
static void
calls_ofono_provider_provider_interface_init (CallsProviderInterface *iface)
{
......@@ -493,6 +475,7 @@ calls_ofono_provider_provider_interface_init (CallsProviderInterface *iface)
iface->get_origins = get_origins;
}
static void
calls_ofono_provider_init (CallsOfonoProvider *self)
{
......@@ -501,3 +484,14 @@ calls_ofono_provider_init (CallsOfonoProvider *self)
self->origins = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
}
G_MODULE_EXPORT void
peas_register_types (PeasObjectModule *module)
{
calls_ofono_provider_register_type (G_TYPE_MODULE (module));
peas_object_module_register_extension_type (module,
CALLS_TYPE_PROVIDER,
CALLS_TYPE_OFONO_PROVIDER);
}
......@@ -34,8 +34,6 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (CallsOfonoProvider, calls_ofono_provider, CALLS, OFONO_PROVIDER, GObject);
CallsOfonoProvider *calls_ofono_provider_new (GDBusConnection *connection);
G_END_DECLS
#endif /* CALLS_OFONO_PROVIDER_H__ */
#
# Copyright (C) 2018 Purism SPC
#
# This file is part of Calls.
#
# Calls 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 3 of the License, or
# (at your option) any later version.
#
# Calls 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 Calls. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Bob Ham <bob.ham@puri.sm>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
gnome = import('gnome')
dbus_interfaces = ['manager', 'modem', 'call']
gdbofono_src = []
gdbofono_headers = []
foreach iface: dbus_interfaces
src = gnome.gdbus_codegen(
'gdbo-' + iface,
iface + '.xml',
interface_prefix: 'org.ofono.',
namespace: 'GDBO'
)
gdbofono_src += src
gdbofono_headers += src[1]
endforeach
gdbofono_deps = [
dependency('gio-2.0'),
dependency('gio-unix-2.0'),
]
gdbofono_lib = static_library(
'gdbofono',
gdbofono_src,
include_directories: top_include,
dependencies: gdbofono_deps
)
#
# Copyright (C) 2018 Purism SPC
#
# This file is part of Calls.
#
# Calls 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 3 of the License, or
# (at your option) any later version.
#
# Calls 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 Calls. If not, see <http://www.gnu.org/licenses/>.
#
# Author: Bob Ham <bob.ham@puri.sm>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
subdir('libgdbofono')
ofono_install_dir = join_paths(full_calls_plugin_libdir, 'ofono')
ofono_plugin = configure_file(
input: 'ofono.plugin.in',
output: 'ofono.plugin',
configuration: config_data,
install_dir: ofono_install_dir
)
ofono_deps = [
dependency('gobject-2.0'),
dependency('gtk+-3.0'),
dependency('libpeas-1.0'),
]
ofono_sources = files(
[
'calls-ofono-call.c', 'calls-ofono-call.h',
'calls-ofono-origin.c', 'calls-ofono-origin.h',
'calls-ofono-provider.c', 'calls-ofono-provider.h'
]
)
shared_module(
'ofono',
ofono_sources, gdbofono_headers,
dependencies: ofono_deps,
include_directories: [
src_include,
include_directories('.')
],
link_with: gdbofono_lib,
install: true,
install_dir: ofono_install_dir
)
[Plugin]
Module=ofono
Name=oFono
Description=oFono calls provider
Authors=Bob Ham <rah@settrans.net>
Copyright=Copyright (C) 2018 Purism SPC
Website=@PACKAGE_URL_RAW@
......@@ -25,23 +25,23 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <glib/gi18n.h>
#define HANDY_USE_UNSTABLE_API
#include <handy.h>
#include "config.h"
#include "calls-new-call-header-bar.h"
#include "calls-history-header-bar.h"
#include "calls-history-box.h"
#include "calls-new-call-box.h"
#include "calls-encryption-indicator.h"
#include "calls-mm-provider.h"
#include "calls-ringer.h"
#include "calls-call-window.h"
#include "calls-main-window.h"
#include "calls-application.h"
#define HANDY_USE_UNSTABLE_API
#include <handy.h>
#include <libpeas/peas.h>
#include <glib/gi18n.h>
/**
* SECTION: calls-application
* @title: CallsApplication
......@@ -49,10 +49,13 @@
* @include: "calls-application.h"
*/
#define DEFAULT_PROVIDER_PLUGIN "mm"
struct _CallsApplication
{
GtkApplication parent_instance;
GString *provider_name;
CallsProvider *provider;
CallsRinger *ringer;
};
......@@ -60,68 +63,251 @@ struct _CallsApplication
G_DEFINE_TYPE (CallsApplication, calls_application, GTK_TYPE_APPLICATION)
static gint
handle_local_options (GApplication *application,
GVariantDict *options)
{
gboolean ok;
g_autoptr(GError) error = NULL;
const gchar *name;
g_debug ("Registering application");
ok = g_application_register (application, NULL, &error);
if (!ok)
{
g_error ("Error registering application: %s",
error->message);
}
ok = g_variant_dict_lookup (options, "provider", "&s", &name);
if (ok)
{
g_action_group_activate_action (G_ACTION_GROUP (application),
"set-provider-name",
g_variant_new_string (name));
}
return -1; // Continue processing signal
}
static void
dispose (GObject *object)
set_provider_name_action (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
CallsApplication *self = (CallsApplication *)object;
CallsApplication *self = CALLS_APPLICATION (user_data);
const gchar *name;
g_clear_object (&self->ringer);
g_clear_object (&self->provider);
name = g_variant_get_string (parameter, NULL);
g_return_if_fail (name != NULL);
G_OBJECT_CLASS (calls_application_parent_class)->finalize (object);
if (self->provider)
{
g_warning ("Cannot set provider name to `%s'"
" because provider is already created",
name);
return;
}
g_string_assign (self->provider_name, name);
g_debug ("Provider name set to `%s'",
self->provider_name->str);
}
static const GActionEntry actions[] =
{
{ "set-provider-name", set_provider_name_action, "s" },
};
static void
startup (GApplication *application)
{
CallsApplication *self = (CallsApplication *)application;
g_autoptr(GError) error = NULL;
G_APPLICATION_CLASS (calls_application_parent_class)->startup (application);
g_set_prgname (APP_ID);
g_set_application_name (_("Calls"));
self->provider = CALLS_PROVIDER (calls_mm_provider_new ());
g_assert (self->provider != NULL);
g_action_map_add_action_entries (G_ACTION_MAP (application),
actions,
G_N_ELEMENTS (actions),
application);
}
static void
load_provider_plugin (CallsApplication *self)
{
const gchar * const name = self->provider_name->str;
PeasEngine *plugins;
PeasPluginInfo *info;
PeasExtension *extension;
g_assert (self->provider == NULL);
// Add Calls search path and rescan
plugins = peas_engine_get_default ();
peas_engine_add_search_path (plugins, PLUGIN_LIBDIR, PLUGIN_LIBDIR);
g_debug ("Scanning for plugins in `%s'", PLUGIN_LIBDIR);
// Find the plugin
info = peas_engine_get_plugin_info (plugins, name);
if (!info)
{
g_critical ("Could not find plugin `%s'", name);
return;
}
// Possibly load the plugin
if (!peas_plugin_info_is_loaded (info))
{
g_autoptr(GError) error = NULL;
self->ringer = calls_ringer_new (self->provider);
g_assert (self->ringer != NULL);
peas_engine_load_plugin (plugins, info);
if (!peas_plugin_info_is_available (info, &error))
{
if (error)
{
g_critical ("Error loading plugin `%s': %s",
name, error->message);
}
else
{
g_critical ("Could not load plugin `%s'", name);
}
return;
}
g_debug ("Loaded plugin `%s'", name);
}
// Check the plugin provides CallsProvider
if (!peas_engine_provides_extension
(plugins, info, CALLS_TYPE_PROVIDER))
{
g_critical ("Plugin `%s' does not have a provider extension",
name);
return;
}
// Get the extension
extension = peas_engine_create_extensionv
(plugins, info, CALLS_TYPE_PROVIDER, 0, NULL);
if (!extension)
{
g_critical ("Could not create provider from plugin `%s'",
name);
return;
}
g_debug ("Created provider from plugin `%s'", name);
self->provider = CALLS_PROVIDER (extension);
}
static void
activate (GApplication *application)
{
CallsApplication *self = (CallsApplication *)application;
GtkApplication *app = (GtkApplication *)application;
GtkApplication *gtk_app;
GtkWindow *window;
g_assert (GTK_IS_APPLICATION (app));
g_assert (GTK_IS_APPLICATION (application));
gtk_app = GTK_APPLICATION (application);
window = gtk_application_get_active_window (app);
window = gtk_application_get_active_window (gtk_app);
if (window == NULL)
{
CallsApplication *self = CALLS_APPLICATION (application);
// Later we will make provider loading/unloaded a dynamic
// process but that will have far-reaching consequences and is
// of no use immediately so for now, we just load one provider
// at startup. We can't put this in the actual startup() method
// though, because we need to be able to set the provider name
// from the command line and we use actions to do that, which
// depend on the application already being started up.
if (!self->provider)
{
load_provider_plugin (self);
if (!self->provider)
{
g_application_quit (application);
return;
}
self->ringer = calls_ringer_new (self->provider);
g_assert (self->ringer != NULL);
}
/*
* We don't track the memory created. Ideally, we might have to.
* But we assume that the application is closed by closing the
* window. In that case, GTK+ frees the resources right.
*/
window = GTK_WINDOW (calls_main_window_new (app, self->provider));
calls_call_window_new (app, self->provider);
window = GTK_WINDOW (calls_main_window_new (gtk_app, self->provider));
calls_call_window_new (gtk_app, self->provider);
}
gtk_window_present (window);
}
static void
constructed (GObject *object)
{
GObjectClass *parent_class = g_type_class_peek (GTK_TYPE_APPLICATION);
CallsApplication *self = CALLS_APPLICATION (object);
GSimpleActionGroup *action_group;
action_group = g_simple_action_group_new ();
g_action_map_add_action_entries (G_ACTION_MAP (action_group),
actions, G_N_ELEMENTS (actions), self);
g_object_unref (action_group);
parent_class->constructed (object);
}
static void
dispose (GObject *object)
{
CallsApplication *self = (CallsApplication *)object;
g_clear_object (&self->ringer);
g_clear_object (&self->provider);
G_OBJECT_CLASS (calls_application_parent_class)->dispose (object);
}
static void
finalize (GObject *object)
{
CallsApplication *self = (CallsApplication *)object;
g_string_free (self->provider_name, TRUE);
G_OBJECT_CLASS (calls_application_parent_class)->finalize (object);
}
static void
calls_application_class_init (CallsApplicationClass *klass)
{
GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = constructed;
object_class->dispose = dispose;
object_class->finalize = finalize;
application_class->handle_local_options = handle_local_options;
application_class->startup = startup;
application_class->activate = activate;
......@@ -133,11 +319,28 @@ calls_application_class_init (CallsApplicationClass *klass)
g_type_ensure (HDY_TYPE_DIALER);
}
static void
calls_application_init (CallsApplication *self)
{
const GOptionEntry options[] = {
{
"provider", 'p', G_OPTION_FLAG_NONE,
G_OPTION_ARG_STRING, NULL,
_("The name of the plugin to use for the call Provider"),
_("PLUGIN")
},
{
NULL
}
};
g_application_add_main_option_entries (G_APPLICATION (self), options);
self->provider_name = g_string_new (DEFAULT_PROVIDER_PLUGIN);
}
CallsApplication *
calls_application_new (void)
{
......
......@@ -23,12 +23,13 @@
gnome = import('gnome')
src_include = include_directories('.')
calls_deps = [ dependency('gobject-2.0'),
dependency('gtk+-3.0'),
dependency('libhandy-0.0'),
dependency('ModemManager'),
dependency('mm-glib'),
dependency('gsound'),
dependency('libpeas-1.0'),
]
calls_sources = files(['calls-message-source.c', 'calls-message-source.h',
......@@ -37,12 +38,6 @@ calls_sources = files(['calls-message-source.c', 'calls-message-source.h',
'calls-provider.c', 'calls-provider.h',
'calls-enumerate-params.c', 'calls-enumerate-params.h',
'calls-enumerate.c', 'calls-enumerate.h',
'calls-ofono-call.c', 'calls-ofono-call.h',
'calls-ofono-origin.c', 'calls-ofono-origin.h',
'calls-ofono-provider.c', 'calls-ofono-provider.h',
'calls-mm-call.c', 'calls-mm-call.h',
'calls-mm-origin.c', 'calls-mm-origin.h',
'calls-mm-provider.c', 'calls-mm-provider.h',
'calls-party.c', 'calls-party.h',
'calls-call-data.c', 'calls-call-data.h',
'calls-call-holder.c', 'calls-call-holder.h',
......@@ -60,23 +55,12 @@ calls_sources = files(['calls-message-source.c', 'calls-message-source.h',
'util.c', 'util.h',
])
calls_dummy_sources = files(['calls-dummy-call.c', 'calls-dummy-call.h',
'calls-dummy-origin.c', 'calls-dummy-origin.h',
'calls-dummy-provider.c', 'calls-dummy-provider.h',
])
prefix = get_option('prefix')
config_data = configuration_data()
config_data.set_quoted('APP_ID', calls_id)
config_data.set_quoted('GETTEXT_PACKAGE', calls_name)
config_data.set_quoted('LOCALEDIR', join_paths(prefix, get_option('localedir')))
config_data.set_quoted('PACKAGE_URL', calls_homepage)
config_data.set_quoted('PACKAGE_VERSION', calls_version)
config_data.set_quoted('VCS_TAG', '@VCS_TAG@')
calls_config_data = config_data
calls_config_data.set_quoted('VCS_TAG', '@VCS_TAG@')
config_h_in = configure_file(
output: 'config.h.in',
configuration: config_data
configuration: calls_config_data
)
config_h = vcs_tag(
......@@ -99,6 +83,6 @@ calls_resources = gnome.compile_resources(
executable('calls',
calls_sources, calls_enum_sources, calls_resources, 'main.c',
dependencies : calls_deps,
link_with : gdbofono_lib,
export_dynamic : true,
include_directories : include_directories('..'),
install : true)
......@@ -11,6 +11,7 @@ test_env = [
test_cflags = [
'-fPIE',
'-DFOR_TESTING'
]
test_link_args = [
......@@ -38,13 +39,16 @@ foreach test : tests
'common.h' ]
t = executable(name, test_sources,
calls_sources, calls_dummy_sources, calls_enum_sources, calls_resources,
calls_sources, dummy_sources, calls_enum_sources, calls_resources,
c_args : test_cflags,
link_args: test_link_args,
link_with : gdbofono_lib,
dependencies: calls_deps,
include_directories : include_directories('..',
join_paths('..', 'src')),
include_directories : [
top_include,
src_include,
dummy_include
]
)
test(name, t, env: test_env)
endforeach
......
......@@ -7,7 +7,7 @@
#include "setup-provider.h"
#include "calls-dummy-origin.h"
#define TEST_ORIGIN_NAME "Test origin"
#define TEST_ORIGIN_NAME "Dummy origin"
#define TEST_CALL_NUMBER "0123456789"
......
......@@ -43,14 +43,9 @@ test_dummy_provider_origins (ProviderFixture *fixture,
{
GList *origins;
calls_dummy_provider_add_origin (fixture->dummy_provider,
"Test origin 1");
calls_dummy_provider_add_origin (fixture->dummy_provider,
"Test origin 2");
origins = calls_provider_get_origins
(CALLS_PROVIDER (fixture->dummy_provider));
g_assert_cmpuint (g_list_length (origins), ==, 2);
g_assert_cmpuint (g_list_length (origins), ==, 1);
g_list_free (origins);
}
......