mirror of
https://gitlab.gnome.org/GNOME/calls.git
synced 2024-12-04 20:07:36 +00:00
refactor: Switch to CallsPluginManager
This commit is contained in:
parent
37b208f040
commit
d3e42c93cd
9 changed files with 371 additions and 589 deletions
|
@ -32,6 +32,11 @@
|
|||
#include "calls-account-provider.h"
|
||||
#include "calls-manager.h"
|
||||
#include "calls-in-app-notification.h"
|
||||
#include "calls-plugin-manager.h"
|
||||
#include "calls-util.h"
|
||||
|
||||
#include "gtkcustomfilter.h"
|
||||
#include "gtkfilterlistmodel.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
|
@ -66,11 +71,16 @@ struct _CallsAccountOverview {
|
|||
GtkWindow *account_window;
|
||||
GtkWidget *current_account_widget;
|
||||
|
||||
/* models */
|
||||
GtkFilter *account_provider_filter;
|
||||
GtkFilter *account_filter;
|
||||
GListModel *providers;
|
||||
GListModel *accounts;
|
||||
|
||||
/* misc */
|
||||
GtkEventController *key_controller;
|
||||
GtkEventController *key_controller_account;
|
||||
CallsAccountOverviewState state;
|
||||
GList *providers;
|
||||
CallsInAppNotification *in_app_notification;
|
||||
};
|
||||
|
||||
|
@ -101,14 +111,25 @@ static void
|
|||
update_state (CallsAccountOverview *self)
|
||||
{
|
||||
guint n_origins = 0;
|
||||
guint n_providers;
|
||||
|
||||
g_assert (CALLS_IS_ACCOUNT_OVERVIEW (self));
|
||||
|
||||
for (GList *node = self->providers; node != NULL; node = node->next) {
|
||||
CallsProvider *provider = CALLS_PROVIDER (node->data);
|
||||
GListModel *model = calls_provider_get_origins (provider);
|
||||
n_providers = g_list_model_get_n_items (self->providers);
|
||||
|
||||
n_origins += g_list_model_get_n_items (model);
|
||||
for (guint i = 0; i < n_providers; i++) {
|
||||
g_autoptr (CallsProvider) provider = g_list_model_get_item (self->providers, i);
|
||||
GListModel *origins;
|
||||
|
||||
/* we might be in the middle of the lists being updated! */
|
||||
if (!provider) {
|
||||
n_providers--;
|
||||
break;
|
||||
}
|
||||
|
||||
origins = calls_provider_get_origins (provider);
|
||||
|
||||
n_origins += g_list_model_get_n_items (origins);
|
||||
}
|
||||
|
||||
if (n_origins > 0)
|
||||
|
@ -116,6 +137,8 @@ update_state (CallsAccountOverview *self)
|
|||
else
|
||||
self->state = SHOW_INTRO;
|
||||
|
||||
gtk_widget_set_sensitive (self->add_btn, n_providers > 0);
|
||||
|
||||
update_visibility (self);
|
||||
}
|
||||
|
||||
|
@ -145,18 +168,20 @@ on_account_row_activated (GtkListBox *box,
|
|||
GtkListBoxRow *row,
|
||||
CallsAccountOverview *self)
|
||||
{
|
||||
CallsAccountProvider *provider;
|
||||
CallsAccount *account = NULL;
|
||||
CallsAccountRow *acc_row;
|
||||
CallsAccountProvider *provider;
|
||||
GtkWidget *widget;
|
||||
|
||||
g_assert (GTK_IS_LIST_BOX_ROW (row) );
|
||||
g_assert (CALLS_IS_ACCOUNT_OVERVIEW (self));
|
||||
g_assert (g_list_model_get_n_items (self->providers) > 0);
|
||||
|
||||
if (row == self->add_row) {
|
||||
/* TODO this needs changing if we ever have multiple account providers */
|
||||
provider = CALLS_ACCOUNT_PROVIDER (self->providers->data);
|
||||
provider = g_list_model_get_item (self->providers, 0);
|
||||
widget = calls_account_provider_get_account_widget (provider);
|
||||
g_object_unref (provider);
|
||||
|
||||
} else if (CALLS_IS_ACCOUNT_ROW (row)) {
|
||||
acc_row = CALLS_ACCOUNT_ROW (row);
|
||||
|
@ -215,84 +240,72 @@ on_account_message (CallsAccount *account,
|
|||
|
||||
|
||||
static void
|
||||
update_account_list (CallsAccountOverview *self)
|
||||
on_accounts_changed (GListModel *accounts,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
CallsAccountOverview *self)
|
||||
{
|
||||
gboolean removed_all = FALSE;
|
||||
guint n_providers = g_list_model_get_n_items (self->providers);
|
||||
|
||||
g_assert (CALLS_IS_ACCOUNT_OVERVIEW (self));
|
||||
for (guint i = removed; i > 0; i--) {
|
||||
GtkListBoxRow *row =
|
||||
gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->overview), position + i - 1);
|
||||
|
||||
/* TODO rework with GTK4 FlattenListModel (to flatten a GListModel of GListModels)
|
||||
* in particular we could then connect to the items-changed signal of the flattened list.
|
||||
* Always rebuilding the account list is not particularly efficient, but since
|
||||
* we're not constantly doing this it's fine for now.
|
||||
*/
|
||||
while (!removed_all) {
|
||||
GtkListBoxRow *row = gtk_list_box_get_row_at_index (GTK_LIST_BOX (self->overview), 0);
|
||||
|
||||
if (row == NULL || row == GTK_LIST_BOX_ROW (self->add_row))
|
||||
removed_all = TRUE;
|
||||
else
|
||||
gtk_container_remove (GTK_CONTAINER (self->overview), GTK_WIDGET (row));
|
||||
gtk_container_remove (GTK_CONTAINER (self->overview), GTK_WIDGET (row));
|
||||
}
|
||||
|
||||
for (GList *node = self->providers; node != NULL; node = node->next) {
|
||||
CallsAccountProvider *provider = CALLS_ACCOUNT_PROVIDER (node->data);
|
||||
GListModel *model = calls_provider_get_origins (CALLS_PROVIDER (provider));
|
||||
guint n_origins = g_list_model_get_n_items (model);
|
||||
for (guint i = 0; i < added; i++) {
|
||||
g_autoptr (CallsAccount) account =
|
||||
CALLS_ACCOUNT (g_list_model_get_item (accounts, position + i));
|
||||
CallsAccountProvider *provider = NULL;
|
||||
CallsAccountRow *account_row;
|
||||
|
||||
for (guint i = 0; i < n_origins; i++) {
|
||||
g_autoptr (CallsAccount) account = CALLS_ACCOUNT (g_list_model_get_item (model, i));
|
||||
CallsAccountRow *account_row = calls_account_row_new (provider, account);
|
||||
/* which provider does this account belong to? */
|
||||
for (guint j = 0; j < n_providers; j++) {
|
||||
g_autoptr (CallsProvider) candidate = g_list_model_get_item (self->providers, j);
|
||||
|
||||
g_signal_handlers_disconnect_by_data (account, self);
|
||||
g_signal_connect_object (account, "message",
|
||||
G_CALLBACK (on_account_message),
|
||||
self,
|
||||
G_CONNECT_AFTER);
|
||||
|
||||
gtk_list_box_insert (GTK_LIST_BOX (self->overview),
|
||||
GTK_WIDGET (account_row),
|
||||
0);
|
||||
if (calls_find_in_model (calls_provider_get_origins (candidate), account, NULL)) {
|
||||
provider = CALLS_ACCOUNT_PROVIDER (candidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (CALLS_IS_ACCOUNT_PROVIDER (provider));
|
||||
|
||||
account_row = calls_account_row_new (provider, account);
|
||||
|
||||
g_signal_connect_object (account, "message",
|
||||
G_CALLBACK (on_account_message),
|
||||
self,
|
||||
0);
|
||||
gtk_list_box_insert (GTK_LIST_BOX (self->overview),
|
||||
GTK_WIDGET (account_row),
|
||||
position + i);
|
||||
}
|
||||
|
||||
update_state (self);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
on_providers_changed (CallsAccountOverview *self)
|
||||
on_providers_changed (GListModel *providers,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
CallsAccountOverview *self)
|
||||
{
|
||||
GList *providers;
|
||||
for (guint i = 0; i < added; i++) {
|
||||
g_autoptr (CallsProvider) provider =
|
||||
g_list_model_get_item (providers, position + i);
|
||||
|
||||
g_clear_pointer (&self->providers, g_list_free);
|
||||
providers = calls_manager_get_providers (calls_manager_get_default ());
|
||||
|
||||
for (GList *node = providers; node != NULL; node = node->next) {
|
||||
CallsProvider *provider = node->data;
|
||||
|
||||
if (CALLS_IS_ACCOUNT_PROVIDER (provider)) {
|
||||
self->providers = g_list_append (self->providers, provider);
|
||||
g_signal_connect_object (calls_provider_get_origins (provider),
|
||||
"items-changed",
|
||||
G_CALLBACK (update_account_list),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (provider,
|
||||
"widget-edit-done",
|
||||
G_CALLBACK (gtk_widget_hide),
|
||||
self->account_window,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
g_signal_connect_swapped (provider, "widget-edit-done",
|
||||
G_CALLBACK (gtk_widget_hide), self->account_window);
|
||||
}
|
||||
|
||||
/* Clear any acccount widgets, because they might've gone stale */
|
||||
attach_account_widget (self, NULL);
|
||||
gtk_widget_hide (GTK_WIDGET (self->account_window));
|
||||
|
||||
update_account_list (self);
|
||||
|
||||
gtk_widget_set_sensitive (self->add_btn, !!self->providers);
|
||||
}
|
||||
|
||||
|
||||
|
@ -316,6 +329,12 @@ calls_account_overview_dispose (GObject *object)
|
|||
{
|
||||
CallsAccountOverview *self = CALLS_ACCOUNT_OVERVIEW (object);
|
||||
|
||||
g_clear_object (&self->providers);
|
||||
g_clear_object (&self->account_provider_filter);
|
||||
|
||||
g_clear_object (&self->accounts);
|
||||
g_clear_object (&self->account_filter);
|
||||
|
||||
g_clear_object (&self->key_controller);
|
||||
g_clear_object (&self->key_controller_account);
|
||||
|
||||
|
@ -348,24 +367,65 @@ calls_account_overview_class_init (CallsAccountOverviewClass *klass)
|
|||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
match_account_provider (gpointer item,
|
||||
gpointer unused)
|
||||
{
|
||||
g_assert (CALLS_IS_PROVIDER (item));
|
||||
|
||||
return CALLS_IS_ACCOUNT_PROVIDER (item);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
match_account (gpointer item,
|
||||
gpointer unused)
|
||||
{
|
||||
g_assert (CALLS_IS_ORIGIN (item));
|
||||
|
||||
return CALLS_IS_ACCOUNT (item);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calls_account_overview_init (CallsAccountOverview *self)
|
||||
{
|
||||
GListModel *all_providers =
|
||||
calls_plugin_manager_get_providers (calls_plugin_manager_get_default ());
|
||||
GListModel *all_origins =
|
||||
calls_manager_get_origins (calls_manager_get_default ());
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
|
||||
g_signal_connect_swapped (calls_manager_get_default (),
|
||||
"providers-changed",
|
||||
G_CALLBACK (on_providers_changed),
|
||||
self);
|
||||
on_providers_changed (self);
|
||||
self->account_provider_filter = gtk_custom_filter_new (match_account_provider, NULL, NULL);
|
||||
self->providers =
|
||||
G_LIST_MODEL (gtk_filter_list_model_new (all_providers,
|
||||
self->account_provider_filter));
|
||||
|
||||
g_signal_connect (self->providers,
|
||||
"items-changed",
|
||||
G_CALLBACK (on_providers_changed),
|
||||
self);
|
||||
on_providers_changed (self->providers,
|
||||
0, 0, g_list_model_get_n_items (self->providers),
|
||||
self);
|
||||
|
||||
self->account_filter = gtk_custom_filter_new (match_account, NULL, NULL);
|
||||
self->accounts =
|
||||
G_LIST_MODEL (gtk_filter_list_model_new (all_origins,
|
||||
self->account_filter));
|
||||
g_signal_connect_object (self->accounts,
|
||||
"items-changed",
|
||||
G_CALLBACK (on_accounts_changed),
|
||||
self,
|
||||
G_CONNECT_AFTER);
|
||||
on_accounts_changed (self->accounts, 0, 0, g_list_model_get_n_items (self->accounts), self);
|
||||
|
||||
gtk_list_box_insert (GTK_LIST_BOX (self->overview),
|
||||
GTK_WIDGET (self->add_row),
|
||||
-1);
|
||||
gtk_window_set_transient_for (self->account_window, GTK_WINDOW (self));
|
||||
|
||||
update_state (self);
|
||||
|
||||
self->key_controller = gtk_event_controller_key_new (GTK_WIDGET (self));
|
||||
g_signal_connect (self->key_controller,
|
||||
"key-pressed",
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "calls-message-source.h"
|
||||
#include "calls-new-call-box.h"
|
||||
#include "calls-notifier.h"
|
||||
#include "calls-plugin-manager.h"
|
||||
#include "calls-record-store.h"
|
||||
#include "calls-ringer.h"
|
||||
#include "version.h"
|
||||
|
@ -73,6 +74,8 @@ struct _CallsApplication {
|
|||
guint id_sigint;
|
||||
gboolean shutdown;
|
||||
gboolean db_done;
|
||||
CallsPluginManager *plugin_manager;
|
||||
CallsSettings *settings;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (CallsApplication, calls_application, GTK_TYPE_APPLICATION);
|
||||
|
@ -155,60 +158,76 @@ calls_application_dbus_unregister (GApplication *application,
|
|||
|
||||
|
||||
static void
|
||||
set_provider_names_action (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
set_plugin_names_action (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
CallsManager *manager;
|
||||
g_autofree const char **names = NULL;
|
||||
g_autofree const char **loaded = NULL;
|
||||
CallsApplication *self = user_data;
|
||||
gsize length;
|
||||
guint length_loaded;
|
||||
|
||||
g_assert (CALLS_IS_APPLICATION (self));
|
||||
|
||||
names = g_variant_get_strv (parameter, &length);
|
||||
g_return_if_fail (names && *names);
|
||||
|
||||
manager = calls_manager_get_default ();
|
||||
loaded = calls_manager_get_provider_names (manager, &length_loaded);
|
||||
loaded = calls_plugin_manager_get_plugin_names (self->plugin_manager, &length_loaded);
|
||||
|
||||
/* remove unwanted providers */
|
||||
/* remove unwanted plugins */
|
||||
for (guint i = 0; i < length_loaded; i++) {
|
||||
g_autofree char *provider = g_strdup (loaded[i]);
|
||||
if (!g_strv_contains (names, provider))
|
||||
calls_manager_remove_provider (manager, provider);
|
||||
g_autofree char *plugin = g_strdup (loaded[i]);
|
||||
|
||||
if (!g_strv_contains (names, plugin)) {
|
||||
g_autoptr (GError) error = NULL;
|
||||
gboolean ok = calls_plugin_manager_unload_plugin (self->plugin_manager, plugin, &error);
|
||||
|
||||
g_debug ("Unloading plugin `%s' %ssuccessful", plugin, ok ? "" : "un");
|
||||
if (!ok)
|
||||
g_warning ("Plugin '%s' not unloaded: %s", plugin, error->message);
|
||||
}
|
||||
}
|
||||
|
||||
for (guint i = 0; i < length; i++) {
|
||||
g_autoptr (GError) error = NULL;
|
||||
const char *name = names[i];
|
||||
gboolean ok;
|
||||
|
||||
if (calls_manager_has_provider (manager, name))
|
||||
if (calls_plugin_manager_has_plugin (self->plugin_manager, name))
|
||||
continue;
|
||||
|
||||
g_debug ("Loading provider `%s'", name);
|
||||
calls_manager_add_provider (manager, name);
|
||||
ok = calls_plugin_manager_load_plugin (self->plugin_manager, name, &error);
|
||||
g_debug ("Loading plugin `%s' %ssuccessful", name, ok ? "" : "un");
|
||||
if (!ok)
|
||||
g_warning ("Plugin '%s' not loaded: %s", name, error->message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_default_providers_action (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
set_default_plugins_action (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
CallsManager *manager = calls_manager_get_default ();
|
||||
CallsSettings *settings = calls_manager_get_settings (manager);
|
||||
CallsApplication *self = CALLS_APPLICATION (user_data);
|
||||
|
||||
g_auto (GStrv) plugins = NULL;
|
||||
/**
|
||||
* Only add default providers when there are none added yet,
|
||||
* This makes sure we're not resetting explicitly set providers
|
||||
*/
|
||||
if (calls_manager_has_any_provider (manager))
|
||||
if (calls_plugin_manager_has_any_plugins (self->plugin_manager))
|
||||
return;
|
||||
|
||||
plugins = calls_settings_get_autoload_plugins (settings);
|
||||
plugins = calls_settings_get_autoload_plugins (self->settings);
|
||||
for (guint i = 0; plugins[i] != NULL; i++) {
|
||||
calls_manager_add_provider (manager, plugins[i]);
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
g_debug ("Loading default provider %s", plugins[i]);
|
||||
|
||||
if (!calls_plugin_manager_load_plugin (self->plugin_manager, plugins[i], &error))
|
||||
g_warning ("Could not load plugin '%s': %s", plugins[i], error->message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -417,8 +436,8 @@ manager_state_changed_cb (GApplication *application)
|
|||
|
||||
static const GActionEntry actions[] =
|
||||
{
|
||||
{ "set-provider-names", set_provider_names_action, "as" },
|
||||
{ "set-default-providers", set_default_providers_action, NULL },
|
||||
{ "set-plugin-names", set_plugin_names_action, "as" },
|
||||
{ "set-default-plugins", set_default_plugins_action, NULL },
|
||||
{ "set-daemon", set_daemon_action, "b" },
|
||||
{ "dial", dial_action, "s" },
|
||||
{ "copy-number", copy_number, "s" },
|
||||
|
@ -509,7 +528,7 @@ calls_application_command_line (GApplication *application,
|
|||
GVariantDict *options;
|
||||
const char *arg;
|
||||
|
||||
g_autoptr (GVariant) providers = NULL;
|
||||
g_autoptr (GVariant) plugins = NULL;
|
||||
g_auto (GStrv) arguments = NULL;
|
||||
gint argc;
|
||||
guint verbosity;
|
||||
|
@ -529,14 +548,14 @@ calls_application_command_line (GApplication *application,
|
|||
|
||||
start_proper (self);
|
||||
|
||||
providers = g_variant_dict_lookup_value (options, "provider", G_VARIANT_TYPE_STRING_ARRAY);
|
||||
if (providers) {
|
||||
plugins = g_variant_dict_lookup_value (options, "plugins", G_VARIANT_TYPE_STRING_ARRAY);
|
||||
if (plugins) {
|
||||
g_action_group_activate_action (G_ACTION_GROUP (application),
|
||||
"set-provider-names",
|
||||
providers);
|
||||
"set-plugin-names",
|
||||
plugins);
|
||||
} else {
|
||||
g_action_group_activate_action (G_ACTION_GROUP (application),
|
||||
"set-default-providers",
|
||||
"set-default-plugins",
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
@ -629,6 +648,12 @@ start_proper (CallsApplication *self)
|
|||
|
||||
gtk_app = GTK_APPLICATION (self);
|
||||
|
||||
self->settings = calls_settings_get_default ();
|
||||
g_assert (self->settings);
|
||||
|
||||
self->plugin_manager = calls_plugin_manager_get_default ();
|
||||
g_assert (self->plugin_manager);
|
||||
|
||||
self->manager = calls_manager_get_default ();
|
||||
g_assert (self->manager);
|
||||
|
||||
|
@ -746,6 +771,8 @@ finalize (GObject *object)
|
|||
g_clear_object (&self->ringer);
|
||||
g_clear_object (&self->notifier);
|
||||
g_clear_object (&self->manager);
|
||||
g_clear_object (&self->plugin_manager);
|
||||
g_clear_object (&self->settings);
|
||||
|
||||
g_free (self->uri);
|
||||
|
||||
|
@ -780,9 +807,9 @@ calls_application_init (CallsApplication *self)
|
|||
{
|
||||
const GOptionEntry options[] = {
|
||||
{
|
||||
"provider", 'p', G_OPTION_FLAG_NONE,
|
||||
"plugins", 'p', G_OPTION_FLAG_NONE,
|
||||
G_OPTION_ARG_STRING_ARRAY, NULL,
|
||||
_("The name of the plugin to use as a call provider"),
|
||||
_("The name of the plugins to load"),
|
||||
_("PLUGIN")
|
||||
},
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "calls-contacts-provider.h"
|
||||
#include "calls-manager.h"
|
||||
#include "calls-message-source.h"
|
||||
#include "calls-plugin-manager.h"
|
||||
#include "calls-provider.h"
|
||||
#include "calls-settings.h"
|
||||
#include "calls-ui-call-data.h"
|
||||
|
@ -39,6 +40,10 @@
|
|||
|
||||
#include "enum-types.h"
|
||||
|
||||
#include "gtkcustomfilter.h"
|
||||
#include "gtkfilterlistmodel.h"
|
||||
#include "gtkflattenlistmodel.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <libpeas/peas.h>
|
||||
|
||||
|
@ -59,12 +64,23 @@ static const char * const protocols[] = {
|
|||
"sips"
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
match_origin_supports_protocol (gpointer item,
|
||||
gpointer protocol)
|
||||
{
|
||||
g_assert (CALLS_IS_ORIGIN (item));
|
||||
|
||||
return calls_origin_supports_protocol (CALLS_ORIGIN (item), (char *) protocol);
|
||||
}
|
||||
|
||||
|
||||
struct _CallsManager {
|
||||
GObject parent_instance;
|
||||
|
||||
GHashTable *providers;
|
||||
|
||||
GListStore *origins;
|
||||
GtkFlattenListModel *origins_flat;
|
||||
|
||||
/* origins_by_protocol maps protocol names to GListStore's of suitable origins */
|
||||
GHashTable *origins_by_protocol;
|
||||
/* dial_actions_by_protocol maps protocol names to GSimpleActions */
|
||||
|
@ -123,16 +139,17 @@ set_state_flags (CallsManager *self, CallsManagerFlags state_flags)
|
|||
static void
|
||||
update_state_flags (CallsManager *self)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
CallsManagerFlags state_flags = CALLS_MANAGER_FLAGS_UNKNOWN;
|
||||
GListModel *providers;
|
||||
guint n_providers;
|
||||
|
||||
g_assert (CALLS_IS_MANAGER (self));
|
||||
|
||||
g_hash_table_iter_init (&iter, self->providers);
|
||||
providers = calls_plugin_manager_get_providers (calls_plugin_manager_get_default ());
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value)) {
|
||||
CallsProvider *provider = CALLS_PROVIDER (value);
|
||||
n_providers = g_list_model_get_n_items (providers);
|
||||
for (guint i = 0; i < n_providers; i++) {
|
||||
g_autoptr (CallsProvider) provider = g_list_model_get_item (providers, i);
|
||||
|
||||
if (calls_provider_is_modem (provider)) {
|
||||
state_flags |= CALLS_MANAGER_FLAGS_HAS_CELLULAR_PROVIDER;
|
||||
|
@ -242,6 +259,8 @@ add_call (CallsManager *self, CallsCall *call, CallsOrigin *origin)
|
|||
call_data = calls_ui_call_data_new (call, origin_id);
|
||||
g_hash_table_insert (self->calls, call, call_data);
|
||||
|
||||
g_object_set_data (G_OBJECT (call), "call-origin", origin);
|
||||
|
||||
g_signal_emit (self, signals[UI_CALL_ADDDED], 0, call_data);
|
||||
}
|
||||
|
||||
|
@ -363,8 +382,6 @@ add_origin (CallsManager *self, CallsOrigin *origin)
|
|||
name = calls_origin_get_name (origin);
|
||||
g_debug ("Adding origin %s (%p)", name, origin);
|
||||
|
||||
g_list_store_append (self->origins, origin);
|
||||
|
||||
g_signal_connect_object (origin,
|
||||
"message",
|
||||
G_CALLBACK (on_message),
|
||||
|
@ -388,238 +405,27 @@ add_origin (CallsManager *self, CallsOrigin *origin)
|
|||
calls_origin_foreach_call (origin, (CallsOriginForeachCallFunc) add_call, self);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
remove_call_cb (gpointer self, CallsCall *call, CallsOrigin *origin)
|
||||
on_origins_changed (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
CallsManager *self)
|
||||
{
|
||||
remove_call (self, call, NULL, origin);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
remove_origin (CallsManager *self, CallsOrigin *origin)
|
||||
{
|
||||
g_autofree const char *name = NULL;
|
||||
guint position;
|
||||
|
||||
g_assert (CALLS_IS_MANAGER (self));
|
||||
g_assert (CALLS_IS_ORIGIN (origin));
|
||||
g_assert (model == G_LIST_MODEL (self->origins_flat));
|
||||
|
||||
name = calls_origin_get_name (origin);
|
||||
g_debug ("Removing origin %s (%p)", name, origin);
|
||||
for (guint i = 0; i < added; i++) {
|
||||
g_autoptr (CallsOrigin) origin = g_list_model_get_item (model, position + i);
|
||||
|
||||
g_signal_handlers_disconnect_by_data (origin, self);
|
||||
|
||||
calls_origin_foreach_call (origin, remove_call_cb, self);
|
||||
|
||||
if (!g_list_store_find (self->origins, origin, &position))
|
||||
g_warning ("Origin %p not found in list store while trying to remove it",
|
||||
origin);
|
||||
else
|
||||
g_list_store_remove (self->origins, position);
|
||||
}
|
||||
|
||||
/* rebuild_origins_by_protocols() when any origins were added or removed */
|
||||
static void
|
||||
rebuild_origins_by_protocols (CallsManager *self)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
guint n_origins;
|
||||
|
||||
g_assert (CALLS_IS_MANAGER (self));
|
||||
|
||||
/* Remove everything */
|
||||
g_hash_table_iter_init (&iter, self->origins_by_protocol);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value)) {
|
||||
GListStore *store = G_LIST_STORE (value);
|
||||
g_list_store_remove_all (store);
|
||||
}
|
||||
|
||||
/* Iterate over all origins and check which protocols they support */
|
||||
n_origins = g_list_model_get_n_items (G_LIST_MODEL (self->origins));
|
||||
|
||||
for (guint i = 0; i < n_origins; i++) {
|
||||
g_autoptr (CallsOrigin) origin =
|
||||
g_list_model_get_item (G_LIST_MODEL (self->origins), i);
|
||||
|
||||
for (guint j = 0; j < G_N_ELEMENTS (protocols); j++) {
|
||||
GListStore *store =
|
||||
G_LIST_STORE (g_hash_table_lookup (self->origins_by_protocol, protocols[j]));
|
||||
|
||||
g_assert (store);
|
||||
|
||||
if (calls_origin_supports_protocol (origin, protocols[j]))
|
||||
g_list_store_append (store, origin);
|
||||
}
|
||||
add_origin (self, origin);
|
||||
}
|
||||
|
||||
update_state_flags (self);
|
||||
update_protocol_dial_actions (self);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
remove_provider (CallsManager *self,
|
||||
const char *name)
|
||||
{
|
||||
g_autoptr (CallsProvider) provider = NULL;
|
||||
|
||||
GListModel *origins;
|
||||
guint n_items;
|
||||
|
||||
g_assert (CALLS_IS_MANAGER (self));
|
||||
g_assert (name);
|
||||
|
||||
provider = g_hash_table_lookup (self->providers, name);
|
||||
if (provider) {
|
||||
/* Hold a ref since g_hash_table_remove () might drop the last one */
|
||||
g_object_ref (provider);
|
||||
} else {
|
||||
g_warning ("Trying to remove provider %s which has not been found", name);
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("Remove provider: %s", name);
|
||||
g_signal_handlers_disconnect_by_data (provider, self);
|
||||
|
||||
origins = calls_provider_get_origins (provider);
|
||||
g_signal_handlers_disconnect_by_data (origins, self);
|
||||
n_items = g_list_model_get_n_items (origins);
|
||||
|
||||
for (guint i = 0; i < n_items; i++) {
|
||||
g_autoptr (CallsOrigin) origin = NULL;
|
||||
|
||||
origin = g_list_model_get_item (origins, i);
|
||||
remove_origin (self, origin);
|
||||
}
|
||||
|
||||
g_hash_table_remove (self->providers, name);
|
||||
calls_provider_unload_plugin (name);
|
||||
|
||||
rebuild_origins_by_protocols (self);
|
||||
update_state_flags (self);
|
||||
|
||||
g_signal_emit (self, signals[PROVIDERS_CHANGED], 0);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
origin_found_in_any_provider (CallsManager *self,
|
||||
CallsOrigin *origin)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
|
||||
g_return_val_if_fail (CALLS_IS_MANAGER (self), FALSE);
|
||||
g_return_val_if_fail (CALLS_IS_ORIGIN (origin), FALSE);
|
||||
|
||||
g_hash_table_iter_init (&iter, self->providers);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value)) {
|
||||
guint position;
|
||||
CallsProvider *provider = CALLS_PROVIDER (value);
|
||||
GListModel *origins = calls_provider_get_origins (provider);
|
||||
|
||||
if (origins && calls_find_in_model (origins,
|
||||
origin,
|
||||
&position))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
origin_items_changed_cb (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
CallsManager *self)
|
||||
{
|
||||
guint i;
|
||||
CallsOrigin *origin;
|
||||
guint purged = 0;
|
||||
guint total_origins;
|
||||
|
||||
g_assert (CALLS_IS_MANAGER (self));
|
||||
|
||||
total_origins = g_list_model_get_n_items (G_LIST_MODEL (self->origins));
|
||||
g_debug ("origins changed: pos=%d rem=%d added=%d total=%d",
|
||||
position, removed, added, g_list_model_get_n_items (model));
|
||||
|
||||
/* Check stale/removed origins: We need to look up */
|
||||
if (removed == 0)
|
||||
goto skip_remove;
|
||||
|
||||
for (i = 0; i < total_origins - purged; i++) {
|
||||
origin = g_list_model_get_item (G_LIST_MODEL (self->origins), i - purged);
|
||||
|
||||
if (!origin_found_in_any_provider (self, origin)) {
|
||||
remove_origin (self, origin);
|
||||
purged++;
|
||||
}
|
||||
}
|
||||
|
||||
/** The number of purged entries from self->origins must be equal to removed
|
||||
* origins from the providers list
|
||||
*/
|
||||
if (purged != removed) {
|
||||
g_warning ("Managed origins are not in sync anymore!");
|
||||
}
|
||||
|
||||
skip_remove:
|
||||
for (i = 0; i < added; i++) {
|
||||
g_debug ("before adding: %d",
|
||||
g_list_model_get_n_items (G_LIST_MODEL (self->origins)));
|
||||
|
||||
origin = g_list_model_get_item (model, position + i);
|
||||
add_origin (self, origin); // add to list store
|
||||
g_object_unref (origin);
|
||||
|
||||
g_debug ("after adding: %d",
|
||||
g_list_model_get_n_items (G_LIST_MODEL (self->origins)));
|
||||
}
|
||||
|
||||
rebuild_origins_by_protocols (self);
|
||||
update_state_flags (self);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_provider (CallsManager *self, const gchar *name)
|
||||
{
|
||||
GListModel *origins;
|
||||
CallsProvider *provider;
|
||||
guint n_items;
|
||||
|
||||
g_assert (CALLS_IS_MANAGER (self));
|
||||
g_assert (name);
|
||||
|
||||
if (g_hash_table_lookup (self->providers, name))
|
||||
return;
|
||||
|
||||
provider = calls_provider_load_plugin (name);
|
||||
if (provider == NULL) {
|
||||
g_warning ("Could not load a plugin with name `%s'", name);
|
||||
return;
|
||||
}
|
||||
|
||||
g_hash_table_insert (self->providers, g_strdup (name), provider);
|
||||
|
||||
origins = calls_provider_get_origins (provider);
|
||||
|
||||
g_signal_connect_object (origins, "items-changed",
|
||||
G_CALLBACK (origin_items_changed_cb), self,
|
||||
G_CONNECT_AFTER);
|
||||
|
||||
n_items = g_list_model_get_n_items (origins);
|
||||
origin_items_changed_cb (origins, 0, 0, n_items, self);
|
||||
|
||||
g_signal_emit (self, signals[PROVIDERS_CHANGED], 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calls_manager_get_property (GObject *object,
|
||||
guint property_id,
|
||||
|
@ -649,7 +455,6 @@ calls_manager_finalize (GObject *object)
|
|||
g_clear_object (&self->contacts_provider);
|
||||
|
||||
g_clear_pointer (&self->origins_by_protocol, g_hash_table_unref);
|
||||
g_clear_pointer (&self->providers, g_hash_table_unref);
|
||||
g_clear_pointer (&self->dial_actions_by_protocol, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (calls_manager_parent_class)->finalize (object);
|
||||
|
@ -736,36 +541,101 @@ calls_manager_class_init (CallsManagerClass *klass)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
on_providers_changed (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
CallsManager *self)
|
||||
{
|
||||
g_autoptr (GPtrArray) origins_add = g_ptr_array_sized_new (added);
|
||||
|
||||
g_assert (CALLS_IS_MANAGER (self));
|
||||
|
||||
g_debug ("Provider changed at pos %u; removed %u; added %u",
|
||||
position, removed, added);
|
||||
|
||||
for (guint i = 0; i < added; i++) {
|
||||
g_autoptr (CallsProvider) provider =
|
||||
g_list_model_get_item (model, position + i);
|
||||
|
||||
g_ptr_array_add (origins_add, calls_provider_get_origins (provider));
|
||||
g_debug ("Adding provider %s with %u items",
|
||||
calls_provider_get_name (provider),
|
||||
g_list_model_get_n_items (calls_provider_get_origins (provider)));
|
||||
}
|
||||
|
||||
g_list_store_splice (self->origins,
|
||||
position,
|
||||
removed,
|
||||
origins_add->pdata,
|
||||
added);
|
||||
|
||||
if (removed > 0) {
|
||||
GHashTableIter calls_iter;
|
||||
gpointer key;
|
||||
|
||||
g_hash_table_iter_init (&calls_iter, self->calls);
|
||||
while (g_hash_table_iter_next (&calls_iter, &key, NULL)) {
|
||||
gpointer origin = g_object_get_data (G_OBJECT (key), "call-origin");
|
||||
|
||||
if (!calls_find_in_model (G_LIST_MODEL (self->origins_flat), origin, NULL))
|
||||
calls_call_hang_up (CALLS_CALL (key));
|
||||
}
|
||||
}
|
||||
|
||||
update_state_flags (self);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calls_manager_init (CallsManager *self)
|
||||
{
|
||||
g_autoptr (GVariantType) variant_type = NULL;
|
||||
GApplication *application;
|
||||
PeasEngine *peas;
|
||||
const gchar *dir;
|
||||
g_autofree char *default_plugin_dir_provider = NULL;
|
||||
CallsPluginManager *plugin_manager = calls_plugin_manager_get_default ();
|
||||
GListModel *providers;
|
||||
|
||||
self->state_flags = CALLS_MANAGER_FLAGS_UNKNOWN;
|
||||
self->providers = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_object_unref);
|
||||
|
||||
self->origins = g_list_store_new (G_TYPE_LIST_MODEL); /* list of lists */
|
||||
self->origins_flat = gtk_flatten_list_model_new (CALLS_TYPE_ORIGIN, G_LIST_MODEL (self->origins));
|
||||
|
||||
g_signal_connect_object (self->origins_flat,
|
||||
"items-changed",
|
||||
G_CALLBACK (on_origins_changed),
|
||||
self,
|
||||
0);
|
||||
|
||||
providers = calls_plugin_manager_get_providers (plugin_manager);
|
||||
g_signal_connect_object (providers,
|
||||
"items-changed",
|
||||
G_CALLBACK (on_providers_changed),
|
||||
self,
|
||||
0); /* G_CONNECT_DEFAULT */
|
||||
if (g_list_model_get_n_items (providers) > 0)
|
||||
on_providers_changed (providers, 0, 0, g_list_model_get_n_items (providers), self);
|
||||
|
||||
self->origins_by_protocol = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
NULL,
|
||||
g_object_unref);
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (protocols); i++) {
|
||||
GListStore *origin_store = g_list_store_new (calls_origin_get_type ());
|
||||
g_autoptr (GtkFilter) filter =
|
||||
gtk_custom_filter_new (match_origin_supports_protocol, (gpointer) protocols[i], NULL);
|
||||
GtkFilterListModel *f_list =
|
||||
gtk_filter_list_model_new (G_LIST_MODEL (self->origins_flat), filter);
|
||||
|
||||
g_debug ("Adding filter list model for protocol '%s'", protocols[i]);
|
||||
g_hash_table_insert (self->origins_by_protocol,
|
||||
g_strdup (protocols[i]),
|
||||
origin_store);
|
||||
(gpointer) protocols[i],
|
||||
f_list);
|
||||
}
|
||||
|
||||
self->dial_actions_by_protocol = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
NULL,
|
||||
g_object_unref);
|
||||
|
||||
application = g_application_get_default ();
|
||||
|
@ -780,7 +650,7 @@ calls_manager_init (CallsManager *self)
|
|||
self);
|
||||
|
||||
g_hash_table_insert (self->dial_actions_by_protocol,
|
||||
g_strdup (protocols[i]),
|
||||
(gpointer) protocols[i],
|
||||
g_object_ref (action));
|
||||
|
||||
/* Enable action if there are suitable origins */
|
||||
|
@ -791,36 +661,12 @@ calls_manager_init (CallsManager *self)
|
|||
g_action_map_add_action (G_ACTION_MAP (application), G_ACTION (action));
|
||||
}
|
||||
|
||||
self->origins = g_list_store_new (calls_origin_get_type ());
|
||||
|
||||
/* This hash table only owns the value, not the key */
|
||||
self->calls = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
|
||||
|
||||
self->settings = calls_settings_get_default ();
|
||||
// Load the contacts provider
|
||||
/* Load the contacts provider */
|
||||
self->contacts_provider = calls_contacts_provider_new ();
|
||||
|
||||
peas = peas_engine_get_default ();
|
||||
|
||||
dir = g_getenv ("CALLS_PLUGIN_DIR");
|
||||
if (dir && dir[0] != '\0') {
|
||||
g_autofree char *plugin_dir_provider = NULL;
|
||||
|
||||
plugin_dir_provider = g_build_filename (dir, "provider", NULL);
|
||||
|
||||
if (g_file_test (plugin_dir_provider, G_FILE_TEST_EXISTS)) {
|
||||
g_debug ("Adding %s to plugin search path", plugin_dir_provider);
|
||||
peas_engine_prepend_search_path (peas, plugin_dir_provider, NULL);
|
||||
} else {
|
||||
g_warning ("Not adding %s to plugin search path, because the directory doesn't exist. Check if env CALLS_PLUGIN_DIR is set correctly", plugin_dir_provider);
|
||||
}
|
||||
}
|
||||
|
||||
default_plugin_dir_provider = g_build_filename(PLUGIN_LIBDIR, "provider", NULL);
|
||||
peas_engine_add_search_path (peas, default_plugin_dir_provider, NULL);
|
||||
g_debug ("Scanning for plugins in `%s'", default_plugin_dir_provider);
|
||||
|
||||
peas_engine_rescan_plugins (peas);
|
||||
}
|
||||
|
||||
|
||||
|
@ -853,55 +699,6 @@ calls_manager_get_contacts_provider (CallsManager *self)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
calls_manager_add_provider (CallsManager *self,
|
||||
const char *name)
|
||||
{
|
||||
g_return_if_fail (CALLS_IS_MANAGER (self));
|
||||
g_return_if_fail (name);
|
||||
|
||||
add_provider (self, name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
calls_manager_remove_provider (CallsManager *self,
|
||||
const char *name)
|
||||
{
|
||||
g_return_if_fail (CALLS_IS_MANAGER (self));
|
||||
g_return_if_fail (name);
|
||||
|
||||
remove_provider (self, name);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
calls_manager_has_provider (CallsManager *self,
|
||||
const char *name)
|
||||
{
|
||||
g_return_val_if_fail (CALLS_IS_MANAGER (self), FALSE);
|
||||
g_return_val_if_fail (name, FALSE);
|
||||
|
||||
return !!g_hash_table_lookup (self->providers, name);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
calls_manager_is_modem_provider (CallsManager *self,
|
||||
const char *name)
|
||||
{
|
||||
CallsProvider *provider;
|
||||
|
||||
g_return_val_if_fail (CALLS_IS_MANAGER (self), FALSE);
|
||||
g_return_val_if_fail (name, FALSE);
|
||||
|
||||
provider = g_hash_table_lookup (self->providers, name);
|
||||
g_return_val_if_fail (provider, FALSE);
|
||||
|
||||
return calls_provider_is_modem (provider);
|
||||
}
|
||||
|
||||
|
||||
CallsManagerFlags
|
||||
calls_manager_get_state_flags (CallsManager *self)
|
||||
{
|
||||
|
@ -916,7 +713,7 @@ calls_manager_get_origins (CallsManager *self)
|
|||
{
|
||||
g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL);
|
||||
|
||||
return G_LIST_MODEL (self->origins);
|
||||
return G_LIST_MODEL (self->origins_flat);
|
||||
}
|
||||
|
||||
|
||||
|
@ -952,7 +749,7 @@ calls_manager_hang_up_all_calls (CallsManager *self)
|
|||
|
||||
g_return_if_fail (CALLS_IS_MANAGER (self));
|
||||
|
||||
origins = G_LIST_MODEL (self->origins);
|
||||
origins = G_LIST_MODEL (self->origins_flat);
|
||||
n_items = g_list_model_get_n_items (origins);
|
||||
|
||||
for (uint i = 0; i < n_items; i++) {
|
||||
|
@ -996,58 +793,6 @@ calls_manager_get_suitable_origins (CallsManager *self,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* calls_manager_has_any_provider:
|
||||
* @self: The #CallsManager
|
||||
*
|
||||
* Returns: %TRUE if any provider is loaded, %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
calls_manager_has_any_provider (CallsManager *self)
|
||||
{
|
||||
g_return_val_if_fail (CALLS_IS_MANAGER (self), FALSE);
|
||||
|
||||
return !!g_hash_table_size (self->providers);
|
||||
}
|
||||
|
||||
/**
|
||||
* calls_manager_get_provider_names:
|
||||
* @self: The #CallsManager
|
||||
* @length: (optional) (out): the length of the returned array
|
||||
*
|
||||
* Retrieves the names of all providers loaded by @self, as an array.
|
||||
*
|
||||
* You should free the return value with g_free().
|
||||
*
|
||||
* Returns: (array length=length) (transfer container): a
|
||||
* %NULL-terminated array containing the names of providers.
|
||||
*/
|
||||
const char **
|
||||
calls_manager_get_provider_names (CallsManager *self,
|
||||
guint *length)
|
||||
{
|
||||
g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL);
|
||||
|
||||
return (const char **) g_hash_table_get_keys_as_array (self->providers, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* calls_manager_get_providers:
|
||||
* @self: A #CallsManager
|
||||
*
|
||||
* Get the currently loaded providers
|
||||
*
|
||||
* Returns: (transfer container): A #GList of #CallsProvider.
|
||||
* Use g_list_free() when done using the list.
|
||||
*/
|
||||
GList *
|
||||
calls_manager_get_providers (CallsManager *self)
|
||||
{
|
||||
g_return_val_if_fail (CALLS_IS_MANAGER (self), NULL);
|
||||
|
||||
return g_hash_table_get_values (self->providers);
|
||||
}
|
||||
|
||||
|
||||
CallsSettings *
|
||||
calls_manager_get_settings (CallsManager *self)
|
||||
|
@ -1076,10 +821,10 @@ calls_manager_get_origin_by_id (CallsManager *self,
|
|||
if (STR_IS_NULL_OR_EMPTY (origin_id))
|
||||
return NULL;
|
||||
|
||||
n_origins = g_list_model_get_n_items (G_LIST_MODEL (self->origins));
|
||||
n_origins = g_list_model_get_n_items (G_LIST_MODEL (self->origins_flat));
|
||||
for (uint i = 0; i < n_origins; i++) {
|
||||
g_autoptr (CallsOrigin) origin =
|
||||
g_list_model_get_item (G_LIST_MODEL (self->origins), i);
|
||||
g_list_model_get_item (G_LIST_MODEL (self->origins_flat), i);
|
||||
g_autofree char *id = calls_origin_get_id (origin);
|
||||
|
||||
if (g_strcmp0 (id, origin_id) == 0)
|
||||
|
|
|
@ -51,14 +51,6 @@ CallsManager *calls_manager_new (void);
|
|||
CallsManager *calls_manager_get_default (void);
|
||||
CallsContactsProvider *calls_manager_get_contacts_provider (CallsManager *self);
|
||||
CallsSettings *calls_manager_get_settings (CallsManager *self);
|
||||
void calls_manager_add_provider (CallsManager *self,
|
||||
const char *name);
|
||||
void calls_manager_remove_provider (CallsManager *self,
|
||||
const char *name);
|
||||
gboolean calls_manager_has_provider (CallsManager *self,
|
||||
const char *name);
|
||||
gboolean calls_manager_is_modem_provider (CallsManager *self,
|
||||
const char *name);
|
||||
CallsManagerFlags calls_manager_get_state_flags (CallsManager *self);
|
||||
GListModel *calls_manager_get_origins (CallsManager *self);
|
||||
GList *calls_manager_get_calls (CallsManager *self);
|
||||
|
@ -67,9 +59,5 @@ GListModel *calls_manager_get_suitable_origins (CallsManager *sel
|
|||
CallsOrigin *calls_manager_get_origin_by_id (CallsManager *self,
|
||||
const char *origin_id);
|
||||
void calls_manager_hang_up_all_calls (CallsManager *self);
|
||||
gboolean calls_manager_has_any_provider (CallsManager *self);
|
||||
const char **calls_manager_get_provider_names (CallsManager *self,
|
||||
guint *length);
|
||||
GList *calls_manager_get_providers (CallsManager *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -187,72 +187,6 @@ calls_provider_get_origins (CallsProvider *self)
|
|||
return CALLS_PROVIDER_GET_CLASS (self)->get_origins (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* calls_provider_load_plugin:
|
||||
* @name: The name of the provider plugin to load
|
||||
*
|
||||
* Get a #CallsProvider plugin by name
|
||||
*
|
||||
* Returns: (transfer full): A #CallsProvider
|
||||
*/
|
||||
CallsProvider *
|
||||
calls_provider_load_plugin (const char *name)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
PeasEngine *plugins;
|
||||
PeasPluginInfo *info;
|
||||
PeasExtension *extension;
|
||||
|
||||
plugins = peas_engine_get_default ();
|
||||
|
||||
// Find the plugin
|
||||
info = peas_engine_get_plugin_info (plugins, name);
|
||||
if (!info) {
|
||||
g_debug ("Could not find plugin `%s'", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Possibly load the plugin
|
||||
if (!peas_plugin_info_is_loaded (info)) {
|
||||
peas_engine_load_plugin (plugins, info);
|
||||
|
||||
if (!peas_plugin_info_is_available (info, &error)) {
|
||||
g_debug ("Error loading plugin `%s': %s", name, error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_debug ("Loaded plugin `%s'", name);
|
||||
}
|
||||
|
||||
// Check the plugin provides CallsProvider
|
||||
if (!peas_engine_provides_extension (plugins, info, CALLS_TYPE_PROVIDER)) {
|
||||
g_debug ("Plugin `%s' does not have a provider extension", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the extension
|
||||
extension = peas_engine_create_extensionv (plugins, info, CALLS_TYPE_PROVIDER, 0, NULL);
|
||||
if (!extension) {
|
||||
g_debug ("Could not create provider from plugin `%s'", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_debug ("Created provider from plugin `%s'", name);
|
||||
return CALLS_PROVIDER (extension);
|
||||
}
|
||||
|
||||
void
|
||||
calls_provider_unload_plugin (const char *name)
|
||||
{
|
||||
PeasEngine *engine = peas_engine_get_default ();
|
||||
PeasPluginInfo *plugin = peas_engine_get_plugin_info (engine, name);
|
||||
|
||||
if (plugin)
|
||||
peas_engine_unload_plugin (engine, plugin);
|
||||
else
|
||||
g_warning ("Can't unload plugin: No plugin with name %s found", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* calls_provider_get_protocols:
|
||||
* @self: A #CallsProvider
|
||||
|
|
|
@ -53,8 +53,6 @@ struct _CallsProviderClass {
|
|||
const char *calls_provider_get_name (CallsProvider *self);
|
||||
const char *calls_provider_get_status (CallsProvider *self);
|
||||
GListModel *calls_provider_get_origins (CallsProvider *self);
|
||||
CallsProvider *calls_provider_load_plugin (const char *name);
|
||||
void calls_provider_unload_plugin (const char *name);
|
||||
const char *const *calls_provider_get_protocols (CallsProvider *self);
|
||||
gboolean calls_provider_is_modem (CallsProvider *self);
|
||||
gboolean calls_provider_is_operational (CallsProvider *self);
|
||||
|
|
|
@ -52,7 +52,6 @@ t = executable('emergency-call-types', test_sources,
|
|||
)
|
||||
test('emergency-call-types', t, env: test_env)
|
||||
|
||||
|
||||
test_sources = [ 'test-manager.c' ]
|
||||
|
||||
t = executable('manager', test_sources,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "calls-manager.h"
|
||||
#include "calls-dbus-manager.h"
|
||||
#include "calls-plugin-manager.h"
|
||||
|
||||
#include <glib-unix.h>
|
||||
|
||||
|
@ -51,8 +52,10 @@ int
|
|||
main (int argc, char *argv[])
|
||||
{
|
||||
g_autoptr (CallsManager) manager = NULL;
|
||||
CallsDBusManager *dbus_manager = NULL;
|
||||
g_autoptr (CallsPluginManager) plugin_manager = NULL;
|
||||
g_autoptr (GMainLoop) loop = g_main_loop_new (NULL, FALSE);
|
||||
g_autoptr (GError) error = NULL;
|
||||
CallsDBusManager *dbus_manager = NULL;
|
||||
guint bus_id;
|
||||
|
||||
/* Setup environment */
|
||||
|
@ -62,9 +65,11 @@ main (int argc, char *argv[])
|
|||
|
||||
g_print ("Starting up DBus service\n");
|
||||
|
||||
plugin_manager = calls_plugin_manager_get_default ();
|
||||
manager = calls_manager_get_default ();
|
||||
dbus_manager = calls_dbus_manager_new ();
|
||||
calls_manager_add_provider (manager, "dummy");
|
||||
g_assert_true (calls_plugin_manager_load_plugin (plugin_manager, "dummy", &error));
|
||||
g_assert_no_error (error);
|
||||
|
||||
bus_id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
||||
CALLS_DBUS_NAME,
|
||||
|
@ -79,7 +84,8 @@ main (int argc, char *argv[])
|
|||
|
||||
g_print ("Shutting down DBus service\n");
|
||||
|
||||
calls_manager_remove_provider (manager, "dummy");
|
||||
g_assert_true (calls_plugin_manager_unload_plugin (plugin_manager, "dummy", &error));
|
||||
g_assert_no_error (error);
|
||||
|
||||
/* The DBus manager unexports any objects it may still have.
|
||||
* Do this before releasing the DBus name ownership */
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
#include "calls-manager.h"
|
||||
#include "calls-plugin-manager.h"
|
||||
#include "calls-util.h"
|
||||
|
||||
#include <cui-call.h>
|
||||
#include <glib.h>
|
||||
|
@ -12,6 +14,7 @@
|
|||
struct TestData {
|
||||
GMainLoop *loop;
|
||||
CallsManager *manager;
|
||||
CallsPluginManager *plugin_manager;
|
||||
GListModel *origins;
|
||||
GListModel *origins_tel;
|
||||
CallsOrigin *origin;
|
||||
|
@ -24,6 +27,7 @@ call_add_cb (CallsManager *manager,
|
|||
struct TestData *data)
|
||||
{
|
||||
static guint phase = 0;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
data->call = call;
|
||||
switch (phase++) {
|
||||
|
@ -33,9 +37,11 @@ call_add_cb (CallsManager *manager,
|
|||
|
||||
case 1:
|
||||
/* Unload the provider */
|
||||
calls_manager_remove_provider (data->manager, "dummy");
|
||||
g_assert_false (calls_manager_has_provider (data->manager, "dummy"));
|
||||
g_assert_false (calls_manager_has_any_provider (data->manager));
|
||||
calls_plugin_manager_unload_plugin (data->plugin_manager, "dummy", &error);
|
||||
g_assert_false (calls_plugin_manager_has_plugin (data->plugin_manager, "dummy"));
|
||||
g_assert_false (calls_plugin_manager_has_any_plugins (data->plugin_manager));
|
||||
g_assert_cmpuint (g_list_model_get_n_items (calls_manager_get_origins (data->manager)),
|
||||
==, 0);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -72,19 +78,20 @@ call_remove_cb (CallsManager *manager,
|
|||
static void
|
||||
test_calls_manager_without_provider (void)
|
||||
{
|
||||
guint no_origins;
|
||||
GListModel *origins;
|
||||
g_autoptr (CallsManager) manager = calls_manager_new ();
|
||||
CallsManager *manager = calls_manager_get_default ();
|
||||
CallsPluginManager *plugin_manager = calls_plugin_manager_get_default ();
|
||||
|
||||
g_assert_true (CALLS_IS_MANAGER (manager));
|
||||
g_assert_true (CALLS_IS_PLUGIN_MANAGER (plugin_manager));
|
||||
|
||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||
|
||||
origins = calls_manager_get_origins (manager);
|
||||
no_origins = g_list_model_get_n_items (origins);
|
||||
g_assert_cmpuint (no_origins, ==, 0);
|
||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||
|
||||
g_assert_null (calls_manager_get_calls (manager));
|
||||
g_assert_false (calls_manager_has_any_provider (manager));
|
||||
g_assert_false (calls_plugin_manager_has_any_plugins (plugin_manager));
|
||||
|
||||
origins = calls_manager_get_suitable_origins (manager, "tel:+123456789");
|
||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||
|
@ -94,11 +101,16 @@ test_calls_manager_without_provider (void)
|
|||
|
||||
origins = calls_manager_get_suitable_origins (manager, "sips:bob@example.org");
|
||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||
|
||||
g_assert_finalize_object (manager);
|
||||
g_assert_finalize_object (plugin_manager);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_calls_manager_dummy_provider (void)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
CallsManager *manager;
|
||||
GListModel *origins;
|
||||
GListModel *origins_tel;
|
||||
|
@ -106,7 +118,9 @@ test_calls_manager_dummy_provider (void)
|
|||
struct TestData *test_data;
|
||||
|
||||
test_data = g_new0 (struct TestData, 1);
|
||||
test_data->manager = calls_manager_new ();
|
||||
test_data->manager = calls_manager_get_default ();
|
||||
test_data->plugin_manager = calls_plugin_manager_get_default ();
|
||||
|
||||
manager = test_data->manager;
|
||||
g_assert_true (CALLS_IS_MANAGER (manager));
|
||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||
|
@ -117,9 +131,11 @@ test_calls_manager_dummy_provider (void)
|
|||
g_assert_true (origins);
|
||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||
|
||||
calls_manager_add_provider (manager, "dummy");
|
||||
g_assert_true (calls_manager_has_any_provider (manager));
|
||||
g_assert_true (calls_manager_has_provider (manager, "dummy"));
|
||||
g_assert_true (calls_plugin_manager_load_plugin (test_data->plugin_manager, "dummy", &error));
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_true (calls_plugin_manager_has_any_plugins (test_data->plugin_manager));
|
||||
g_assert_true (calls_plugin_manager_has_plugin (test_data->plugin_manager, "dummy"));
|
||||
/* Dummy plugin fakes being a modem */
|
||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==,
|
||||
CALLS_MANAGER_FLAGS_HAS_CELLULAR_PROVIDER |
|
||||
|
@ -134,8 +150,7 @@ test_calls_manager_dummy_provider (void)
|
|||
test_data->origins_tel = calls_manager_get_suitable_origins (manager, "tel:+393422342");
|
||||
origins_tel = test_data->origins_tel;
|
||||
g_assert_true (G_IS_LIST_MODEL (origins_tel));
|
||||
g_assert_true (G_IS_LIST_STORE (origins_tel));
|
||||
g_assert_true (g_list_store_find (G_LIST_STORE (origins_tel), test_data->origin, &position));
|
||||
g_assert_true (calls_find_in_model (origins_tel, test_data->origin, &position));
|
||||
|
||||
g_signal_connect (manager, "ui-call-added", G_CALLBACK (call_add_cb), test_data);
|
||||
g_signal_connect (manager, "ui-call-removed", G_CALLBACK (call_remove_cb), test_data);
|
||||
|
@ -155,22 +170,29 @@ test_calls_manager_dummy_provider (void)
|
|||
|
||||
g_assert_finalize_object (test_data->origin);
|
||||
g_assert_finalize_object (test_data->manager);
|
||||
g_assert_finalize_object (test_data->plugin_manager);
|
||||
|
||||
g_free (test_data);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_calls_manager_mm_provider (void)
|
||||
{
|
||||
GListModel *origins_tel;
|
||||
g_autoptr (CallsManager) manager = calls_manager_new ();
|
||||
CallsManager *manager = calls_manager_get_default ();
|
||||
CallsPluginManager *plugin_manager = calls_plugin_manager_get_default ();
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
g_assert_true (CALLS_IS_MANAGER (manager));
|
||||
g_assert_true (CALLS_IS_PLUGIN_MANAGER (plugin_manager));
|
||||
|
||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||
|
||||
calls_manager_add_provider (manager, "mm");
|
||||
g_assert_true (calls_manager_has_any_provider (manager));
|
||||
g_assert_true (calls_manager_has_provider (manager, "mm"));
|
||||
g_assert_true (calls_plugin_manager_load_plugin (plugin_manager, "mm", &error));
|
||||
g_assert_no_error (error);
|
||||
g_assert_true (calls_plugin_manager_has_any_plugins (plugin_manager));
|
||||
g_assert_true (calls_plugin_manager_has_plugin (plugin_manager, "mm"));
|
||||
|
||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), >, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||
|
||||
|
@ -180,22 +202,28 @@ test_calls_manager_mm_provider (void)
|
|||
g_assert_nonnull (origins_tel);
|
||||
g_assert_cmpuint (g_list_model_get_n_items (origins_tel), ==, 0);
|
||||
|
||||
calls_manager_remove_provider (manager, "mm");
|
||||
g_assert_true (calls_plugin_manager_unload_plugin (plugin_manager, "mm", &error));
|
||||
g_assert_no_error (error);
|
||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||
|
||||
g_assert_finalize_object (manager);
|
||||
g_assert_finalize_object (plugin_manager);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_calls_manager_multiple_providers_mm_sip (void)
|
||||
{
|
||||
g_autoptr (CallsOrigin) origin_alice = NULL;
|
||||
g_autoptr (CallsOrigin) origin_bob = NULL;
|
||||
g_autoptr (CallsManager) manager = calls_manager_new ();
|
||||
CallsManager *manager = calls_manager_get_default ();
|
||||
CallsPluginManager *plugin_manager = calls_plugin_manager_get_default ();
|
||||
GListModel *origins;
|
||||
GListModel *origins_tel;
|
||||
GListModel *origins_sip;
|
||||
GListModel *origins_sips;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
g_assert_true (CALLS_IS_MANAGER (manager));
|
||||
g_assert_true (CALLS_IS_PLUGIN_MANAGER (plugin_manager));
|
||||
|
||||
origins = calls_manager_get_origins (manager);
|
||||
g_assert_true (G_IS_LIST_MODEL (origins));
|
||||
|
@ -215,10 +243,7 @@ test_calls_manager_multiple_providers_mm_sip (void)
|
|||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||
|
||||
/* First add the SIP provider, MM provider later */
|
||||
calls_manager_add_provider (manager, "sip");
|
||||
g_assert_true (calls_manager_has_any_provider (manager));
|
||||
g_assert_true (calls_manager_has_provider (manager, "sip"));
|
||||
g_assert_true (calls_manager_is_modem_provider (manager, "sip") == FALSE);
|
||||
g_assert_true (calls_plugin_manager_load_plugin (plugin_manager, "sip", &error));
|
||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_HAS_VOIP_PROVIDER);
|
||||
|
||||
/* Still no origins */
|
||||
|
@ -237,13 +262,13 @@ test_calls_manager_multiple_providers_mm_sip (void)
|
|||
* see https://source.puri.sm/Librem5/calls/-/issues/280
|
||||
* and https://source.puri.sm/Librem5/calls/-/issues/178
|
||||
*/
|
||||
calls_manager_add_provider (manager, "mm");
|
||||
g_assert_true (calls_manager_has_any_provider (manager));
|
||||
g_assert_true (calls_manager_has_provider (manager, "mm"));
|
||||
g_assert_true (calls_plugin_manager_load_plugin (plugin_manager, "mm", &error));
|
||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==,
|
||||
CALLS_MANAGER_FLAGS_HAS_VOIP_PROVIDER |
|
||||
CALLS_MANAGER_FLAGS_HAS_CELLULAR_PROVIDER);
|
||||
|
||||
g_assert_finalize_object (manager);
|
||||
g_assert_finalize_object (plugin_manager);
|
||||
}
|
||||
|
||||
gint
|
||||
|
|
Loading…
Reference in a new issue