call: allow setting DTMF tone duration at call creation time
Instead of hard-coding a 500ms DTMF tone duration, let applications use a specific duration at call setup time. Signed-off-by: Dan Williams <dan@ioncontrol.co>
This commit is contained in:
@@ -105,7 +105,7 @@
|
|||||||
SendDtmf:
|
SendDtmf:
|
||||||
@dtmf: DTMF tone identifier [0-9A-D*#].
|
@dtmf: DTMF tone identifier [0-9A-D*#].
|
||||||
|
|
||||||
Send a DTMF tone (Dual Tone Multi-Frequency) (only on supported modem).
|
Send a DTMF tone (Dual Tone Multi-Frequency) (only on supported modems).
|
||||||
|
|
||||||
Applicable only if state is <link linkend="MM-CALL-STATE-ACTIVE:CAPS"><constant>MM_CALL_STATE_ACTIVE</constant></link>.
|
Applicable only if state is <link linkend="MM-CALL-STATE-ACTIVE:CAPS"><constant>MM_CALL_STATE_ACTIVE</constant></link>.
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
DtmfReceived:
|
DtmfReceived:
|
||||||
@dtmf: DTMF tone identifier [0-9A-D*#].
|
@dtmf: DTMF tone identifier [0-9A-D*#].
|
||||||
|
|
||||||
Emitted when a DTMF tone is received (only on supported modem)
|
Emitted when a DTMF tone is received (only on supported modems)
|
||||||
|
|
||||||
Since: 1.6
|
Since: 1.6
|
||||||
-->
|
-->
|
||||||
@@ -232,5 +232,18 @@
|
|||||||
Since: 1.10
|
Since: 1.10
|
||||||
-->
|
-->
|
||||||
<property name="AudioFormat" type="a{sv}" access="read" />
|
<property name="AudioFormat" type="a{sv}" access="read" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
DtmfToneDuration:
|
||||||
|
|
||||||
|
The length of DTMF tones, in milliseconds. Valid range is 100ms to
|
||||||
|
1000ms and is rounded up to the next 100ms if not evenly divisble
|
||||||
|
by 100. Set the duration by passing this property to
|
||||||
|
<link linkend="gdbus-method-org-freedesktop-ModemManager1-Voice.CreateCall">CreateCall()</link>
|
||||||
|
at call creation time.
|
||||||
|
|
||||||
|
Since: 1.26
|
||||||
|
-->
|
||||||
|
<property name="DtmfToneDuration" type="u" access="read" />
|
||||||
</interface>
|
</interface>
|
||||||
</node>
|
</node>
|
||||||
|
|||||||
@@ -44,10 +44,12 @@
|
|||||||
|
|
||||||
G_DEFINE_TYPE (MMCallProperties, mm_call_properties, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (MMCallProperties, mm_call_properties, G_TYPE_OBJECT)
|
||||||
|
|
||||||
#define PROPERTY_NUMBER "number"
|
#define PROPERTY_NUMBER "number"
|
||||||
|
#define PROPERTY_DTMF_TONE_DURATION "dtmf-tone-duration"
|
||||||
|
|
||||||
struct _MMCallPropertiesPrivate {
|
struct _MMCallPropertiesPrivate {
|
||||||
gchar *number;
|
gchar *number;
|
||||||
|
guint dtmf_tone_duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -92,6 +94,43 @@ mm_call_properties_get_number (MMCallProperties *self)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_call_properties_set_dtmf_tone_duration:
|
||||||
|
* @self: A #MMCallProperties.
|
||||||
|
* @duration_ms: The desired duration of DTMF tones in milliseconds.
|
||||||
|
*
|
||||||
|
* Sets the DTMF tone duration if supported by the modem.
|
||||||
|
*
|
||||||
|
* Since: 1.26
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mm_call_properties_set_dtmf_tone_duration (MMCallProperties *self,
|
||||||
|
const guint duration_ms)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MM_IS_CALL_PROPERTIES (self));
|
||||||
|
|
||||||
|
self->priv->dtmf_tone_duration = duration_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mm_call_properties_get_dtmf_tone_duration:
|
||||||
|
* @self: A #MMCallProperties.
|
||||||
|
*
|
||||||
|
* Gets the desired DTMF tone duration in milliseconds.
|
||||||
|
*
|
||||||
|
* Returns: the DTMF tone duration in milliseconds.
|
||||||
|
*
|
||||||
|
* Since: 1.26
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
mm_call_properties_get_dtmf_tone_duration (MMCallProperties *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MM_IS_CALL_PROPERTIES (self), 0);
|
||||||
|
|
||||||
|
return self->priv->dtmf_tone_duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* mm_call_properties_get_dictionary: (skip)
|
* mm_call_properties_get_dictionary: (skip)
|
||||||
*/
|
*/
|
||||||
@@ -114,6 +153,12 @@ mm_call_properties_get_dictionary (MMCallProperties *self)
|
|||||||
PROPERTY_NUMBER,
|
PROPERTY_NUMBER,
|
||||||
g_variant_new_string (self->priv->number));
|
g_variant_new_string (self->priv->number));
|
||||||
|
|
||||||
|
if (self->priv->dtmf_tone_duration)
|
||||||
|
g_variant_builder_add (&builder,
|
||||||
|
"{sv}",
|
||||||
|
PROPERTY_DTMF_TONE_DURATION,
|
||||||
|
g_variant_new_uint32 (self->priv->dtmf_tone_duration));
|
||||||
|
|
||||||
return g_variant_ref_sink (g_variant_builder_end (&builder));
|
return g_variant_ref_sink (g_variant_builder_end (&builder));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +171,18 @@ consume_string (MMCallProperties *self,
|
|||||||
{
|
{
|
||||||
if (g_str_equal (key, PROPERTY_NUMBER)) {
|
if (g_str_equal (key, PROPERTY_NUMBER)) {
|
||||||
mm_call_properties_set_number (self, value);
|
mm_call_properties_set_number (self, value);
|
||||||
|
} else if (g_str_equal (key, PROPERTY_DTMF_TONE_DURATION)) {
|
||||||
|
guint num;
|
||||||
|
|
||||||
|
if (!mm_get_uint_from_str (value, &num)) {
|
||||||
|
g_set_error (error,
|
||||||
|
MM_CORE_ERROR,
|
||||||
|
MM_CORE_ERROR_INVALID_ARGS,
|
||||||
|
"Failed to parse DTMF tone duration from value '%s'",
|
||||||
|
value);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
mm_call_properties_set_dtmf_tone_duration (self, num);
|
||||||
} else {
|
} else {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
MM_CORE_ERROR,
|
MM_CORE_ERROR,
|
||||||
@@ -189,11 +246,29 @@ consume_variant (MMCallProperties *properties,
|
|||||||
GVariant *value,
|
GVariant *value,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
if (g_str_equal (key, PROPERTY_NUMBER))
|
if (g_str_equal (key, PROPERTY_NUMBER)) {
|
||||||
|
if (!g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
MM_CORE_ERROR,
|
||||||
|
MM_CORE_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid properties dictionary; number not a string");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
mm_call_properties_set_number (
|
mm_call_properties_set_number (
|
||||||
properties,
|
properties,
|
||||||
g_variant_get_string (value, NULL));
|
g_variant_get_string (value, NULL));
|
||||||
else {
|
} else if (g_str_equal (key, PROPERTY_DTMF_TONE_DURATION)) {
|
||||||
|
if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
MM_CORE_ERROR,
|
||||||
|
MM_CORE_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid properties dictionary; dtmf-tone-duration not a uint32");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
mm_call_properties_set_dtmf_tone_duration (
|
||||||
|
properties,
|
||||||
|
g_variant_get_uint32 (value));
|
||||||
|
} else {
|
||||||
/* Set error */
|
/* Set error */
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
MM_CORE_ERROR,
|
MM_CORE_ERROR,
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ void mm_call_properties_set_number (MMCallProperties *self,
|
|||||||
const gchar *text);
|
const gchar *text);
|
||||||
const gchar *mm_call_properties_get_number (MMCallProperties *self);
|
const gchar *mm_call_properties_get_number (MMCallProperties *self);
|
||||||
|
|
||||||
|
void mm_call_properties_set_dtmf_tone_duration (MMCallProperties *self,
|
||||||
|
const guint duration_ms);
|
||||||
|
guint mm_call_properties_get_dtmf_tone_duration (MMCallProperties *self);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* ModemManager/libmm-glib/mmcli specific methods */
|
/* ModemManager/libmm-glib/mmcli specific methods */
|
||||||
|
|
||||||
|
|||||||
@@ -922,6 +922,20 @@ mm_base_call_set_multiparty (MMBaseCall *self,
|
|||||||
return mm_gdbus_call_set_multiparty (MM_GDBUS_CALL (self), multiparty);
|
return mm_gdbus_call_set_multiparty (MM_GDBUS_CALL (self), multiparty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
mm_base_call_get_dtmf_tone_duration (MMBaseCall *self)
|
||||||
|
{
|
||||||
|
return mm_dtmf_duration_normalize (mm_gdbus_call_get_dtmf_tone_duration (MM_GDBUS_CALL (self)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mm_base_call_set_dtmf_tone_duration (MMBaseCall *self,
|
||||||
|
guint duration_ms)
|
||||||
|
{
|
||||||
|
return mm_gdbus_call_set_dtmf_tone_duration (MM_GDBUS_CALL (self),
|
||||||
|
mm_dtmf_duration_normalize (duration_ms));
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Current call index, only applicable while the call is ongoing
|
/* Current call index, only applicable while the call is ongoing
|
||||||
* See 3GPP TS 22.030 [27], subclause 6.5.5.1.
|
* See 3GPP TS 22.030 [27], subclause 6.5.5.1.
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ typedef struct _MMBaseCall MMBaseCall;
|
|||||||
typedef struct _MMBaseCallClass MMBaseCallClass;
|
typedef struct _MMBaseCallClass MMBaseCallClass;
|
||||||
typedef struct _MMBaseCallPrivate MMBaseCallPrivate;
|
typedef struct _MMBaseCallPrivate MMBaseCallPrivate;
|
||||||
|
|
||||||
|
#define MM_CALL_DIRECTION "direction"
|
||||||
|
#define MM_CALL_NUMBER "number"
|
||||||
|
#define MM_CALL_DTMF_TONE_DURATION "dtmf-tone-duration"
|
||||||
|
|
||||||
#define MM_BASE_CALL_PATH "call-path"
|
#define MM_BASE_CALL_PATH "call-path"
|
||||||
#define MM_BASE_CALL_CONNECTION "call-connection"
|
#define MM_BASE_CALL_CONNECTION "call-connection"
|
||||||
#define MM_BASE_CALL_IFACE_MODEM_VOICE "call-iface-modem-voice"
|
#define MM_BASE_CALL_IFACE_MODEM_VOICE "call-iface-modem-voice"
|
||||||
@@ -129,4 +133,9 @@ void mm_base_call_received_dtmf (MMBaseCall *self,
|
|||||||
|
|
||||||
void mm_base_call_incoming_refresh (MMBaseCall *self);
|
void mm_base_call_incoming_refresh (MMBaseCall *self);
|
||||||
|
|
||||||
|
guint mm_base_call_get_dtmf_tone_duration (MMBaseCall *self);
|
||||||
|
|
||||||
|
void mm_base_call_set_dtmf_tone_duration (MMBaseCall *self,
|
||||||
|
guint duration_ms);
|
||||||
|
|
||||||
#endif /* MM_BASE_CALL_H */
|
#endif /* MM_BASE_CALL_H */
|
||||||
|
|||||||
@@ -12190,11 +12190,13 @@ modem_voice_load_call_list (MMIfaceModemVoice *self,
|
|||||||
static MMBaseCall *
|
static MMBaseCall *
|
||||||
modem_voice_create_call (MMIfaceModemVoice *self,
|
modem_voice_create_call (MMIfaceModemVoice *self,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number)
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration)
|
||||||
{
|
{
|
||||||
return mm_call_qmi_new (MM_BASE_MODEM (self),
|
return mm_call_qmi_new (MM_BASE_MODEM (self),
|
||||||
direction,
|
direction,
|
||||||
number);
|
number,
|
||||||
|
dtmf_tone_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
@@ -8899,7 +8899,8 @@ modem_voice_disable_unsolicited_events (MMIfaceModemVoice *self,
|
|||||||
static MMBaseCall *
|
static MMBaseCall *
|
||||||
modem_voice_create_call (MMIfaceModemVoice *_self,
|
modem_voice_create_call (MMIfaceModemVoice *_self,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number)
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration)
|
||||||
{
|
{
|
||||||
MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
|
MMBroadbandModem *self = MM_BROADBAND_MODEM (_self);
|
||||||
|
|
||||||
@@ -8907,6 +8908,7 @@ modem_voice_create_call (MMIfaceModemVoice *_self,
|
|||||||
G_OBJECT (self),
|
G_OBJECT (self),
|
||||||
direction,
|
direction,
|
||||||
number,
|
number,
|
||||||
|
dtmf_tone_duration,
|
||||||
/* If +CLCC is supported, we want no incoming timeout.
|
/* If +CLCC is supported, we want no incoming timeout.
|
||||||
* Also, we're able to support detailed call state updates without
|
* Also, we're able to support detailed call state updates without
|
||||||
* additional vendor-specific commands. */
|
* additional vendor-specific commands. */
|
||||||
|
|||||||
+66
-15
@@ -36,9 +36,18 @@
|
|||||||
|
|
||||||
G_DEFINE_TYPE (MMCallAt, mm_call_at, MM_TYPE_BASE_CALL)
|
G_DEFINE_TYPE (MMCallAt, mm_call_at, MM_TYPE_BASE_CALL)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FEATURE_SUPPORT_UNKNOWN,
|
||||||
|
FEATURE_NOT_SUPPORTED,
|
||||||
|
FEATURE_SUPPORTED,
|
||||||
|
} FeatureSupport;
|
||||||
|
|
||||||
struct _MMCallAtPrivate {
|
struct _MMCallAtPrivate {
|
||||||
/* The modem which owns this call */
|
/* The modem which owns this call */
|
||||||
MMBaseModem *modem;
|
MMBaseModem *modem;
|
||||||
|
|
||||||
|
/* DTMF support */
|
||||||
|
FeatureSupport vtd_supported;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -334,26 +343,66 @@ call_send_dtmf_ready (MMBaseModem *modem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
call_send_dtmf (MMBaseCall *_self,
|
send_dtmf_digit (MMCallAt *self,
|
||||||
const gchar *dtmf,
|
GTask *task,
|
||||||
GAsyncReadyCallback callback,
|
const gchar dtmf_digit)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
MMCallAt *self = MM_CALL_AT (_self);
|
g_autofree gchar *cmd = NULL;
|
||||||
GTask *task;
|
|
||||||
gchar *cmd;
|
|
||||||
|
|
||||||
task = g_task_new (self, NULL, callback, user_data);
|
cmd = g_strdup_printf ("AT+VTS=%c", dtmf_digit);
|
||||||
|
|
||||||
cmd = g_strdup_printf ("AT+VTS=%c", dtmf[0]);
|
|
||||||
mm_base_modem_at_command (self->priv->modem,
|
mm_base_modem_at_command (self->priv->modem,
|
||||||
cmd,
|
cmd,
|
||||||
3,
|
3,
|
||||||
FALSE,
|
FALSE,
|
||||||
(GAsyncReadyCallback)call_send_dtmf_ready,
|
(GAsyncReadyCallback)call_send_dtmf_ready,
|
||||||
task);
|
task);
|
||||||
|
}
|
||||||
|
|
||||||
g_free (cmd);
|
static void
|
||||||
|
call_dtmf_vtd_ready (MMBaseModem *modem,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GTask *task)
|
||||||
|
{
|
||||||
|
MMCallAt *self;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
gchar dtmf_digit;
|
||||||
|
|
||||||
|
self = g_task_get_source_object (task);
|
||||||
|
|
||||||
|
mm_base_modem_at_command_finish (modem, res, &error);
|
||||||
|
self->priv->vtd_supported = error ? FEATURE_NOT_SUPPORTED : FEATURE_SUPPORTED;
|
||||||
|
|
||||||
|
dtmf_digit = (gchar) GPOINTER_TO_UINT (g_task_get_task_data (task));
|
||||||
|
send_dtmf_digit (self, task, dtmf_digit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
call_send_dtmf (MMBaseCall *_self,
|
||||||
|
const gchar *dtmf,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MMCallAt *self = MM_CALL_AT (_self);
|
||||||
|
GTask *task;
|
||||||
|
g_autofree gchar *cmd = NULL;
|
||||||
|
|
||||||
|
task = g_task_new (self, NULL, callback, user_data);
|
||||||
|
|
||||||
|
if (self->priv->vtd_supported == FEATURE_NOT_SUPPORTED) {
|
||||||
|
send_dtmf_digit (self, task, dtmf[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_task_set_task_data (task, GUINT_TO_POINTER (dtmf[0]), NULL);
|
||||||
|
|
||||||
|
/* Otherwise try to set duration */
|
||||||
|
cmd = g_strdup_printf ("AT+VTD=%u", mm_base_call_get_dtmf_tone_duration (_self));
|
||||||
|
mm_base_modem_at_command (self->priv->modem,
|
||||||
|
cmd,
|
||||||
|
3,
|
||||||
|
FALSE,
|
||||||
|
(GAsyncReadyCallback)call_dtmf_vtd_ready,
|
||||||
|
task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -363,6 +412,7 @@ mm_call_at_new (MMBaseModem *modem,
|
|||||||
GObject *bind_to,
|
GObject *bind_to,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number,
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration,
|
||||||
gboolean skip_incoming_timeout,
|
gboolean skip_incoming_timeout,
|
||||||
gboolean supports_dialing_to_ringing,
|
gboolean supports_dialing_to_ringing,
|
||||||
gboolean supports_ringing_to_active)
|
gboolean supports_ringing_to_active)
|
||||||
@@ -370,10 +420,11 @@ mm_call_at_new (MMBaseModem *modem,
|
|||||||
MMBaseCall *call;
|
MMBaseCall *call;
|
||||||
|
|
||||||
call = MM_BASE_CALL (g_object_new (MM_TYPE_CALL_AT,
|
call = MM_BASE_CALL (g_object_new (MM_TYPE_CALL_AT,
|
||||||
MM_BASE_CALL_IFACE_MODEM_VOICE, modem,
|
MM_BASE_CALL_IFACE_MODEM_VOICE, modem,
|
||||||
MM_BIND_TO, bind_to,
|
MM_BIND_TO, bind_to,
|
||||||
"direction", direction,
|
MM_CALL_DIRECTION, direction,
|
||||||
"number", number,
|
MM_CALL_NUMBER, number,
|
||||||
|
MM_CALL_DTMF_TONE_DURATION, dtmf_tone_duration,
|
||||||
MM_BASE_CALL_SKIP_INCOMING_TIMEOUT, skip_incoming_timeout,
|
MM_BASE_CALL_SKIP_INCOMING_TIMEOUT, skip_incoming_timeout,
|
||||||
MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING, supports_dialing_to_ringing,
|
MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING, supports_dialing_to_ringing,
|
||||||
MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE, supports_ringing_to_active,
|
MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE, supports_ringing_to_active,
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ MMBaseCall *mm_call_at_new (MMBaseModem *modem,
|
|||||||
GObject *bind_to,
|
GObject *bind_to,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number,
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration,
|
||||||
gboolean skip_incoming_timeout,
|
gboolean skip_incoming_timeout,
|
||||||
gboolean supports_dialing_to_ringing,
|
gboolean supports_dialing_to_ringing,
|
||||||
gboolean supports_ringing_to_active);
|
gboolean supports_ringing_to_active);
|
||||||
|
|||||||
+14
-7
@@ -402,9 +402,12 @@ voice_start_continuous_dtmf_ready (QmiClientVoice *client,
|
|||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GTask *task)
|
GTask *task)
|
||||||
{
|
{
|
||||||
|
MMCallQmi *self;
|
||||||
g_autoptr(QmiMessageVoiceStartContinuousDtmfOutput) output = NULL;
|
g_autoptr(QmiMessageVoiceStartContinuousDtmfOutput) output = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
|
self = g_task_get_source_object (task);
|
||||||
|
|
||||||
output = qmi_client_voice_start_continuous_dtmf_finish (client, res, &error);
|
output = qmi_client_voice_start_continuous_dtmf_finish (client, res, &error);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
g_prefix_error (&error, "QMI operation failed: ");
|
g_prefix_error (&error, "QMI operation failed: ");
|
||||||
@@ -420,8 +423,10 @@ voice_start_continuous_dtmf_ready (QmiClientVoice *client,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable DTMF press after 500 ms */
|
/* Disable DTMF press after DTMF tone duration elapses */
|
||||||
g_timeout_add (500, (GSourceFunc) voice_stop_continuous_dtmf, task);
|
g_timeout_add (mm_base_call_get_dtmf_tone_duration (MM_BASE_CALL (self)),
|
||||||
|
(GSourceFunc) voice_stop_continuous_dtmf,
|
||||||
|
task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -489,15 +494,17 @@ call_send_dtmf (MMBaseCall *self,
|
|||||||
MMBaseCall *
|
MMBaseCall *
|
||||||
mm_call_qmi_new (MMBaseModem *modem,
|
mm_call_qmi_new (MMBaseModem *modem,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number)
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration)
|
||||||
{
|
{
|
||||||
MMBaseCall *call;
|
MMBaseCall *call;
|
||||||
|
|
||||||
call = MM_BASE_CALL (g_object_new (MM_TYPE_CALL_QMI,
|
call = MM_BASE_CALL (g_object_new (MM_TYPE_CALL_QMI,
|
||||||
MM_BASE_CALL_IFACE_MODEM_VOICE, modem,
|
MM_BASE_CALL_IFACE_MODEM_VOICE, modem,
|
||||||
MM_BIND_TO, modem,
|
MM_BIND_TO, modem,
|
||||||
"direction", direction,
|
MM_CALL_DIRECTION, direction,
|
||||||
"number", number,
|
MM_CALL_NUMBER, number,
|
||||||
|
MM_CALL_DTMF_TONE_DURATION, dtmf_tone_duration,
|
||||||
MM_BASE_CALL_SKIP_INCOMING_TIMEOUT, TRUE,
|
MM_BASE_CALL_SKIP_INCOMING_TIMEOUT, TRUE,
|
||||||
MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING, TRUE,
|
MM_BASE_CALL_SUPPORTS_DIALING_TO_RINGING, TRUE,
|
||||||
MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE, TRUE,
|
MM_BASE_CALL_SUPPORTS_RINGING_TO_ACTIVE, TRUE,
|
||||||
|
|||||||
+2
-1
@@ -49,6 +49,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMCallQmi, g_object_unref)
|
|||||||
|
|
||||||
MMBaseCall *mm_call_qmi_new (MMBaseModem *modem,
|
MMBaseCall *mm_call_qmi_new (MMBaseModem *modem,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number);
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration);
|
||||||
|
|
||||||
#endif /* MM_CALL_QMI_H */
|
#endif /* MM_CALL_QMI_H */
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ create_incoming_call (MMIfaceModemVoice *self,
|
|||||||
|
|
||||||
g_assert (MM_IFACE_MODEM_VOICE_GET_IFACE (self)->create_call != NULL);
|
g_assert (MM_IFACE_MODEM_VOICE_GET_IFACE (self)->create_call != NULL);
|
||||||
|
|
||||||
call = MM_IFACE_MODEM_VOICE_GET_IFACE (self)->create_call (self, MM_CALL_DIRECTION_INCOMING, number);
|
call = MM_IFACE_MODEM_VOICE_GET_IFACE (self)->create_call (self, MM_CALL_DIRECTION_INCOMING, number, 0);
|
||||||
update_audio_settings_in_call (self, call);
|
update_audio_settings_in_call (self, call);
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
@@ -173,6 +173,7 @@ create_outgoing_call_from_properties (MMIfaceModemVoice *self,
|
|||||||
{
|
{
|
||||||
MMBaseCall *call;
|
MMBaseCall *call;
|
||||||
const gchar *number;
|
const gchar *number;
|
||||||
|
guint dtmf_tone_duration;
|
||||||
|
|
||||||
/* Don't create CALL from properties if either number is missing */
|
/* Don't create CALL from properties if either number is missing */
|
||||||
number = mm_call_properties_get_number (properties) ;
|
number = mm_call_properties_get_number (properties) ;
|
||||||
@@ -184,9 +185,14 @@ create_outgoing_call_from_properties (MMIfaceModemVoice *self,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dtmf_tone_duration = mm_call_properties_get_dtmf_tone_duration (properties) ;
|
||||||
|
|
||||||
/* Create a call object as defined by the interface */
|
/* Create a call object as defined by the interface */
|
||||||
g_assert (MM_IFACE_MODEM_VOICE_GET_IFACE (self)->create_call != NULL);
|
g_assert (MM_IFACE_MODEM_VOICE_GET_IFACE (self)->create_call != NULL);
|
||||||
call = MM_IFACE_MODEM_VOICE_GET_IFACE (self)->create_call (self, MM_CALL_DIRECTION_OUTGOING, number);
|
call = MM_IFACE_MODEM_VOICE_GET_IFACE (self)->create_call (self,
|
||||||
|
MM_CALL_DIRECTION_OUTGOING,
|
||||||
|
number,
|
||||||
|
dtmf_tone_duration);
|
||||||
update_audio_settings_in_call (self, call);
|
update_audio_settings_in_call (self, call);
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ struct _MMIfaceModemVoiceInterface {
|
|||||||
/* Create call objects */
|
/* Create call objects */
|
||||||
MMBaseCall * (* create_call) (MMIfaceModemVoice *self,
|
MMBaseCall * (* create_call) (MMIfaceModemVoice *self,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number);
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration);
|
||||||
|
|
||||||
/* Hold and accept */
|
/* Hold and accept */
|
||||||
void (* hold_and_accept) (MMIfaceModemVoice *self,
|
void (* hold_and_accept) (MMIfaceModemVoice *self,
|
||||||
|
|||||||
@@ -5871,3 +5871,19 @@ mm_parse_cpin_response (const gchar *response,
|
|||||||
|
|
||||||
return MM_MODEM_LOCK_UNKNOWN;
|
return MM_MODEM_LOCK_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
guint
|
||||||
|
mm_dtmf_duration_normalize (guint duration_ms)
|
||||||
|
{
|
||||||
|
/* Default to 500ms */
|
||||||
|
if (duration_ms == 0)
|
||||||
|
return 500;
|
||||||
|
|
||||||
|
/* round to next highest 100ms */
|
||||||
|
if (duration_ms % 100)
|
||||||
|
duration_ms = ((duration_ms + 100) / 100) * 100;
|
||||||
|
|
||||||
|
return CLAMP (duration_ms, 100, 1000);
|
||||||
|
}
|
||||||
|
|||||||
@@ -643,4 +643,9 @@ guint mm_string_uint_map_lookup (const MMStringUintMap *map,
|
|||||||
MMModemLock mm_parse_cpin_response (const gchar *response,
|
MMModemLock mm_parse_cpin_response (const gchar *response,
|
||||||
gboolean expect_cpin_prefix);
|
gboolean expect_cpin_prefix);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/* Helper to clamp duration and round to next 100ms */
|
||||||
|
guint mm_dtmf_duration_normalize (guint duration_ms);
|
||||||
|
|
||||||
#endif /* MM_MODEM_HELPERS_H */
|
#endif /* MM_MODEM_HELPERS_H */
|
||||||
|
|||||||
@@ -998,7 +998,8 @@ mm_shared_cinterion_enable_location_gathering (MMIfaceModemLocation *self,
|
|||||||
MMBaseCall *
|
MMBaseCall *
|
||||||
mm_shared_cinterion_create_call (MMIfaceModemVoice *self,
|
mm_shared_cinterion_create_call (MMIfaceModemVoice *self,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number)
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration)
|
||||||
{
|
{
|
||||||
Private *priv;
|
Private *priv;
|
||||||
|
|
||||||
@@ -1010,6 +1011,7 @@ mm_shared_cinterion_create_call (MMIfaceModemVoice *self,
|
|||||||
G_OBJECT (self),
|
G_OBJECT (self),
|
||||||
direction,
|
direction,
|
||||||
number,
|
number,
|
||||||
|
dtmf_tone_duration,
|
||||||
/* When SLCC is supported we have support for detailed
|
/* When SLCC is supported we have support for detailed
|
||||||
* call list events via call list report URCs */
|
* call list events via call list report URCs */
|
||||||
TRUE, /* incoming timeout not required */
|
TRUE, /* incoming timeout not required */
|
||||||
@@ -1020,7 +1022,7 @@ mm_shared_cinterion_create_call (MMIfaceModemVoice *self,
|
|||||||
/* otherwise, run parent's generic base call logic */
|
/* otherwise, run parent's generic base call logic */
|
||||||
g_assert (priv->iface_modem_voice_parent);
|
g_assert (priv->iface_modem_voice_parent);
|
||||||
g_assert (priv->iface_modem_voice_parent->create_call);
|
g_assert (priv->iface_modem_voice_parent->create_call);
|
||||||
return priv->iface_modem_voice_parent->create_call (self, direction, number);
|
return priv->iface_modem_voice_parent->create_call (self, direction, number, dtmf_tone_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
@@ -105,7 +105,8 @@ gboolean mm_shared_cinterion_disable_location_gathering_finish (MMI
|
|||||||
|
|
||||||
MMBaseCall *mm_shared_cinterion_create_call (MMIfaceModemVoice *self,
|
MMBaseCall *mm_shared_cinterion_create_call (MMIfaceModemVoice *self,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number);
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration);
|
||||||
|
|
||||||
void mm_shared_cinterion_voice_check_support (MMIfaceModemVoice *self,
|
void mm_shared_cinterion_voice_check_support (MMIfaceModemVoice *self,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
|
|||||||
@@ -3879,12 +3879,14 @@ modem_voice_disable_unsolicited_events (MMIfaceModemVoice *self,
|
|||||||
static MMBaseCall *
|
static MMBaseCall *
|
||||||
create_call (MMIfaceModemVoice *self,
|
create_call (MMIfaceModemVoice *self,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number)
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration)
|
||||||
{
|
{
|
||||||
return mm_call_at_new (MM_BASE_MODEM (self),
|
return mm_call_at_new (MM_BASE_MODEM (self),
|
||||||
G_OBJECT (self),
|
G_OBJECT (self),
|
||||||
direction,
|
direction,
|
||||||
number,
|
number,
|
||||||
|
dtmf_tone_duration,
|
||||||
TRUE, /* skip_incoming_timeout */
|
TRUE, /* skip_incoming_timeout */
|
||||||
TRUE, /* supports_dialing_to_ringing */
|
TRUE, /* supports_dialing_to_ringing */
|
||||||
TRUE); /* supports_ringing_to_active) */
|
TRUE); /* supports_ringing_to_active) */
|
||||||
|
|||||||
@@ -1504,12 +1504,14 @@ modem_voice_setup_unsolicited_events (MMIfaceModemVoice *self,
|
|||||||
static MMBaseCall *
|
static MMBaseCall *
|
||||||
create_call (MMIfaceModemVoice *self,
|
create_call (MMIfaceModemVoice *self,
|
||||||
MMCallDirection direction,
|
MMCallDirection direction,
|
||||||
const gchar *number)
|
const gchar *number,
|
||||||
|
const guint dtmf_tone_duration)
|
||||||
{
|
{
|
||||||
return mm_call_at_new (MM_BASE_MODEM (self),
|
return mm_call_at_new (MM_BASE_MODEM (self),
|
||||||
G_OBJECT (self),
|
G_OBJECT (self),
|
||||||
direction,
|
direction,
|
||||||
number,
|
number,
|
||||||
|
dtmf_tone_duration,
|
||||||
TRUE, /* skip_incoming_timeout */
|
TRUE, /* skip_incoming_timeout */
|
||||||
TRUE, /* supports_dialing_to_ringing */
|
TRUE, /* supports_dialing_to_ringing */
|
||||||
TRUE); /* supports_ringing_to_active */
|
TRUE); /* supports_ringing_to_active */
|
||||||
|
|||||||
Reference in New Issue
Block a user