2018-11-09 16:30:40 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2018 Purism SPC
|
|
|
|
*
|
|
|
|
* This file is part of Calls.
|
|
|
|
*
|
|
|
|
* Calls is free software: you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Calls is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Calls. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* Author: Bob Ham <bob.ham@puri.sm>
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
*
|
|
|
|
*/
|
2021-06-18 08:55:47 +00:00
|
|
|
#define G_LOG_DOMAIN "CallsRinger"
|
2018-11-09 16:30:40 +00:00
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2022-01-31 16:01:50 +00:00
|
|
|
#include "calls-manager.h"
|
|
|
|
#include "calls-ringer.h"
|
2022-01-31 16:18:35 +00:00
|
|
|
#include "calls-ui-call-data.h"
|
2022-01-31 16:01:50 +00:00
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
#include <glib/gi18n.h>
|
|
|
|
#include <glib-object.h>
|
|
|
|
|
2020-05-20 14:14:23 +00:00
|
|
|
#define LIBFEEDBACK_USE_UNSTABLE_API
|
|
|
|
#include <libfeedback.h>
|
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
enum {
|
|
|
|
PROP_0,
|
|
|
|
PROP_IS_RINGING,
|
2021-11-26 07:40:11 +00:00
|
|
|
PROP_RING_IS_QUIET,
|
2021-10-25 14:58:40 +00:00
|
|
|
PROP_LAST_PROP
|
|
|
|
};
|
|
|
|
static GParamSpec *props[PROP_LAST_PROP];
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
CALLS_RING_STATE_INACTIVE,
|
|
|
|
CALLS_RING_STATE_REQUEST_PLAY,
|
|
|
|
CALLS_RING_STATE_PLAYING,
|
|
|
|
CALLS_RING_STATE_REQUEST_STOP
|
|
|
|
} CallsRingState;
|
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2021-10-14 08:38:30 +00:00
|
|
|
struct _CallsRinger {
|
2022-04-24 10:24:55 +00:00
|
|
|
GObject parent_instance;
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
GList *calls;
|
|
|
|
LfbEvent *event;
|
|
|
|
GCancellable *cancel_ring;
|
2021-10-25 14:58:40 +00:00
|
|
|
CallsRingState state;
|
2021-11-26 07:40:11 +00:00
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
guint restart_id;
|
|
|
|
gboolean is_quiet;
|
2018-11-09 16:30:40 +00:00
|
|
|
};
|
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
|
|
|
|
G_DEFINE_TYPE (CallsRinger, calls_ringer, G_TYPE_OBJECT)
|
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2021-10-26 22:14:10 +00:00
|
|
|
static const char *
|
|
|
|
ring_state_to_string (CallsRingState state)
|
|
|
|
{
|
|
|
|
switch (state) {
|
|
|
|
case CALLS_RING_STATE_INACTIVE:
|
|
|
|
return "inactive";
|
|
|
|
case CALLS_RING_STATE_REQUEST_PLAY:
|
|
|
|
return "request-play";
|
|
|
|
case CALLS_RING_STATE_PLAYING:
|
|
|
|
return "playing";
|
|
|
|
case CALLS_RING_STATE_REQUEST_STOP:
|
|
|
|
return "request-stop";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
2021-10-25 14:58:40 +00:00
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
static void
|
|
|
|
change_ring_state (CallsRinger *self,
|
|
|
|
CallsRingState state)
|
|
|
|
{
|
2021-10-26 22:14:10 +00:00
|
|
|
g_debug ("%s: old: %s; new: %s",
|
|
|
|
__func__, ring_state_to_string (self->state), ring_state_to_string (state));
|
2021-10-25 14:58:40 +00:00
|
|
|
if (self->state == state)
|
|
|
|
return;
|
|
|
|
|
|
|
|
self->state = state;
|
|
|
|
|
2021-11-26 06:42:40 +00:00
|
|
|
/* Currently restarting, so don't notify */
|
|
|
|
if (self->restart_id)
|
|
|
|
return;
|
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
/* Ringing has not yet started/stopped */
|
|
|
|
if (state == CALLS_RING_STATE_REQUEST_PLAY ||
|
|
|
|
state == CALLS_RING_STATE_REQUEST_STOP)
|
|
|
|
return;
|
|
|
|
|
2021-10-26 22:14:10 +00:00
|
|
|
g_debug ("%s: notify ring", __func__);
|
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_IS_RINGING]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
static void
|
2020-05-20 14:14:23 +00:00
|
|
|
on_event_triggered (LfbEvent *event,
|
|
|
|
GAsyncResult *res,
|
|
|
|
CallsRinger *self)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2022-04-24 10:24:55 +00:00
|
|
|
g_autoptr (GError) err = NULL;
|
|
|
|
|
|
|
|
g_return_if_fail (LFB_IS_EVENT (event));
|
|
|
|
g_return_if_fail (CALLS_IS_RINGER (self));
|
|
|
|
|
|
|
|
g_debug ("%s", __func__);
|
|
|
|
if (lfb_event_trigger_feedback_finish (event, res, &err)) {
|
|
|
|
change_ring_state (self, CALLS_RING_STATE_PLAYING);
|
|
|
|
} else {
|
|
|
|
if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
g_warning ("Failed to trigger feedback for '%s': %s",
|
|
|
|
lfb_event_get_event (event), err->message);
|
|
|
|
change_ring_state (self, CALLS_RING_STATE_INACTIVE);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_unref (self);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
2021-11-26 06:42:40 +00:00
|
|
|
|
|
|
|
static void restart (CallsRinger *self, gboolean quiet);
|
|
|
|
|
2020-05-19 08:47:54 +00:00
|
|
|
static void
|
2021-10-14 09:41:18 +00:00
|
|
|
start (CallsRinger *self,
|
|
|
|
gboolean quiet)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2021-10-26 22:14:10 +00:00
|
|
|
g_debug ("%s: state: %s", __func__, ring_state_to_string (self->state));
|
2021-10-28 14:43:42 +00:00
|
|
|
if (self->event)
|
|
|
|
lfb_event_set_feedback_profile (self->event, quiet ? "quiet" : NULL);
|
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
if (self->state == CALLS_RING_STATE_PLAYING ||
|
2021-11-26 06:42:40 +00:00
|
|
|
self->state == CALLS_RING_STATE_REQUEST_PLAY) {
|
|
|
|
if (self->is_quiet != quiet)
|
|
|
|
restart (self, quiet);
|
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
return;
|
2021-11-26 06:42:40 +00:00
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2021-10-14 08:38:30 +00:00
|
|
|
if (self->event) {
|
2021-10-25 14:58:40 +00:00
|
|
|
g_clear_object (&self->cancel_ring);
|
|
|
|
self->cancel_ring = g_cancellable_new ();
|
|
|
|
|
2021-11-26 07:40:11 +00:00
|
|
|
self->is_quiet = quiet;
|
2021-10-14 08:38:30 +00:00
|
|
|
g_object_ref (self);
|
|
|
|
lfb_event_trigger_feedback_async (self->event,
|
2021-10-25 14:58:40 +00:00
|
|
|
self->cancel_ring,
|
|
|
|
(GAsyncReadyCallback) on_event_triggered,
|
2021-10-14 08:38:30 +00:00
|
|
|
self);
|
2021-10-25 14:58:40 +00:00
|
|
|
change_ring_state (self, CALLS_RING_STATE_REQUEST_PLAY);
|
2021-10-14 08:38:30 +00:00
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
static void
|
2020-05-20 14:14:23 +00:00
|
|
|
on_event_feedback_ended (LfbEvent *event,
|
|
|
|
GAsyncResult *res,
|
|
|
|
CallsRinger *self)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2022-04-24 10:24:55 +00:00
|
|
|
g_autoptr (GError) err = NULL;
|
2021-10-14 08:38:30 +00:00
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
g_return_if_fail (LFB_IS_EVENT (event));
|
|
|
|
g_return_if_fail (CALLS_IS_RINGER (self));
|
2020-05-20 14:14:23 +00:00
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
g_debug ("%s: state: %s", __func__, ring_state_to_string (self->state));
|
2021-10-26 22:14:10 +00:00
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
if (self->state == CALLS_RING_STATE_REQUEST_PLAY ||
|
|
|
|
self->state == CALLS_RING_STATE_PLAYING)
|
|
|
|
g_warning ("Feedback ended although it should be playing");
|
2021-10-25 14:58:40 +00:00
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
if (!lfb_event_end_feedback_finish (event, res, &err))
|
|
|
|
g_warning ("Failed to end feedback for '%s': %s",
|
|
|
|
lfb_event_get_event (event), err->message);
|
2021-10-25 14:58:40 +00:00
|
|
|
|
2022-04-24 10:24:55 +00:00
|
|
|
change_ring_state (self, CALLS_RING_STATE_INACTIVE);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
static void
|
2021-10-14 08:38:30 +00:00
|
|
|
on_feedback_ended (LfbEvent *event,
|
2020-05-20 14:14:23 +00:00
|
|
|
CallsRinger *self)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2020-05-20 14:14:23 +00:00
|
|
|
g_debug ("Feedback ended");
|
2021-10-26 22:14:10 +00:00
|
|
|
g_debug ("%s: state: %s", __func__, ring_state_to_string (self->state));
|
2021-10-25 14:58:40 +00:00
|
|
|
change_ring_state (self, CALLS_RING_STATE_INACTIVE);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
static void
|
|
|
|
stop (CallsRinger *self)
|
|
|
|
{
|
2021-10-26 22:14:10 +00:00
|
|
|
g_debug ("%s: state: %s", __func__, ring_state_to_string (self->state));
|
2021-10-25 14:58:40 +00:00
|
|
|
if (self->state == CALLS_RING_STATE_INACTIVE ||
|
|
|
|
self->state == CALLS_RING_STATE_REQUEST_STOP)
|
|
|
|
return;
|
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
g_debug ("Stopping ringtone");
|
2021-10-25 14:58:40 +00:00
|
|
|
if (self->state == CALLS_RING_STATE_PLAYING) {
|
2021-10-26 22:14:10 +00:00
|
|
|
g_debug ("ending event feedback");
|
2021-10-25 14:58:40 +00:00
|
|
|
lfb_event_end_feedback_async (self->event,
|
|
|
|
NULL,
|
|
|
|
(GAsyncReadyCallback) on_event_feedback_ended,
|
|
|
|
self);
|
|
|
|
change_ring_state (self, CALLS_RING_STATE_REQUEST_STOP);
|
|
|
|
} else if (self->state == CALLS_RING_STATE_REQUEST_PLAY) {
|
2021-10-26 22:14:10 +00:00
|
|
|
g_debug ("cancelling event feedback");
|
2021-10-25 14:58:40 +00:00
|
|
|
g_cancellable_cancel (self->cancel_ring);
|
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 06:42:40 +00:00
|
|
|
typedef struct {
|
|
|
|
CallsRinger *ringer;
|
|
|
|
gboolean quiet;
|
|
|
|
} RestartRingerData;
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
on_ringer_restart (gpointer user_data)
|
|
|
|
{
|
|
|
|
RestartRingerData *data = user_data;
|
|
|
|
|
|
|
|
if (data->ringer->state == CALLS_RING_STATE_PLAYING) {
|
|
|
|
stop (data->ringer);
|
|
|
|
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* wait until requests have been fulfilled */
|
|
|
|
if (data->ringer->state == CALLS_RING_STATE_REQUEST_PLAY ||
|
|
|
|
data->ringer->state == CALLS_RING_STATE_REQUEST_STOP) {
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data->ringer->state == CALLS_RING_STATE_INACTIVE) {
|
|
|
|
start (data->ringer, data->quiet);
|
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_return_val_if_reached (G_SOURCE_CONTINUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
clean_up_restart_data (gpointer user_data)
|
|
|
|
{
|
|
|
|
RestartRingerData *data = user_data;
|
|
|
|
|
|
|
|
data->ringer->restart_id = 0;
|
|
|
|
|
|
|
|
g_free (data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
restart (CallsRinger *self,
|
|
|
|
gboolean quiet)
|
|
|
|
{
|
|
|
|
RestartRingerData *data = g_new0 (RestartRingerData, 1);
|
|
|
|
|
|
|
|
data->ringer = self;
|
|
|
|
data->quiet = quiet;
|
|
|
|
|
|
|
|
if (self->restart_id)
|
|
|
|
g_source_remove (self->restart_id);
|
|
|
|
|
|
|
|
self->restart_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
|
|
|
|
G_SOURCE_FUNC (on_ringer_restart),
|
|
|
|
data,
|
|
|
|
clean_up_restart_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
static inline gboolean
|
2022-01-31 16:18:35 +00:00
|
|
|
is_ring_state (CuiCallState state)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2022-01-31 16:18:35 +00:00
|
|
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
switch (state) {
|
2022-01-31 16:18:35 +00:00
|
|
|
case CUI_CALL_STATE_INCOMING:
|
|
|
|
case CUI_CALL_STATE_WAITING:
|
2021-10-14 09:41:18 +00:00
|
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
2021-10-14 08:38:30 +00:00
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline gboolean
|
2022-01-31 16:18:35 +00:00
|
|
|
is_active_state (CuiCallState state)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2021-10-14 08:38:30 +00:00
|
|
|
switch (state) {
|
2022-01-31 16:18:35 +00:00
|
|
|
case CUI_CALL_STATE_ACTIVE:
|
|
|
|
case CUI_CALL_STATE_CALLING:
|
|
|
|
case CUI_CALL_STATE_ALERTING:
|
|
|
|
case CUI_CALL_STATE_HELD:
|
2021-10-14 08:38:30 +00:00
|
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
return FALSE;
|
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
2022-01-31 16:18:35 +00:00
|
|
|
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
|
2018-11-09 16:30:40 +00:00
|
|
|
|
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
static gboolean
|
|
|
|
has_active_call (CallsRinger *self)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2021-10-14 09:41:18 +00:00
|
|
|
g_assert (CALLS_IS_RINGER (self));
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
for (GList *node = self->calls; node != NULL; node = node->next) {
|
2022-01-31 16:18:35 +00:00
|
|
|
CallsUiCallData *call = node->data;
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2022-01-31 16:18:35 +00:00
|
|
|
if (is_active_state (cui_call_get_state (CUI_CALL (call))))
|
2021-10-14 09:41:18 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
|
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
static gboolean
|
|
|
|
has_incoming_call (CallsRinger *self)
|
|
|
|
{
|
|
|
|
g_assert (CALLS_IS_RINGER (self));
|
|
|
|
|
|
|
|
for (GList *node = self->calls; node != NULL; node = node->next) {
|
2022-01-31 16:18:35 +00:00
|
|
|
CallsUiCallData *call = node->data;
|
2021-10-14 09:41:18 +00:00
|
|
|
|
2022-01-31 16:18:35 +00:00
|
|
|
if (is_ring_state (cui_call_get_state (CUI_CALL (call))) &&
|
2022-02-01 07:25:14 +00:00
|
|
|
!calls_ui_call_data_get_silenced (call) &&
|
|
|
|
calls_ui_call_data_get_ui_active (call))
|
2021-10-14 09:41:18 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2021-10-14 09:41:18 +00:00
|
|
|
update_ring (CallsRinger *self)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2021-10-14 09:41:18 +00:00
|
|
|
g_assert (CALLS_IS_RINGER (self));
|
2021-03-12 17:21:41 +00:00
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
if (!self->event) {
|
|
|
|
g_debug ("Can't ring because libfeedback is not initialized");
|
|
|
|
return;
|
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
if (has_incoming_call (self))
|
|
|
|
start (self, has_active_call (self));
|
|
|
|
else
|
|
|
|
stop (self);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-01-31 16:18:35 +00:00
|
|
|
call_added_cb (CallsRinger *self,
|
|
|
|
CallsUiCallData *call)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2021-10-14 09:41:18 +00:00
|
|
|
g_assert (CALLS_IS_RINGER (self));
|
2022-01-31 16:18:35 +00:00
|
|
|
g_assert (CALLS_IS_UI_CALL_DATA (call));
|
2021-10-14 09:41:18 +00:00
|
|
|
|
|
|
|
self->calls = g_list_append (self->calls, call);
|
2020-03-18 11:53:13 +00:00
|
|
|
|
2022-02-01 07:25:14 +00:00
|
|
|
g_object_connect (call,
|
|
|
|
"swapped-signal::notify::state", G_CALLBACK (update_ring), self,
|
|
|
|
"swapped-signal::notify::silenced", G_CALLBACK (update_ring), self,
|
|
|
|
"swapped-signal::notify::ui-active", G_CALLBACK (update_ring), self,
|
|
|
|
NULL);
|
|
|
|
|
2021-10-14 09:41:18 +00:00
|
|
|
update_ring (self);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2022-01-31 16:18:35 +00:00
|
|
|
call_removed_cb (CallsRinger *self,
|
|
|
|
CallsUiCallData *call)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2021-10-14 09:41:18 +00:00
|
|
|
self->calls = g_list_remove (self->calls, call);
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2020-03-18 11:53:13 +00:00
|
|
|
g_signal_handlers_disconnect_by_data (call, self);
|
2021-10-14 09:41:18 +00:00
|
|
|
|
|
|
|
update_ring (self);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2020-03-18 11:53:13 +00:00
|
|
|
calls_ringer_init (CallsRinger *self)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2021-02-10 23:38:10 +00:00
|
|
|
g_autoptr (GError) err = NULL;
|
2020-05-20 14:14:23 +00:00
|
|
|
|
2021-10-14 08:38:30 +00:00
|
|
|
if (lfb_init (APP_ID, &err)) {
|
|
|
|
self->event = lfb_event_new ("phone-incoming-call");
|
|
|
|
/* Let feedbackd do the loop */
|
|
|
|
lfb_event_set_timeout (self->event, 0);
|
|
|
|
g_signal_connect (self->event,
|
|
|
|
"feedback-ended",
|
|
|
|
G_CALLBACK (on_feedback_ended),
|
|
|
|
self);
|
|
|
|
} else {
|
|
|
|
g_warning ("Failed to init libfeedback: %s", err->message);
|
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
static void
|
|
|
|
get_property (GObject *object,
|
|
|
|
guint property_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
switch (property_id) {
|
|
|
|
case PROP_IS_RINGING:
|
|
|
|
g_value_set_boolean (value, calls_ringer_get_is_ringing (CALLS_RINGER (object)));
|
|
|
|
break;
|
|
|
|
|
2021-11-26 07:40:11 +00:00
|
|
|
case PROP_RING_IS_QUIET:
|
|
|
|
g_value_set_boolean (value, calls_ringer_get_ring_is_quiet (CALLS_RINGER (object)));
|
|
|
|
break;
|
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
static void
|
|
|
|
constructed (GObject *object)
|
|
|
|
{
|
2020-03-18 11:53:13 +00:00
|
|
|
g_autoptr (GList) calls = NULL;
|
|
|
|
GList *c;
|
2018-11-09 16:30:40 +00:00
|
|
|
CallsRinger *self = CALLS_RINGER (object);
|
|
|
|
|
2020-03-18 11:53:13 +00:00
|
|
|
g_signal_connect_swapped (calls_manager_get_default (),
|
2022-01-31 16:18:35 +00:00
|
|
|
"ui-call-added",
|
2020-03-18 11:53:13 +00:00
|
|
|
G_CALLBACK (call_added_cb),
|
|
|
|
self);
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2020-03-18 11:53:13 +00:00
|
|
|
g_signal_connect_swapped (calls_manager_get_default (),
|
2022-01-31 16:18:35 +00:00
|
|
|
"ui-call-removed",
|
2020-03-18 11:53:13 +00:00
|
|
|
G_CALLBACK (call_removed_cb),
|
|
|
|
self);
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2020-03-18 11:53:13 +00:00
|
|
|
calls = calls_manager_get_calls (calls_manager_get_default ());
|
|
|
|
for (c = calls; c != NULL; c = c->next) {
|
|
|
|
call_added_cb (self, c->data);
|
|
|
|
}
|
2018-11-09 16:30:40 +00:00
|
|
|
|
2020-03-18 11:53:13 +00:00
|
|
|
G_OBJECT_CLASS (calls_ringer_parent_class)->constructed (object);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-23 14:22:31 +00:00
|
|
|
static void
|
2020-05-20 14:14:23 +00:00
|
|
|
dispose (GObject *object)
|
2019-09-23 14:22:31 +00:00
|
|
|
{
|
|
|
|
CallsRinger *self = CALLS_RINGER (object);
|
|
|
|
|
2021-10-14 08:38:30 +00:00
|
|
|
if (self->event) {
|
|
|
|
g_clear_object (&self->event);
|
|
|
|
lfb_uninit ();
|
|
|
|
}
|
2021-10-26 12:43:59 +00:00
|
|
|
g_signal_handlers_disconnect_by_data (calls_manager_get_default (), self);
|
2019-09-23 14:22:31 +00:00
|
|
|
|
2021-11-26 06:42:40 +00:00
|
|
|
g_clear_handle_id (&self->restart_id, g_source_remove);
|
|
|
|
|
2020-05-20 14:14:23 +00:00
|
|
|
G_OBJECT_CLASS (calls_ringer_parent_class)->dispose (object);
|
2019-09-23 14:22:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-11-09 16:30:40 +00:00
|
|
|
static void
|
|
|
|
calls_ringer_class_init (CallsRingerClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->constructed = constructed;
|
2020-05-20 14:14:23 +00:00
|
|
|
object_class->dispose = dispose;
|
2021-10-25 14:58:40 +00:00
|
|
|
object_class->get_property = get_property;
|
|
|
|
|
|
|
|
props[PROP_IS_RINGING] =
|
|
|
|
g_param_spec_boolean ("ringing",
|
|
|
|
"Ringing",
|
|
|
|
"Whether we're currently ringing",
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
|
|
|
|
2021-11-26 07:40:11 +00:00
|
|
|
props[PROP_RING_IS_QUIET] =
|
|
|
|
g_param_spec_boolean ("is-quiet",
|
|
|
|
"is quiet",
|
|
|
|
"Whether the ringing is of the quiet persuasion",
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
|
|
|
|
2021-10-25 14:58:40 +00:00
|
|
|
g_object_class_install_properties (object_class,
|
|
|
|
PROP_LAST_PROP,
|
|
|
|
props);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CallsRinger *
|
2020-03-18 11:53:13 +00:00
|
|
|
calls_ringer_new (void)
|
2018-11-09 16:30:40 +00:00
|
|
|
{
|
2020-03-18 11:53:13 +00:00
|
|
|
return g_object_new (CALLS_TYPE_RINGER, NULL);
|
2018-11-09 16:30:40 +00:00
|
|
|
}
|
2021-10-25 14:58:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* calls_ringer_get_ring_is_ringing:
|
|
|
|
* @self: A #CallsRinger
|
|
|
|
*
|
|
|
|
* Returns: %TRUE if currently ringing, %FALSE otherwise.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
calls_ringer_get_is_ringing (CallsRinger *self)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (CALLS_IS_RINGER (self), FALSE);
|
|
|
|
|
|
|
|
return self->state == CALLS_RING_STATE_PLAYING ||
|
2022-04-24 10:24:55 +00:00
|
|
|
self->state == CALLS_RING_STATE_REQUEST_STOP;
|
2021-10-25 14:58:40 +00:00
|
|
|
}
|
2021-11-26 07:40:11 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* calls_ringer_get_ring_is_quiet:
|
|
|
|
* @self: A #CallsRinger
|
|
|
|
*
|
|
|
|
* Returns: %TRUE if currently ringing quietly, %FALSE otherwise.
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
calls_ringer_get_ring_is_quiet (CallsRinger *self)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (CALLS_IS_RINGER (self), FALSE);
|
|
|
|
|
|
|
|
return calls_ringer_get_is_ringing (self) && self->is_quiet;
|
|
|
|
}
|