LCOV - code coverage report
Current view: top level - src/plugins/systemvolume - valent-systemvolume-device.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 89.4 % 217 194
Test Date: 2024-12-21 23:29:11 Functions: 100.0 % 23 23
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 56.9 % 130 74

             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-systemvolume-device"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <inttypes.h>
       9                 :             : #include <math.h>
      10                 :             : 
      11                 :             : #include <gio/gio.h>
      12                 :             : #include <libtracker-sparql/tracker-sparql.h>
      13                 :             : #include <valent.h>
      14                 :             : 
      15                 :             : #include "valent-systemvolume-device.h"
      16                 :             : 
      17                 :             : static inline void
      18                 :           3 : valent_device_send_packet_cb (ValentDevice *device,
      19                 :             :                               GAsyncResult *result,
      20                 :             :                               gpointer      user_data)
      21                 :             : {
      22                 :           6 :   g_autoptr (GError) error = NULL;
      23                 :             : 
      24         [ -  + ]:           3 :   if (!valent_device_send_packet_finish (device, result, &error))
      25                 :             :     {
      26         [ #  # ]:           0 :       if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
      27                 :           0 :         g_critical ("%s(): %s", G_STRFUNC, error->message);
      28         [ #  # ]:           0 :       else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_CONNECTED))
      29                 :           0 :         g_warning ("%s(): %s", G_STRFUNC, error->message);
      30         [ #  # ]:           0 :       else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
      31                 :           0 :         g_debug ("%s(): %s", G_STRFUNC, error->message);
      32                 :             :     }
      33                 :           3 : }
      34                 :             : 
      35                 :             : #define VALENT_TYPE_SYSTEMVOLUME_STREAM (valent_systemvolume_stream_get_type ())
      36   [ +  -  +  -  :           4 : G_DECLARE_FINAL_TYPE (ValentSystemvolumeStream, valent_systemvolume_stream, VALENT, SYSTEMVOLUME_STREAM, ValentMixerStream)
                   -  + ]
      37                 :             : 
      38                 :             : struct _ValentSystemvolumeStream
      39                 :             : {
      40                 :             :   ValentMixerStream  parent_instance;
      41                 :             : 
      42                 :             :   ValentDevice      *device;
      43                 :             :   GCancellable      *cancellable;
      44                 :             : 
      45                 :             :   int64_t            max_volume;
      46                 :             :   int64_t            volume;
      47                 :             :   unsigned int       muted : 1;
      48                 :             : };
      49                 :             : 
      50   [ +  +  +  - ]:           8 : G_DEFINE_FINAL_TYPE (ValentSystemvolumeStream, valent_systemvolume_stream, VALENT_TYPE_MIXER_STREAM)
      51                 :             : 
      52                 :             : /*
      53                 :             :  * ValentMixerStream
      54                 :             :  */
      55                 :             : static unsigned int
      56                 :           1 : valent_systemvolume_stream_get_level (ValentMixerStream *stream)
      57                 :             : {
      58                 :           1 :   ValentSystemvolumeStream *self = VALENT_SYSTEMVOLUME_STREAM (stream);
      59                 :           1 :   double percent;
      60                 :             : 
      61         [ +  - ]:           1 :   g_assert (VALENT_IS_SYSTEMVOLUME_STREAM (self));
      62                 :             : 
      63                 :           1 :   percent = (double)self->volume / (double)self->max_volume;
      64                 :             : 
      65                 :           1 :   return (unsigned int)round (percent * 100.0);
      66                 :             : }
      67                 :             : 
      68                 :             : static void
      69                 :           1 : valent_systemvolume_stream_set_level (ValentMixerStream *stream,
      70                 :             :                                       unsigned int       level)
      71                 :             : {
      72                 :           1 :   ValentSystemvolumeStream *self = VALENT_SYSTEMVOLUME_STREAM (stream);
      73                 :           2 :   g_autoptr (JsonBuilder) builder = NULL;
      74         [ -  + ]:           1 :   g_autoptr (JsonNode) packet = NULL;
      75                 :           1 :   double percent;
      76                 :           1 :   int64_t volume;
      77                 :             : 
      78         [ +  - ]:           1 :   g_assert (VALENT_IS_SYSTEMVOLUME_STREAM (self));
      79                 :             : 
      80                 :           1 :   percent = (double)level / 100.0;
      81                 :           1 :   volume = (int64_t)round (percent * self->max_volume);
      82                 :             : 
      83                 :           1 :   valent_packet_init (&builder,  "kdeconnect.systemvolume.request");
      84                 :           1 :   json_builder_set_member_name (builder, "name");
      85                 :           1 :   json_builder_add_string_value (builder, valent_mixer_stream_get_name (stream));
      86                 :           1 :   json_builder_set_member_name (builder, "volume");
      87                 :           1 :   json_builder_add_int_value (builder, volume);
      88                 :           1 :   packet = valent_packet_end (&builder);
      89                 :             : 
      90         [ +  - ]:           1 :   valent_device_send_packet (self->device,
      91                 :             :                              packet,
      92                 :             :                              self->cancellable,
      93                 :             :                              (GAsyncReadyCallback) valent_device_send_packet_cb,
      94                 :             :                              NULL);
      95                 :           1 : }
      96                 :             : 
      97                 :             : static gboolean
      98                 :           1 : valent_systemvolume_stream_get_muted (ValentMixerStream *stream)
      99                 :             : {
     100                 :           1 :   ValentSystemvolumeStream *self = VALENT_SYSTEMVOLUME_STREAM (stream);
     101                 :             : 
     102         [ +  - ]:           1 :   g_assert (VALENT_IS_SYSTEMVOLUME_STREAM (self));
     103                 :             : 
     104                 :           1 :   return self->muted;
     105                 :             : }
     106                 :             : 
     107                 :             : static void
     108                 :           1 : valent_systemvolume_stream_set_muted (ValentMixerStream *stream,
     109                 :             :                                       gboolean           state)
     110                 :             : {
     111                 :           1 :   ValentSystemvolumeStream *self = VALENT_SYSTEMVOLUME_STREAM (stream);
     112                 :           2 :   g_autoptr (JsonBuilder) builder = NULL;
     113         [ -  + ]:           1 :   g_autoptr (JsonNode) packet = NULL;
     114                 :             : 
     115         [ +  - ]:           1 :   g_assert (VALENT_IS_SYSTEMVOLUME_STREAM (self));
     116                 :             : 
     117                 :           1 :   valent_packet_init (&builder, "kdeconnect.systemvolume.request");
     118                 :           1 :   json_builder_set_member_name (builder, "name");
     119                 :           1 :   json_builder_add_string_value (builder, valent_mixer_stream_get_name (stream));
     120                 :           1 :   json_builder_set_member_name (builder, "muted");
     121                 :           1 :   json_builder_add_boolean_value (builder, state);
     122                 :           1 :   packet = valent_packet_end (&builder);
     123                 :             : 
     124         [ +  - ]:           1 :   valent_device_send_packet (self->device,
     125                 :             :                              packet,
     126                 :             :                              self->cancellable,
     127                 :             :                              (GAsyncReadyCallback) valent_device_send_packet_cb,
     128                 :             :                              NULL);
     129                 :           1 : }
     130                 :             : 
     131                 :             : static void
     132                 :           7 : valent_systemvolume_stream_update (ValentMixerStream *stream,
     133                 :             :                                    JsonObject        *state)
     134                 :             : {
     135                 :           7 :   ValentSystemvolumeStream *self = VALENT_SYSTEMVOLUME_STREAM (stream);
     136                 :           7 :   JsonNode *node;
     137                 :             : 
     138                 :           7 :   node = json_object_get_member (state, "maxVolume");
     139         [ +  + ]:           7 :   if (node != NULL)
     140                 :             :     {
     141         [ +  - ]:           4 :       if (json_node_get_value_type (node) == G_TYPE_INT64)
     142                 :             :         {
     143                 :           4 :           self->max_volume = json_node_get_int (node);
     144                 :             :         }
     145                 :             :       else
     146                 :             :         {
     147                 :           0 :           g_warning ("%s(): expected \"maxVolume\" field holding an integer",
     148                 :             :                      G_STRFUNC);
     149                 :             :         }
     150                 :             :     }
     151                 :             : 
     152                 :           7 :   node = json_object_get_member (state, "muted");
     153         [ +  + ]:           7 :   if (node != NULL)
     154                 :             :     {
     155         [ +  - ]:           5 :       if (json_node_get_value_type (node) == G_TYPE_BOOLEAN)
     156                 :             :         {
     157                 :           5 :           gboolean muted = json_node_get_boolean (node);
     158         [ +  + ]:           5 :           if (self->muted != muted)
     159                 :             :             {
     160                 :           2 :               self->muted = muted;
     161                 :           2 :               g_object_notify (G_OBJECT (self), "muted");
     162                 :             :             }
     163                 :             :         }
     164                 :             :       else
     165                 :             :         {
     166                 :           0 :           g_warning ("%s(): expected \"muted\" field holding a boolean",
     167                 :             :                      G_STRFUNC);
     168                 :             :         }
     169                 :             :     }
     170                 :             : 
     171                 :           7 :   node = json_object_get_member (state, "volume");
     172         [ +  + ]:           7 :   if (node != NULL)
     173                 :             :     {
     174         [ +  - ]:           5 :       if (json_node_get_value_type (node) == G_TYPE_INT64)
     175                 :             :         {
     176                 :           5 :           int64_t volume = json_node_get_int (node);
     177         [ +  + ]:           5 :           if (self->volume != volume)
     178                 :             :             {
     179                 :           4 :               self->volume = volume;
     180                 :           4 :               g_object_notify (G_OBJECT (self), "level");
     181                 :             :             }
     182                 :             :         }
     183                 :             :       else
     184                 :             :         {
     185                 :           0 :           g_warning ("%s(): expected \"volume\" field holding an integer",
     186                 :             :                      G_STRFUNC);
     187                 :             :         }
     188                 :             :     }
     189                 :           7 : }
     190                 :             : 
     191                 :             : static void
     192                 :           1 : valent_systemvolume_stream_class_init (ValentSystemvolumeStreamClass *klass)
     193                 :             : {
     194                 :           1 :   ValentMixerStreamClass *stream_class = VALENT_MIXER_STREAM_CLASS (klass);
     195                 :             : 
     196                 :           1 :   stream_class->get_level = valent_systemvolume_stream_get_level;
     197                 :           1 :   stream_class->set_level = valent_systemvolume_stream_set_level;
     198                 :           1 :   stream_class->get_muted = valent_systemvolume_stream_get_muted;
     199                 :           1 :   stream_class->set_muted = valent_systemvolume_stream_set_muted;
     200                 :             : }
     201                 :             : 
     202                 :             : static void
     203                 :           2 : valent_systemvolume_stream_init (ValentSystemvolumeStream *self)
     204                 :             : {
     205                 :           2 : }
     206                 :             : 
     207                 :             : 
     208                 :             : /* <private>
     209                 :             :  * ValentSystemvolumeDevice:
     210                 :             :  *
     211                 :             :  * A `ValentMixerAdapter` for KDE Connect devices.
     212                 :             :  */
     213                 :             : struct _ValentSystemvolumeDevice
     214                 :             : {
     215                 :             :   ValentMixerAdapter  parent_instance;
     216                 :             : 
     217                 :             :   ValentDevice       *device;
     218                 :             :   GCancellable       *cancellable;
     219                 :             :   ValentMixerStream  *default_output;
     220                 :             :   GHashTable         *outputs;
     221                 :             : };
     222                 :             : 
     223   [ +  +  +  - ]:          17 : G_DEFINE_FINAL_TYPE (ValentSystemvolumeDevice, valent_systemvolume_device, VALENT_TYPE_MIXER_ADAPTER)
     224                 :             : 
     225                 :             : #if 0
     226                 :             : static void
     227                 :             : valent_systemvolume_device_request_sinks (ValentSystemvolumeDevice *self)
     228                 :             : {
     229                 :             :   g_autoptr (JsonBuilder) builder = NULL;
     230                 :             :   g_autoptr (JsonNode) packet = NULL;
     231                 :             : 
     232                 :             :   valent_packet_init (&builder, "kdeconnect.systemvolume.request");
     233                 :             :   json_builder_set_member_name (builder, "requestSinks");
     234                 :             :   json_builder_add_boolean_value (builder, TRUE);
     235                 :             :   packet = valent_packet_end (&builder);
     236                 :             : 
     237                 :             :   valent_device_send_packet (self->device,
     238                 :             :                              packet,
     239                 :             :                              self->cancellable,
     240                 :             :                              (GAsyncReadyCallback) valent_device_send_packet_cb,
     241                 :             :                              NULL);
     242                 :             : }
     243                 :             : #endif
     244                 :             : 
     245                 :             : /*
     246                 :             :  * ValentMixerAdapter
     247                 :             :  */
     248                 :             : static void
     249                 :           4 : on_device_state_changed (ValentDevice             *device,
     250                 :             :                          GParamSpec               *pspec,
     251                 :             :                          ValentSystemvolumeDevice *self)
     252                 :             : {
     253                 :           4 :   ValentDeviceState state = VALENT_DEVICE_STATE_NONE;
     254                 :           4 :   gboolean available;
     255                 :             : 
     256         [ +  - ]:           4 :   g_assert (VALENT_IS_SYSTEMVOLUME_DEVICE (self));
     257                 :             : 
     258                 :           4 :   state = valent_device_get_state (device);
     259                 :           4 :   available = (state & VALENT_DEVICE_STATE_CONNECTED) != 0 &&
     260                 :             :               (state & VALENT_DEVICE_STATE_PAIRED) != 0;
     261                 :             : 
     262   [ +  -  +  + ]:           4 :   if (available && self->cancellable == NULL)
     263                 :             :     {
     264                 :           6 :       g_autoptr (GCancellable) cancellable = NULL;
     265                 :             : 
     266                 :           2 :       cancellable = g_cancellable_new ();
     267         [ +  - ]:           2 :       self->cancellable = valent_object_chain_cancellable (VALENT_OBJECT (self),
     268                 :             :                                                            cancellable);
     269                 :             :     }
     270         [ #  # ]:           0 :   else if (!available && self->cancellable != NULL)
     271                 :             :     {
     272                 :           0 :       GHashTableIter iter;
     273                 :           0 :       ValentMixerStream *output;
     274                 :             : 
     275                 :           0 :       g_cancellable_cancel (self->cancellable);
     276         [ #  # ]:           0 :       g_clear_object (&self->cancellable);
     277                 :             : 
     278                 :           0 :       g_hash_table_iter_init (&iter, self->outputs);
     279         [ #  # ]:           0 :       while (g_hash_table_iter_next (&iter, NULL, (void **)&output))
     280                 :             :         {
     281                 :           0 :           valent_mixer_adapter_stream_removed (VALENT_MIXER_ADAPTER (self),
     282                 :             :                                                output);
     283                 :           0 :           g_hash_table_iter_remove (&iter);
     284                 :             :         }
     285                 :             :     }
     286                 :           4 : }
     287                 :             : 
     288                 :             : static ValentMixerStream  *
     289                 :           2 : valent_systemvolume_device_get_default_output (ValentMixerAdapter *adapter)
     290                 :             : {
     291                 :           2 :   ValentSystemvolumeDevice *self = VALENT_SYSTEMVOLUME_DEVICE (adapter);
     292                 :             : 
     293         [ +  - ]:           2 :   g_assert (VALENT_IS_SYSTEMVOLUME_DEVICE (self));
     294                 :             : 
     295                 :           2 :   return self->default_output;
     296                 :             : }
     297                 :             : 
     298                 :             : static void
     299                 :           1 : valent_systemvolume_device_set_default_output (ValentMixerAdapter *adapter,
     300                 :             :                                                ValentMixerStream  *stream)
     301                 :             : {
     302                 :           1 :   ValentSystemvolumeDevice *self = VALENT_SYSTEMVOLUME_DEVICE (adapter);
     303                 :           1 :   g_autoptr (JsonBuilder) builder = NULL;
     304   [ -  -  -  + ]:           1 :   g_autoptr (JsonNode) packet = NULL;
     305                 :             : 
     306         [ +  - ]:           1 :   g_assert (VALENT_IS_SYSTEMVOLUME_DEVICE (self));
     307                 :             : 
     308         [ -  + ]:           1 :   if (self->default_output == stream)
     309         [ #  # ]:           0 :     return;
     310                 :             : 
     311                 :           1 :   valent_packet_init (&builder, "kdeconnect.systemvolume.request");
     312                 :           1 :   json_builder_set_member_name (builder, "name");
     313                 :           1 :   json_builder_add_string_value (builder, valent_mixer_stream_get_name (stream));
     314                 :           1 :   json_builder_set_member_name (builder, "enabled");
     315                 :           1 :   json_builder_add_boolean_value (builder, TRUE);
     316                 :           1 :   packet = valent_packet_end (&builder);
     317                 :             : 
     318         [ +  - ]:           1 :   valent_device_send_packet (self->device,
     319                 :             :                              packet,
     320                 :             :                              self->cancellable,
     321                 :             :                              (GAsyncReadyCallback) valent_device_send_packet_cb,
     322                 :             :                              NULL);
     323                 :             : }
     324                 :             : 
     325                 :             : /*
     326                 :             :  * GObject
     327                 :             :  */
     328                 :             : static void
     329                 :           2 : valent_systemvolume_device_constructed (GObject *object)
     330                 :             : {
     331                 :           2 :   ValentSystemvolumeDevice *self = VALENT_SYSTEMVOLUME_DEVICE (object);
     332                 :             : 
     333                 :           2 :   G_OBJECT_CLASS (valent_systemvolume_device_parent_class)->constructed (object);
     334                 :             : 
     335                 :           2 :   self->device = valent_resource_get_source (VALENT_RESOURCE (self));
     336                 :           2 :   g_signal_connect_object (self->device,
     337                 :             :                            "notify::state",
     338                 :             :                            G_CALLBACK (on_device_state_changed),
     339                 :             :                            self,
     340                 :             :                            G_CONNECT_DEFAULT);
     341                 :           2 :   on_device_state_changed (self->device, NULL, self);
     342                 :           2 : }
     343                 :             : 
     344                 :             : static void
     345                 :           2 : valent_systemvolume_device_finalize (GObject *object)
     346                 :             : {
     347                 :           2 :   ValentSystemvolumeDevice *self = VALENT_SYSTEMVOLUME_DEVICE (object);
     348                 :             : 
     349         [ +  - ]:           2 :   g_clear_object (&self->cancellable);
     350         [ +  + ]:           2 :   g_clear_object (&self->default_output);
     351         [ +  - ]:           2 :   g_clear_pointer (&self->outputs, g_hash_table_unref);
     352                 :             : 
     353                 :           2 :   G_OBJECT_CLASS (valent_systemvolume_device_parent_class)->finalize (object);
     354                 :           2 : }
     355                 :             : 
     356                 :             : static void
     357                 :           1 : valent_systemvolume_device_class_init (ValentSystemvolumeDeviceClass *klass)
     358                 :             : {
     359                 :           1 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     360                 :           1 :   ValentMixerAdapterClass *adapter_class = VALENT_MIXER_ADAPTER_CLASS (klass);
     361                 :             : 
     362                 :           1 :   object_class->constructed = valent_systemvolume_device_constructed;
     363                 :           1 :   object_class->finalize = valent_systemvolume_device_finalize;
     364                 :             : 
     365                 :           1 :   adapter_class->get_default_output = valent_systemvolume_device_get_default_output;
     366                 :           1 :   adapter_class->set_default_output = valent_systemvolume_device_set_default_output;
     367                 :             : }
     368                 :             : 
     369                 :             : static void
     370                 :           2 : valent_systemvolume_device_init (ValentSystemvolumeDevice *self)
     371                 :             : {
     372                 :           2 :   self->outputs = g_hash_table_new_full (g_str_hash, g_str_equal,
     373                 :             :                                          g_free, g_object_unref);
     374                 :           2 : }
     375                 :             : 
     376                 :             : /**
     377                 :             :  * valent_systemvolume_device_new:
     378                 :             :  * @device: a `ValentDevice`
     379                 :             :  *
     380                 :             :  * Create a new `ValentSystemvolumeDevice`.
     381                 :             :  *
     382                 :             :  * Returns: (transfer full): a new message store
     383                 :             :  */
     384                 :             : ValentMixerAdapter *
     385                 :           2 : valent_systemvolume_device_new (ValentDevice *device)
     386                 :             : {
     387                 :           4 :   g_autoptr (ValentContext) context = NULL;
     388         [ +  - ]:           2 :   g_autofree char *iri = NULL;
     389                 :             : 
     390         [ +  - ]:           2 :   g_return_val_if_fail (VALENT_IS_DEVICE (device), NULL);
     391                 :             : 
     392                 :           2 :   context = valent_context_new (valent_device_get_context (device),
     393                 :             :                                 "plugin",
     394                 :             :                                 "systemvolume");
     395                 :           2 :   iri = tracker_sparql_escape_uri_printf ("urn:valent:mixer:%s",
     396                 :             :                                           valent_device_get_id (device));
     397                 :           2 :   return g_object_new (VALENT_TYPE_SYSTEMVOLUME_DEVICE,
     398                 :             :                        "iri",     iri,
     399                 :             :                        "context", context,
     400                 :             :                        "source",  device,
     401                 :             :                        "title",   valent_device_get_name (device),
     402                 :             :                        NULL);
     403                 :             : }
     404                 :             : 
     405                 :             : static const char *
     406                 :           7 : valent_systemvolume_device_handle_stream (ValentSystemvolumeDevice *self,
     407                 :             :                                           JsonObject               *state)
     408                 :             : {
     409                 :           7 :   ValentMixerStream *stream = NULL;
     410                 :           7 :   gboolean new_stream = FALSE;
     411                 :           7 :   JsonNode *node;
     412                 :           7 :   const char *name = NULL;
     413                 :             : 
     414                 :           7 :   node = json_object_get_member (state, "name");
     415   [ +  -  -  + ]:           7 :   if (node == NULL || json_node_get_value_type (node) != G_TYPE_STRING)
     416                 :             :     {
     417                 :           0 :       g_warning ("%s(): expected \"name\" field holding a string", G_STRFUNC);
     418                 :           0 :       return NULL;
     419                 :             :     }
     420                 :           7 :   name = json_node_get_string (node);
     421                 :             : 
     422                 :           7 :   stream = g_hash_table_lookup (self->outputs, name);
     423         [ +  + ]:           7 :   if (stream == NULL)
     424                 :             :     {
     425                 :           2 :       const char *description = NULL;
     426                 :             : 
     427                 :           2 :       node = json_object_get_member (state, "description");
     428         [ -  + ]:           2 :       if (node != NULL)
     429                 :             :         {
     430         [ +  - ]:           2 :           if (json_node_get_value_type (node) == G_TYPE_STRING)
     431                 :             :             {
     432                 :           2 :               description = json_node_get_string (node);
     433                 :             :             }
     434                 :             :           else
     435                 :             :             {
     436                 :           0 :               g_warning ("%s(): expected \"description\" field holding a string",
     437                 :             :                          G_STRFUNC);
     438                 :             :             }
     439                 :             :         }
     440                 :             : 
     441                 :           2 :       stream = g_object_new (VALENT_TYPE_SYSTEMVOLUME_STREAM,
     442                 :             :                              "name",        name,
     443                 :             :                              "description", description,
     444                 :             :                              "direction",   VALENT_MIXER_OUTPUT,
     445                 :             :                              NULL);
     446                 :           2 :       ((ValentSystemvolumeStream *)stream)->device = self->device;
     447                 :           2 :       ((ValentSystemvolumeStream *)stream)->cancellable = self->cancellable;
     448         [ -  + ]:           2 :       g_hash_table_replace (self->outputs, g_strdup (name), stream /* owned */);
     449                 :           2 :       new_stream = TRUE;
     450                 :             :     }
     451                 :             : 
     452                 :           7 :   valent_systemvolume_stream_update (stream, state);
     453                 :             : 
     454                 :           7 :   node = json_object_get_member (state, "enabled");
     455         [ +  - ]:           7 :   if (node != NULL)
     456                 :             :     {
     457         [ +  - ]:           7 :       if (json_node_get_value_type (node) == G_TYPE_BOOLEAN)
     458                 :             :         {
     459   [ +  +  +  + ]:          13 :           if (json_node_get_boolean (node) &&
     460                 :           6 :               g_set_object (&self->default_output, stream))
     461                 :             :             {
     462                 :           3 :               g_object_notify (G_OBJECT (self), "default-output");
     463                 :             :             }
     464                 :             :         }
     465                 :             :       else
     466                 :             :         {
     467                 :           0 :           g_warning ("%s(): expected \"enabled\" field holding a boolean",
     468                 :             :                      G_STRFUNC);
     469                 :             :         }
     470                 :             :     }
     471                 :             : 
     472         [ +  + ]:           7 :   if (new_stream)
     473                 :           2 :     valent_mixer_adapter_stream_added (VALENT_MIXER_ADAPTER (self), stream);
     474                 :             : 
     475                 :             :   return name;
     476                 :             : }
     477                 :             : 
     478                 :             : /**
     479                 :             :  * valent_systemvolume_device_handle_packet:
     480                 :             :  * @self: a `ValentSystemvolumeDevice`
     481                 :             :  * @packet: a `kdeconnect.systemvolume.*` packet
     482                 :             :  *
     483                 :             :  * Handle a packet of mixer.
     484                 :             :  */
     485                 :             : void
     486                 :           6 : valent_systemvolume_device_handle_packet (ValentSystemvolumeDevice *self,
     487                 :             :                                           JsonNode                 *packet)
     488                 :             : {
     489                 :           6 :   JsonArray *sinks;
     490                 :             : 
     491                 :           6 :   VALENT_ENTRY;
     492                 :             : 
     493         [ +  - ]:           6 :   g_assert (VALENT_IS_SYSTEMVOLUME_DEVICE (self));
     494         [ -  + ]:           6 :   g_assert (VALENT_IS_PACKET (packet));
     495                 :             : 
     496         [ +  + ]:           6 :   if (valent_packet_get_array (packet, "sinkList", &sinks))
     497                 :             :     {
     498                 :           3 :       g_autoptr (GStrvBuilder) names = NULL;
     499         [ +  - ]:           3 :       g_auto (GStrv) namev = NULL;
     500                 :           3 :       unsigned int n_sinks = 0;
     501                 :           3 :       GHashTableIter iter;
     502                 :           3 :       const char *name = NULL;
     503                 :           3 :       ValentMixerStream *output = NULL;
     504                 :             : 
     505                 :           3 :       names = g_strv_builder_new ();
     506                 :           3 :       n_sinks = json_array_get_length (sinks);
     507         [ +  + ]:           7 :       for (unsigned int i = 0; i < n_sinks; i++)
     508                 :             :         {
     509                 :           4 :           JsonObject *sink = json_array_get_object_element (sinks, i);
     510                 :             : 
     511                 :           4 :           name = valent_systemvolume_device_handle_stream (self, sink);
     512         [ +  - ]:           4 :           if (name != NULL)
     513                 :           4 :             g_strv_builder_add (names, name);
     514                 :             :         }
     515                 :           3 :       namev = g_strv_builder_end (names);
     516                 :             : 
     517                 :           3 :       g_hash_table_iter_init (&iter, self->outputs);
     518         [ +  + ]:          11 :       while (g_hash_table_iter_next (&iter, (void **)&name, (void **)&output))
     519                 :             :         {
     520         [ +  + ]:           5 :           if (!g_strv_contains ((const char * const *)namev, name))
     521                 :             :             {
     522                 :           1 :               valent_mixer_adapter_stream_removed (VALENT_MIXER_ADAPTER (self),
     523                 :             :                                                    output);
     524                 :           1 :               g_hash_table_iter_remove (&iter);
     525                 :             :             }
     526                 :             :         }
     527                 :             :     }
     528                 :             :   else
     529                 :             :     {
     530                 :           3 :       JsonObject *body;
     531                 :             : 
     532                 :           3 :       body = valent_packet_get_body (packet);
     533                 :           3 :       valent_systemvolume_device_handle_stream (self, body);
     534                 :             :     }
     535                 :             : 
     536                 :           6 :   VALENT_EXIT;
     537                 :             : }
     538                 :             : 
        

Generated by: LCOV version 2.0-1