diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-base-call.c | 111 | ||||
-rw-r--r-- | src/mm-base-call.h | 9 |
2 files changed, 120 insertions, 0 deletions
diff --git a/src/mm-base-call.c b/src/mm-base-call.c index e208b007..5b83b4e5 100644 --- a/src/mm-base-call.c +++ b/src/mm-base-call.c @@ -511,7 +511,114 @@ handle_accept (MMBaseCall *self, } /*****************************************************************************/ +/* Deflect call (DBus call handling) */ +typedef struct { + MMBaseCall *self; + MMBaseModem *modem; + GDBusMethodInvocation *invocation; + gchar *number; +} HandleDeflectContext; + +static void +handle_deflect_context_free (HandleDeflectContext *ctx) +{ + g_free (ctx->number); + g_object_unref (ctx->invocation); + g_object_unref (ctx->modem); + g_object_unref (ctx->self); + g_slice_free (HandleDeflectContext, ctx); +} + +static void +handle_deflect_ready (MMBaseCall *self, + GAsyncResult *res, + HandleDeflectContext *ctx) +{ + GError *error = NULL; + + if (!MM_BASE_CALL_GET_CLASS (self)->deflect_finish (self, res, &error)) { + mm_base_call_change_state (self, MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_ERROR); + g_dbus_method_invocation_take_error (ctx->invocation, error); + handle_deflect_context_free (ctx); + return; + } + + mm_info ("call is deflected to '%s'", ctx->number); + mm_base_call_change_state (ctx->self, MM_CALL_STATE_TERMINATED, MM_CALL_STATE_REASON_DEFLECTED); + mm_gdbus_call_complete_deflect (MM_GDBUS_CALL (ctx->self), ctx->invocation); + handle_deflect_context_free (ctx); +} + +static void +handle_deflect_auth_ready (MMBaseModem *modem, + GAsyncResult *res, + HandleDeflectContext *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_deflect_context_free (ctx); + return; + } + + state = mm_gdbus_call_get_state (MM_GDBUS_CALL (ctx->self)); + + /* We can only deflect incoming call in ringing or waiting state */ + if (state != MM_CALL_STATE_RINGING_IN && state != MM_CALL_STATE_WAITING) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "This call was not ringing/waiting, cannot deflect"); + handle_deflect_context_free (ctx); + return; + } + + mm_info ("user request to deflect call"); + + /* Check if we do support doing it */ + if (!MM_BASE_CALL_GET_CLASS (ctx->self)->deflect || + !MM_BASE_CALL_GET_CLASS (ctx->self)->deflect_finish) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Deflecting call is not supported by this modem"); + handle_deflect_context_free (ctx); + return; + } + + MM_BASE_CALL_GET_CLASS (ctx->self)->deflect (ctx->self, + ctx->number, + (GAsyncReadyCallback)handle_deflect_ready, + ctx); +} + +static gboolean +handle_deflect (MMBaseCall *self, + GDBusMethodInvocation *invocation, + const gchar *number) +{ + HandleDeflectContext *ctx; + + ctx = g_slice_new0 (HandleDeflectContext); + ctx->self = g_object_ref (self); + ctx->invocation = g_object_ref (invocation); + ctx->number = g_strdup (number); + g_object_get (self, + MM_BASE_CALL_MODEM, &ctx->modem, + NULL); + + mm_base_modem_authorize (ctx->modem, + invocation, + MM_AUTHORIZATION_VOICE, + (GAsyncReadyCallback)handle_deflect_auth_ready, + ctx); + return TRUE; +} + +/*****************************************************************************/ /* Hangup call (DBus call handling) */ typedef struct { @@ -756,6 +863,10 @@ call_dbus_export (MMBaseCall *self) G_CALLBACK (handle_accept), NULL); g_signal_connect (self, + "handle-deflect", + G_CALLBACK (handle_deflect), + NULL); + g_signal_connect (self, "handle-hangup", G_CALLBACK (handle_hangup), NULL); diff --git a/src/mm-base-call.h b/src/mm-base-call.h index 5dddb6bc..e1a64e1e 100644 --- a/src/mm-base-call.h +++ b/src/mm-base-call.h @@ -67,6 +67,15 @@ struct _MMBaseCallClass { GAsyncResult *res, GError **error); + /* Deflect the call */ + void (* deflect) (MMBaseCall *self, + const gchar *number, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* deflect_finish) (MMBaseCall *self, + GAsyncResult *res, + GError **error); + /* Hangup the call */ void (* hangup) (MMBaseCall *self, GAsyncReadyCallback callback, |