aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2017-02-06 20:53:39 -0600
committerDan Williams <dcbw@redhat.com>2018-10-16 17:09:21 +0000
commit627303a748cce7274b05a6861a1dc0c779d9263a (patch)
tree52acb186721f9c48ccf1c042e620a86a06a7265c
parent16162a5033593e017775eab640a3b9bf1b805c39 (diff)
api/libmm-glib/cli: add AudioPort and AudioFormat properties to the Call object
-rw-r--r--cli/mmcli-call.c23
-rw-r--r--docs/reference/libmm-glib/libmm-glib-sections.txt32
-rw-r--r--introspection/org.freedesktop.ModemManager1.Call.xml39
-rw-r--r--libmm-glib/Makefile.am3
-rw-r--r--libmm-glib/mm-call-audio-format.c276
-rw-r--r--libmm-glib/mm-call-audio-format.h88
-rw-r--r--libmm-glib/mm-call.c188
-rw-r--r--libmm-glib/mm-call.h10
-rw-r--r--src/mm-base-call.c15
-rw-r--r--src/mm-base-call.h6
10 files changed, 678 insertions, 2 deletions
diff --git a/cli/mmcli-call.c b/cli/mmcli-call.c
index 5991d073..09cf0871 100644
--- a/cli/mmcli-call.c
+++ b/cli/mmcli-call.c
@@ -145,6 +145,12 @@ mmcli_call_shutdown (void)
static void
print_call_info (MMCall *call)
{
+ const gchar *audio_port;
+ MMCallAudioFormat *audio_format;
+
+ audio_port = mm_call_get_audio_port (call);
+ audio_format = mm_call_peek_audio_format (call);
+
/* Not the best thing to do, as we may be doing _get() calls twice, but
* easiest to maintain */
#undef VALIDATE
@@ -161,6 +167,23 @@ print_call_info (MMCall *call)
if (mm_call_get_state_reason(call) != MM_CALL_STATE_REASON_UNKNOWN)
g_print (" | state reason: '%s'\n",
mm_call_state_reason_get_string(mm_call_get_state_reason (call)));
+
+ if (audio_port)
+ g_print (" | audio port: '%s'\n", VALIDATE (audio_port));
+
+ if (audio_format) {
+ guint rate = mm_call_audio_format_get_rate (audio_format);
+ gchar *rate_str = rate ? g_strdup_printf ("%u", rate) : NULL;
+
+ g_print (" -------------------------\n"
+ " Audio Format | encoding: '%s'\n"
+ " | resolution: '%s'\n"
+ " | rate: '%s'\n",
+ VALIDATE (mm_call_audio_format_get_encoding (audio_format)),
+ VALIDATE (mm_call_audio_format_get_resolution (audio_format)),
+ VALIDATE (rate_str));
+ g_free (rate_str);
+ }
}
static void
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index f41f4a7e..65d8e364 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -1257,6 +1257,10 @@ mm_call_dup_number
mm_call_get_direction
mm_call_get_state
mm_call_get_state_reason
+mm_call_get_audio_port
+mm_call_dup_audio_port
+mm_call_get_audio_format
+mm_call_peek_audio_format
<SUBSECTION Methods>
mm_call_start
mm_call_start_finish
@@ -1342,6 +1346,34 @@ mm_pco_get_type
</SECTION>
<SECTION>
+<FILE>mm-call-audio-format</FILE>
+<TITLE>MMCallAudioFormat</TITLE>
+MMCallAudioFormat
+<SUBSECTION Getters>
+mm_call_audio_format_get_encoding
+mm_call_audio_format_get_resolution
+mm_call_audio_format_get_rate
+<SUBSECTION Private>
+mm_call_audio_format_get_dictionary
+mm_call_audio_format_new
+mm_call_audio_format_new_from_dictionary
+mm_call_audio_format_set_encoding
+mm_call_audio_format_set_resolution
+mm_call_audio_format_set_rate
+mm_call_audio_format_dup
+<SUBSECTION Standard>
+MMCallAudioFormatClass
+MMCallAudioFormatPrivate
+MM_CALL_AUDIO_FORMAT
+MM_CALL_AUDIO_FORMAT_CLASS
+MM_CALL_AUDIO_FORMAT_GET_CLASS
+MM_IS_CALL_AUDIO_FORMAT
+MM_IS_CALL_AUDIO_FORMAT_CLASS
+MM_TYPE_CALL_AUDIO_FORMAT
+mm_call_audio_format_get_type
+</SECTION>
+
+<SECTION>
<FILE>mm-enums-types</FILE>
<TITLE>Flags and Enumerations</TITLE>
mm_bearer_ip_method_get_string
diff --git a/introspection/org.freedesktop.ModemManager1.Call.xml b/introspection/org.freedesktop.ModemManager1.Call.xml
index f095726b..f53f5b7b 100644
--- a/introspection/org.freedesktop.ModemManager1.Call.xml
+++ b/introspection/org.freedesktop.ModemManager1.Call.xml
@@ -111,5 +111,44 @@
The remote phone number.
-->
<property name="Number" type="s" access="read" />
+
+ <!--
+ AudioPort:
+
+ If call audio is routed via the host, the name of the kernel device that
+ provides the audio. For example, with certain Huawei USB modems, this
+ property might be "ttyUSB2" indicating audio is available via ttyUSB2 in
+ the format described by the AudioFormat property.
+ -->
+ <property name="AudioPort" type="s" access="read" />
+
+ <!--
+ AudioFormat:
+
+ If call audio is routed via the host, a description of the audio format
+ supported by the audio port.
+
+ This property may include the following items:
+ <variablelist>
+ <varlistentry><term><literal>"encoding"</literal></term>
+ <listitem>
+ The audio encoding format. For example, "pcm" for PCM audio.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"resolution"</literal></term>
+ <listitem>
+ The sampling precision and its encoding format. For example,
+ "s16le" for signed 16-bit little-endian samples.
+ </listitem>
+ </varlistentry>
+ <varlistentry><term><literal>"rate"</literal></term>
+ <listitem>
+ The sampling rate as an unsigned integer. For example, 8000 for
+ 8000hz.
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ -->
+ <property name="AudioFormat" type="a{sv}" access="read" />
</interface>
</node>
diff --git a/libmm-glib/Makefile.am b/libmm-glib/Makefile.am
index 4c890592..0ebfd7e2 100644
--- a/libmm-glib/Makefile.am
+++ b/libmm-glib/Makefile.am
@@ -85,6 +85,8 @@ libmm_glib_la_SOURCES = \
mm-kernel-event-properties.c \
mm-pco.h \
mm-pco.c \
+ mm-call-audio-format.h \
+ mm-call-audio-format.c \
$(NULL)
libmm_glib_la_CPPFLAGS = \
@@ -155,6 +157,7 @@ include_HEADERS = \
mm-signal.h \
mm-kernel-event-properties.h \
mm-pco.h \
+ mm-call-audio-format.h \
$(NULL)
CLEANFILES =
diff --git a/libmm-glib/mm-call-audio-format.c b/libmm-glib/mm-call-audio-format.c
new file mode 100644
index 00000000..a5e5126a
--- /dev/null
+++ b/libmm-glib/mm-call-audio-format.c
@@ -0,0 +1,276 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ */
+
+#include <string.h>
+
+#include "mm-errors-types.h"
+#include "mm-call-audio-format.h"
+
+/**
+ * SECTION: mm-call-audio-format
+ * @title: MMCallAudioFormat
+ * @short_description: Helper object to handle voice call audio formats.
+ *
+ * The #MMCallAudioFormat is an object handling the voice call audio format
+ * which describes how to send/receive voice call audio from the host.
+ *
+ * This object is retrieved with either mm_call_get_audio_format() or
+ * mm_call_peek_audio_format().
+ */
+
+G_DEFINE_TYPE (MMCallAudioFormat, mm_call_audio_format, G_TYPE_OBJECT)
+
+#define PROPERTY_ENCODING "encoding"
+#define PROPERTY_RESOLUTION "resolution"
+#define PROPERTY_RATE "rate"
+
+struct _MMCallAudioFormatPrivate {
+ gchar *encoding;
+ gchar *resolution;
+ guint rate;
+};
+
+/*****************************************************************************/
+
+/**
+ * mm_call_audio_format_get_encoding:
+ * @self: a #MMCallAudioFormat.
+ *
+ * Gets the encoding of the audio format. For example, "pcm" for PCM-encoded
+ * audio.
+ *
+ * Returns: a string with the encoding, or #NULL if unknown. Do not free the returned value, it is owned by @self.
+ */
+const gchar *
+mm_call_audio_format_get_encoding (MMCallAudioFormat *self)
+{
+ g_return_val_if_fail (MM_IS_CALL_AUDIO_FORMAT (self), NULL);
+
+ return self->priv->encoding;
+}
+
+void
+mm_call_audio_format_set_encoding (MMCallAudioFormat *self,
+ const gchar *encoding)
+{
+ g_return_if_fail (MM_IS_CALL_AUDIO_FORMAT (self));
+
+ g_free (self->priv->encoding);
+ self->priv->encoding = g_strdup (encoding);
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_call_audio_format_get_resolution:
+ * @self: a #MMCallAudioFormat.
+ *
+ * Gets the resolution of the audio format. For example, "s16le" for signed
+ * 16-bit little-endian audio sampling resolution.
+ *
+ * Returns: a string with the resolution, or #NULL if unknown. Do not free the returned value, it is owned by @self.
+ */
+const gchar *
+mm_call_audio_format_get_resolution (MMCallAudioFormat *self)
+{
+ g_return_val_if_fail (MM_IS_CALL_AUDIO_FORMAT (self), NULL);
+
+ return self->priv->resolution;
+}
+
+void
+mm_call_audio_format_set_resolution (MMCallAudioFormat *self,
+ const gchar *resolution)
+{
+ g_return_if_fail (MM_IS_CALL_AUDIO_FORMAT (self));
+
+ g_free (self->priv->resolution);
+ self->priv->resolution = g_strdup (resolution);
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_call_audio_format_get_rate:
+ * @self: a #MMCallAudioFormat.
+ *
+ * Gets the sampling rate of the audio format. For example, 8000 for an 8000hz
+ * sampling rate.
+ *
+ * Returns: the sampling rate, or 0 if unknown.
+ */
+guint
+mm_call_audio_format_get_rate (MMCallAudioFormat *self)
+{
+ g_return_val_if_fail (MM_IS_CALL_AUDIO_FORMAT (self), 0);
+
+ return self->priv->rate;
+}
+
+void
+mm_call_audio_format_set_rate (MMCallAudioFormat *self,
+ guint rate)
+{
+ g_return_if_fail (MM_IS_CALL_AUDIO_FORMAT (self));
+
+ self->priv->rate = rate;
+}
+
+/*****************************************************************************/
+
+GVariant *
+mm_call_audio_format_get_dictionary (MMCallAudioFormat *self)
+{
+ GVariantBuilder builder;
+
+ /* We do allow NULL */
+ if (!self)
+ return NULL;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ if (self) {
+ if (self->priv->encoding)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_ENCODING,
+ g_variant_new_string (self->priv->encoding));
+
+ if (self->priv->resolution)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_RESOLUTION,
+ g_variant_new_string (self->priv->resolution));
+
+ if (self->priv->rate)
+ g_variant_builder_add (&builder,
+ "{sv}",
+ PROPERTY_RATE,
+ g_variant_new_uint32 (self->priv->rate));
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/*****************************************************************************/
+
+MMCallAudioFormat *
+mm_call_audio_format_new_from_dictionary (GVariant *dictionary,
+ GError **error)
+{
+ GVariantIter iter;
+ gchar *key;
+ GVariant *value;
+ MMCallAudioFormat *self;
+
+ self = mm_call_audio_format_new ();
+ if (!dictionary)
+ return self;
+
+ if (!g_variant_is_of_type (dictionary, G_VARIANT_TYPE ("a{sv}"))) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Cannot create call audio format from dictionary: "
+ "invalid variant type received");
+ g_object_unref (self);
+ return NULL;
+ }
+
+ g_variant_iter_init (&iter, dictionary);
+ while (g_variant_iter_next (&iter, "{sv}", &key, &value)) {
+ if (g_str_equal (key, PROPERTY_ENCODING))
+ mm_call_audio_format_set_encoding (
+ self,
+ g_variant_get_string (value, NULL));
+ else if (g_str_equal (key, PROPERTY_RESOLUTION))
+ mm_call_audio_format_set_resolution (
+ self,
+ g_variant_get_string (value, NULL));
+ else if (g_str_equal (key, PROPERTY_RATE))
+ mm_call_audio_format_set_rate (
+ self,
+ g_variant_get_uint32 (value));
+
+ g_free (key);
+ g_variant_unref (value);
+ }
+
+ return self;
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_call_audio_format_dup:
+ * @orig: a #MMCallAudioFormat
+ *
+ * Creates a copy of @orig.
+ *
+ * Returns: (transfer full): a newly created #MMCallAudioFormat
+ */
+MMCallAudioFormat *
+mm_call_audio_format_dup (MMCallAudioFormat *orig)
+{
+ GVariant *dict;
+ MMCallAudioFormat *copy;
+ GError *error = NULL;
+
+ g_return_val_if_fail (MM_IS_CALL_AUDIO_FORMAT (orig), NULL);
+
+ dict = mm_call_audio_format_get_dictionary (orig);
+ copy = mm_call_audio_format_new_from_dictionary (dict, &error);
+ g_assert_no_error (error);
+ g_variant_unref (dict);
+
+ return copy;
+}
+
+/*****************************************************************************/
+
+MMCallAudioFormat *
+mm_call_audio_format_new (void)
+{
+ return (MM_CALL_AUDIO_FORMAT (
+ g_object_new (MM_TYPE_CALL_AUDIO_FORMAT, NULL)));
+}
+
+static void
+mm_call_audio_format_init (MMCallAudioFormat *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self),
+ MM_TYPE_CALL_AUDIO_FORMAT,
+ MMCallAudioFormatPrivate);
+}
+
+static void
+finalize (GObject *object)
+{
+ MMCallAudioFormat *self = MM_CALL_AUDIO_FORMAT (object);
+
+ g_free (self->priv->encoding);
+ g_free (self->priv->resolution);
+
+ G_OBJECT_CLASS (mm_call_audio_format_parent_class)->finalize (object);
+}
+
+static void
+mm_call_audio_format_class_init (MMCallAudioFormatClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (MMCallAudioFormatPrivate));
+
+ object_class->finalize = finalize;
+}
diff --git a/libmm-glib/mm-call-audio-format.h b/libmm-glib/mm-call-audio-format.h
new file mode 100644
index 00000000..f6da710a
--- /dev/null
+++ b/libmm-glib/mm-call-audio-format.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ */
+
+#ifndef MM_CALL_AUDIO_FORMAT_H
+#define MM_CALL_AUDIO_FORMAT_H
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#include <ModemManager.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MM_TYPE_CALL_AUDIO_FORMAT (mm_call_audio_format_get_type ())
+#define MM_CALL_AUDIO_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_CALL_AUDIO_FORMAT, MMCallAudioFormat))
+#define MM_CALL_AUDIO_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_CALL_AUDIO_FORMAT, MMCallAudioFormatClass))
+#define MM_IS_CALL_AUDIO_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_CALL_AUDIO_FORMAT))
+#define MM_IS_CALL_AUDIO_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_CALL_AUDIO_FORMAT))
+#define MM_CALL_AUDIO_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_CALL_AUDIO_FORMAT, MMCallAudioFormatClass))
+
+typedef struct _MMCallAudioFormat MMCallAudioFormat;
+typedef struct _MMCallAudioFormatClass MMCallAudioFormatClass;
+typedef struct _MMCallAudioFormatPrivate MMCallAudioFormatPrivate;
+
+/**
+ * MMCallAudioFormat:
+ *
+ * The #MMCallAudioFormat structure contains private data and should
+ * only be accessed using the provided API.
+ */
+struct _MMCallAudioFormat {
+ /*< private >*/
+ GObject parent;
+ MMCallAudioFormatPrivate *priv;
+};
+
+struct _MMCallAudioFormatClass {
+ /*< private >*/
+ GObjectClass parent;
+};
+
+GType mm_call_audio_format_get_type (void);
+
+const gchar *mm_call_audio_format_get_encoding (MMCallAudioFormat *self);
+const gchar *mm_call_audio_format_get_resolution (MMCallAudioFormat *self);
+guint mm_call_audio_format_get_rate (MMCallAudioFormat *self);
+
+/*****************************************************************************/
+/* ModemManager/libmm-glib/mmcli specific methods */
+
+#if defined (_LIBMM_INSIDE_MM) || \
+ defined (_LIBMM_INSIDE_MMCLI) || \
+ defined (LIBMM_GLIB_COMPILATION)
+
+MMCallAudioFormat *mm_call_audio_format_new (void);
+MMCallAudioFormat *mm_call_audio_format_new_from_dictionary (GVariant *dictionary,
+ GError **error);
+
+MMCallAudioFormat *mm_call_audio_format_dup (MMCallAudioFormat *orig);
+
+void mm_call_audio_format_set_encoding (MMCallAudioFormat *self,
+ const gchar *encoding);
+void mm_call_audio_format_set_resolution (MMCallAudioFormat *self,
+ const gchar *resolution);
+void mm_call_audio_format_set_rate (MMCallAudioFormat *self,
+ guint rate);
+
+GVariant *mm_call_audio_format_get_dictionary (MMCallAudioFormat *self);
+
+#endif
+
+G_END_DECLS
+
+#endif /* MM_CALL_AUDIO_FORMAT_H */
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;
}
diff --git a/libmm-glib/mm-call.h b/libmm-glib/mm-call.h
index a5aeb730..baf51cc4 100644
--- a/libmm-glib/mm-call.h
+++ b/libmm-glib/mm-call.h
@@ -26,7 +26,7 @@
#include <ModemManager.h>
#include "mm-gdbus-call.h"
-#include "mm-call-properties.h"
+#include "mm-call-audio-format.h"
G_BEGIN_DECLS
@@ -39,6 +39,7 @@ G_BEGIN_DECLS
typedef struct _MMCall MMCall;
typedef struct _MMCallClass MMCallClass;
+typedef struct _MMCallPrivate MMCallPrivate;
/**
* MMCall:
@@ -49,7 +50,7 @@ typedef struct _MMCallClass MMCallClass;
struct _MMCall {
/*< private >*/
MmGdbusCallProxy parent;
- gpointer unused;
+ MMCallPrivate *priv;
};
struct _MMCallClass {
@@ -71,6 +72,11 @@ MMCallStateReason mm_call_get_state_reason (MMCall *self);
MMCallDirection mm_call_get_direction (MMCall *self);
+const gchar *mm_call_get_audio_port (MMCall *self);
+gchar *mm_call_dup_audio_port (MMCall *self);
+
+MMCallAudioFormat *mm_call_get_audio_format (MMCall *self);
+MMCallAudioFormat *mm_call_peek_audio_format(MMCall *self);
void mm_call_start (MMCall *self,
diff --git a/src/mm-base-call.c b/src/mm-base-call.c
index c0fada6e..5637ddcf 100644
--- a/src/mm-base-call.c
+++ b/src/mm-base-call.c
@@ -724,6 +724,21 @@ mm_base_call_received_dtmf (MMBaseCall *self,
mm_gdbus_call_emit_dtmf_received (MM_GDBUS_CALL (self), dtmf);
}
+void
+mm_base_call_set_audio_port (MMBaseCall *self, const gchar *port)
+{
+ mm_gdbus_call_set_audio_port (MM_GDBUS_CALL (self), port);
+}
+
+void
+mm_base_call_set_audio_format (MMBaseCall *self,
+ MMCallAudioFormat *audio_format)
+{
+ mm_gdbus_call_set_audio_format (
+ MM_GDBUS_CALL (self),
+ mm_call_audio_format_get_dictionary (audio_format));
+}
+
/*****************************************************************************/
/* Start the CALL */
diff --git a/src/mm-base-call.h b/src/mm-base-call.h
index 0ef3ffcf..f68e9f6b 100644
--- a/src/mm-base-call.h
+++ b/src/mm-base-call.h
@@ -23,6 +23,7 @@
#include <libmm-glib.h>
#include "mm-base-modem.h"
+#include "mm-call-audio-format.h"
#define MM_TYPE_BASE_CALL (mm_base_call_get_type ())
#define MM_BASE_CALL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BASE_CALL, MMBaseCall))
@@ -104,6 +105,11 @@ void mm_base_call_change_state (MMBaseCall *self,
MMCallState new_state,
MMCallStateReason reason);
+void mm_base_call_set_audio_port (MMBaseCall *self,
+ const gchar *port);
+void mm_base_call_set_audio_format (MMBaseCall *self,
+ MMCallAudioFormat *audio_format);
+
void mm_base_call_received_dtmf (MMBaseCall *self,
const gchar *dtmf);