diff --git a/src/calls-ofono-call.c b/src/calls-ofono-call.c index e024923..cd8b13e 100644 --- a/src/calls-ofono-call.c +++ b/src/calls-ofono-call.c @@ -57,6 +57,12 @@ enum { }; static GParamSpec *props[PROP_LAST_PROP]; +enum { + SIGNAL_TONE, + SIGNAL_LAST_SIGNAL, +}; +static guint signals [SIGNAL_LAST_SIGNAL]; + #define DEFINE_GET_BODY(member) \ get_##member (CallsCall *iface) \ @@ -154,14 +160,15 @@ hang_up (CallsCall *call) static void tone_start (CallsCall *call, gchar key) { - g_info ("Beep! (%c)", (int)key); -} + CallsOfonoCall *self = CALLS_OFONO_CALL (call); + if (self->state != CALLS_CALL_STATE_ACTIVE) + { + g_warning ("Tone start requested for non-active call to `%s'", + self->number); + return; + } - -static void -tone_stop (CallsCall *call, gchar key) -{ - g_info ("Beep end (%c)", (int)key); + g_signal_emit_by_name (self, "tone", key); } @@ -308,6 +315,7 @@ static void calls_ofono_call_class_init (CallsOfonoCallClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + GType tone_arg_types = G_TYPE_CHAR; object_class->set_property = set_property; object_class->constructed = constructed; @@ -330,6 +338,15 @@ calls_ofono_call_class_init (CallsOfonoCallClass *klass) G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties (object_class, PROP_LAST_PROP, props); + + + signals[SIGNAL_TONE] = + g_signal_newv ("tone", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + NULL, NULL, NULL, NULL, + G_TYPE_NONE, + 1, &tone_arg_types); } @@ -348,7 +365,6 @@ calls_ofono_call_call_interface_init (CallsCallInterface *iface) iface->answer = answer; iface->hang_up = hang_up; iface->tone_start = tone_start; - iface->tone_stop = tone_stop; } diff --git a/src/calls-ofono-origin.c b/src/calls-ofono-origin.c index e95dd18..71c85d4 100644 --- a/src/calls-ofono-origin.c +++ b/src/calls-ofono-origin.c @@ -37,6 +37,8 @@ struct _CallsOfonoOrigin GDBOModem *modem; gchar *name; GDBOVoiceCallManager *voice; + gboolean sending_tones; + GString *tone_queue; GHashTable *calls; }; @@ -210,6 +212,78 @@ struct CallsVoiceCallProxyNewData }; +static void +send_tones_cb (GDBOVoiceCallManager *voice, + GAsyncResult *res, + CallsOfonoOrigin *self) +{ + gboolean ok; + GError *error = NULL; + + /* Deal with old tones */ + ok = gdbo_voice_call_manager_call_send_tones_finish + (voice, res, &error); + if (!ok) + { + g_warning ("Error sending DTMF tones to network on modem `%s': %s", + self->name, error->message); + CALLS_EMIT_MESSAGE (self, error->message, GTK_MESSAGE_WARNING); + } + + /* Possibly send new tones */ + if (self->tone_queue) + { + g_debug ("Sending queued DTMF tones `%s'", self->tone_queue->str); + + gdbo_voice_call_manager_call_send_tones + (voice, + self->tone_queue->str, + NULL, + (GAsyncReadyCallback) send_tones_cb, + self); + + g_string_free (self->tone_queue, TRUE); + self->tone_queue = NULL; + } + else + { + self->sending_tones = FALSE; + } +} + + +static void +tone_cb (CallsOfonoOrigin *self, + gchar key) +{ + const gchar key_str[2] = { key, '\0' }; + + if (self->sending_tones) + { + if (self->tone_queue) + { + g_string_append_c (self->tone_queue, key); + } + else + { + self->tone_queue = g_string_new (key_str); + } + } + else + { + g_debug ("Sending immediate DTMF tone `%c'", key); + + gdbo_voice_call_manager_call_send_tones + (self->voice, + key_str, + NULL, + (GAsyncReadyCallback) send_tones_cb, + self); + + self->sending_tones = TRUE; + } +} + static void voice_call_proxy_new_cb (GDBusConnection *connection, GAsyncResult *res, @@ -233,6 +307,8 @@ voice_call_proxy_new_cb (GDBusConnection *connection, } call = calls_ofono_call_new (voice_call, data->properties); + g_signal_connect_swapped (call, "tone", + G_CALLBACK (tone_cb), self); path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (voice_call)); g_hash_table_insert (self->calls, g_strdup(path), call); @@ -447,10 +523,11 @@ finalize (GObject *object) GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT); CallsOfonoOrigin *self = CALLS_OFONO_ORIGIN (object); - if (self->name) + if (self->tone_queue) { - g_free (self->name); + g_string_free (self->tone_queue, TRUE); } + CALLS_FREE_PTR_PROPERTY (self->name); parent_class->finalize (object); }