[calls] ringer: Restart ringer if quiet parameter changed



commit 0f727808143da594c2cfeb680e1a5a283594d243
Author: Evangelos Ribeiro Tzaras <devrtz fortysixandtwo eu>
Date:   Fri Nov 26 07:42:40 2021 +0100

    ringer: Restart ringer if quiet parameter changed
    
    This makes sure the following sequence of events works:
    
    - Call A incoming
    - Rings loudly
    - Call B incoming
    - Still rings loudly
    - Call A accepted
    - Rings quietly
    - Call A hung up
    - Rings loudly again
    
    Being able to restart the ringing is needed for this case because we cannot
    retroactively change the feedback levels of a event that has already been
    triggered.
    
    Without this patch Calls would continue ringing for the scenario above even
    after call A was accepted.

 src/calls-ringer.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 1 deletion(-)
---
diff --git a/src/calls-ringer.c b/src/calls-ringer.c
index 97bef3cf..6e566fba 100644
--- a/src/calls-ringer.c
+++ b/src/calls-ringer.c
@@ -58,6 +58,7 @@ struct _CallsRinger {
   GCancellable *cancel_ring;
   CallsRingState state;
 
+  guint restart_id;
   gboolean is_quiet;
 };
 
@@ -91,6 +92,10 @@ change_ring_state (CallsRinger   *self,
 
   self->state = state;
 
+  /* Currently restarting, so don't notify */
+  if (self->restart_id)
+    return;
+
   /* Ringing has not yet started/stopped */
   if (state == CALLS_RING_STATE_REQUEST_PLAY ||
       state == CALLS_RING_STATE_REQUEST_STOP)
@@ -124,6 +129,9 @@ on_event_triggered (LfbEvent     *event,
     g_object_unref (self);
 }
 
+
+static void restart (CallsRinger *self, gboolean quiet);
+
 static void
 start (CallsRinger *self,
        gboolean     quiet)
@@ -133,8 +141,12 @@ start (CallsRinger *self,
     lfb_event_set_feedback_profile (self->event, quiet ? "quiet" : NULL);
 
   if (self->state == CALLS_RING_STATE_PLAYING ||
-      self->state == CALLS_RING_STATE_REQUEST_PLAY)
+      self->state == CALLS_RING_STATE_REQUEST_PLAY) {
+    if (self->is_quiet != quiet)
+      restart (self, quiet);
+
     return;
+  }
 
   if (self->event) {
     g_clear_object (&self->cancel_ring);
@@ -208,6 +220,69 @@ stop (CallsRinger *self)
 }
 
 
+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);
+}
+
+
 static inline gboolean
 is_ring_state (CallsCallState state)
 {
@@ -395,6 +470,8 @@ dispose (GObject *object)
   }
   g_signal_handlers_disconnect_by_data (calls_manager_get_default (), self);
 
+  g_clear_handle_id (&self->restart_id, g_source_remove);
+
   G_OBJECT_CLASS (calls_ringer_parent_class)->dispose (object);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]