aboutsummaryrefslogtreecommitdiff
path: root/libmm-glib/mm-call.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmm-glib/mm-call.c')
-rw-r--r--libmm-glib/mm-call.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/libmm-glib/mm-call.c b/libmm-glib/mm-call.c
index 92689f85..af1d8f12 100644
--- a/libmm-glib/mm-call.c
+++ b/libmm-glib/mm-call.c
@@ -36,6 +36,13 @@
G_DEFINE_TYPE (MMCall, mm_call, MM_GDBUS_TYPE_CALL_PROXY)
+struct _MMCallPrivate {
+ /* Audio Format */
+ GMutex audio_format_mutex;
+ guint audio_format_id;
+ MMCallAudioFormat *audio_format;
+};
+
/*****************************************************************************/
/**
@@ -177,6 +184,156 @@ mm_call_get_state_reason (MMCall *self)
/*****************************************************************************/
/**
+ * mm_call_get_audio_port:
+ * @self: A #MMCall.
+ *
+ * Gets the kernel device used for audio (if any).
+ *
+ * Returns: (transfer none): The audio port, or %NULL if call audio is not
+ * routed via the host or couldn't be retrieved.
+ */
+const gchar *
+mm_call_get_audio_port (MMCall *self)
+{
+ g_return_val_if_fail (MM_IS_CALL (self), NULL);
+
+ RETURN_NON_EMPTY_CONSTANT_STRING (
+ mm_gdbus_call_get_audio_port (MM_GDBUS_CALL (self)));
+}
+
+/**
+ * mm_call_dup_audio_port:
+ * @self: A #MMCall.
+ *
+ * Gets the kernel device used for audio (if any).
+ *
+ * Returns: (transfer full): The audio port, or %NULL if call audio is not
+ * routed via the host or couldn't be retrieved.
+ */
+gchar *
+mm_call_dup_audio_port (MMCall *self)
+{
+ g_return_val_if_fail (MM_IS_CALL (self), NULL);
+
+ RETURN_NON_EMPTY_STRING (
+ mm_gdbus_call_dup_audio_port (MM_GDBUS_CALL (self)));
+}
+
+/*****************************************************************************/
+
+static void
+audio_format_updated (MMCall *self,
+ GParamSpec *pspec)
+{
+ g_mutex_lock (&self->priv->audio_format_mutex);
+ {
+ GVariant *dictionary;
+
+ g_clear_object (&self->priv->audio_format);
+
+ /* TODO: update existing object instead of re-creating? */
+ dictionary = mm_gdbus_call_get_audio_format (MM_GDBUS_CALL (self));
+ if (dictionary) {
+ GError *error = NULL;
+
+ self->priv->audio_format = mm_call_audio_format_new_from_dictionary (dictionary, &error);
+ if (error) {
+ g_warning ("Invalid audio format update received: %s", error->message);
+ g_error_free (error);
+ }
+ }
+ }
+ g_mutex_unlock (&self->priv->audio_format_mutex);
+}
+
+static void
+ensure_internal_audio_format (MMCall *self,
+ MMCallAudioFormat **dup)
+{
+ g_mutex_lock (&self->priv->audio_format_mutex);
+ {
+ /* If this is the first time ever asking for the object, setup the
+ * update listener and the initial object, if any. */
+ if (!self->priv->audio_format_id) {
+ GVariant *dictionary;
+
+ dictionary = mm_gdbus_call_dup_audio_format (MM_GDBUS_CALL (self));
+ if (dictionary) {
+ GError *error = NULL;
+
+ self->priv->audio_format = mm_call_audio_format_new_from_dictionary (dictionary, &error);
+ if (error) {
+ g_warning ("Invalid initial audio format: %s", error->message);
+ g_error_free (error);
+ }
+ g_variant_unref (dictionary);
+ }
+
+ /* No need to clear this signal connection when freeing self */
+ self->priv->audio_format_id =
+ g_signal_connect (self,
+ "notify::audio-format",
+ G_CALLBACK (audio_format_updated),
+ NULL);
+ }
+
+ if (dup && self->priv->audio_format)
+ *dup = g_object_ref (self->priv->audio_format);
+ }
+ g_mutex_unlock (&self->priv->audio_format_mutex);
+}
+
+/**
+ * mm_call_get_audio_format:
+ * @self: A #MMCall.
+ *
+ * Gets a #MMCallAudioFormat object specifying the audio format used by the
+ * audio port if call audio is routed via the host.
+ *
+ * <warning>The values reported by @self are not updated when the values in the
+ * interface change. Instead, the client is expected to call
+ * mm_call_get_audio_format() again to get a new #MMCallAudioFormat with the
+ * new values.</warning>
+ *
+ * Returns: (transfer full): A #MMCallAudioFormat that must be freed with g_object_unref() or %NULL if unknown.
+ */
+MMCallAudioFormat *
+mm_call_get_audio_format (MMCall *self)
+{
+ MMCallAudioFormat *format = NULL;
+
+ g_return_val_if_fail (MM_IS_CALL (self), NULL);
+
+ ensure_internal_audio_format (self, &format);
+ return format;
+}
+
+/**
+ * mm_call_peek_audio_format:
+ * @self: A #MMCall.
+ *
+ * Gets a #MMCallAudioFormat object specifying the audio format used by the
+ * audio port if call audio is routed via the host.
+ *
+ * <warning>The returned value is only valid until the property changes so
+ * it is only safe to use this function on the thread where
+ * @self was constructed. Use mm_call_get_audio_format() if on another
+ * thread.</warning>
+ *
+ * Returns: (transfer none): A #MMCallAudioFormat. Do not free the returned value, it belongs to @self.
+ */
+MMCallAudioFormat *
+mm_call_peek_audio_format (MMCall *self)
+{
+ g_return_val_if_fail (MM_IS_CALL (self), NULL);
+
+ ensure_internal_audio_format (self, NULL);
+ return self->priv->audio_format;
+}
+
+/*****************************************************************************/
+
+/**
* mm_call_start_finish:
* @self: A #MMCall.
* @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to mm_call_start().
@@ -500,9 +657,40 @@ mm_call_send_dtmf_sync (MMCall *self,
static void
mm_call_init (MMCall *self)
{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ MM_TYPE_CALL,
+ MMCallPrivate);
+ g_mutex_init (&self->priv->audio_format_mutex);
+}
+
+static void
+finalize (GObject *object)
+{
+ MMCall *self = MM_CALL (object);
+
+ g_mutex_clear (&self->priv->audio_format_mutex);
+
+ G_OBJECT_CLASS (mm_call_parent_class)->finalize (object);
+}
+
+static void
+dispose (GObject *object)
+{
+ MMCall *self = MM_CALL (object);
+
+ g_clear_object (&self->priv->audio_format);
+
+ G_OBJECT_CLASS (mm_call_parent_class)->dispose (object);
}
static void
mm_call_class_init (MMCallClass *call_class)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (call_class);
+
+ g_type_class_add_private (object_class, sizeof (MMCallPrivate));
+
+ /* Virtual methods */
+ object_class->dispose = dispose;
+ object_class->finalize = finalize;
}