aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2019-07-01 15:21:18 +0200
committerAleksander Morgado <aleksander@aleksander.es>2019-07-11 23:20:59 +0200
commit222874299eb16cba8e71ff2b4152d364615f2235 (patch)
tree123c38497e8da4187d1b90a2a0afd67bbb930967 /src
parent81f1483eecb26ff16576e28a7058b37f095584c1 (diff)
api,call: new Deflect() method
This method allows deflecting an incoming or waiting call to a different number.
Diffstat (limited to 'src')
-rw-r--r--src/mm-base-call.c111
-rw-r--r--src/mm-base-call.h9
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,