Outgoing DTMF / dialpad support

Eion Robb eion at robbmob.com
Mon Oct 14 15:45:34 EDT 2013


Neat :)

The only UI thing left is a switch between the various in-band/out-of-band
mechanisms, on a per-account basis.

On 15 Oct 2013 01:43, "David Woodhouse" <dwmw2 at infradead.org> wrote:

> There are two open requests about DTMF support.
>
>  - https://developer.pidgin.im/ticket/12617
>    (Patch to add out-of-band DTMF support)
>
> This adds a generic way for protocols to send DTMF out-of-band, and
> falls back to sending in-band in the media stream. And a second patch
> adds the required protocol-specific support for Jabber. The patches
> didn't even seem to build out-of-the-box, due to typos and mismatched
> function declarations, and the ticket has been open and mostly unloved
> for three years.
>
>  - https://developer.pidgin.im/ticket/15575
>    (dialpad support)
>
> This is more recent, and actually adds a UI for users to dial DTMF tones
> whilst in an audio call. The patch here operates directly on a gstreamer
> pipeline to send dtmf-events, and looking at the code I'm not entirely
> sure the pipeline it selects will have *anything* to do with the media
> stream it was actually *asked* to send DTMF on.
>
> So I've generated a patch which combines the two — fixing up the generic
> part of the media_dtmf patch in ticket 12617, and combining it with the
> UI support added in ticket 15575. I am inclined to suggest we should
> leave ticket 12617 open for the Jabber support which I haven't updated
> and can't easily test, and handle the UI along with the generic part
> (i.e. my patch) in the new ticket 15575.
>
> I have some outstanding issues with my patch which I would appreciate
> some more clueful input on...
>
> Firstly, to make the generic DTMF support build cleanly I had to go
> through all the protocol plugins and add an explicit extra NULL to each
> PurplePluginProtocolInfo structure. Do we *really* still have to do it
> this way and use structure declarations from last century, or should I
> submit a separate patch which updates the code to use C99 structure
> initialisation? It's been 14 years now...
>
> Secondly, and more importantly, see the FIXME and the leak of the
> session-id string in the gtkmedia.c patch. I didn't bother to fix that
> because I'm assuming the session-id is going to be stored *somewhere* we
> can access it anyway, but I wasn't sure. Or perhaps we can even continue
> to use the one we were given, and its lifetime will exceed that of the
> UI? Suggestions welcome...
>
> Third: why wasn't pidgin_media_ready_cb() passing the sid to
> pidgin_media_add_audio_widget()? If you look carefully at the final hunk
> below, you'll see I 'fix' that too...
>
> This is just the patch of the patch which affects gtkmedia.c:
>
> diff --git a/pidgin/gtkmedia.c b/pidgin/gtkmedia.c
> index d91a951..9d5f4d8 100644
> --- a/pidgin/gtkmedia.c
> +++ b/pidgin/gtkmedia.c
> @@ -759,6 +759,150 @@ pidgin_media_add_audio_widget(PidginMedia *gtkmedia,
>  }
>
>  static void
> +phone_dtmf_pressed_cb(GtkButton *button, gpointer user_data)
> +{
> +       PidginMedia *gtkmedia = user_data;
> +       gint num;
> +       gchar *sid;
> +
> +       num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),
> "dtmf-digit"));
> +       sid = g_object_get_data(G_OBJECT(button), "session-id");
> +
> +       purple_media_send_dtmf(gtkmedia->priv->media, sid, num, 25, 50);
> +}
> +
> +static inline GtkWidget *
> +phone_create_button(const gchar *text_hi, const gchar *text_lo)
> +{
> +       GtkWidget *button;
> +       GtkWidget *label_hi;
> +       GtkWidget *label_lo;
> +       GtkWidget *grid;
> +
> +       grid = gtk_vbox_new(TRUE, 0);
> +
> +       button = gtk_button_new();
> +       label_hi = gtk_label_new(text_hi);
> +       gtk_misc_set_alignment(GTK_MISC(label_hi), 0.5, 0.5);
> +       gtk_box_pack_end(GTK_BOX(grid), label_hi, FALSE, TRUE, 0);
> +       label_lo = gtk_label_new(text_lo);
> +       gtk_misc_set_alignment(GTK_MISC(label_lo), 0.5, 0.5);
> +       gtk_label_set_use_markup(GTK_LABEL(label_lo), TRUE);
> +       gtk_box_pack_end(GTK_BOX(grid), label_lo, FALSE, TRUE, 0);
> +       gtk_container_add(GTK_CONTAINER(button), grid);
> +
> +       return button;
> +}
> +
> +static GtkWidget *
> +pidgin_media_add_dtmf_widget(PidginMedia *gtkmedia,
> +               PurpleMediaSessionType type, const gchar *_sid)
> +{
> +       GtkWidget *grid = gtk_table_new(4, 3, TRUE);
> +       GtkWidget *button1;
> +       GtkWidget *button2;
> +       GtkWidget *button3;
> +       GtkWidget *button4;
> +       GtkWidget *button5;
> +       GtkWidget *button6;
> +       GtkWidget *button7;
> +       GtkWidget *button8;
> +       GtkWidget *button9;
> +       GtkWidget *button_asterisk;
> +       GtkWidget *button0;
> +       GtkWidget *button_pound;
> +       gchar *sid = g_strdup(_sid); /* FIXME: This leaks. */
> +
> +       /* Button 1 */
> +       button1 = phone_create_button("o_o", "<b>1</b>");
> +       g_signal_connect(button1, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button1), "dtmf-digit",
> GINT_TO_POINTER('1'));
> +       g_object_set_data(G_OBJECT(button1), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button1, 0, 1, 0, 1, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 2 */
> +       button2 = phone_create_button("ABC", "<b>2</b>");
> +       g_signal_connect(button2, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button2), "dtmf-digit",
> GINT_TO_POINTER('2'));
> +       g_object_set_data(G_OBJECT(button2), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button2, 1, 2, 0, 1, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 3 */
> +       button3 = phone_create_button("DEF", "<b>3</b>");
> +       g_signal_connect(button3, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button3), "dtmf-digit",
> GINT_TO_POINTER('3'));
> +       g_object_set_data(G_OBJECT(button3), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button3, 2, 3, 0, 1, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 4 */
> +       button4 = phone_create_button("GHI", "<b>4</b>");
> +       g_signal_connect(button4, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button4), "dtmf-digit",
> GINT_TO_POINTER('4'));
> +       g_object_set_data(G_OBJECT(button4), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button4, 0, 1, 1, 2, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 5 */
> +       button5 = phone_create_button("JKL", "<b>5</b>");
> +       g_signal_connect(button5, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button5), "dtmf-digit",
> GINT_TO_POINTER('5'));
> +       g_object_set_data(G_OBJECT(button5), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button5, 1, 2, 1, 2, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 6 */
> +       button6 = phone_create_button("MNO", "<b>6</b>");
> +       g_signal_connect(button6, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button6), "dtmf-digit",
> GINT_TO_POINTER('6'));
> +       g_object_set_data(G_OBJECT(button6), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button6, 2, 3, 1, 2, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 7 */
> +       button7 = phone_create_button("PQRS", "<b>7</b>");
> +       g_signal_connect(button7, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button7), "dtmf-digit",
> GINT_TO_POINTER('7'));
> +       g_object_set_data(G_OBJECT(button7), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button7, 0, 1, 2, 3, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 8 */
> +       button8 = phone_create_button("TUV", "<b>8</b>");
> +       g_signal_connect(button8, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button8), "dtmf-digit",
> GINT_TO_POINTER('8'));
> +       g_object_set_data(G_OBJECT(button8), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button8, 1, 2, 2, 3, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 9 */
> +       button9 = phone_create_button("WXYZ", "<b>9</b>");
> +       g_signal_connect(button9, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button9), "dtmf-digit",
> GINT_TO_POINTER('9'));
> +       g_object_set_data(G_OBJECT(button9), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button9, 2, 3, 2, 3, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button Asterisk */
> +       button_asterisk = phone_create_button(_("DEL"), "<b>*</b>");
> +       g_signal_connect(button_asterisk, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button_asterisk), "dtmf-digit",
> GINT_TO_POINTER('*'));
> +       g_object_set_data(G_OBJECT(button_asterisk), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button_asterisk, 0, 1, 3, 4,
> GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button 0 */
> +       button0 = phone_create_button("", "<b>0</b>");
> +       g_signal_connect(button0, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button0), "dtmf-digit",
> GINT_TO_POINTER('0'));
> +       g_object_set_data(G_OBJECT(button0), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button0, 1, 2, 3, 4, GTK_FILL |
> GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       /* Button Pound */
> +       button_pound = phone_create_button(_("RETURN"), "<b>#</b>");
> +       g_signal_connect(button_pound, "pressed",
> G_CALLBACK(phone_dtmf_pressed_cb), gtkmedia);
> +       g_object_set_data(G_OBJECT(button_pound), "dtmf-digit",
> GINT_TO_POINTER('#'));
> +       g_object_set_data(G_OBJECT(button_pound), "session-id", sid);
> +       gtk_table_attach(GTK_TABLE(grid), button_pound, 2, 3, 3, 4,
> GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 2, 2);
> +
> +       gtk_widget_show_all(grid);
> +
> +       return grid;
> +}
> +
> +static void
>  pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia, const
> gchar *sid)
>  {
>         GtkWidget *send_widget = NULL, *recv_widget = NULL, *button_widget
> = NULL;
> @@ -888,7 +1032,11 @@ pidgin_media_ready_cb(PurpleMedia *media,
> PidginMedia *gtkmedia, const gchar *si
>
>                 gtk_box_pack_end(GTK_BOX(recv_widget),
>                                 pidgin_media_add_audio_widget(gtkmedia,
> -                               PURPLE_MEDIA_SEND_AUDIO, NULL), FALSE,
> FALSE, 0);
> +                               PURPLE_MEDIA_SEND_AUDIO, sid), FALSE,
> FALSE, 0);
> +
> +               gtk_box_pack_end(GTK_BOX(recv_widget),
> +                               pidgin_media_add_dtmf_widget(gtkmedia,
> +                               PURPLE_MEDIA_SEND_AUDIO, sid), FALSE,
> FALSE, 0);
>         }
>
>         if (type & PURPLE_MEDIA_AUDIO &&
>
>
>
> --
> David Woodhouse                            Open Source Technology Centre
> David.Woodhouse at intel.com                              Intel Corporation
>
> _______________________________________________
> Devel mailing list
> Devel at pidgin.im
> http://pidgin.im/cgi-bin/mailman/listinfo/devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://pidgin.im/pipermail/devel/attachments/20131015/9d57dd19/attachment.html>


More information about the Devel mailing list