pidgin/pidgin

Really disable some plugins
default tip
31 hours ago, Gary Kramlich
44125b8e3b27
Really disable some plugins

Previous we disabled some plugins that we want to keep around but can't port
yet by setting `build_by_default` to `false`. However, this isn't working on
many machines. I haven't figured out why, so instead lets just make their
meson.build files exit early.

Testing Done:
Ran the turtles on a machine that was still building these plugins.

Reviewed at https://reviews.imfreedom.org/r/3142/
/* pidgin
*
* Pidgin is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <purpleconfig.h>
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include <purple.h>
#include "gtkmedia.h"
#include "gtkutils.h"
#include "pidgincore.h"
#include "pidginkeypad.h"
#define PIDGIN_TYPE_MEDIA (pidgin_media_get_type())
#define PIDGIN_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PIDGIN_TYPE_MEDIA, PidginMedia))
#define PIDGIN_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PIDGIN_TYPE_MEDIA, PidginMediaClass))
#define PIDGIN_IS_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PIDGIN_TYPE_MEDIA))
#define PIDGIN_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PIDGIN_TYPE_MEDIA))
#define PIDGIN_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PIDGIN_TYPE_MEDIA, PidginMediaClass))
typedef struct _PidginMedia PidginMedia;
typedef struct _PidginMediaClass PidginMediaClass;
typedef struct _PidginMediaPrivate PidginMediaPrivate;
typedef enum
{
/* Waiting for response */
PIDGIN_MEDIA_WAITING = 1,
/* Got request */
PIDGIN_MEDIA_REQUESTED,
/* Accepted call */
PIDGIN_MEDIA_ACCEPTED,
/* Rejected call */
PIDGIN_MEDIA_REJECTED,
} PidginMediaState;
struct _PidginMediaClass
{
GtkApplicationWindowClass parent_class;
};
struct _PidginMedia
{
GtkApplicationWindow parent;
PidginMediaPrivate *priv;
};
struct _PidginMediaPrivate
{
PurpleMedia *media;
gchar *screenname;
gulong level_handler_id;
GtkWidget *menubar;
GtkLabel *status;
GtkWidget *hold;
GtkWidget *mute;
GtkWidget *pause;
GtkWidget *send_progress;
GHashTable *recv_progressbars;
PidginMediaState state;
GtkWidget *display;
GtkWidget *send_widget;
GtkWidget *recv_widget;
GtkWidget *button_widget;
GtkWidget *local_video;
GHashTable *remote_videos;
guint timeout_id;
PurpleMediaSessionType request_type;
};
static GType pidgin_media_get_type(void);
G_DEFINE_TYPE_WITH_PRIVATE(PidginMedia, pidgin_media,
GTK_TYPE_APPLICATION_WINDOW);
static void pidgin_media_dispose (GObject *object);
static void pidgin_media_finalize (GObject *object);
static void pidgin_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void pidgin_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void pidgin_media_set_state(PidginMedia *gtkmedia, PidginMediaState state);
enum {
PROP_0,
PROP_MEDIA,
PROP_SCREENNAME,
N_PROPERTIES,
};
static gboolean
pidgin_media_close_request_cb(G_GNUC_UNUSED GtkWindow *window, gpointer data) {
PidginMedia *media = data;
if(media->priv->media) {
g_action_group_activate_action(G_ACTION_GROUP(media),
"Hangup", NULL);
}
return FALSE;
}
static void
pidgin_media_class_init (PidginMediaClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
gobject_class->dispose = pidgin_media_dispose;
gobject_class->finalize = pidgin_media_finalize;
gobject_class->set_property = pidgin_media_set_property;
gobject_class->get_property = pidgin_media_get_property;
g_object_class_install_property(gobject_class, PROP_MEDIA,
g_param_spec_object("media",
"PurpleMedia",
"The PurpleMedia associated with this media.",
PURPLE_TYPE_MEDIA,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property(gobject_class, PROP_SCREENNAME,
g_param_spec_string("screenname",
"Screenname",
"The screenname of the user this session is with.",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gtk_widget_class_set_template_from_resource(
widget_class,
"/im/pidgin/Pidgin3/Media/window.ui"
);
gtk_widget_class_bind_template_child_private(widget_class, PidginMedia,
display);
gtk_widget_class_bind_template_child_private(widget_class, PidginMedia,
status);
gtk_widget_class_bind_template_callback(widget_class,
pidgin_media_close_request_cb);
}
static void
pidgin_media_hangup_activate_cb(G_GNUC_UNUSED GSimpleAction *action,
G_GNUC_UNUSED GVariant *parameter,
gpointer user_data)
{
PidginMedia *media = PIDGIN_MEDIA(user_data);
purple_media_stream_info(media->priv->media,
PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, TRUE);
}
static void
pidgin_media_hold_change_state_cb(GSimpleAction *action, GVariant *value,
gpointer user_data)
{
PidginMedia *media = PIDGIN_MEDIA(user_data);
purple_media_stream_info(media->priv->media,
g_variant_get_boolean(value) ?
PURPLE_MEDIA_INFO_HOLD : PURPLE_MEDIA_INFO_UNHOLD,
NULL, NULL, TRUE);
g_simple_action_set_state(action, value);
}
static void
pidgin_media_mute_change_state_cb(GSimpleAction *action, GVariant *value,
gpointer user_data)
{
PidginMedia *media = PIDGIN_MEDIA(user_data);
purple_media_stream_info(media->priv->media,
g_variant_get_boolean(value) ?
PURPLE_MEDIA_INFO_MUTE : PURPLE_MEDIA_INFO_UNMUTE,
NULL, NULL, TRUE);
g_simple_action_set_state(action, value);
}
static void
pidgin_media_pause_change_state_cb(GSimpleAction *action, GVariant *value,
gpointer user_data)
{
PidginMedia *media = PIDGIN_MEDIA(user_data);
purple_media_stream_info(media->priv->media,
g_variant_get_boolean(value) ?
PURPLE_MEDIA_INFO_PAUSE : PURPLE_MEDIA_INFO_UNPAUSE,
NULL, NULL, TRUE);
g_simple_action_set_state(action, value);
}
static const GActionEntry media_action_entries[] = {
{
.name = "Hangup",
.activate = pidgin_media_hangup_activate_cb,
},
{
.name = "Hold",
.state = "false",
.change_state = pidgin_media_hold_change_state_cb,
},
{
.name = "Mute",
.state = "false",
.change_state = pidgin_media_mute_change_state_cb,
},
{
.name = "Pause",
.state = "false",
.change_state = pidgin_media_pause_change_state_cb,
},
};
static void
pidgin_media_init (PidginMedia *media)
{
media->priv = pidgin_media_get_instance_private(media);
gtk_widget_init_template(GTK_WIDGET(media));
g_action_map_add_action_entries(G_ACTION_MAP(media),
media_action_entries,
G_N_ELEMENTS(media_action_entries), media);
gtk_label_set_text(media->priv->status, _("Calling..."));
media->priv->recv_progressbars =
g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
media->priv->remote_videos =
g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
}
static gchar *
create_key(const gchar *session_id, const gchar *participant)
{
return g_strdup_printf("%s_%s", session_id, participant);
}
static void
pidgin_media_insert_widget(PidginMedia *gtkmedia, GtkWidget *widget,
const gchar *session_id, const gchar *participant)
{
gchar *key = create_key(session_id, participant);
PurpleMediaSessionType type =
purple_media_get_session_type(gtkmedia->priv->media, session_id);
if (type & PURPLE_MEDIA_AUDIO) {
g_hash_table_insert(gtkmedia->priv->recv_progressbars, key, widget);
} else if (type & PURPLE_MEDIA_VIDEO) {
g_hash_table_insert(gtkmedia->priv->remote_videos, key, widget);
}
}
static GtkWidget *
pidgin_media_get_widget(PidginMedia *gtkmedia,
const gchar *session_id, const gchar *participant)
{
GtkWidget *widget = NULL;
gchar *key = create_key(session_id, participant);
PurpleMediaSessionType type =
purple_media_get_session_type(gtkmedia->priv->media, session_id);
if (type & PURPLE_MEDIA_AUDIO) {
widget = g_hash_table_lookup(gtkmedia->priv->recv_progressbars, key);
} else if (type & PURPLE_MEDIA_VIDEO) {
widget = g_hash_table_lookup(gtkmedia->priv->remote_videos, key);
}
g_free(key);
return widget;
}
static void
pidgin_media_remove_widget(PidginMedia *gtkmedia,
const gchar *session_id, const gchar *participant)
{
GtkWidget *widget = NULL;
PurpleMediaSessionType type = PURPLE_MEDIA_NONE;
gchar *key = NULL;
widget = pidgin_media_get_widget(gtkmedia, session_id, participant);
if (widget == NULL) {
return;
}
type = purple_media_get_session_type(gtkmedia->priv->media, session_id);
key = create_key(session_id, participant);
if (type & PURPLE_MEDIA_AUDIO) {
g_hash_table_remove(gtkmedia->priv->recv_progressbars, key);
if (g_hash_table_size(gtkmedia->priv->recv_progressbars) == 0 &&
gtkmedia->priv->send_progress) {
g_clear_pointer(&gtkmedia->priv->send_progress, gtk_widget_unparent);
g_clear_pointer(&gtkmedia->priv->mute, gtk_widget_unparent);
}
} else if (type & PURPLE_MEDIA_VIDEO) {
g_hash_table_remove(gtkmedia->priv->remote_videos, key);
if (g_hash_table_size(gtkmedia->priv->remote_videos) == 0 &&
gtkmedia->priv->local_video) {
g_clear_pointer(&gtkmedia->priv->local_video, gtk_widget_unparent);
g_clear_pointer(&gtkmedia->priv->pause, gtk_widget_unparent);
}
}
g_free(key);
gtk_widget_unparent(widget);
}
static void
level_message_cb(G_GNUC_UNUSED PurpleMedia *media, char *session_id,
char *participant, double level, PidginMedia *gtkmedia)
{
GtkWidget *progress = NULL;
if (participant == NULL) {
progress = gtkmedia->priv->send_progress;
} else {
progress = pidgin_media_get_widget(gtkmedia, session_id, participant);
}
if (progress) {
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level);
}
}
static void
pidgin_media_disconnect_levels(PurpleMedia *media, PidginMedia *gtkmedia)
{
PurpleMediaManager *manager = NULL;
GstElement *element = NULL;
GstBus *bus = NULL;
manager = purple_media_get_manager(media);
element = purple_media_manager_get_pipeline(manager);
bus = gst_pipeline_get_bus(GST_PIPELINE(element));
g_signal_handlers_disconnect_by_func(bus, level_message_cb, gtkmedia);
}
static void
pidgin_media_dispose(GObject *media)
{
PidginMedia *gtkmedia = PIDGIN_MEDIA(media);
purple_debug_info("gtkmedia", "pidgin_media_dispose\n");
if (gtkmedia->priv->media) {
purple_request_close_with_handle(gtkmedia);
purple_media_remove_output_windows(gtkmedia->priv->media);
pidgin_media_disconnect_levels(gtkmedia->priv->media, gtkmedia);
g_clear_object(&gtkmedia->priv->media);
}
g_clear_handle_id(&gtkmedia->priv->timeout_id, g_source_remove);
g_clear_pointer(&gtkmedia->priv->recv_progressbars, g_hash_table_destroy);
g_clear_pointer(&gtkmedia->priv->remote_videos, g_hash_table_destroy);
g_clear_pointer(&gtkmedia->priv->screenname, g_free);
G_OBJECT_CLASS(pidgin_media_parent_class)->dispose(media);
}
static void
pidgin_media_finalize(GObject *media)
{
/* PidginMedia *gtkmedia = PIDGIN_MEDIA(media); */
purple_debug_info("gtkmedia", "pidgin_media_finalize\n");
G_OBJECT_CLASS(pidgin_media_parent_class)->finalize(media);
}
static void
pidgin_media_emit_message(PidginMedia *gtkmedia, const char *msg)
{
PurpleConversation *conv;
PurpleConversationManager *manager;
PurpleAccount *account;
account = purple_media_get_account(gtkmedia->priv->media);
manager = purple_conversation_manager_get_default();
conv = purple_conversation_manager_find(manager, account,
gtkmedia->priv->screenname);
if(PURPLE_IS_CONVERSATION(conv)) {
purple_conversation_write_system_message(conv, msg, 0);
}
g_object_unref(account);
}
static void
pidgin_media_error_cb(G_GNUC_UNUSED PidginMedia *media, const char *error,
PidginMedia *gtkmedia)
{
PurpleConversation *conv;
PurpleConversationManager *manager;
PurpleAccount *account;
account = purple_media_get_account(gtkmedia->priv->media);
manager = purple_conversation_manager_get_default();
conv = purple_conversation_manager_find(manager, account,
gtkmedia->priv->screenname);
if(PURPLE_IS_CONVERSATION(conv)) {
purple_conversation_write_system_message(conv, error,
PURPLE_MESSAGE_ERROR);
} else {
purple_notify_error(NULL, NULL, _("Media error"), error,
purple_request_cpar_from_conversation(conv));
}
gtk_label_set_text(gtkmedia->priv->status, error);
g_object_unref(account);
}
static void
pidgin_media_accept_cb(PurpleMedia *media, G_GNUC_UNUSED int index)
{
purple_media_stream_info(media, PURPLE_MEDIA_INFO_ACCEPT,
NULL, NULL, TRUE);
}
static void
pidgin_media_reject_cb(PurpleMedia *media, G_GNUC_UNUSED int index)
{
GList *iter = purple_media_get_session_ids(media);
for (; iter; iter = g_list_delete_link(iter, iter)) {
const gchar *sessionid = iter->data;
if (!purple_media_accepted(media, sessionid, NULL)) {
purple_media_stream_info(media, PURPLE_MEDIA_INFO_REJECT,
sessionid, NULL, TRUE);
}
}
}
static gboolean
pidgin_request_timeout_cb(PidginMedia *gtkmedia)
{
PurpleAccount *account;
const gchar *alias;
PurpleMediaSessionType type;
gchar *message = NULL;
account = purple_media_get_account(gtkmedia->priv->media);
alias = gtkmedia->priv->screenname;
type = gtkmedia->priv->request_type;
gtkmedia->priv->timeout_id = 0;
if (type & PURPLE_MEDIA_AUDIO && type & PURPLE_MEDIA_VIDEO) {
message = g_strdup_printf(_("%s wishes to start an audio/video session with you."),
alias);
} else if (type & PURPLE_MEDIA_AUDIO) {
message = g_strdup_printf(_("%s wishes to start an audio session with you."),
alias);
} else if (type & PURPLE_MEDIA_VIDEO) {
message = g_strdup_printf(_("%s wishes to start a video session with you."),
alias);
}
gtkmedia->priv->request_type = PURPLE_MEDIA_NONE;
if (!purple_media_accepted(gtkmedia->priv->media, NULL, NULL)) {
purple_request_accept_cancel(gtkmedia, _("Incoming Call"),
message, NULL, PURPLE_DEFAULT_ACTION_NONE,
purple_request_cpar_from_account(account),
gtkmedia->priv->media, pidgin_media_accept_cb,
pidgin_media_reject_cb);
}
pidgin_media_emit_message(gtkmedia, message);
g_free(message);
g_object_unref(account);
return FALSE;
}
static void
pidgin_media_input_volume_changed(G_GNUC_UNUSED GtkScaleButton *range,
double value, PurpleMedia *media)
{
double val = (double)value * 100.0;
purple_media_set_input_volume(media, NULL, val);
}
static void
pidgin_media_output_volume_changed(G_GNUC_UNUSED GtkScaleButton *range,
double value, PurpleMedia *media)
{
double val = (double)value * 100.0;
purple_media_set_output_volume(media, NULL, NULL, val);
}
static void
destroy_parent_widget_cb(G_GNUC_UNUSED GtkWidget *widget, GtkWidget *parent)
{
g_return_if_fail(GTK_IS_WIDGET(parent));
gtk_widget_unparent(parent);
}
static GtkWidget *
pidgin_media_add_audio_widget(PidginMedia *gtkmedia,
PurpleMediaSessionType type, const gchar *sid)
{
GtkWidget *volume_widget, *progress_parent, *volume, *progress;
double value;
static const gchar * input_volume_icons[] = {
"microphone-sensitivity-muted-symbolic",
"microphone-sensitivity-high-symbolic",
"microphone-sensitivity-low-symbolic",
"microphone-sensitivity-medium-symbolic",
NULL
};
if (type & PURPLE_MEDIA_SEND_AUDIO) {
value = purple_prefs_get_int("/purple/media/audio/volume/input");
} else if (type & PURPLE_MEDIA_RECV_AUDIO) {
value = purple_prefs_get_int("/purple/media/audio/volume/output");
} else {
g_return_val_if_reached(NULL);
}
/* Setup widget structure */
volume_widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
progress_parent = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_hexpand(progress_parent, TRUE);
gtk_box_append(GTK_BOX(volume_widget), progress_parent);
/* Volume button */
volume = gtk_volume_button_new();
gtk_scale_button_set_value(GTK_SCALE_BUTTON(volume), value/100.0);
gtk_box_append(GTK_BOX(volume_widget), volume);
/* Volume level indicator */
progress = gtk_progress_bar_new();
gtk_widget_set_size_request(progress, 250, 10);
gtk_widget_set_vexpand(progress, TRUE);
gtk_box_append(GTK_BOX(progress_parent), progress);
if (type & PURPLE_MEDIA_SEND_AUDIO) {
g_signal_connect (G_OBJECT(volume), "value-changed",
G_CALLBACK(pidgin_media_input_volume_changed),
gtkmedia->priv->media);
gtk_scale_button_set_icons(GTK_SCALE_BUTTON(volume),
input_volume_icons);
gtkmedia->priv->send_progress = progress;
} else if (type & PURPLE_MEDIA_RECV_AUDIO) {
g_signal_connect (G_OBJECT(volume), "value-changed",
G_CALLBACK(pidgin_media_output_volume_changed),
gtkmedia->priv->media);
pidgin_media_insert_widget(gtkmedia, progress, sid, gtkmedia->priv->screenname);
}
g_signal_connect(G_OBJECT(progress), "destroy",
G_CALLBACK(destroy_parent_widget_cb),
volume_widget);
return volume_widget;
}
static void
pidgin_media_keypad_pressed_cb(G_GNUC_UNUSED PidginKeypad *keypad, guint key,
gpointer data)
{
PidginMedia *gtkmedia = data;
gchar *sid;
sid = g_object_get_data(G_OBJECT(gtkmedia), "session-id");
purple_media_send_dtmf(gtkmedia->priv->media, sid, key, 25, 50);
}
static GtkWidget *
pidgin_media_add_dtmf_widget(PidginMedia *gtkmedia,
G_GNUC_UNUSED PurpleMediaSessionType type,
const char *_sid)
{
GtkApplicationWindow *win = GTK_APPLICATION_WINDOW(gtkmedia);
GtkWidget *keypad = NULL;
keypad = pidgin_keypad_new();
pidgin_keypad_set_key_capture_widget(PIDGIN_KEYPAD(keypad),
GTK_WIDGET(win));
g_signal_connect(keypad, "pressed",
G_CALLBACK(pidgin_media_keypad_pressed_cb), gtkmedia);
g_object_set_data_full(G_OBJECT(win), "session-id",
g_strdup(_sid), g_free);
return keypad;
}
static void
pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia, const gchar *sid)
{
GtkWidget *send_widget = NULL, *recv_widget = NULL, *button_widget = NULL;
PurpleMediaSessionType type =
purple_media_get_session_type(media, sid);
if (gtkmedia->priv->recv_widget == NULL
&& type & (PURPLE_MEDIA_RECV_VIDEO |
PURPLE_MEDIA_RECV_AUDIO)) {
recv_widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
gtk_widget_set_hexpand(recv_widget, TRUE);
gtk_widget_set_vexpand(recv_widget, TRUE);
gtk_box_append(GTK_BOX(gtkmedia->priv->display), recv_widget);
} else {
recv_widget = gtkmedia->priv->recv_widget;
}
if (gtkmedia->priv->send_widget == NULL
&& type & (PURPLE_MEDIA_SEND_VIDEO |
PURPLE_MEDIA_SEND_AUDIO)) {
send_widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
gtk_box_prepend(GTK_BOX(gtkmedia->priv->display), send_widget);
button_widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_append(GTK_BOX(send_widget), button_widget);
/* Hold button */
gtkmedia->priv->hold =
gtk_toggle_button_new_with_mnemonic(_("_Hold"));
gtk_box_prepend(GTK_BOX(button_widget), gtkmedia->priv->hold);
gtk_actionable_set_action_name(
GTK_ACTIONABLE(gtkmedia->priv->hold),
"win.Hold");
} else {
send_widget = gtkmedia->priv->send_widget;
button_widget = gtkmedia->priv->button_widget;
}
if (type & PURPLE_MEDIA_RECV_VIDEO) {
PidginMediaPrivate *priv = gtkmedia->priv;
PurpleMediaManager *manager = NULL;
GstElement *pipeline = NULL;
GstElement *sink = NULL;
GtkWidget *remote_video = NULL;
purple_media_set_output_window(priv->media, sid, priv->screenname);
manager = purple_media_get_manager(priv->media);
pipeline = purple_media_manager_get_pipeline(manager);
sink = gst_bin_get_by_name(GST_BIN(pipeline), "gtkglsink");
if (sink == NULL) {
sink = gst_bin_get_by_name(GST_BIN(pipeline), "gtksink");
}
g_object_get(sink, "widget", &remote_video, NULL);
gtk_widget_set_visible(remote_video, TRUE);
gtk_widget_set_vexpand(remote_video, TRUE);
gtk_box_append(GTK_BOX(recv_widget), remote_video);
pidgin_media_insert_widget(gtkmedia, remote_video, sid, priv->screenname);
}
if (type & PURPLE_MEDIA_SEND_VIDEO && !gtkmedia->priv->local_video) {
PidginMediaPrivate *priv = gtkmedia->priv;
PurpleMediaManager *manager = NULL;
GstElement *pipeline = NULL;
GstElement *sink = NULL;
GtkWidget *local_video = NULL;
purple_media_set_output_window(priv->media, sid, NULL);
manager = purple_media_get_manager(priv->media);
pipeline = purple_media_manager_get_pipeline(manager);
sink = gst_bin_get_by_name(GST_BIN(pipeline), "gtkglsink");
if (sink == NULL) {
sink = gst_bin_get_by_name(GST_BIN(pipeline), "gtksink");
}
g_object_get(sink, "widget", &local_video, NULL);
gtk_widget_set_visible(local_video, TRUE);
gtk_widget_set_vexpand(local_video, TRUE);
gtk_box_append(GTK_BOX(send_widget), local_video);
gtkmedia->priv->pause =
gtk_toggle_button_new_with_mnemonic(_("_Pause"));
gtk_box_prepend(GTK_BOX(button_widget), gtkmedia->priv->pause);
gtk_actionable_set_action_name(
GTK_ACTIONABLE(gtkmedia->priv->pause),
"win.Pause");
gtkmedia->priv->local_video = local_video;
}
if (type & PURPLE_MEDIA_RECV_AUDIO) {
GtkWidget *audio = NULL;
audio = pidgin_media_add_audio_widget(gtkmedia, PURPLE_MEDIA_RECV_AUDIO,
sid);
gtk_box_prepend(GTK_BOX(recv_widget), audio);
}
if (type & PURPLE_MEDIA_SEND_AUDIO) {
gtkmedia->priv->mute =
gtk_toggle_button_new_with_mnemonic(_("_Mute"));
gtk_box_prepend(GTK_BOX(button_widget), gtkmedia->priv->mute);
gtk_actionable_set_action_name(
GTK_ACTIONABLE(gtkmedia->priv->mute),
"win.Mute");
gtk_box_prepend(GTK_BOX(recv_widget),
pidgin_media_add_audio_widget(gtkmedia,
PURPLE_MEDIA_SEND_AUDIO, sid));
gtk_box_prepend(GTK_BOX(recv_widget),
pidgin_media_add_dtmf_widget(gtkmedia,
PURPLE_MEDIA_SEND_AUDIO, sid));
}
if (type & PURPLE_MEDIA_AUDIO &&
gtkmedia->priv->level_handler_id == 0) {
gtkmedia->priv->level_handler_id = g_signal_connect(
media, "level", G_CALLBACK(level_message_cb),
gtkmedia);
}
if (send_widget != NULL) {
gtkmedia->priv->send_widget = send_widget;
}
if (recv_widget != NULL) {
gtkmedia->priv->recv_widget = recv_widget;
}
if (button_widget != NULL) {
gtkmedia->priv->button_widget = button_widget;
}
if (purple_media_is_initiator(media, sid, NULL) == FALSE) {
g_clear_handle_id(&gtkmedia->priv->timeout_id, g_source_remove);
gtkmedia->priv->request_type |= type;
gtkmedia->priv->timeout_id = g_timeout_add(500,
G_SOURCE_FUNC(pidgin_request_timeout_cb),
gtkmedia);
}
/* set the window icon according to the type */
if (type & PURPLE_MEDIA_VIDEO) {
gtk_window_set_icon_name(GTK_WINDOW(gtkmedia), "video-call");
} else if (type & PURPLE_MEDIA_AUDIO) {
gtk_window_set_icon_name(GTK_WINDOW(gtkmedia), "audio-call");
}
}
static void
pidgin_media_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
gchar *sid, gchar *name, PidginMedia *gtkmedia)
{
purple_debug_info("gtkmedia", "state: %d sid: %s name: %s\n",
state, sid ? sid : "(null)", name ? name : "(null)");
if (state == PURPLE_MEDIA_STATE_END) {
if (sid != NULL && name != NULL) {
pidgin_media_remove_widget(gtkmedia, sid, name);
} else if (sid == NULL && name == NULL) {
pidgin_media_emit_message(gtkmedia,
_("The call has been terminated."));
gtk_window_destroy(GTK_WINDOW(gtkmedia));
}
} else if (state == PURPLE_MEDIA_STATE_NEW &&
sid != NULL && name != NULL) {
pidgin_media_ready_cb(media, gtkmedia, sid);
}
}
static void
pidgin_media_stream_info_cb(G_GNUC_UNUSED PurpleMedia *media,
PurpleMediaInfoType type,
G_GNUC_UNUSED gchar *sid,
G_GNUC_UNUSED gchar *name, gboolean local,
PidginMedia *gtkmedia)
{
if (type == PURPLE_MEDIA_INFO_REJECT) {
pidgin_media_emit_message(gtkmedia,
_("You have rejected the call."));
} else if (type == PURPLE_MEDIA_INFO_ACCEPT) {
if (local) {
purple_request_close_with_handle(gtkmedia);
}
pidgin_media_set_state(gtkmedia, PIDGIN_MEDIA_ACCEPTED);
pidgin_media_emit_message(gtkmedia, _("Call in progress."));
gtk_label_set_text(gtkmedia->priv->status, _("Call in progress"));
gtk_widget_set_visible(GTK_WIDGET(gtkmedia), TRUE);
} else if (type == PURPLE_MEDIA_INFO_MUTE && !local) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkmedia->priv->mute), TRUE);
} else if (type == PURPLE_MEDIA_INFO_UNMUTE && !local) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gtkmedia->priv->mute), FALSE);
}
}
static void
pidgin_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
PidginMedia *media = PIDGIN_MEDIA(object);
switch (prop_id) {
case PROP_MEDIA:
g_set_object(&media->priv->media, g_value_get_object(value));
if (purple_media_is_initiator(media->priv->media, NULL, NULL)) {
pidgin_media_set_state(media, PIDGIN_MEDIA_WAITING);
} else {
pidgin_media_set_state(media, PIDGIN_MEDIA_REQUESTED);
}
g_signal_connect(G_OBJECT(media->priv->media), "error",
G_CALLBACK(pidgin_media_error_cb), media);
g_signal_connect(G_OBJECT(media->priv->media), "state-changed",
G_CALLBACK(pidgin_media_state_changed_cb), media);
g_signal_connect(G_OBJECT(media->priv->media), "stream-info",
G_CALLBACK(pidgin_media_stream_info_cb), media);
break;
case PROP_SCREENNAME:
g_free(media->priv->screenname);
media->priv->screenname = g_value_dup_string(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
pidgin_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
PidginMedia *media = PIDGIN_MEDIA(object);
switch (prop_id) {
case PROP_MEDIA:
g_value_set_object(value, media->priv->media);
break;
case PROP_SCREENNAME:
g_value_set_string(value, media->priv->screenname);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GtkWidget *
pidgin_media_new(PurpleMedia *media, const gchar *screenname)
{
PidginMedia *gtkmedia = g_object_new(pidgin_media_get_type(),
"media", media,
"screenname", screenname, NULL);
return GTK_WIDGET(gtkmedia);
}
static void
pidgin_media_set_state(PidginMedia *gtkmedia, PidginMediaState state)
{
gtkmedia->priv->state = state;
}
static gboolean
pidgin_media_new_cb(G_GNUC_UNUSED PurpleMediaManager *manager,
PurpleMedia *media,
G_GNUC_UNUSED PurpleAccount *account,
char *screenname, G_GNUC_UNUSED gpointer data)
{
PidginMedia *gtkmedia = NULL;
const gchar *alias = NULL;
gtkmedia = PIDGIN_MEDIA(pidgin_media_new(media, screenname));
alias = screenname;
gtk_window_set_title(GTK_WINDOW(gtkmedia), alias);
gtk_widget_set_visible(GTK_WIDGET(gtkmedia),
purple_media_is_initiator(media, NULL, NULL));
return TRUE;
}
void
pidgin_medias_init(void)
{
PurpleMediaManager *manager = purple_media_manager_get();
PurpleMediaElementInfo *video_src = NULL;
PurpleMediaElementInfo *video_sink = NULL;
PurpleMediaElementInfo *audio_src = NULL;
PurpleMediaElementInfo *audio_sink = NULL;
const char *pref;
pref = purple_prefs_get_string(
PIDGIN_PREFS_ROOT "/vvconfig/video/src/device");
if (pref) {
video_src = purple_media_manager_get_element_info(manager, pref);
}
if (!video_src) {
pref = "autovideosrc";
purple_prefs_set_string(
PIDGIN_PREFS_ROOT "/vvconfig/video/src/device", pref);
video_src = purple_media_manager_get_element_info(manager,
pref);
}
pref = purple_prefs_get_string(
PIDGIN_PREFS_ROOT "/vvconfig/video/sink/device");
if (pref) {
video_sink = purple_media_manager_get_element_info(manager, pref);
}
if (!video_sink) {
pref = "autovideosink";
purple_prefs_set_string(
PIDGIN_PREFS_ROOT "/vvconfig/video/sink/device", pref);
video_sink = purple_media_manager_get_element_info(manager,
pref);
}
pref = purple_prefs_get_string(
PIDGIN_PREFS_ROOT "/vvconfig/audio/src/device");
if (pref) {
audio_src = purple_media_manager_get_element_info(manager, pref);
}
if (!audio_src) {
pref = "autoaudiosrc";
purple_prefs_set_string(
PIDGIN_PREFS_ROOT "/vvconfig/audio/src/device", pref);
audio_src = purple_media_manager_get_element_info(manager,
pref);
}
pref = purple_prefs_get_string(
PIDGIN_PREFS_ROOT "/vvconfig/audio/sink/device");
if (pref) {
audio_sink = purple_media_manager_get_element_info(manager, pref);
}
if (!audio_sink) {
pref = "autoaudiosink";
purple_prefs_set_string(
PIDGIN_PREFS_ROOT "/vvconfig/audio/sink/device", pref);
audio_sink = purple_media_manager_get_element_info(manager,
pref);
}
g_signal_connect(G_OBJECT(manager), "init-media",
G_CALLBACK(pidgin_media_new_cb), NULL);
purple_media_manager_set_ui_caps(manager,
PURPLE_MEDIA_CAPS_AUDIO |
PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION |
PURPLE_MEDIA_CAPS_VIDEO |
PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION |
PURPLE_MEDIA_CAPS_AUDIO_VIDEO);
purple_debug_info("gtkmedia", "Registering media element types\n");
purple_media_manager_set_active_element(manager, video_src);
purple_media_manager_set_active_element(manager, video_sink);
purple_media_manager_set_active_element(manager, audio_src);
purple_media_manager_set_active_element(manager, audio_sink);
g_object_unref(video_src);
g_object_unref(video_sink);
g_object_unref(audio_src);
g_object_unref(audio_sink);
}