aboutsummaryrefslogtreecommitdiff
path: root/src/mm-base-call.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mm-base-call.c')
-rw-r--r--src/mm-base-call.c194
1 files changed, 193 insertions, 1 deletions
diff --git a/src/mm-base-call.c b/src/mm-base-call.c
index bc4f0311..32f1e8fb 100644
--- a/src/mm-base-call.c
+++ b/src/mm-base-call.c
@@ -368,6 +368,111 @@ handle_hangup (MMBaseCall *self,
/*****************************************************************************/
+/* Send tone (DBus call handling) */
+
+typedef struct {
+ MMBaseCall *self;
+ MMBaseModem *modem;
+ GDBusMethodInvocation *invocation;
+ gchar *tone;
+} HandleSendToneContext;
+
+static void
+handle_send_tone_context_free (HandleSendToneContext *ctx)
+{
+ g_object_unref (ctx->invocation);
+ g_object_unref (ctx->modem);
+ g_object_unref (ctx->self);
+ g_free(ctx->tone);
+ g_free (ctx);
+}
+
+static void
+handle_send_tone_ready (MMBaseCall *self,
+ GAsyncResult *res,
+ HandleSendToneContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!MM_BASE_CALL_GET_CLASS (self)->send_tone_finish (self, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ } else {
+ mm_gdbus_call_complete_send_tone (MM_GDBUS_CALL (ctx->self), ctx->invocation);
+ }
+
+ handle_send_tone_context_free (ctx);
+}
+
+static void
+handle_send_tone_auth_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ HandleSendToneContext *ctx)
+{
+ MMCallState state;
+ GError *error = NULL;
+
+ if (!mm_base_modem_authorize_finish (modem, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_send_tone_context_free (ctx);
+ return;
+ }
+
+ state = mm_gdbus_call_get_state (MM_GDBUS_CALL (ctx->self));
+
+ /* Check if we do support doing it */
+ if (!MM_BASE_CALL_GET_CLASS (ctx->self)->send_tone ||
+ !MM_BASE_CALL_GET_CLASS (ctx->self)->send_tone_finish) {
+ g_dbus_method_invocation_return_error (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "SendToneing call is not supported by this modem");
+ handle_send_tone_context_free (ctx);
+ return;
+ }
+
+ /* We can only send_tone when call is in ACTIVE state */
+ if (state != MM_CALL_STATE_ACTIVE ){
+ g_dbus_method_invocation_return_error (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "This call was not active, cannot send_tone ");
+ handle_send_tone_context_free (ctx);
+ return;
+ }
+
+ mm_dbg("[%s:%d] Tone string: '%s'", __func__, __LINE__, ctx->tone);
+ MM_BASE_CALL_GET_CLASS (ctx->self)->send_tone (ctx->self, ctx->tone,
+ (GAsyncReadyCallback)handle_send_tone_ready,
+ ctx);
+}
+
+static gboolean
+handle_send_tone (MMBaseCall *self,
+ GDBusMethodInvocation *invocation,
+ const gchar *tone)
+{
+ HandleSendToneContext *ctx;
+
+ ctx = g_new0 (HandleSendToneContext, 1);
+ ctx->self = g_object_ref (self);
+ ctx->invocation = g_object_ref (invocation);
+
+ mm_dbg("[%s:%d] Tone string: '%s'", __func__, __LINE__, tone);
+ ctx->tone = g_strdup(tone);
+ g_object_get (self,
+ MM_BASE_CALL_MODEM, &ctx->modem,
+ NULL);
+
+ mm_base_modem_authorize (ctx->modem,
+ invocation,
+ MM_AUTHORIZATION_VOICE,
+ (GAsyncReadyCallback)handle_send_tone_auth_ready,
+ ctx);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
void
mm_base_call_export (MMBaseCall *self)
{
@@ -409,6 +514,10 @@ call_dbus_export (MMBaseCall *self)
"handle-hangup",
G_CALLBACK (handle_hangup),
NULL);
+ g_signal_connect (self,
+ "handle-send-tone",
+ G_CALLBACK (handle_send_tone),
+ NULL);
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self),
@@ -457,6 +566,11 @@ mm_base_call_change_state(MMBaseCall *self, MMCallState new_state, MMCallStateRe
reason);
}
+void mm_base_call_received_dtmf (MMBaseCall *self, gchar *tone)
+{
+ mm_gdbus_call_emit_tone_received(MM_GDBUS_CALL (self), tone);
+}
+
/*****************************************************************************/
/* Start the CALL */
@@ -671,7 +785,6 @@ call_accept (MMBaseCall *self,
/*****************************************************************************/
-
/* Hangup the CALL */
typedef struct {
@@ -760,6 +873,83 @@ call_hangup (MMBaseCall *self,
}
/*****************************************************************************/
+/* Send DTMF tone to call */
+
+typedef struct {
+ MMBaseCall *self;
+ MMBaseModem *modem;
+ GSimpleAsyncResult *result;
+} CallSendToneContext;
+
+static void
+call_send_tone_context_complete_and_free (CallSendToneContext *ctx)
+{
+ g_simple_async_result_complete_in_idle (ctx->result);
+ g_object_unref (ctx->result);
+ g_object_unref (ctx->modem);
+ g_object_unref (ctx->self);
+ g_free (ctx);
+}
+
+static gboolean
+call_send_tone_finish (MMBaseCall *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+}
+
+static void
+call_send_tone_ready (MMBaseModem *modem,
+ GAsyncResult *res,
+ CallSendToneContext *ctx)
+{
+ GError *error = NULL;
+ const gchar *response = NULL;
+
+ response = mm_base_modem_at_command_finish (modem, res, &error);
+ if (error) {
+ mm_dbg ("Couldn't send_tone: '%s'", error->message);
+ g_simple_async_result_take_error (ctx->result, error);
+ call_send_tone_context_complete_and_free (ctx);
+ return;
+ }
+
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ call_send_tone_context_complete_and_free (ctx);
+}
+
+static void
+call_send_tone (MMBaseCall *self,
+ const gchar *tone,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CallSendToneContext *ctx;
+ gchar *cmd;
+
+ /* Setup the context */
+ ctx = g_new0 (CallSendToneContext, 1);
+ ctx->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ call_send_tone);
+ ctx->self = g_object_ref (self);
+ ctx->modem = g_object_ref (self->priv->modem);
+
+ mm_dbg("[%s:%d] Tone string: '%s'", __func__, __LINE__, tone);
+ cmd = g_strdup_printf ("AT+VTS=%c",tone[0]);
+ mm_base_modem_at_command (ctx->modem,
+ cmd,
+ 3,
+ FALSE,
+ (GAsyncReadyCallback)call_send_tone_ready,
+ ctx);
+
+ g_free (cmd);
+}
+
+/*****************************************************************************/
typedef struct {
MMBaseCall *self;
MMBaseModem *modem;
@@ -1018,6 +1208,8 @@ mm_base_call_class_init (MMBaseCallClass *klass)
klass->hangup_finish = call_hangup_finish;
klass->delete = call_delete;
klass->delete_finish = call_delete_finish;
+ klass->send_tone = call_send_tone;
+ klass->send_tone_finish = call_send_tone_finish;
properties[PROP_CONNECTION] =