[calls] Introduce CallsUiCallData to feed CuiDisplay



commit 4321381f23c198c09c03bdb99e700ae800b7c8cd
Author: Evangelos Ribeiro Tzaras <devrtz fortysixandtwo eu>
Date:   Fri Oct 1 18:35:00 2021 +0200

    Introduce CallsUiCallData to feed CuiDisplay
    
    We need a proxy object because implementing the CuiCall interface in the
    CallsCall base class has it's own set of problems (f.e. the "state" property
    would have a type collision CallsCallState vs CuiCallState).

 src/calls-ui-call-data.c | 368 +++++++++++++++++++++++++++++++++++++++++++++++
 src/calls-ui-call-data.h |  17 +++
 src/meson.build          |   1 +
 3 files changed, 386 insertions(+)
---
diff --git a/src/calls-ui-call-data.c b/src/calls-ui-call-data.c
new file mode 100644
index 00000000..af044cba
--- /dev/null
+++ b/src/calls-ui-call-data.c
@@ -0,0 +1,368 @@
+
+#include "calls-ui-call-data.h"
+#include "calls-contacts-provider.h"
+#include "calls-manager.h"
+
+#include <cui-call.h>
+
+enum {
+  PROP_0,
+  PROP_CALL,
+  PROP_DISPLAY_NAME,
+  PROP_ID,
+  PROP_STATE,
+  PROP_ENCRYPTED,
+  PROP_CAN_DTMF,
+  PROP_LAST_PROP
+};
+
+static GParamSpec *props[PROP_LAST_PROP];
+
+
+struct _CallsUiCallData
+{
+  GObject parent_instance;
+
+  CallsCall *call;
+  CallsBestMatch *best_match;
+};
+
+static void calls_ui_call_data_cui_call_interface_init (CuiCallInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (CallsUiCallData, calls_ui_call_data, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (CUI_TYPE_CALL,
+                                                calls_ui_call_data_cui_call_interface_init))
+
+struct DtmfData
+{
+  CallsCall *call;
+  char dtmf;
+};
+
+
+static gboolean
+on_stop_dtmf (struct DtmfData *dtmf_data)
+{
+  calls_call_tone_stop (dtmf_data->call, dtmf_data->dtmf);
+
+  g_free (dtmf_data);
+  return G_SOURCE_REMOVE;
+}
+
+static const char *
+calls_ui_call_data_get_display_name (CuiCall *call_data)
+{
+  CallsUiCallData *self = (CallsUiCallData *) call_data;
+
+  g_return_val_if_fail (CALLS_IS_UI_CALL_DATA (self), NULL);
+  g_return_val_if_fail (!!self->call, NULL);
+
+  return calls_best_match_get_name (self->best_match);
+}
+
+static const char *
+calls_ui_call_data_get_id (CuiCall *call_data)
+{
+  CallsUiCallData *self = (CallsUiCallData *) call_data;
+
+  g_return_val_if_fail (CALLS_IS_UI_CALL_DATA (self), NULL);
+  g_return_val_if_fail (!!self->call, NULL);
+
+  return calls_call_get_number (self->call);
+}
+
+static CuiCallState
+calls_state_to_cui_call_state (CallsCallState state)
+{
+  switch (state) {
+  case CALLS_CALL_STATE_ACTIVE:
+    return CUI_CALL_STATE_ACTIVE;
+  case CALLS_CALL_STATE_HELD:
+    return CUI_CALL_STATE_HELD;
+  case CALLS_CALL_STATE_DIALING:
+    return CUI_CALL_STATE_DIALING;
+  case CALLS_CALL_STATE_ALERTING:
+    return CUI_CALL_STATE_ALERTING;
+  case CALLS_CALL_STATE_INCOMING:
+    return CUI_CALL_STATE_INCOMING;
+  case CALLS_CALL_STATE_WAITING:
+    return CUI_CALL_STATE_WAITING;
+  case CALLS_CALL_STATE_DISCONNECTED:
+    return CUI_CALL_STATE_DISCONNECTED;
+  default:
+    return CUI_CALL_STATE_UNKNOWN;
+  }
+}
+
+static CuiCallState
+calls_ui_call_data_get_state (CuiCall *call_data)
+{
+  CallsUiCallData *self = (CallsUiCallData *) call_data;
+
+  g_return_val_if_fail (CALLS_IS_UI_CALL_DATA (self), CUI_CALL_STATE_UNKNOWN);
+  g_return_val_if_fail (!!self->call, CUI_CALL_STATE_UNKNOWN);
+
+  return calls_state_to_cui_call_state (calls_call_get_state (self->call));
+}
+
+
+static gboolean
+calls_ui_call_data_get_encrypted (CuiCall *call_data)
+{
+  CallsUiCallData *self = (CallsUiCallData *) call_data;
+
+  g_return_val_if_fail (CALLS_IS_UI_CALL_DATA (self), FALSE);
+  g_return_val_if_fail (!!self->call, FALSE);
+
+  return FALSE;
+}
+
+static gboolean
+calls_ui_call_data_get_can_dtmf (CuiCall *call_data)
+{
+  CallsUiCallData *self = (CallsUiCallData *) call_data;
+
+  g_return_val_if_fail (CALLS_IS_UI_CALL_DATA (self), FALSE);
+  g_return_val_if_fail (!!self->call, FALSE);
+
+  return calls_call_can_dtmf (self->call);
+}
+
+
+static void
+calls_ui_call_data_accept (CuiCall *call_data)
+{
+  CallsUiCallData *self = (CallsUiCallData *) call_data;
+
+  g_return_if_fail (CALLS_IS_UI_CALL_DATA (self));
+  g_return_if_fail (!!self->call);
+
+  calls_call_answer (self->call);
+}
+
+
+static void
+calls_ui_call_data_hang_up (CuiCall *call_data)
+{
+  CallsUiCallData *self = (CallsUiCallData *) call_data;
+
+  g_return_if_fail (CALLS_IS_UI_CALL_DATA (self));
+  g_return_if_fail (!!self->call);
+
+  calls_call_hang_up (self->call);
+}
+
+
+static void
+calls_ui_call_data_send_dtmf (CuiCall    *call_data,
+                              const char *dtmf)
+{
+  CallsUiCallData *self = (CallsUiCallData *) call_data;
+
+  g_return_if_fail (CALLS_IS_UI_CALL_DATA (self));
+  g_return_if_fail (!!self->call);
+
+  calls_call_tone_start (self->call, *dtmf);
+  if (calls_call_tone_stoppable (self->call)) {
+    struct DtmfData *dtmf_data = g_new0 (struct DtmfData, 1);
+    dtmf_data->call = self->call;
+    dtmf_data->dtmf = *dtmf;
+
+    g_timeout_add (250, G_SOURCE_FUNC (on_stop_dtmf), dtmf_data);
+  }
+}
+
+static void
+calls_ui_call_data_cui_call_interface_init (CuiCallInterface *iface)
+{
+  iface->get_id = calls_ui_call_data_get_id;
+  iface->get_display_name = calls_ui_call_data_get_display_name;
+  iface->get_state = calls_ui_call_data_get_state;
+  iface->get_encrypted = calls_ui_call_data_get_encrypted;
+  iface->get_can_dtmf = calls_ui_call_data_get_can_dtmf;
+
+  iface->accept = calls_ui_call_data_accept;
+  iface->hang_up = calls_ui_call_data_hang_up;
+  iface->send_dtmf = calls_ui_call_data_send_dtmf;
+}
+
+
+static void
+on_notify_state (CallsUiCallData *self)
+{
+  g_assert (CALLS_UI_CALL_DATA (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]);
+}
+
+
+static void
+on_notify_name (CallsUiCallData *self)
+{
+  g_assert (CALLS_UI_CALL_DATA (self));
+
+  g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DISPLAY_NAME]);
+}
+
+
+static void
+set_call_data (CallsUiCallData *self,
+               CallsCall       *call)
+{
+  CallsManager *manager;
+  CallsContactsProvider *contacts_provider;
+
+  g_return_if_fail (CALLS_IS_UI_CALL_DATA (self));
+  g_return_if_fail (CALLS_IS_CALL (call));
+
+  manager = calls_manager_get_default ();
+  contacts_provider = calls_manager_get_contacts_provider (manager);
+
+  self->best_match =
+    calls_contacts_provider_lookup_phone_number (contacts_provider,
+                                                 calls_call_get_number (call));
+
+  g_signal_connect_object (self->best_match,
+                           "notify::name",
+                           G_CALLBACK (on_notify_name),
+                           self,
+                           G_CONNECT_SWAPPED);
+  g_signal_connect_object (self->best_match,
+                           "notify::has-individual",
+                           G_CALLBACK (on_notify_name),
+                           self,
+                           G_CONNECT_SWAPPED);
+  self->call = call;
+
+  g_signal_connect_object (self->call,
+                           "notify::state",
+                           G_CALLBACK (on_notify_state),
+                           self,
+                           G_CONNECT_SWAPPED);
+}
+
+static void
+calls_ui_call_data_set_property (GObject      *object,
+                                 guint         property_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  CallsUiCallData *self = CALLS_UI_CALL_DATA (object);
+
+  switch (property_id) {
+  case PROP_CALL:
+    // construct only
+    set_call_data (self, g_value_dup_object (value));
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    break;
+  }
+}
+
+
+static void
+calls_ui_call_data_get_property (GObject    *object,
+                                 guint       property_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  CallsUiCallData *self = CALLS_UI_CALL_DATA (object);
+  CuiCall *cui_call = CUI_CALL (object);
+
+  switch (property_id) {
+  case PROP_CALL:
+    g_value_set_object (value, self->call);
+    break;
+
+  case PROP_DISPLAY_NAME:
+    g_value_set_string (value, calls_ui_call_data_get_display_name (cui_call));
+    break;
+
+  case PROP_ID:
+    g_value_set_string (value, calls_ui_call_data_get_id (cui_call));
+    break;
+
+  case PROP_STATE:
+    g_value_set_enum (value, calls_ui_call_data_get_state (cui_call));
+    break;
+
+  case PROP_ENCRYPTED:
+    g_value_set_boolean (value, calls_ui_call_data_get_encrypted (cui_call));
+    break;
+
+  case PROP_CAN_DTMF:
+    g_value_set_boolean (value, calls_ui_call_data_get_can_dtmf (cui_call));
+    break;
+
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    break;
+  }
+}
+
+static void
+calls_ui_call_data_finalize (GObject *object)
+{
+  CallsUiCallData *self = CALLS_UI_CALL_DATA (object);
+
+  g_object_unref (self->call);
+  g_object_unref (self->best_match);
+
+  G_OBJECT_CLASS (calls_ui_call_data_parent_class)->finalize (object);
+}
+
+static void
+calls_ui_call_data_init (CallsUiCallData *self)
+{
+}
+
+static void
+calls_ui_call_data_class_init (CallsUiCallDataClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = calls_ui_call_data_set_property;
+  object_class->get_property = calls_ui_call_data_get_property;
+  object_class->finalize = calls_ui_call_data_finalize;
+
+  props[PROP_CALL] =
+    g_param_spec_object ("call",
+                         "Call",
+                         "The call",
+                         CALLS_TYPE_CALL,
+                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
+                         G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_property (object_class, PROP_CALL, props[PROP_CALL]);
+
+  g_object_class_override_property (object_class, PROP_ID, "id");
+  props[PROP_ID] = g_object_class_find_property (object_class, "id");
+
+  g_object_class_override_property (object_class, PROP_DISPLAY_NAME, "display-name");
+  props[PROP_DISPLAY_NAME] = g_object_class_find_property (object_class, "display-name");
+
+  g_object_class_override_property (object_class, PROP_STATE, "state");
+  props[PROP_STATE] = g_object_class_find_property (object_class, "state");
+
+  g_object_class_override_property (object_class, PROP_ENCRYPTED, "encrypted");
+  props[PROP_ENCRYPTED] = g_object_class_find_property (object_class, "encrypted");
+
+  g_object_class_override_property (object_class, PROP_CAN_DTMF, "can-dtmf");
+  props[PROP_CAN_DTMF] = g_object_class_find_property (object_class, "can-dtmf");
+}
+
+CallsUiCallData *
+calls_ui_call_data_new (CallsCall *call)
+{
+  return g_object_new (CALLS_TYPE_UI_CALL_DATA, "call", call, NULL);
+}
+
+
+CallsCall *
+calls_ui_call_data_get_call (CallsUiCallData *self)
+{
+  g_return_val_if_fail (CALLS_IS_UI_CALL_DATA (self), NULL);
+
+  return self->call;
+}
diff --git a/src/calls-ui-call-data.h b/src/calls-ui-call-data.h
new file mode 100644
index 00000000..0fdba5f5
--- /dev/null
+++ b/src/calls-ui-call-data.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "calls-call.h"
+
+#include <cui-call.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define CALLS_TYPE_UI_CALL_DATA (calls_ui_call_data_get_type ())
+
+G_DECLARE_FINAL_TYPE (CallsUiCallData, calls_ui_call_data, CALLS, UI_CALL_DATA, GObject)
+
+CallsUiCallData         *calls_ui_call_data_new       (CallsCall       *call);
+CallsCall               *calls_ui_call_data_get_call  (CallsUiCallData *self);
+
+G_END_DECLS
diff --git a/src/meson.build b/src/meson.build
index 66fa4e5b..addbcf7e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -116,6 +116,7 @@ calls_sources = files(['calls-message-source.c', 'calls-message-source.h',
                        'calls-settings.c', 'calls-settings.h',
                        'calls-secret-store.c', 'calls-secret-store.h',
                        'calls-network-watch.c', 'calls-network-watch.h',
+                       'calls-ui-call-data.c', 'calls-ui-call-data.h',
                       ]) + calls_generated_sources
 
 calls_config_data = config_data


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