diff options
author | Marco Bascetta <marco.bascetta@sadel.it> | 2015-05-11 13:40:46 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2015-08-02 10:39:47 +0200 |
commit | 9874f10e1f27509219b6fe6b0a5374d04d1a3e3b (patch) | |
tree | 2b0b7715451408d90997a011941e94fa8eb84c5c /src/mm-base-call.c | |
parent | 8edead919343809d7c4bd7732a15c1a6c3912cba (diff) |
base-call,iface-modem-voice:: handle DTMF
Diffstat (limited to 'src/mm-base-call.c')
-rw-r--r-- | src/mm-base-call.c | 194 |
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] = |