From 627303a748cce7274b05a6861a1dc0c779d9263a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 6 Feb 2017 20:53:39 -0600 Subject: api/libmm-glib/cli: add AudioPort and AudioFormat properties to the Call object --- libmm-glib/mm-call.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) (limited to 'libmm-glib/mm-call.c') 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; +}; + /*****************************************************************************/ /** @@ -176,6 +183,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. + * + * 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. + * + * 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. + * + * 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. + * + * 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. @@ -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; } -- cgit v1.2.3-70-g09d2