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-account-provider.h"
|
||||||
#include "calls-manager.h"
|
#include "calls-manager.h"
|
||||||
#include "calls-in-app-notification.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>
|
#include <glib/gi18n-lib.h>
|
||||||
|
|
||||||
|
@ -66,11 +71,16 @@ struct _CallsAccountOverview {
|
||||||
GtkWindow *account_window;
|
GtkWindow *account_window;
|
||||||
GtkWidget *current_account_widget;
|
GtkWidget *current_account_widget;
|
||||||
|
|
||||||
|
/* models */
|
||||||
|
GtkFilter *account_provider_filter;
|
||||||
|
GtkFilter *account_filter;
|
||||||
|
GListModel *providers;
|
||||||
|
GListModel *accounts;
|
||||||
|
|
||||||
/* misc */
|
/* misc */
|
||||||
GtkEventController *key_controller;
|
GtkEventController *key_controller;
|
||||||
GtkEventController *key_controller_account;
|
GtkEventController *key_controller_account;
|
||||||
CallsAccountOverviewState state;
|
CallsAccountOverviewState state;
|
||||||
GList *providers;
|
|
||||||
CallsInAppNotification *in_app_notification;
|
CallsInAppNotification *in_app_notification;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,14 +111,25 @@ static void
|
||||||
update_state (CallsAccountOverview *self)
|
update_state (CallsAccountOverview *self)
|
||||||
{
|
{
|
||||||
guint n_origins = 0;
|
guint n_origins = 0;
|
||||||
|
guint n_providers;
|
||||||
|
|
||||||
g_assert (CALLS_IS_ACCOUNT_OVERVIEW (self));
|
g_assert (CALLS_IS_ACCOUNT_OVERVIEW (self));
|
||||||
|
|
||||||
for (GList *node = self->providers; node != NULL; node = node->next) {
|
n_providers = g_list_model_get_n_items (self->providers);
|
||||||
CallsProvider *provider = CALLS_PROVIDER (node->data);
|
|
||||||
GListModel *model = calls_provider_get_origins (provider);
|
|
||||||
|
|
||||||
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)
|
if (n_origins > 0)
|
||||||
|
@ -116,6 +137,8 @@ update_state (CallsAccountOverview *self)
|
||||||
else
|
else
|
||||||
self->state = SHOW_INTRO;
|
self->state = SHOW_INTRO;
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (self->add_btn, n_providers > 0);
|
||||||
|
|
||||||
update_visibility (self);
|
update_visibility (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,18 +168,20 @@ on_account_row_activated (GtkListBox *box,
|
||||||
GtkListBoxRow *row,
|
GtkListBoxRow *row,
|
||||||
CallsAccountOverview *self)
|
CallsAccountOverview *self)
|
||||||
{
|
{
|
||||||
|
CallsAccountProvider *provider;
|
||||||
CallsAccount *account = NULL;
|
CallsAccount *account = NULL;
|
||||||
CallsAccountRow *acc_row;
|
CallsAccountRow *acc_row;
|
||||||
CallsAccountProvider *provider;
|
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
|
|
||||||
g_assert (GTK_IS_LIST_BOX_ROW (row) );
|
g_assert (GTK_IS_LIST_BOX_ROW (row) );
|
||||||
g_assert (CALLS_IS_ACCOUNT_OVERVIEW (self));
|
g_assert (CALLS_IS_ACCOUNT_OVERVIEW (self));
|
||||||
|
g_assert (g_list_model_get_n_items (self->providers) > 0);
|
||||||
|
|
||||||
if (row == self->add_row) {
|
if (row == self->add_row) {
|
||||||
/* TODO this needs changing if we ever have multiple account providers */
|
/* 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);
|
widget = calls_account_provider_get_account_widget (provider);
|
||||||
|
g_object_unref (provider);
|
||||||
|
|
||||||
} else if (CALLS_IS_ACCOUNT_ROW (row)) {
|
} else if (CALLS_IS_ACCOUNT_ROW (row)) {
|
||||||
acc_row = CALLS_ACCOUNT_ROW (row);
|
acc_row = CALLS_ACCOUNT_ROW (row);
|
||||||
|
@ -215,84 +240,72 @@ on_account_message (CallsAccount *account,
|
||||||
|
|
||||||
|
|
||||||
static void
|
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)
|
gtk_container_remove (GTK_CONTAINER (self->overview), GTK_WIDGET (row));
|
||||||
* 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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GList *node = self->providers; node != NULL; node = node->next) {
|
for (guint i = 0; i < added; i++) {
|
||||||
CallsAccountProvider *provider = CALLS_ACCOUNT_PROVIDER (node->data);
|
g_autoptr (CallsAccount) account =
|
||||||
GListModel *model = calls_provider_get_origins (CALLS_PROVIDER (provider));
|
CALLS_ACCOUNT (g_list_model_get_item (accounts, position + i));
|
||||||
guint n_origins = g_list_model_get_n_items (model);
|
CallsAccountProvider *provider = NULL;
|
||||||
|
CallsAccountRow *account_row;
|
||||||
|
|
||||||
for (guint i = 0; i < n_origins; i++) {
|
/* which provider does this account belong to? */
|
||||||
g_autoptr (CallsAccount) account = CALLS_ACCOUNT (g_list_model_get_item (model, i));
|
for (guint j = 0; j < n_providers; j++) {
|
||||||
CallsAccountRow *account_row = calls_account_row_new (provider, account);
|
g_autoptr (CallsProvider) candidate = g_list_model_get_item (self->providers, j);
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_data (account, self);
|
if (calls_find_in_model (calls_provider_get_origins (candidate), account, NULL)) {
|
||||||
g_signal_connect_object (account, "message",
|
provider = CALLS_ACCOUNT_PROVIDER (candidate);
|
||||||
G_CALLBACK (on_account_message),
|
break;
|
||||||
self,
|
}
|
||||||
G_CONNECT_AFTER);
|
|
||||||
|
|
||||||
gtk_list_box_insert (GTK_LIST_BOX (self->overview),
|
|
||||||
GTK_WIDGET (account_row),
|
|
||||||
0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
update_state (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
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);
|
g_signal_connect_swapped (provider, "widget-edit-done",
|
||||||
providers = calls_manager_get_providers (calls_manager_get_default ());
|
G_CALLBACK (gtk_widget_hide), self->account_window);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear any acccount widgets, because they might've gone stale */
|
/* Clear any acccount widgets, because they might've gone stale */
|
||||||
attach_account_widget (self, NULL);
|
attach_account_widget (self, NULL);
|
||||||
gtk_widget_hide (GTK_WIDGET (self->account_window));
|
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);
|
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);
|
||||||
g_clear_object (&self->key_controller_account);
|
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
|
static void
|
||||||
calls_account_overview_init (CallsAccountOverview *self)
|
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));
|
gtk_widget_init_template (GTK_WIDGET (self));
|
||||||
|
|
||||||
g_signal_connect_swapped (calls_manager_get_default (),
|
self->account_provider_filter = gtk_custom_filter_new (match_account_provider, NULL, NULL);
|
||||||
"providers-changed",
|
self->providers =
|
||||||
G_CALLBACK (on_providers_changed),
|
G_LIST_MODEL (gtk_filter_list_model_new (all_providers,
|
||||||
self);
|
self->account_provider_filter));
|
||||||
on_providers_changed (self);
|
|
||||||
|
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_list_box_insert (GTK_LIST_BOX (self->overview),
|
||||||
GTK_WIDGET (self->add_row),
|
GTK_WIDGET (self->add_row),
|
||||||
-1);
|
-1);
|
||||||
gtk_window_set_transient_for (self->account_window, GTK_WINDOW (self));
|
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));
|
self->key_controller = gtk_event_controller_key_new (GTK_WIDGET (self));
|
||||||
g_signal_connect (self->key_controller,
|
g_signal_connect (self->key_controller,
|
||||||
"key-pressed",
|
"key-pressed",
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "calls-message-source.h"
|
#include "calls-message-source.h"
|
||||||
#include "calls-new-call-box.h"
|
#include "calls-new-call-box.h"
|
||||||
#include "calls-notifier.h"
|
#include "calls-notifier.h"
|
||||||
|
#include "calls-plugin-manager.h"
|
||||||
#include "calls-record-store.h"
|
#include "calls-record-store.h"
|
||||||
#include "calls-ringer.h"
|
#include "calls-ringer.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -73,6 +74,8 @@ struct _CallsApplication {
|
||||||
guint id_sigint;
|
guint id_sigint;
|
||||||
gboolean shutdown;
|
gboolean shutdown;
|
||||||
gboolean db_done;
|
gboolean db_done;
|
||||||
|
CallsPluginManager *plugin_manager;
|
||||||
|
CallsSettings *settings;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (CallsApplication, calls_application, GTK_TYPE_APPLICATION);
|
G_DEFINE_TYPE (CallsApplication, calls_application, GTK_TYPE_APPLICATION);
|
||||||
|
@ -155,60 +158,76 @@ calls_application_dbus_unregister (GApplication *application,
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_provider_names_action (GSimpleAction *action,
|
set_plugin_names_action (GSimpleAction *action,
|
||||||
GVariant *parameter,
|
GVariant *parameter,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
CallsManager *manager;
|
|
||||||
g_autofree const char **names = NULL;
|
g_autofree const char **names = NULL;
|
||||||
g_autofree const char **loaded = NULL;
|
g_autofree const char **loaded = NULL;
|
||||||
|
CallsApplication *self = user_data;
|
||||||
gsize length;
|
gsize length;
|
||||||
guint length_loaded;
|
guint length_loaded;
|
||||||
|
|
||||||
|
g_assert (CALLS_IS_APPLICATION (self));
|
||||||
|
|
||||||
names = g_variant_get_strv (parameter, &length);
|
names = g_variant_get_strv (parameter, &length);
|
||||||
g_return_if_fail (names && *names);
|
g_return_if_fail (names && *names);
|
||||||
|
|
||||||
manager = calls_manager_get_default ();
|
loaded = calls_plugin_manager_get_plugin_names (self->plugin_manager, &length_loaded);
|
||||||
loaded = calls_manager_get_provider_names (manager, &length_loaded);
|
|
||||||
|
|
||||||
/* remove unwanted providers */
|
/* remove unwanted plugins */
|
||||||
for (guint i = 0; i < length_loaded; i++) {
|
for (guint i = 0; i < length_loaded; i++) {
|
||||||
g_autofree char *provider = g_strdup (loaded[i]);
|
g_autofree char *plugin = g_strdup (loaded[i]);
|
||||||
if (!g_strv_contains (names, provider))
|
|
||||||
calls_manager_remove_provider (manager, provider);
|
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++) {
|
for (guint i = 0; i < length; i++) {
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
const char *name = names[i];
|
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;
|
continue;
|
||||||
|
|
||||||
g_debug ("Loading provider `%s'", name);
|
ok = calls_plugin_manager_load_plugin (self->plugin_manager, name, &error);
|
||||||
calls_manager_add_provider (manager, name);
|
g_debug ("Loading plugin `%s' %ssuccessful", name, ok ? "" : "un");
|
||||||
|
if (!ok)
|
||||||
|
g_warning ("Plugin '%s' not loaded: %s", name, error->message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_default_providers_action (GSimpleAction *action,
|
set_default_plugins_action (GSimpleAction *action,
|
||||||
GVariant *parameter,
|
GVariant *parameter,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
CallsManager *manager = calls_manager_get_default ();
|
CallsApplication *self = CALLS_APPLICATION (user_data);
|
||||||
CallsSettings *settings = calls_manager_get_settings (manager);
|
|
||||||
|
|
||||||
g_auto (GStrv) plugins = NULL;
|
g_auto (GStrv) plugins = NULL;
|
||||||
/**
|
/**
|
||||||
* Only add default providers when there are none added yet,
|
* Only add default providers when there are none added yet,
|
||||||
* This makes sure we're not resetting explicitly set providers
|
* 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;
|
return;
|
||||||
|
|
||||||
plugins = calls_settings_get_autoload_plugins (settings);
|
plugins = calls_settings_get_autoload_plugins (self->settings);
|
||||||
for (guint i = 0; plugins[i] != NULL; i++) {
|
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[] =
|
static const GActionEntry actions[] =
|
||||||
{
|
{
|
||||||
{ "set-provider-names", set_provider_names_action, "as" },
|
{ "set-plugin-names", set_plugin_names_action, "as" },
|
||||||
{ "set-default-providers", set_default_providers_action, NULL },
|
{ "set-default-plugins", set_default_plugins_action, NULL },
|
||||||
{ "set-daemon", set_daemon_action, "b" },
|
{ "set-daemon", set_daemon_action, "b" },
|
||||||
{ "dial", dial_action, "s" },
|
{ "dial", dial_action, "s" },
|
||||||
{ "copy-number", copy_number, "s" },
|
{ "copy-number", copy_number, "s" },
|
||||||
|
@ -509,7 +528,7 @@ calls_application_command_line (GApplication *application,
|
||||||
GVariantDict *options;
|
GVariantDict *options;
|
||||||
const char *arg;
|
const char *arg;
|
||||||
|
|
||||||
g_autoptr (GVariant) providers = NULL;
|
g_autoptr (GVariant) plugins = NULL;
|
||||||
g_auto (GStrv) arguments = NULL;
|
g_auto (GStrv) arguments = NULL;
|
||||||
gint argc;
|
gint argc;
|
||||||
guint verbosity;
|
guint verbosity;
|
||||||
|
@ -529,14 +548,14 @@ calls_application_command_line (GApplication *application,
|
||||||
|
|
||||||
start_proper (self);
|
start_proper (self);
|
||||||
|
|
||||||
providers = g_variant_dict_lookup_value (options, "provider", G_VARIANT_TYPE_STRING_ARRAY);
|
plugins = g_variant_dict_lookup_value (options, "plugins", G_VARIANT_TYPE_STRING_ARRAY);
|
||||||
if (providers) {
|
if (plugins) {
|
||||||
g_action_group_activate_action (G_ACTION_GROUP (application),
|
g_action_group_activate_action (G_ACTION_GROUP (application),
|
||||||
"set-provider-names",
|
"set-plugin-names",
|
||||||
providers);
|
plugins);
|
||||||
} else {
|
} else {
|
||||||
g_action_group_activate_action (G_ACTION_GROUP (application),
|
g_action_group_activate_action (G_ACTION_GROUP (application),
|
||||||
"set-default-providers",
|
"set-default-plugins",
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,6 +648,12 @@ start_proper (CallsApplication *self)
|
||||||
|
|
||||||
gtk_app = GTK_APPLICATION (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 ();
|
self->manager = calls_manager_get_default ();
|
||||||
g_assert (self->manager);
|
g_assert (self->manager);
|
||||||
|
|
||||||
|
@ -746,6 +771,8 @@ finalize (GObject *object)
|
||||||
g_clear_object (&self->ringer);
|
g_clear_object (&self->ringer);
|
||||||
g_clear_object (&self->notifier);
|
g_clear_object (&self->notifier);
|
||||||
g_clear_object (&self->manager);
|
g_clear_object (&self->manager);
|
||||||
|
g_clear_object (&self->plugin_manager);
|
||||||
|
g_clear_object (&self->settings);
|
||||||
|
|
||||||
g_free (self->uri);
|
g_free (self->uri);
|
||||||
|
|
||||||
|
@ -780,9 +807,9 @@ calls_application_init (CallsApplication *self)
|
||||||
{
|
{
|
||||||
const GOptionEntry options[] = {
|
const GOptionEntry options[] = {
|
||||||
{
|
{
|
||||||
"provider", 'p', G_OPTION_FLAG_NONE,
|
"plugins", 'p', G_OPTION_FLAG_NONE,
|
||||||
G_OPTION_ARG_STRING_ARRAY, NULL,
|
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")
|
_("PLUGIN")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "calls-contacts-provider.h"
|
#include "calls-contacts-provider.h"
|
||||||
#include "calls-manager.h"
|
#include "calls-manager.h"
|
||||||
#include "calls-message-source.h"
|
#include "calls-message-source.h"
|
||||||
|
#include "calls-plugin-manager.h"
|
||||||
#include "calls-provider.h"
|
#include "calls-provider.h"
|
||||||
#include "calls-settings.h"
|
#include "calls-settings.h"
|
||||||
#include "calls-ui-call-data.h"
|
#include "calls-ui-call-data.h"
|
||||||
|
@ -39,6 +40,10 @@
|
||||||
|
|
||||||
#include "enum-types.h"
|
#include "enum-types.h"
|
||||||
|
|
||||||
|
#include "gtkcustomfilter.h"
|
||||||
|
#include "gtkfilterlistmodel.h"
|
||||||
|
#include "gtkflattenlistmodel.h"
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
#include <libpeas/peas.h>
|
#include <libpeas/peas.h>
|
||||||
|
|
||||||
|
@ -59,12 +64,23 @@ static const char * const protocols[] = {
|
||||||
"sips"
|
"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 {
|
struct _CallsManager {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
GHashTable *providers;
|
|
||||||
|
|
||||||
GListStore *origins;
|
GListStore *origins;
|
||||||
|
GtkFlattenListModel *origins_flat;
|
||||||
|
|
||||||
/* origins_by_protocol maps protocol names to GListStore's of suitable origins */
|
/* origins_by_protocol maps protocol names to GListStore's of suitable origins */
|
||||||
GHashTable *origins_by_protocol;
|
GHashTable *origins_by_protocol;
|
||||||
/* dial_actions_by_protocol maps protocol names to GSimpleActions */
|
/* dial_actions_by_protocol maps protocol names to GSimpleActions */
|
||||||
|
@ -123,16 +139,17 @@ set_state_flags (CallsManager *self, CallsManagerFlags state_flags)
|
||||||
static void
|
static void
|
||||||
update_state_flags (CallsManager *self)
|
update_state_flags (CallsManager *self)
|
||||||
{
|
{
|
||||||
GHashTableIter iter;
|
|
||||||
gpointer value;
|
|
||||||
CallsManagerFlags state_flags = CALLS_MANAGER_FLAGS_UNKNOWN;
|
CallsManagerFlags state_flags = CALLS_MANAGER_FLAGS_UNKNOWN;
|
||||||
|
GListModel *providers;
|
||||||
|
guint n_providers;
|
||||||
|
|
||||||
g_assert (CALLS_IS_MANAGER (self));
|
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)) {
|
n_providers = g_list_model_get_n_items (providers);
|
||||||
CallsProvider *provider = CALLS_PROVIDER (value);
|
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)) {
|
if (calls_provider_is_modem (provider)) {
|
||||||
state_flags |= CALLS_MANAGER_FLAGS_HAS_CELLULAR_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);
|
call_data = calls_ui_call_data_new (call, origin_id);
|
||||||
g_hash_table_insert (self->calls, call, call_data);
|
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);
|
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);
|
name = calls_origin_get_name (origin);
|
||||||
g_debug ("Adding origin %s (%p)", name, origin);
|
g_debug ("Adding origin %s (%p)", name, origin);
|
||||||
|
|
||||||
g_list_store_append (self->origins, origin);
|
|
||||||
|
|
||||||
g_signal_connect_object (origin,
|
g_signal_connect_object (origin,
|
||||||
"message",
|
"message",
|
||||||
G_CALLBACK (on_message),
|
G_CALLBACK (on_message),
|
||||||
|
@ -388,238 +405,27 @@ add_origin (CallsManager *self, CallsOrigin *origin)
|
||||||
calls_origin_foreach_call (origin, (CallsOriginForeachCallFunc) add_call, self);
|
calls_origin_foreach_call (origin, (CallsOriginForeachCallFunc) add_call, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
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_MANAGER (self));
|
||||||
g_assert (CALLS_IS_ORIGIN (origin));
|
g_assert (model == G_LIST_MODEL (self->origins_flat));
|
||||||
|
|
||||||
name = calls_origin_get_name (origin);
|
for (guint i = 0; i < added; i++) {
|
||||||
g_debug ("Removing origin %s (%p)", name, origin);
|
g_autoptr (CallsOrigin) origin = g_list_model_get_item (model, position + i);
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_data (origin, self);
|
add_origin (self, origin);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_state_flags (self);
|
||||||
update_protocol_dial_actions (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
|
static void
|
||||||
calls_manager_get_property (GObject *object,
|
calls_manager_get_property (GObject *object,
|
||||||
guint property_id,
|
guint property_id,
|
||||||
|
@ -649,7 +455,6 @@ calls_manager_finalize (GObject *object)
|
||||||
g_clear_object (&self->contacts_provider);
|
g_clear_object (&self->contacts_provider);
|
||||||
|
|
||||||
g_clear_pointer (&self->origins_by_protocol, g_hash_table_unref);
|
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_clear_pointer (&self->dial_actions_by_protocol, g_hash_table_unref);
|
||||||
|
|
||||||
G_OBJECT_CLASS (calls_manager_parent_class)->finalize (object);
|
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
|
static void
|
||||||
calls_manager_init (CallsManager *self)
|
calls_manager_init (CallsManager *self)
|
||||||
{
|
{
|
||||||
g_autoptr (GVariantType) variant_type = NULL;
|
g_autoptr (GVariantType) variant_type = NULL;
|
||||||
GApplication *application;
|
GApplication *application;
|
||||||
PeasEngine *peas;
|
CallsPluginManager *plugin_manager = calls_plugin_manager_get_default ();
|
||||||
const gchar *dir;
|
GListModel *providers;
|
||||||
g_autofree char *default_plugin_dir_provider = NULL;
|
|
||||||
|
|
||||||
self->state_flags = CALLS_MANAGER_FLAGS_UNKNOWN;
|
self->state_flags = CALLS_MANAGER_FLAGS_UNKNOWN;
|
||||||
self->providers = g_hash_table_new_full (g_str_hash,
|
|
||||||
g_str_equal,
|
self->origins = g_list_store_new (G_TYPE_LIST_MODEL); /* list of lists */
|
||||||
g_free,
|
self->origins_flat = gtk_flatten_list_model_new (CALLS_TYPE_ORIGIN, G_LIST_MODEL (self->origins));
|
||||||
g_object_unref);
|
|
||||||
|
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,
|
self->origins_by_protocol = g_hash_table_new_full (g_str_hash,
|
||||||
g_str_equal,
|
g_str_equal,
|
||||||
g_free,
|
NULL,
|
||||||
g_object_unref);
|
g_object_unref);
|
||||||
|
|
||||||
for (guint i = 0; i < G_N_ELEMENTS (protocols); i++) {
|
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_hash_table_insert (self->origins_by_protocol,
|
||||||
g_strdup (protocols[i]),
|
(gpointer) protocols[i],
|
||||||
origin_store);
|
f_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
self->dial_actions_by_protocol = g_hash_table_new_full (g_str_hash,
|
self->dial_actions_by_protocol = g_hash_table_new_full (g_str_hash,
|
||||||
g_str_equal,
|
g_str_equal,
|
||||||
g_free,
|
NULL,
|
||||||
g_object_unref);
|
g_object_unref);
|
||||||
|
|
||||||
application = g_application_get_default ();
|
application = g_application_get_default ();
|
||||||
|
@ -780,7 +650,7 @@ calls_manager_init (CallsManager *self)
|
||||||
self);
|
self);
|
||||||
|
|
||||||
g_hash_table_insert (self->dial_actions_by_protocol,
|
g_hash_table_insert (self->dial_actions_by_protocol,
|
||||||
g_strdup (protocols[i]),
|
(gpointer) protocols[i],
|
||||||
g_object_ref (action));
|
g_object_ref (action));
|
||||||
|
|
||||||
/* Enable action if there are suitable origins */
|
/* 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));
|
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 */
|
/* This hash table only owns the value, not the key */
|
||||||
self->calls = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
|
self->calls = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
|
||||||
|
|
||||||
self->settings = calls_settings_get_default ();
|
self->settings = calls_settings_get_default ();
|
||||||
// Load the contacts provider
|
/* Load the contacts provider */
|
||||||
self->contacts_provider = calls_contacts_provider_new ();
|
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
|
CallsManagerFlags
|
||||||
calls_manager_get_state_flags (CallsManager *self)
|
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);
|
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));
|
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);
|
n_items = g_list_model_get_n_items (origins);
|
||||||
|
|
||||||
for (uint i = 0; i < n_items; i++) {
|
for (uint i = 0; i < n_items; i++) {
|
||||||
|
@ -996,58 +793,6 @@ calls_manager_get_suitable_origins (CallsManager *self,
|
||||||
return NULL;
|
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 *
|
CallsSettings *
|
||||||
calls_manager_get_settings (CallsManager *self)
|
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))
|
if (STR_IS_NULL_OR_EMPTY (origin_id))
|
||||||
return NULL;
|
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++) {
|
for (uint i = 0; i < n_origins; i++) {
|
||||||
g_autoptr (CallsOrigin) origin =
|
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);
|
g_autofree char *id = calls_origin_get_id (origin);
|
||||||
|
|
||||||
if (g_strcmp0 (id, origin_id) == 0)
|
if (g_strcmp0 (id, origin_id) == 0)
|
||||||
|
|
|
@ -51,14 +51,6 @@ CallsManager *calls_manager_new (void);
|
||||||
CallsManager *calls_manager_get_default (void);
|
CallsManager *calls_manager_get_default (void);
|
||||||
CallsContactsProvider *calls_manager_get_contacts_provider (CallsManager *self);
|
CallsContactsProvider *calls_manager_get_contacts_provider (CallsManager *self);
|
||||||
CallsSettings *calls_manager_get_settings (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);
|
CallsManagerFlags calls_manager_get_state_flags (CallsManager *self);
|
||||||
GListModel *calls_manager_get_origins (CallsManager *self);
|
GListModel *calls_manager_get_origins (CallsManager *self);
|
||||||
GList *calls_manager_get_calls (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,
|
CallsOrigin *calls_manager_get_origin_by_id (CallsManager *self,
|
||||||
const char *origin_id);
|
const char *origin_id);
|
||||||
void calls_manager_hang_up_all_calls (CallsManager *self);
|
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
|
G_END_DECLS
|
||||||
|
|
|
@ -187,72 +187,6 @@ calls_provider_get_origins (CallsProvider *self)
|
||||||
return CALLS_PROVIDER_GET_CLASS (self)->get_origins (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:
|
* calls_provider_get_protocols:
|
||||||
* @self: A #CallsProvider
|
* @self: A #CallsProvider
|
||||||
|
|
|
@ -53,8 +53,6 @@ struct _CallsProviderClass {
|
||||||
const char *calls_provider_get_name (CallsProvider *self);
|
const char *calls_provider_get_name (CallsProvider *self);
|
||||||
const char *calls_provider_get_status (CallsProvider *self);
|
const char *calls_provider_get_status (CallsProvider *self);
|
||||||
GListModel *calls_provider_get_origins (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);
|
const char *const *calls_provider_get_protocols (CallsProvider *self);
|
||||||
gboolean calls_provider_is_modem (CallsProvider *self);
|
gboolean calls_provider_is_modem (CallsProvider *self);
|
||||||
gboolean calls_provider_is_operational (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('emergency-call-types', t, env: test_env)
|
||||||
|
|
||||||
|
|
||||||
test_sources = [ 'test-manager.c' ]
|
test_sources = [ 'test-manager.c' ]
|
||||||
|
|
||||||
t = executable('manager', test_sources,
|
t = executable('manager', test_sources,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "calls-manager.h"
|
#include "calls-manager.h"
|
||||||
#include "calls-dbus-manager.h"
|
#include "calls-dbus-manager.h"
|
||||||
|
#include "calls-plugin-manager.h"
|
||||||
|
|
||||||
#include <glib-unix.h>
|
#include <glib-unix.h>
|
||||||
|
|
||||||
|
@ -51,8 +52,10 @@ int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
g_autoptr (CallsManager) manager = NULL;
|
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 (GMainLoop) loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
CallsDBusManager *dbus_manager = NULL;
|
||||||
guint bus_id;
|
guint bus_id;
|
||||||
|
|
||||||
/* Setup environment */
|
/* Setup environment */
|
||||||
|
@ -62,9 +65,11 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
g_print ("Starting up DBus service\n");
|
g_print ("Starting up DBus service\n");
|
||||||
|
|
||||||
|
plugin_manager = calls_plugin_manager_get_default ();
|
||||||
manager = calls_manager_get_default ();
|
manager = calls_manager_get_default ();
|
||||||
dbus_manager = calls_dbus_manager_new ();
|
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,
|
bus_id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
||||||
CALLS_DBUS_NAME,
|
CALLS_DBUS_NAME,
|
||||||
|
@ -79,7 +84,8 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
g_print ("Shutting down DBus service\n");
|
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.
|
/* The DBus manager unexports any objects it may still have.
|
||||||
* Do this before releasing the DBus name ownership */
|
* Do this before releasing the DBus name ownership */
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "calls-manager.h"
|
#include "calls-manager.h"
|
||||||
|
#include "calls-plugin-manager.h"
|
||||||
|
#include "calls-util.h"
|
||||||
|
|
||||||
#include <cui-call.h>
|
#include <cui-call.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
@ -12,6 +14,7 @@
|
||||||
struct TestData {
|
struct TestData {
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
CallsManager *manager;
|
CallsManager *manager;
|
||||||
|
CallsPluginManager *plugin_manager;
|
||||||
GListModel *origins;
|
GListModel *origins;
|
||||||
GListModel *origins_tel;
|
GListModel *origins_tel;
|
||||||
CallsOrigin *origin;
|
CallsOrigin *origin;
|
||||||
|
@ -24,6 +27,7 @@ call_add_cb (CallsManager *manager,
|
||||||
struct TestData *data)
|
struct TestData *data)
|
||||||
{
|
{
|
||||||
static guint phase = 0;
|
static guint phase = 0;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
data->call = call;
|
data->call = call;
|
||||||
switch (phase++) {
|
switch (phase++) {
|
||||||
|
@ -33,9 +37,11 @@ call_add_cb (CallsManager *manager,
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
/* Unload the provider */
|
/* Unload the provider */
|
||||||
calls_manager_remove_provider (data->manager, "dummy");
|
calls_plugin_manager_unload_plugin (data->plugin_manager, "dummy", &error);
|
||||||
g_assert_false (calls_manager_has_provider (data->manager, "dummy"));
|
g_assert_false (calls_plugin_manager_has_plugin (data->plugin_manager, "dummy"));
|
||||||
g_assert_false (calls_manager_has_any_provider (data->manager));
|
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;
|
break;
|
||||||
|
|
||||||
|
@ -72,19 +78,20 @@ call_remove_cb (CallsManager *manager,
|
||||||
static void
|
static void
|
||||||
test_calls_manager_without_provider (void)
|
test_calls_manager_without_provider (void)
|
||||||
{
|
{
|
||||||
guint no_origins;
|
|
||||||
GListModel *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_MANAGER (manager));
|
||||||
|
g_assert_true (CALLS_IS_PLUGIN_MANAGER (plugin_manager));
|
||||||
|
|
||||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||||
|
|
||||||
origins = calls_manager_get_origins (manager);
|
origins = calls_manager_get_origins (manager);
|
||||||
no_origins = g_list_model_get_n_items (origins);
|
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||||
g_assert_cmpuint (no_origins, ==, 0);
|
|
||||||
|
|
||||||
g_assert_null (calls_manager_get_calls (manager));
|
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");
|
origins = calls_manager_get_suitable_origins (manager, "tel:+123456789");
|
||||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
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");
|
origins = calls_manager_get_suitable_origins (manager, "sips:bob@example.org");
|
||||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||||
|
|
||||||
|
g_assert_finalize_object (manager);
|
||||||
|
g_assert_finalize_object (plugin_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_calls_manager_dummy_provider (void)
|
test_calls_manager_dummy_provider (void)
|
||||||
{
|
{
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
CallsManager *manager;
|
CallsManager *manager;
|
||||||
GListModel *origins;
|
GListModel *origins;
|
||||||
GListModel *origins_tel;
|
GListModel *origins_tel;
|
||||||
|
@ -106,7 +118,9 @@ test_calls_manager_dummy_provider (void)
|
||||||
struct TestData *test_data;
|
struct TestData *test_data;
|
||||||
|
|
||||||
test_data = g_new0 (struct TestData, 1);
|
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;
|
manager = test_data->manager;
|
||||||
g_assert_true (CALLS_IS_MANAGER (manager));
|
g_assert_true (CALLS_IS_MANAGER (manager));
|
||||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
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_true (origins);
|
||||||
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||||
|
|
||||||
calls_manager_add_provider (manager, "dummy");
|
g_assert_true (calls_plugin_manager_load_plugin (test_data->plugin_manager, "dummy", &error));
|
||||||
g_assert_true (calls_manager_has_any_provider (manager));
|
g_assert_no_error (error);
|
||||||
g_assert_true (calls_manager_has_provider (manager, "dummy"));
|
|
||||||
|
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 */
|
/* Dummy plugin fakes being a modem */
|
||||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==,
|
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==,
|
||||||
CALLS_MANAGER_FLAGS_HAS_CELLULAR_PROVIDER |
|
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");
|
test_data->origins_tel = calls_manager_get_suitable_origins (manager, "tel:+393422342");
|
||||||
origins_tel = test_data->origins_tel;
|
origins_tel = test_data->origins_tel;
|
||||||
g_assert_true (G_IS_LIST_MODEL (origins_tel));
|
g_assert_true (G_IS_LIST_MODEL (origins_tel));
|
||||||
g_assert_true (G_IS_LIST_STORE (origins_tel));
|
g_assert_true (calls_find_in_model (origins_tel, test_data->origin, &position));
|
||||||
g_assert_true (g_list_store_find (G_LIST_STORE (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-added", G_CALLBACK (call_add_cb), test_data);
|
||||||
g_signal_connect (manager, "ui-call-removed", G_CALLBACK (call_remove_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->origin);
|
||||||
g_assert_finalize_object (test_data->manager);
|
g_assert_finalize_object (test_data->manager);
|
||||||
|
g_assert_finalize_object (test_data->plugin_manager);
|
||||||
|
|
||||||
g_free (test_data);
|
g_free (test_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_calls_manager_mm_provider (void)
|
test_calls_manager_mm_provider (void)
|
||||||
{
|
{
|
||||||
GListModel *origins_tel;
|
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_MANAGER (manager));
|
||||||
|
g_assert_true (CALLS_IS_PLUGIN_MANAGER (plugin_manager));
|
||||||
|
|
||||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||||
|
|
||||||
calls_manager_add_provider (manager, "mm");
|
g_assert_true (calls_plugin_manager_load_plugin (plugin_manager, "mm", &error));
|
||||||
g_assert_true (calls_manager_has_any_provider (manager));
|
g_assert_no_error (error);
|
||||||
g_assert_true (calls_manager_has_provider (manager, "mm"));
|
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);
|
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_nonnull (origins_tel);
|
||||||
g_assert_cmpuint (g_list_model_get_n_items (origins_tel), ==, 0);
|
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_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_UNKNOWN);
|
||||||
|
|
||||||
|
g_assert_finalize_object (manager);
|
||||||
|
g_assert_finalize_object (plugin_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_calls_manager_multiple_providers_mm_sip (void)
|
test_calls_manager_multiple_providers_mm_sip (void)
|
||||||
{
|
{
|
||||||
g_autoptr (CallsOrigin) origin_alice = NULL;
|
CallsManager *manager = calls_manager_get_default ();
|
||||||
g_autoptr (CallsOrigin) origin_bob = NULL;
|
CallsPluginManager *plugin_manager = calls_plugin_manager_get_default ();
|
||||||
g_autoptr (CallsManager) manager = calls_manager_new ();
|
|
||||||
GListModel *origins;
|
GListModel *origins;
|
||||||
GListModel *origins_tel;
|
GListModel *origins_tel;
|
||||||
GListModel *origins_sip;
|
GListModel *origins_sip;
|
||||||
GListModel *origins_sips;
|
GListModel *origins_sips;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
g_assert_true (CALLS_IS_MANAGER (manager));
|
g_assert_true (CALLS_IS_MANAGER (manager));
|
||||||
|
g_assert_true (CALLS_IS_PLUGIN_MANAGER (plugin_manager));
|
||||||
|
|
||||||
origins = calls_manager_get_origins (manager);
|
origins = calls_manager_get_origins (manager);
|
||||||
g_assert_true (G_IS_LIST_MODEL (origins));
|
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);
|
g_assert_cmpuint (g_list_model_get_n_items (origins), ==, 0);
|
||||||
|
|
||||||
/* First add the SIP provider, MM provider later */
|
/* First add the SIP provider, MM provider later */
|
||||||
calls_manager_add_provider (manager, "sip");
|
g_assert_true (calls_plugin_manager_load_plugin (plugin_manager, "sip", &error));
|
||||||
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_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_HAS_VOIP_PROVIDER);
|
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==, CALLS_MANAGER_FLAGS_HAS_VOIP_PROVIDER);
|
||||||
|
|
||||||
/* Still no origins */
|
/* Still no origins */
|
||||||
|
@ -237,13 +262,13 @@ test_calls_manager_multiple_providers_mm_sip (void)
|
||||||
* see https://source.puri.sm/Librem5/calls/-/issues/280
|
* see https://source.puri.sm/Librem5/calls/-/issues/280
|
||||||
* and https://source.puri.sm/Librem5/calls/-/issues/178
|
* and https://source.puri.sm/Librem5/calls/-/issues/178
|
||||||
*/
|
*/
|
||||||
calls_manager_add_provider (manager, "mm");
|
g_assert_true (calls_plugin_manager_load_plugin (plugin_manager, "mm", &error));
|
||||||
g_assert_true (calls_manager_has_any_provider (manager));
|
|
||||||
g_assert_true (calls_manager_has_provider (manager, "mm"));
|
|
||||||
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==,
|
g_assert_cmpuint (calls_manager_get_state_flags (manager), ==,
|
||||||
CALLS_MANAGER_FLAGS_HAS_VOIP_PROVIDER |
|
CALLS_MANAGER_FLAGS_HAS_VOIP_PROVIDER |
|
||||||
CALLS_MANAGER_FLAGS_HAS_CELLULAR_PROVIDER);
|
CALLS_MANAGER_FLAGS_HAS_CELLULAR_PROVIDER);
|
||||||
|
|
||||||
|
g_assert_finalize_object (manager);
|
||||||
|
g_assert_finalize_object (plugin_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
|
|
Loading…
Reference in a new issue