LCOV - code coverage report
Current view: top level - src/plugins/findmyphone - valent-findmyphone-ringer.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 26.0 % 96 25
Test Date: 2024-04-13 23:00:06 Functions: 38.5 % 13 5
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 12.9 % 62 8

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-3.0-or-later
       2                 :             : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
       3                 :             : 
       4                 :             : #define G_LOG_DOMAIN "valent-findmyphone-plugin"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <glib/gi18n.h>
       9                 :             : #include <gst/gst.h>
      10                 :             : #include <gtk/gtk.h>
      11                 :             : #include <adwaita.h>
      12                 :             : 
      13                 :             : #include "valent-findmyphone-ringer.h"
      14                 :             : 
      15                 :             : 
      16                 :             : struct _ValentFindmyphoneRinger
      17                 :             : {
      18                 :             :   GtkWindow    *dialog;
      19                 :             :   GstElement   *playbin;
      20                 :             :   unsigned int  source_id;
      21                 :             :   gpointer      owner;
      22                 :             : };
      23                 :             : 
      24                 :             : static ValentFindmyphoneRinger *default_ringer = NULL;
      25                 :             : 
      26                 :             : 
      27                 :             : static gboolean
      28                 :           0 : gtk_window_destroy_idle (gpointer data)
      29                 :             : {
      30                 :           0 :   gtk_window_destroy (GTK_WINDOW (data));
      31                 :           0 :   return G_SOURCE_REMOVE;
      32                 :             : }
      33                 :             : 
      34                 :             : static void
      35                 :           0 : on_motion_event (GtkWindow *dialog)
      36                 :             : {
      37                 :           0 :   g_idle_add (gtk_window_destroy_idle, dialog);
      38                 :           0 : }
      39                 :             : 
      40                 :             : static gboolean
      41                 :           0 : ringer_source_func (GstBus     *bus,
      42                 :             :                     GstMessage *message,
      43                 :             :                     gpointer    user_data)
      44                 :             : {
      45                 :           0 :   ValentFindmyphoneRinger *ringer = user_data;
      46                 :             : 
      47         [ #  # ]:           0 :   if (message->type == GST_MESSAGE_ERROR)
      48                 :             :     {
      49                 :           0 :       g_autoptr (GError) error = NULL;
      50         [ #  # ]:           0 :       g_autofree char *debug = NULL;
      51                 :             : 
      52                 :           0 :       gst_message_parse_error (message, &error, &debug);
      53                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, error->message);
      54         [ #  # ]:           0 :       g_debug ("%s: %s", G_STRFUNC, (debug) ? debug : "none");
      55                 :             : 
      56                 :           0 :       return G_SOURCE_REMOVE;
      57                 :             :     }
      58                 :             : 
      59                 :             :   /* Rewind to beginning */
      60         [ #  # ]:           0 :   if (message->type == GST_MESSAGE_EOS)
      61                 :             :     {
      62                 :           0 :       return gst_element_seek_simple (ringer->playbin,
      63                 :             :                                       GST_FORMAT_TIME,
      64                 :             :                                       GST_SEEK_FLAG_FLUSH,
      65                 :             :                                       0);
      66                 :             :     }
      67                 :             : 
      68                 :             :   return G_SOURCE_CONTINUE;
      69                 :             : }
      70                 :             : 
      71                 :             : static void
      72                 :           4 : valent_findmyphone_ringer_free (gpointer data)
      73                 :             : {
      74                 :           4 :   ValentFindmyphoneRinger *ringer = data;
      75                 :             : 
      76         [ -  + ]:           4 :   g_clear_pointer (&ringer->dialog, gtk_window_destroy);
      77                 :             : 
      78         [ -  + ]:           4 :   if (ringer->playbin != NULL)
      79                 :             :     {
      80                 :           0 :       gst_element_set_state (ringer->playbin, GST_STATE_NULL);
      81         [ #  # ]:           0 :       gst_clear_object (&ringer->playbin);
      82                 :             :     }
      83                 :             : 
      84                 :           4 :   default_ringer = NULL;
      85                 :           4 : }
      86                 :             : 
      87                 :             : /**
      88                 :             :  * valent_findmyphone_ringer_new:
      89                 :             :  *
      90                 :             :  * Create a new `ValentFindmyphoneRinger`.
      91                 :             :  *
      92                 :             :  * Returns: (transfer full): a `ValentFindmyphoneRinger`
      93                 :             :  */
      94                 :             : ValentFindmyphoneRinger *
      95                 :           4 : valent_findmyphone_ringer_new (void)
      96                 :             : {
      97                 :           4 :   ValentFindmyphoneRinger *ringer;
      98                 :           8 :   g_autoptr (GError) error = NULL;
      99                 :             : 
     100                 :           4 :   ringer = g_rc_box_new0 (ValentFindmyphoneRinger);
     101                 :             : 
     102         [ -  + ]:           4 :   if (!gst_init_check (NULL, NULL, &error))
     103                 :             :     {
     104                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, error->message);
     105                 :           0 :       return ringer;
     106                 :             :     }
     107                 :             : 
     108                 :             :   /* Playbin */
     109                 :           4 :   ringer->playbin = gst_element_factory_make ("playbin", "findmyphone-ringer");
     110                 :             : 
     111         [ -  + ]:           4 :   if (ringer->playbin != NULL)
     112                 :             :     {
     113                 :           0 :       g_object_set (ringer->playbin,
     114                 :             :                     "uri", "resource:///plugins/findmyphone/alert.oga",
     115                 :             :                     NULL);
     116                 :             :     }
     117                 :             : 
     118                 :             :   return ringer;
     119                 :             : }
     120                 :             : 
     121                 :             : /**
     122                 :             :  * valent_findmyphone_ringer_start:
     123                 :             :  * @ringer: a `ValentFindmyphoneRinger`
     124                 :             :  *
     125                 :             :  * Enable the ringing state of @ringer.
     126                 :             :  */
     127                 :             : void
     128                 :           0 : valent_findmyphone_ringer_start (ValentFindmyphoneRinger *ringer)
     129                 :             : {
     130                 :           0 :   g_autoptr (GstBus) playbus = NULL;
     131                 :             : 
     132         [ #  # ]:           0 :   g_return_if_fail (ringer != NULL);
     133                 :             : 
     134   [ #  #  #  # ]:           0 :   if (ringer->playbin == NULL || ringer->source_id > 0)
     135                 :             :     return;
     136                 :             : 
     137                 :           0 :   playbus = gst_element_get_bus (ringer->playbin);
     138                 :           0 :   ringer->source_id = gst_bus_add_watch (playbus, ringer_source_func, ringer);
     139                 :             : 
     140         [ #  # ]:           0 :   if (gst_element_set_state (ringer->playbin, GST_STATE_PLAYING) == 0)
     141   [ #  #  #  # ]:           0 :     g_clear_handle_id (&ringer->source_id, g_source_remove);
     142                 :             : }
     143                 :             : 
     144                 :             : /**
     145                 :             :  * valent_findmyphone_ringer_stop:
     146                 :             :  * @ringer: a `ValentFindmyphoneRinger`
     147                 :             :  *
     148                 :             :  * Disable the ringing state of @ringer.
     149                 :             :  */
     150                 :             : void
     151                 :           0 : valent_findmyphone_ringer_stop (ValentFindmyphoneRinger *ringer)
     152                 :             : {
     153         [ #  # ]:           0 :   g_return_if_fail (ringer != NULL);
     154                 :             : 
     155   [ #  #  #  # ]:           0 :   if (ringer->playbin == NULL || ringer->source_id == 0)
     156                 :             :     return;
     157                 :             : 
     158                 :           0 :   gst_element_set_state (ringer->playbin, GST_STATE_NULL);
     159         [ #  # ]:           0 :   g_clear_handle_id (&ringer->source_id, g_source_remove);
     160                 :           0 :   ringer->owner = NULL;
     161                 :             : }
     162                 :             : 
     163                 :             : /**
     164                 :             :  * valent_findmyphone_ringer_show:
     165                 :             :  * @ringer: a `ValentFindmyphoneRinger`
     166                 :             :  *
     167                 :             :  * Enable the ringing state of @ringer and show a dialog.
     168                 :             :  */
     169                 :             : void
     170                 :           0 : valent_findmyphone_ringer_show (ValentFindmyphoneRinger *ringer)
     171                 :             : {
     172                 :           0 :   GtkEventController *controller;
     173                 :           0 :   GtkWidget *label;
     174                 :             : 
     175         [ #  # ]:           0 :   g_return_if_fail (ringer != NULL);
     176                 :             : 
     177                 :           0 :   valent_findmyphone_ringer_start (ringer);
     178                 :             : 
     179   [ #  #  #  # ]:           0 :   if (!gtk_is_initialized () || ringer->dialog != NULL)
     180                 :             :     return;
     181                 :             : 
     182                 :             :   /* Create the dialog */
     183                 :           0 :   ringer->dialog = g_object_new (GTK_TYPE_WINDOW,
     184                 :             :                                  "fullscreened", TRUE,
     185                 :             :                                  "maximized",    TRUE,
     186                 :             :                                  NULL);
     187                 :           0 :   g_object_add_weak_pointer (G_OBJECT (ringer->dialog),
     188                 :           0 :                              (gpointer)&ringer->dialog);
     189                 :             : 
     190                 :           0 :   label = g_object_new (ADW_TYPE_STATUS_PAGE,
     191                 :             :                         "title",     _("Found"),
     192                 :             :                         "icon-name", "phonelink-ring-symbolic",
     193                 :             :                         NULL);
     194                 :           0 :   gtk_window_set_child (ringer->dialog, label);
     195                 :             : 
     196                 :           0 :   g_signal_connect_swapped (ringer->dialog,
     197                 :             :                             "destroy",
     198                 :             :                             G_CALLBACK (valent_findmyphone_ringer_stop),
     199                 :             :                             ringer);
     200                 :             : 
     201                 :             :   /* Close on keypress, pointer motion or click */
     202                 :           0 :   controller = gtk_event_controller_key_new ();
     203                 :           0 :   gtk_widget_add_controller (GTK_WIDGET (ringer->dialog), controller);
     204                 :           0 :   g_signal_connect_swapped (G_OBJECT (controller),
     205                 :             :                             "key-pressed",
     206                 :             :                             G_CALLBACK (gtk_window_destroy),
     207                 :             :                             ringer->dialog);
     208                 :             : 
     209                 :           0 :   controller = gtk_event_controller_motion_new ();
     210                 :           0 :   gtk_widget_add_controller (GTK_WIDGET (ringer->dialog), controller);
     211                 :           0 :   g_signal_connect_swapped (G_OBJECT (controller),
     212                 :             :                             "motion",
     213                 :             :                             G_CALLBACK (on_motion_event),
     214                 :             :                             ringer->dialog);
     215                 :             : 
     216                 :           0 :   controller = (GtkEventController *)gtk_gesture_click_new ();
     217                 :           0 :   gtk_widget_add_controller (GTK_WIDGET (ringer->dialog), controller);
     218                 :           0 :   g_signal_connect_swapped (G_OBJECT (controller),
     219                 :             :                             "pressed",
     220                 :             :                             G_CALLBACK (gtk_window_destroy),
     221                 :             :                             ringer->dialog);
     222                 :             : 
     223                 :             :   /* Show the dialog */
     224                 :           0 :   gtk_window_present_with_time (ringer->dialog, GDK_CURRENT_TIME);
     225                 :             : }
     226                 :             : 
     227                 :             : /**
     228                 :             :  * valent_findmyphone_ringer_hide:
     229                 :             :  * @ringer: a `ValentFindmyphoneRinger`
     230                 :             :  *
     231                 :             :  * Disable the ringing state of @ringer and hide the dialog.
     232                 :             :  */
     233                 :             : void
     234                 :           0 : valent_findmyphone_ringer_hide (ValentFindmyphoneRinger *ringer)
     235                 :             : {
     236         [ #  # ]:           0 :   g_return_if_fail (ringer != NULL);
     237                 :             : 
     238         [ #  # ]:           0 :   if (ringer->dialog != NULL)
     239                 :           0 :     g_clear_pointer (&ringer->dialog, gtk_window_destroy);
     240                 :             :   else
     241                 :           0 :     valent_findmyphone_ringer_stop (ringer);
     242                 :             : }
     243                 :             : 
     244                 :             : /**
     245                 :             :  * valent_findmyphone_ringer_acquire:
     246                 :             :  *
     247                 :             :  * Acquire a reference on the default `ValentFindmyphoneRinger`.
     248                 :             :  *
     249                 :             :  * Returns: (transfer full): a `ValentFindmyphoneRinger`
     250                 :             :  */
     251                 :             : ValentFindmyphoneRinger *
     252                 :           4 : valent_findmyphone_ringer_acquire (void)
     253                 :             : {
     254         [ +  - ]:           4 :   if (default_ringer == NULL)
     255                 :             :     {
     256                 :           4 :       default_ringer = valent_findmyphone_ringer_new ();
     257                 :           4 :       return default_ringer;
     258                 :             :     }
     259                 :             : 
     260                 :           0 :   return g_rc_box_acquire (default_ringer);
     261                 :             : }
     262                 :             : 
     263                 :             : /**
     264                 :             :  * valent_findmyphone_ringer_release:
     265                 :             :  * @data: (type Valent.FindmyphoneRinger): a `ValentFindmyphoneRinger`
     266                 :             :  *
     267                 :             :  * Release a reference on the default `ValentFindmyphoneRinger`.
     268                 :             :  */
     269                 :             : void
     270                 :           4 : valent_findmyphone_ringer_release (gpointer data)
     271                 :             : {
     272                 :           4 :   ValentFindmyphoneRinger *ringer = data;
     273                 :             : 
     274         [ +  - ]:           4 :   g_return_if_fail (ringer != NULL);
     275                 :             : 
     276                 :           4 :   g_rc_box_release_full (ringer, valent_findmyphone_ringer_free);
     277                 :             : }
     278                 :             : 
     279                 :             : /**
     280                 :             :  * valent_findmyphone_ringer_toggle:
     281                 :             :  * @ringer: a `ValentFindmyphoneRinger`
     282                 :             :  * @owner: (type GObject.Object): a `GObject`
     283                 :             :  *
     284                 :             :  * Toggle the ringing state of @ringer.
     285                 :             :  */
     286                 :             : void
     287                 :           0 : valent_findmyphone_ringer_toggle (ValentFindmyphoneRinger *ringer,
     288                 :             :                                   gpointer                 owner)
     289                 :             : {
     290         [ #  # ]:           0 :   g_return_if_fail (ringer != NULL);
     291                 :             : 
     292   [ #  #  #  # ]:           0 :   if (ringer->dialog != NULL || ringer->source_id > 0)
     293                 :             :     {
     294                 :           0 :       valent_findmyphone_ringer_hide (ringer);
     295                 :           0 :       ringer->owner = NULL;
     296                 :             :     }
     297                 :             :   else
     298                 :             :     {
     299                 :           0 :       valent_findmyphone_ringer_show (ringer);
     300                 :           0 :       ringer->owner = owner;
     301                 :             :     }
     302                 :             : }
     303                 :             : 
     304                 :             : /**
     305                 :             :  * valent_findmyphone_ringer_is_owner:
     306                 :             :  * @ringer: a `ValentFindmyphoneRinger`
     307                 :             :  * @owner: (type GObject.Object): a `GObject`
     308                 :             :  *
     309                 :             :  * Check if @owner is responsible for the current state of @ringer.
     310                 :             :  *
     311                 :             :  * Returns: %TRUE if @owner controls the ringer
     312                 :             :  */
     313                 :             : gboolean
     314                 :           7 : valent_findmyphone_ringer_is_owner (ValentFindmyphoneRinger *ringer,
     315                 :             :                                     gpointer                 owner)
     316                 :             : {
     317         [ +  - ]:           7 :   g_return_val_if_fail (ringer != NULL, FALSE);
     318         [ -  + ]:           7 :   g_return_val_if_fail (G_IS_OBJECT (owner), FALSE);
     319                 :             : 
     320                 :           7 :   return ringer->owner == owner;
     321                 :             : }
     322                 :             : 
        

Generated by: LCOV version 2.0-1