mirror of
https://gitlab.gnome.org/GNOME/calls.git
synced 2024-12-04 20:07:36 +00:00
Expose call objects on DBus
This exports call objects on the session bus: $ gdbus monitor --session -d sm.puri.Calls … /sm/puri/Calls: org.freedesktop.DBus.ObjectManager.InterfacesAdded (objectpath '/sm/puri/Calls/Call/1', {'sm.puri.Calls.Call': {'Inbound': <false>, 'State': <uint32 0>, 'Id': <''>, 'Party': <''>}}) /sm/puri/Calls/Call/1: org.freedesktop.DBus.Properties.PropertiesChanged ('sm.puri.Calls.Call', {'Id': <'0987654321'>, 'Inbound': <true>, 'State': <uint32 5>}, @as []) /sm/puri/Calls: org.freedesktop.DBus.ObjectManager.InterfacesRemoved (objectpath '/sm/puri/Calls/Call/1', ['sm.puri.Calls.Call']) $ gdbus call --session --dest sm.puri.Calls --object-path /sm/puri/Calls/Call/1 --method sm.puri.Calls.Call.Hangup Currenty hangup and accept methods are implemented as well as exposing the current call state.
This commit is contained in:
parent
8d937bedf6
commit
6f93b48ef4
8 changed files with 325 additions and 72 deletions
|
@ -37,7 +37,6 @@
|
|||
|
||||
<chapter id="dbus">
|
||||
<title>DBus interfaces</title>
|
||||
<xi:include href="../src/dbus/calls-sm.puri.Calls.xml"/>
|
||||
<xi:include href="../src/dbus/calls-sm.puri.Calls.Call.xml"/>
|
||||
</chapter>
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "calls-dbus-manager.h"
|
||||
#include "calls-history-box.h"
|
||||
#include "calls-new-call-box.h"
|
||||
#include "calls-encryption-indicator.h"
|
||||
|
@ -65,6 +66,7 @@ struct _CallsApplication
|
|||
CallsMainWindow *main_window;
|
||||
CallsCallWindow *call_window;
|
||||
CallsSettings *settings;
|
||||
CallsDBusManager *dbus_manager;
|
||||
|
||||
char *uri;
|
||||
};
|
||||
|
@ -75,6 +77,39 @@ G_DEFINE_TYPE (CallsApplication, calls_application, GTK_TYPE_APPLICATION);
|
|||
static gboolean start_proper (CallsApplication *self);
|
||||
|
||||
|
||||
static gboolean
|
||||
calls_application_dbus_register (GApplication *application,
|
||||
GDBusConnection *connection,
|
||||
const gchar *object_path,
|
||||
GError **error)
|
||||
{
|
||||
CallsApplication *self = CALLS_APPLICATION (application);
|
||||
|
||||
G_APPLICATION_CLASS (calls_application_parent_class)->dbus_register (application,
|
||||
connection,
|
||||
object_path,
|
||||
error);
|
||||
|
||||
self->dbus_manager = calls_dbus_manager_new ();
|
||||
return calls_dbus_manager_register (self->dbus_manager, connection, object_path, error);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calls_application_dbus_unregister (GApplication *application,
|
||||
GDBusConnection *connection,
|
||||
const gchar *object_path)
|
||||
{
|
||||
CallsApplication *self = CALLS_APPLICATION (application);
|
||||
|
||||
g_clear_object (&self->dbus_manager);
|
||||
|
||||
G_APPLICATION_CLASS (calls_application_parent_class)->dbus_unregister (application,
|
||||
connection,
|
||||
object_path);
|
||||
}
|
||||
|
||||
|
||||
static gint
|
||||
handle_local_options (GApplication *application,
|
||||
GVariantDict *options)
|
||||
|
@ -553,6 +588,8 @@ calls_application_class_init (CallsApplicationClass *klass)
|
|||
application_class->startup = startup;
|
||||
application_class->activate = activate;
|
||||
application_class->open = app_open;
|
||||
application_class->dbus_register = calls_application_dbus_register;
|
||||
application_class->dbus_unregister = calls_application_dbus_unregister;
|
||||
|
||||
g_type_ensure (CALLS_TYPE_ENCRYPTION_INDICATOR);
|
||||
g_type_ensure (CALLS_TYPE_HISTORY_BOX);
|
||||
|
|
245
src/calls-dbus-manager.c
Normal file
245
src/calls-dbus-manager.c
Normal file
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright (C) 2021 Purism SPC
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Author: Guido Günther <agx@sigxcpu.org>
|
||||
*/
|
||||
|
||||
#define G_LOG_DOMAIN "CallsDBusMmanager"
|
||||
|
||||
#include "config.h"
|
||||
#include "calls-call.h"
|
||||
#include "calls-call-dbus.h"
|
||||
#include "calls-dbus-manager.h"
|
||||
#include "calls-manager.h"
|
||||
|
||||
/**
|
||||
* SECTION:calls-dbus-manager
|
||||
* @short_description: Manages the Call DBus interface
|
||||
* @Title: CallsCallDBusManager
|
||||
*
|
||||
* The #CallsCallManager is responsible for exposing the
|
||||
* call objects on the session bus using #GDBusObjectManager.
|
||||
*
|
||||
* Call objects are exported like /sm/puri/Calls/ as
|
||||
* /sm/puri/Calls/Call/1, /sm/puri/Calls/Call/2, … using
|
||||
* org.freedesktop.DBus.ObjectManager.
|
||||
*/
|
||||
|
||||
typedef struct _CallsDBusManager {
|
||||
GObject parent;
|
||||
|
||||
GDBusObjectManagerServer *object_manager;
|
||||
|
||||
guint iface_num;
|
||||
GListStore *objs;
|
||||
char *object_path;
|
||||
} CallsDBusManager;
|
||||
|
||||
|
||||
G_DEFINE_TYPE (CallsDBusManager, calls_dbus_manager, G_TYPE_OBJECT);
|
||||
|
||||
static char *
|
||||
get_obj_path (CallsDBusManager *self, guint num)
|
||||
{
|
||||
return g_strdup_printf ("%s/Call/%u", self->object_path, num);
|
||||
}
|
||||
|
||||
|
||||
static CallsDBusObjectSkeleton *
|
||||
find_call (CallsDBusManager *self, CallsCall *call, int *pos)
|
||||
{
|
||||
CallsDBusObjectSkeleton *found = NULL;
|
||||
|
||||
g_return_val_if_fail (CALLS_IS_CALL (call), NULL);
|
||||
|
||||
for (int i = 0; i >= 0; i++) {
|
||||
g_autoptr (CallsDBusObjectSkeleton) item = g_list_model_get_item (G_LIST_MODEL (self->objs), i);
|
||||
|
||||
if (!item)
|
||||
break;
|
||||
|
||||
if (call == g_object_get_data (G_OBJECT (item), "call")) {
|
||||
*pos = i;
|
||||
found = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
on_handle_call_accept (CallsDBusCallsCall *skeleton,
|
||||
GDBusMethodInvocation *invocation,
|
||||
CallsCall *call)
|
||||
{
|
||||
g_return_val_if_fail (CALLS_DBUS_IS_CALLS_CALL (skeleton), FALSE);
|
||||
g_return_val_if_fail (CALLS_IS_CALL (call), FALSE);
|
||||
|
||||
calls_call_answer (call);
|
||||
|
||||
calls_dbus_calls_call_complete_accept (skeleton, invocation);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
on_handle_call_hangup (CallsDBusCallsCall *skeleton,
|
||||
GDBusMethodInvocation *invocation,
|
||||
CallsCall *call)
|
||||
{
|
||||
g_return_val_if_fail (CALLS_DBUS_IS_CALLS_CALL (skeleton), FALSE);
|
||||
g_return_val_if_fail (CALLS_IS_CALL (call), FALSE);
|
||||
|
||||
calls_call_hang_up (call);
|
||||
|
||||
calls_dbus_calls_call_complete_hangup (skeleton, invocation);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
call_added_cb (CallsDBusManager *self, CallsCall *call)
|
||||
{
|
||||
g_autofree char *path = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (CallsDBusObjectSkeleton) object = NULL;
|
||||
g_autoptr (CallsDBusCallsCall) iface = NULL;
|
||||
|
||||
path = get_obj_path (self, self->iface_num++);
|
||||
object = calls_dbus_object_skeleton_new (path);
|
||||
iface = calls_dbus_calls_call_skeleton_new ();
|
||||
g_dbus_object_skeleton_add_interface (G_DBUS_OBJECT_SKELETON (object),
|
||||
G_DBUS_INTERFACE_SKELETON (iface));
|
||||
g_object_set_data_full (G_OBJECT (object), "call", g_object_ref (call), g_object_unref);
|
||||
|
||||
g_object_connect (iface,
|
||||
"object_signal::handle-accept", G_CALLBACK (on_handle_call_accept), call,
|
||||
"object_signal::handle-hangup", G_CALLBACK (on_handle_call_hangup), call,
|
||||
NULL);
|
||||
|
||||
g_object_bind_property (call, "state", iface, "state", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (call, "inbound", iface, "inbound", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (call, "number", iface, "id", G_BINDING_SYNC_CREATE);
|
||||
|
||||
/* Export with properties bound to reduce DBus traffic: */
|
||||
g_debug ("Exporting %p at %s", call, path);
|
||||
g_dbus_object_manager_server_export (self->object_manager, G_DBUS_OBJECT_SKELETON (object));
|
||||
|
||||
g_list_store_append (self->objs, g_steal_pointer (&object));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
call_removed_cb (CallsDBusManager *self, CallsCall *call)
|
||||
{
|
||||
const char *path = NULL;
|
||||
CallsDBusObjectSkeleton *obj = NULL;
|
||||
gint pos = -1;
|
||||
|
||||
g_debug ("Call %p removed", call);
|
||||
|
||||
obj = find_call (self, call, &pos);
|
||||
g_return_if_fail (CALLS_DBUS_IS_OBJECT (obj));
|
||||
|
||||
path = g_dbus_object_get_object_path (G_DBUS_OBJECT (obj));
|
||||
g_dbus_object_manager_server_unexport (self->object_manager, path);
|
||||
|
||||
g_list_store_remove (self->objs, pos);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calls_dbus_manager_constructed (GObject *object)
|
||||
{
|
||||
g_autoptr (GList) calls = NULL;
|
||||
GList *c;
|
||||
CallsDBusManager *self = CALLS_DBUS_MANAGER (object);
|
||||
|
||||
G_OBJECT_CLASS (calls_dbus_manager_parent_class)->constructed (object);
|
||||
|
||||
self->objs = g_list_store_new (CALLS_DBUS_TYPE_OBJECT_SKELETON);
|
||||
|
||||
g_signal_connect_swapped (calls_manager_get_default (),
|
||||
"call-add",
|
||||
G_CALLBACK (call_added_cb),
|
||||
self);
|
||||
|
||||
g_signal_connect_swapped (calls_manager_get_default (),
|
||||
"call-remove",
|
||||
G_CALLBACK (call_removed_cb),
|
||||
self);
|
||||
calls = calls_manager_get_calls (calls_manager_get_default ());
|
||||
for (c = calls; c != NULL; c = c->next) {
|
||||
call_added_cb (self, c->data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calls_dbus_manager_dispose (GObject *object)
|
||||
{
|
||||
CallsDBusManager *self = CALLS_DBUS_MANAGER (object);
|
||||
|
||||
if (self->objs) {
|
||||
for (int i = 0; i >= 0; i++) {
|
||||
const char *path;
|
||||
g_autoptr (CallsDBusObjectSkeleton) obj = g_list_model_get_item (G_LIST_MODEL (self->objs), i);
|
||||
|
||||
if (!obj)
|
||||
break;
|
||||
|
||||
path = g_dbus_object_get_object_path (G_DBUS_OBJECT (obj));
|
||||
g_dbus_object_manager_server_unexport (self->object_manager, path);
|
||||
}
|
||||
}
|
||||
g_clear_object (&self->objs);
|
||||
g_clear_object (&self->object_manager);
|
||||
g_clear_pointer (&self->object_path, g_free);
|
||||
|
||||
G_OBJECT_CLASS (calls_dbus_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calls_dbus_manager_class_init (CallsDBusManagerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = calls_dbus_manager_constructed;
|
||||
object_class->dispose = calls_dbus_manager_dispose;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
calls_dbus_manager_init (CallsDBusManager *self)
|
||||
{
|
||||
self->iface_num = 1;
|
||||
}
|
||||
|
||||
|
||||
CallsDBusManager *
|
||||
calls_dbus_manager_new (void)
|
||||
{
|
||||
return g_object_new (CALLS_TYPE_DBUS_MANAGER, NULL);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
calls_dbus_manager_register (CallsDBusManager *self,
|
||||
GDBusConnection *connection,
|
||||
const char *object_path,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (CALLS_IS_DBUS_MANAGER (self), FALSE);
|
||||
|
||||
self->object_path = g_strdup (object_path);
|
||||
g_debug ("Registering at %s", self->object_path);
|
||||
self->object_manager = g_dbus_object_manager_server_new (object_path);
|
||||
g_dbus_object_manager_server_set_connection (self->object_manager, connection);
|
||||
|
||||
return TRUE;
|
||||
}
|
26
src/calls-dbus-manager.h
Normal file
26
src/calls-dbus-manager.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2020 Purism SPC
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* Author: Guido Günther <agx@sigxcpu.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLS_TYPE_DBUS_MANAGER calls_dbus_manager_get_type ()
|
||||
|
||||
G_DECLARE_FINAL_TYPE (CallsDBusManager, calls_dbus_manager,
|
||||
CALLS, DBUS_MANAGER, GObject)
|
||||
|
||||
CallsDBusManager *calls_dbus_manager_new (void);
|
||||
gboolean calls_dbus_manager_register (CallsDBusManager *self,
|
||||
GDBusConnection *connection,
|
||||
const char *object_path,
|
||||
GError **error);
|
||||
G_END_DECLS
|
|
@ -1,14 +1,9 @@
|
|||
generated_dbus_sources = []
|
||||
|
||||
# DBus server protocols
|
||||
generated_dbus_sources += gnome.gdbus_codegen('calls-dbus',
|
||||
'sm.puri.Calls.xml',
|
||||
docbook: 'calls',
|
||||
interface_prefix: 'sm.puri',
|
||||
namespace: 'CallsDBus')
|
||||
|
||||
generated_dbus_sources += gnome.gdbus_codegen('calls-call-dbus',
|
||||
'sm.puri.Calls.Call.xml',
|
||||
docbook: 'calls',
|
||||
interface_prefix: 'sm.puri',
|
||||
namespace: 'CallsCallDBus')
|
||||
object_manager: true,
|
||||
namespace: 'CallsDBus')
|
||||
|
|
|
@ -20,17 +20,20 @@
|
|||
-->
|
||||
|
||||
<node>
|
||||
|
||||
<interface name="sm.puri.Calls.Call">
|
||||
<method name="AcceptCall"/>
|
||||
<method name="EndCall"/>
|
||||
<method name="HoldCall"/>
|
||||
<method name="UnholdCall"/>
|
||||
<method name="SendDtmf">
|
||||
<arg direction="in" type="s" name="tones"/>
|
||||
</method>
|
||||
<property name="CallParty" type="as" access="read"/>
|
||||
<property name="CallIsConference" type="b" access="read"/>
|
||||
<property name="CallState" type="u" access="read"/>
|
||||
<property name="Origin" type="s" access="read"/>
|
||||
<method name="Accept"/>
|
||||
<method name="Hangup"/>
|
||||
<property name="Inbound" type="b" access="read"/>
|
||||
<property name="State" type="u" access="read"/>
|
||||
<property name="Id" type="s" access="read">
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>The Id identifying the call, e.g. a phone number</doc:para>
|
||||
</doc:description>
|
||||
</doc:doc>
|
||||
</property>
|
||||
<property name="Party" type="s" access="read"/>
|
||||
</interface>
|
||||
|
||||
</node>
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
<!DOCTYPE node PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
|
||||
<!--
|
||||
Copyright (C) 2021 Purism SPC
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General
|
||||
Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<node>
|
||||
<interface name="sm.puri.Calls">
|
||||
<method name="Dial">
|
||||
<arg type="s" direction="in" name="number"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
<method name="GetCalls">
|
||||
<arg type="ao" direction="out" name="calls">
|
||||
<doc:doc>
|
||||
<doc:summary>an array of ongoing calls</doc:summary>
|
||||
</doc:doc>
|
||||
</arg>
|
||||
<doc:doc>
|
||||
<doc:description>
|
||||
<doc:para>This gets a list of all <doc:ref type="interface" to="sm.puri.Calls.Call">Calls</doc:ref>
|
||||
that are currently ongoing.</doc:para>
|
||||
<doc:para>Each Call is an D-Bus object path for the object that implements the
|
||||
<doc:ref type="interface" to="sm.puri.Calls.Call">Call</doc:ref> interface.</doc:para>
|
||||
</doc:description>
|
||||
</doc:doc>
|
||||
</method>
|
||||
<property name="HasOngoingCall" type="b" access="read"/>
|
||||
<signal name="CallAdded">
|
||||
<arg name="id" type="u"/>
|
||||
<arg name="parameters" type="a{sv}"/>
|
||||
</signal>
|
||||
<signal name="CallRemoved">
|
||||
<arg name="id" type="u"/>
|
||||
<arg name="parameters" type="a{sv}"/>
|
||||
</signal>
|
||||
</interface>
|
||||
</node>
|
|
@ -90,6 +90,7 @@ calls_generated_sources = [
|
|||
|
||||
calls_sources = files(['calls-message-source.c', 'calls-message-source.h',
|
||||
'calls-call.c',
|
||||
'calls-dbus-manager.c',
|
||||
'calls-ussd.c',
|
||||
'calls-origin.c', 'calls-origin.h',
|
||||
'calls-provider.c', 'calls-provider.h',
|
||||
|
|
Loading…
Reference in a new issue