pidgin/pidgin

Add Since tags for 2.12.0.

2019-11-22, Elliott Sales de Andrade
72cbc032cdd1
Add Since tags for 2.12.0.
/*
* finch
*
* Finch 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 <internal.h>
#include "finch.h"
#include "gntconv.h"
#include "gntmedia.h"
#include "gnt.h"
#include "gntbutton.h"
#include "gntbox.h"
#include "gntlabel.h"
#include "cmds.h"
#include "conversation.h"
#include "debug.h"
#include "mediamanager.h"
/* An incredibly large part of the following is from gtkmedia.c */
#ifdef USE_VV
#include "media-gst.h"
#undef hangup
#define FINCH_TYPE_MEDIA (finch_media_get_type())
#define FINCH_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FINCH_TYPE_MEDIA, FinchMedia))
#define FINCH_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FINCH_TYPE_MEDIA, FinchMediaClass))
#define FINCH_IS_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), FINCH_TYPE_MEDIA))
#define FINCH_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FINCH_TYPE_MEDIA))
#define FINCH_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FINCH_TYPE_MEDIA, FinchMediaClass))
typedef struct _FinchMedia FinchMedia;
typedef struct _FinchMediaClass FinchMediaClass;
typedef struct _FinchMediaPrivate FinchMediaPrivate;
typedef enum _FinchMediaState FinchMediaState;
struct _FinchMediaClass
{
GntBoxClass parent_class;
};
struct _FinchMedia
{
GntBox parent;
FinchMediaPrivate *priv;
};
struct _FinchMediaPrivate
{
PurpleMedia *media;
GntWidget *accept;
GntWidget *reject;
GntWidget *hangup;
GntWidget *calling;
PurpleConversation *conv;
};
static GType finch_media_get_type (void);
static void finch_media_class_init (FinchMediaClass *klass);
static void finch_media_init (FinchMedia *media);
static void finch_media_finalize (GObject *object);
static void finch_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void finch_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
enum {
MESSAGE,
LAST_SIGNAL
};
static guint finch_media_signals[LAST_SIGNAL] = {0};
enum {
PROP_0,
PROP_MEDIA,
};
G_DEFINE_TYPE_WITH_PRIVATE(FinchMedia, finch_media, GNT_TYPE_BOX);
static void
finch_media_class_init (FinchMediaClass *klass)
{
GObjectClass *gobject_class = (GObjectClass*)klass;
gobject_class->finalize = finch_media_finalize;
gobject_class->set_property = finch_media_set_property;
gobject_class->get_property = finch_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_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
finch_media_signals[MESSAGE] = g_signal_new("message", G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
}
static void
finch_media_init (FinchMedia *media)
{
media->priv = finch_media_get_instance_private(media);
media->priv->calling = gnt_label_new(_("Calling..."));
media->priv->hangup = gnt_button_new(_("Hangup"));
media->priv->accept = gnt_button_new(_("Accept"));
media->priv->reject = gnt_button_new(_("Reject"));
gnt_box_set_alignment(GNT_BOX(media), GNT_ALIGN_MID);
gnt_box_add_widget(GNT_BOX(media), media->priv->accept);
gnt_box_add_widget(GNT_BOX(media), media->priv->reject);
}
static void
finch_media_finalize (GObject *media)
{
FinchMedia *gntmedia = FINCH_MEDIA(media);
purple_debug_info("gntmedia", "finch_media_finalize\n");
if (gntmedia->priv->media)
g_object_unref(gntmedia->priv->media);
}
static void
finch_media_emit_message(FinchMedia *gntmedia, const char *msg)
{
g_signal_emit(gntmedia, finch_media_signals[MESSAGE], 0, msg);
}
static void
finch_media_connected_cb(PurpleMedia *media, FinchMedia *gntmedia)
{
GntWidget *parent;
finch_media_emit_message(gntmedia, _("Call in progress."));
gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->accept);
gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->reject);
gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->hangup);
gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->calling);
gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->hangup);
gnt_widget_destroy(gntmedia->priv->accept);
gnt_widget_destroy(gntmedia->priv->reject);
gnt_widget_destroy(gntmedia->priv->calling);
gntmedia->priv->accept = NULL;
gntmedia->priv->reject = NULL;
gntmedia->priv->calling = NULL;
parent = gnt_widget_get_toplevel(GNT_WIDGET(gntmedia));
gnt_box_readjust(GNT_BOX(parent));
gnt_widget_draw(parent);
}
static void
finch_media_wait_cb(PurpleMedia *media, FinchMedia *gntmedia)
{
GntWidget *parent;
gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->accept);
gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->reject);
gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->hangup);
gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->calling);
gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->calling);
gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->hangup);
parent = gnt_widget_get_toplevel(GNT_WIDGET(gntmedia));
gnt_box_readjust(GNT_BOX(parent));
gnt_widget_draw(parent);
}
static void
finch_media_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
gchar *sid, gchar *name, FinchMedia *gntmedia)
{
purple_debug_info("gntmedia", "state: %d sid: %s name: %s\n",
state, sid, name);
if (sid == NULL && name == NULL) {
if (state == PURPLE_MEDIA_STATE_END) {
finch_media_emit_message(gntmedia,
_("The call has been terminated."));
finch_conversation_set_info_widget(
gntmedia->priv->conv, NULL);
gnt_widget_destroy(GNT_WIDGET(gntmedia));
/*
* XXX: This shouldn't have to be here
* to free the FinchMedia widget.
*/
g_object_unref(gntmedia);
}
} else if (state == PURPLE_MEDIA_STATE_CONNECTED) {
finch_media_connected_cb(media, gntmedia);
} else if (state == PURPLE_MEDIA_STATE_NEW &&
sid != NULL && name != NULL &&
purple_media_is_initiator(media, sid, name) == FALSE) {
PurpleAccount *account;
PurpleBuddy *buddy;
const gchar *alias;
PurpleMediaSessionType type =
purple_media_get_session_type(media, sid);
gchar *message = NULL;
account = purple_media_get_account(gntmedia->priv->media);
buddy = purple_blist_find_buddy(account, name);
alias = buddy ? purple_buddy_get_contact_alias(buddy) : name;
if (type & PURPLE_MEDIA_AUDIO) {
message = g_strdup_printf(
_("%s wishes to start an audio session with you."),
alias);
} else {
message = g_strdup_printf(
_("%s is trying to start an unsupported media session type with you."),
alias);
}
finch_media_emit_message(gntmedia, message);
g_free(message);
}
}
static void
finch_media_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
gchar *sid, gchar *name, gboolean local, FinchMedia *gntmedia)
{
if (type == PURPLE_MEDIA_INFO_REJECT) {
finch_media_emit_message(gntmedia,
_("You have rejected the call."));
}
}
static void
finch_media_accept_cb(PurpleMedia *media, GntWidget *widget)
{
purple_media_stream_info(media, PURPLE_MEDIA_INFO_ACCEPT,
NULL, NULL, TRUE);
}
static void
finch_media_hangup_cb(PurpleMedia *media, GntWidget *widget)
{
purple_media_stream_info(media, PURPLE_MEDIA_INFO_HANGUP,
NULL, NULL, TRUE);
}
static void
finch_media_reject_cb(PurpleMedia *media, GntWidget *widget)
{
purple_media_stream_info(media, PURPLE_MEDIA_INFO_REJECT,
NULL, NULL, TRUE);
}
static void
finch_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
FinchMedia *media;
g_return_if_fail(FINCH_IS_MEDIA(object));
media = FINCH_MEDIA(object);
switch (prop_id) {
case PROP_MEDIA:
{
if (media->priv->media)
g_object_unref(media->priv->media);
media->priv->media = g_value_dup_object(value);
g_signal_connect_swapped(G_OBJECT(media->priv->accept), "activate",
G_CALLBACK(finch_media_accept_cb), media->priv->media);
g_signal_connect_swapped(G_OBJECT(media->priv->reject), "activate",
G_CALLBACK(finch_media_reject_cb), media->priv->media);
g_signal_connect_swapped(G_OBJECT(media->priv->hangup), "activate",
G_CALLBACK(finch_media_hangup_cb), media->priv->media);
if (purple_media_is_initiator(media->priv->media,
NULL, NULL) == TRUE) {
finch_media_wait_cb(media->priv->media, media);
}
g_signal_connect(G_OBJECT(media->priv->media), "state-changed",
G_CALLBACK(finch_media_state_changed_cb), media);
g_signal_connect(G_OBJECT(media->priv->media), "stream-info",
G_CALLBACK(finch_media_stream_info_cb), media);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
finch_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
FinchMedia *media;
g_return_if_fail(FINCH_IS_MEDIA(object));
media = FINCH_MEDIA(object);
switch (prop_id) {
case PROP_MEDIA:
g_value_set_object(value, media->priv->media);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GntWidget *
finch_media_new(PurpleMedia *media)
{
return GNT_WIDGET(g_object_new(finch_media_get_type(),
"media", media,
"vertical", FALSE,
"homogeneous", FALSE,
NULL));
}
static void
gntmedia_message_cb(FinchMedia *gntmedia, const char *msg, PurpleConversation *conv)
{
if (PURPLE_IS_IM_CONVERSATION(conv)) {
purple_conversation_write_system_message(conv, msg, 0);
}
}
static gboolean
finch_new_media(PurpleMediaManager *manager, PurpleMedia *media,
PurpleAccount *account, gchar *name, gpointer null)
{
GntWidget *gntmedia;
PurpleConversation *conv;
conv = PURPLE_CONVERSATION(purple_im_conversation_new(account, name));
gntmedia = finch_media_new(media);
g_signal_connect(G_OBJECT(gntmedia), "message", G_CALLBACK(gntmedia_message_cb), conv);
FINCH_MEDIA(gntmedia)->priv->conv = conv;
finch_conversation_set_info_widget(conv, gntmedia);
return TRUE;
}
static PurpleCmdRet
call_cmd_cb(PurpleConversation *conv, const char *cmd, char **args,
char **eror, gpointer data)
{
PurpleAccount *account = purple_conversation_get_account(conv);
if (!purple_protocol_initiate_media(account,
purple_conversation_get_name(conv),
PURPLE_MEDIA_AUDIO))
return PURPLE_CMD_RET_FAILED;
return PURPLE_CMD_RET_OK;
}
#endif /* USE_VV */
void finch_media_manager_init(void)
{
#ifdef USE_VV
PurpleMediaManager *manager = purple_media_manager_get();
PurpleMediaElementInfo *audio_src = NULL;
PurpleMediaElementInfo *audio_sink = NULL;
const char *pref;
pref = purple_prefs_get_string(
FINCH_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(
FINCH_PREFS_ROOT "/vvconfig/audio/src/device", pref);
audio_src = purple_media_manager_get_element_info(manager,
pref);
}
pref = purple_prefs_get_string(
FINCH_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(
FINCH_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(finch_new_media), NULL);
purple_cmd_register("call", "", PURPLE_CMD_P_DEFAULT,
PURPLE_CMD_FLAG_IM, NULL,
call_cmd_cb, _("call: Make an audio call."), NULL);
purple_media_manager_set_ui_caps(manager,
PURPLE_MEDIA_CAPS_AUDIO |
PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION);
purple_debug_info("gntmedia", "Registering media element types\n");
purple_media_manager_set_active_element(manager, audio_src);
purple_media_manager_set_active_element(manager, audio_sink);
#endif
}
void finch_media_manager_uninit(void)
{
#ifdef USE_VV
PurpleMediaManager *manager = purple_media_manager_get();
g_signal_handlers_disconnect_by_func(G_OBJECT(manager),
G_CALLBACK(finch_new_media), NULL);
#endif
}