pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Remove the deprecated keyring API.
2021-04-21, Gary Kramlich
32c1f097d4e8
Remove the deprecated keyring API.
I've disable the building of the internal keyring for now but left it so it
can be referenced when it is ported to the CredentialProvider API.
Testing Done:
Ran Pidgin and verified the preferences window worked.
Bugs closed: PIDGIN-17486
Reviewed at https://reviews.imfreedom.org/r/624/
/* 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
*/
#ifdef HAVE_CONFIG_H
#
include
<config.h>
#endif
#include
<glib/gi18n-lib.h>
#include
<gtk/gtk.h>
#include
<purple.h>
#include
"gtkmedia.h"
#include
"gtkutils.h"
#include
"pidgincore.h"
#include
"pidginstock.h"
#ifdef USE_VV
#ifdef GDK_WINDOWING_WIN32
#include
<gdk/gdkwin32.h>
#endif
#ifdef GDK_WINDOWING_X11
#include
<gdk/gdkx.h>
#endif
#ifdef GDK_WINDOWING_QUARTZ
#include
<gdk/gdkquartz.h>
#endif
#include
<gdk/gdkkeysyms.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
;
GtkBuilder
*
ui
;
GtkWidget
*
menubar
;
GtkWidget
*
statusbar
;
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
);
#if 0
enum {
LAST_SIGNAL
};
static guint pidgin_media_signals[LAST_SIGNAL] = {0};
#endif
enum
{
PROP_0
,
PROP_MEDIA
,
PROP_SCREENNAME
};
static
void
pidgin_media_class_init
(
PidginMediaClass
*
klass
)
{
GObjectClass
*
gobject_class
=
G_OBJECT_CLASS
(
klass
);
/* GtkContainerClass *container_class = (GtkContainerClass*)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
));
}
static
void
pidgin_media_hangup_activate_cb
(
GSimpleAction
*
action
,
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
gboolean
pidgin_media_delete_event_cb
(
GtkWidget
*
widget
,
GdkEvent
*
event
,
PidginMedia
*
media
)
{
if
(
media
->
priv
->
media
)
g_action_group_activate_action
(
G_ACTION_GROUP
(
media
),
"Hangup"
,
NULL
);
return
FALSE
;
}
#ifdef HAVE_X11
static
int
pidgin_x_error_handler
(
Display
*
display
,
XErrorEvent
*
event
)
{
const
gchar
*
error_type
;
switch
(
event
->
error_code
)
{
#define XERRORCASE(type) case type: error_type = #type; break
XERRORCASE
(
BadAccess
);
XERRORCASE
(
BadAlloc
);
XERRORCASE
(
BadAtom
);
XERRORCASE
(
BadColor
);
XERRORCASE
(
BadCursor
);
XERRORCASE
(
BadDrawable
);
XERRORCASE
(
BadFont
);
XERRORCASE
(
BadGC
);
XERRORCASE
(
BadIDChoice
);
XERRORCASE
(
BadImplementation
);
XERRORCASE
(
BadLength
);
XERRORCASE
(
BadMatch
);
XERRORCASE
(
BadName
);
XERRORCASE
(
BadPixmap
);
XERRORCASE
(
BadRequest
);
XERRORCASE
(
BadValue
);
XERRORCASE
(
BadWindow
);
#undef XERRORCASE
default
:
error_type
=
"unknown"
;
break
;
}
purple_debug_error
(
"media"
,
"A %s Xlib error has occurred. "
"The program would normally crash now.
\n
"
,
error_type
);
return
0
;
}
#endif
static
const
GActionEntry
media_action_entries
[]
=
{
{
"Hangup"
,
pidgin_media_hangup_activate_cb
},
{
"Hold"
,
NULL
,
NULL
,
"false"
,
pidgin_media_hold_change_state_cb
},
{
"Mute"
,
NULL
,
NULL
,
"false"
,
pidgin_media_mute_change_state_cb
},
{
"Pause"
,
NULL
,
NULL
,
"false"
,
pidgin_media_pause_change_state_cb
},
};
static
const
gchar
*
media_menu
=
"<interface>"
"<menu id='MediaMenu'>"
"<submenu>"
"<attribute name='label' translatable='yes'>_Media</attribute>"
"<section>"
"<item>"
"<attribute name='label' translatable='yes'>_Hangup</attribute>"
"<attribute name='action'>win.Hangup</attribute>"
"</item>"
"</section>"
"</submenu>"
"</menu>"
"</interface>"
;
static
GtkWidget
*
setup_menubar
(
PidginMedia
*
window
)
{
GError
*
error
;
GtkWidget
*
menu
;
window
->
priv
->
ui
=
gtk_builder_new
();
gtk_builder_set_translation_domain
(
window
->
priv
->
ui
,
PACKAGE
);
error
=
NULL
;
if
(
!
gtk_builder_add_from_string
(
window
->
priv
->
ui
,
media_menu
,
-1
,
&
error
))
{
g_message
(
"building menus failed: %s"
,
error
->
message
);
g_error_free
(
error
);
exit
(
EXIT_FAILURE
);
}
menu
=
gtk_menu_bar_new_from_model
(
G_MENU_MODEL
(
gtk_builder_get_object
(
window
->
priv
->
ui
,
"MediaMenu"
)));
gtk_widget_show
(
menu
);
return
menu
;
}
static
void
pidgin_media_init
(
PidginMedia
*
media
)
{
GtkWidget
*
vbox
;
media
->
priv
=
pidgin_media_get_instance_private
(
media
);
#ifdef HAVE_X11
XSetErrorHandler
(
pidgin_x_error_handler
);
#endif
g_action_map_add_action_entries
(
G_ACTION_MAP
(
media
),
media_action_entries
,
G_N_ELEMENTS
(
media_action_entries
),
media
);
vbox
=
gtk_box_new
(
GTK_ORIENTATION_VERTICAL
,
0
);
gtk_container_add
(
GTK_CONTAINER
(
media
),
vbox
);
media
->
priv
->
statusbar
=
gtk_statusbar_new
();
gtk_box_pack_end
(
GTK_BOX
(
vbox
),
media
->
priv
->
statusbar
,
FALSE
,
FALSE
,
0
);
gtk_statusbar_push
(
GTK_STATUSBAR
(
media
->
priv
->
statusbar
),
0
,
_
(
"Calling..."
));
gtk_widget_show
(
media
->
priv
->
statusbar
);
media
->
priv
->
menubar
=
setup_menubar
(
media
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
media
->
priv
->
menubar
,
FALSE
,
TRUE
,
0
);
media
->
priv
->
display
=
gtk_box_new
(
GTK_ORIENTATION_HORIZONTAL
,
6
);
gtk_container_set_border_width
(
GTK_CONTAINER
(
media
->
priv
->
display
),
6
);
gtk_box_pack_start
(
GTK_BOX
(
vbox
),
media
->
priv
->
display
,
TRUE
,
TRUE
,
6
);
gtk_widget_show
(
vbox
);
g_signal_connect
(
G_OBJECT
(
media
),
"delete-event"
,
G_CALLBACK
(
pidgin_media_delete_event_cb
),
media
);
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
=
pidgin_media_get_widget
(
gtkmedia
,
session_id
,
participant
);
if
(
widget
)
{
PurpleMediaSessionType
type
=
purple_media_get_session_type
(
gtkmedia
->
priv
->
media
,
session_id
);
gchar
*
key
=
create_key
(
session_id
,
participant
);
GtkRequisition
req
;
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
)
{
gtk_widget_destroy
(
gtkmedia
->
priv
->
send_progress
);
gtkmedia
->
priv
->
send_progress
=
NULL
;
gtk_widget_destroy
(
gtkmedia
->
priv
->
mute
);
gtkmedia
->
priv
->
mute
=
NULL
;
}
}
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
)
{
gtk_widget_destroy
(
gtkmedia
->
priv
->
local_video
);
gtkmedia
->
priv
->
local_video
=
NULL
;
gtk_widget_destroy
(
gtkmedia
->
priv
->
pause
);
gtkmedia
->
priv
->
pause
=
NULL
;
}
}
g_free
(
key
);
gtk_widget_destroy
(
widget
);
gtk_widget_get_preferred_size
(
GTK_WIDGET
(
gtkmedia
),
NULL
,
&
req
);
gtk_window_resize
(
GTK_WINDOW
(
gtkmedia
),
req
.
width
,
req
.
height
);
}
}
static
void
level_message_cb
(
PurpleMedia
*
media
,
gchar
*
session_id
,
gchar
*
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
=
purple_media_get_manager
(
media
);
GstElement
*
element
=
purple_media_manager_get_pipeline
(
manager
);
gulong
handler_id
=
g_signal_handler_find
(
G_OBJECT
(
gst_pipeline_get_bus
(
GST_PIPELINE
(
element
))),
G_SIGNAL_MATCH_FUNC
|
G_SIGNAL_MATCH_DATA
,
0
,
0
,
NULL
,
G_CALLBACK
(
level_message_cb
),
gtkmedia
);
if
(
handler_id
)
g_signal_handler_disconnect
(
G_OBJECT
(
gst_pipeline_get_bus
(
GST_PIPELINE
(
element
))),
handler_id
);
}
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_object_unref
(
gtkmedia
->
priv
->
media
);
gtkmedia
->
priv
->
media
=
NULL
;
}
if
(
gtkmedia
->
priv
->
ui
)
{
g_object_unref
(
gtkmedia
->
priv
->
ui
);
gtkmedia
->
priv
->
ui
=
NULL
;
}
if
(
gtkmedia
->
priv
->
timeout_id
!=
0
)
g_source_remove
(
gtkmedia
->
priv
->
timeout_id
);
if
(
gtkmedia
->
priv
->
recv_progressbars
)
{
g_hash_table_destroy
(
gtkmedia
->
priv
->
recv_progressbars
);
g_hash_table_destroy
(
gtkmedia
->
priv
->
remote_videos
);
gtkmedia
->
priv
->
recv_progressbars
=
NULL
;
gtkmedia
->
priv
->
remote_videos
=
NULL
;
}
if
(
gtkmedia
->
priv
->
screenname
)
{
g_free
(
gtkmedia
->
priv
->
screenname
);
gtkmedia
->
priv
->
screenname
=
NULL
;
}
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
)
{
PurpleAccount
*
account
=
purple_media_get_account
(
gtkmedia
->
priv
->
media
);
PurpleConversation
*
conv
=
purple_conversations_find_with_account
(
gtkmedia
->
priv
->
screenname
,
account
);
if
(
conv
!=
NULL
)
purple_conversation_write_system_message
(
conv
,
msg
,
0
);
g_object_unref
(
account
);
}
static
void
pidgin_media_error_cb
(
PidginMedia
*
media
,
const
char
*
error
,
PidginMedia
*
gtkmedia
)
{
PurpleAccount
*
account
=
purple_media_get_account
(
gtkmedia
->
priv
->
media
);
PurpleConversation
*
conv
=
purple_conversations_find_with_account
(
gtkmedia
->
priv
->
screenname
,
account
);
if
(
conv
!=
NULL
)
{
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_statusbar_push
(
GTK_STATUSBAR
(
gtkmedia
->
priv
->
statusbar
),
0
,
error
);
g_object_unref
(
account
);
}
static
void
pidgin_media_accept_cb
(
PurpleMedia
*
media
,
int
index
)
{
purple_media_stream_info
(
media
,
PURPLE_MEDIA_INFO_ACCEPT
,
NULL
,
NULL
,
TRUE
);
}
static
void
pidgin_media_reject_cb
(
PurpleMedia
*
media
,
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
;
PurpleBuddy
*
buddy
;
const
gchar
*
alias
;
PurpleMediaSessionType
type
;
gchar
*
message
=
NULL
;
account
=
purple_media_get_account
(
gtkmedia
->
priv
->
media
);
buddy
=
purple_blist_find_buddy
(
account
,
gtkmedia
->
priv
->
screenname
);
alias
=
buddy
?
purple_buddy_get_contact_alias
(
buddy
)
:
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
(
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
(
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
(
GtkWidget
*
widget
,
GtkWidget
*
parent
)
{
g_return_if_fail
(
GTK_IS_WIDGET
(
parent
));
gtk_widget_destroy
(
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_box_pack_start
(
GTK_BOX
(
volume_widget
),
progress_parent
,
TRUE
,
TRUE
,
0
);
/* Volume button */
volume
=
gtk_volume_button_new
();
gtk_scale_button_set_value
(
GTK_SCALE_BUTTON
(
volume
),
value
/
100.0
);
gtk_box_pack_end
(
GTK_BOX
(
volume_widget
),
volume
,
FALSE
,
FALSE
,
0
);
/* Volume level indicator */
progress
=
gtk_progress_bar_new
();
gtk_widget_set_size_request
(
progress
,
250
,
10
);
gtk_box_pack_end
(
GTK_BOX
(
progress_parent
),
progress
,
TRUE
,
FALSE
,
0
);
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
);
gtk_widget_show_all
(
volume_widget
);
return
volume_widget
;
}
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
;
const
gchar
*
text_hi_local
;
if
(
text_hi
)
text_hi_local
=
_
(
text_hi
);
else
text_hi_local
=
""
;
grid
=
gtk_box_new
(
GTK_ORIENTATION_VERTICAL
,
0
);
gtk_box_set_homogeneous
(
GTK_BOX
(
grid
),
TRUE
);
button
=
gtk_button_new
();
label_hi
=
gtk_label_new
(
text_hi_local
);
gtk_box_pack_end
(
GTK_BOX
(
grid
),
label_hi
,
FALSE
,
TRUE
,
0
);
label_lo
=
gtk_label_new
(
text_lo
);
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
struct
phone_label
{
gchar
*
subtext
;
gchar
*
text
;
gchar
chr
;
}
phone_labels
[]
=
{
{
"<b>1</b>"
,
NULL
,
'1'
},
/* Translators note: These are the letters on the keys of a numeric
keypad; translate according to the tables in §7 of ETSI ES 202 130:
http://webapp.etsi.org/WorkProgram/Report_WorkItem.asp?WKI_ID=11730
*/
/* Letters on the '2' key of a numeric keypad */
{
"<b>2</b>"
,
N_
(
"ABC"
),
'2'
},
/* Letters on the '3' key of a numeric keypad */
{
"<b>3</b>"
,
N_
(
"DEF"
),
'3'
},
/* Letters on the '4' key of a numeric keypad */
{
"<b>4</b>"
,
N_
(
"GHI"
),
'4'
},
/* Letters on the '5' key of a numeric keypad */
{
"<b>5</b>"
,
N_
(
"JKL"
),
'5'
},
/* Letters on the '6' key of a numeric keypad */
{
"<b>6</b>"
,
N_
(
"MNO"
),
'6'
},
/* Letters on the '7' key of a numeric keypad */
{
"<b>7</b>"
,
N_
(
"PQRS"
),
'7'
},
/* Letters on the '8' key of a numeric keypad */
{
"<b>8</b>"
,
N_
(
"TUV"
),
'8'
},
/* Letters on the '9' key of a numeric keypad */
{
"<b>9</b>"
,
N_
(
"WXYZ"
),
'9'
},
{
"<b>*</b>"
,
NULL
,
'*'
},
{
"<b>0</b>"
,
NULL
,
'0'
},
{
"<b>#</b>"
,
NULL
,
'#'
},
{
NULL
,
NULL
,
0
}
};
static
gboolean
pidgin_media_dtmf_key_press_event_cb
(
GtkWidget
*
widget
,
GdkEvent
*
event
,
gpointer
user_data
)
{
PidginMedia
*
gtkmedia
=
user_data
;
GdkEventKey
*
key
=
(
GdkEventKey
*
)
event
;
if
(
event
->
type
!=
GDK_KEY_PRESS
)
{
return
FALSE
;
}
if
((
key
->
keyval
>=
GDK_KEY_0
&&
key
->
keyval
<=
GDK_KEY_9
)
||
key
->
keyval
==
GDK_KEY_asterisk
||
key
->
keyval
==
GDK_KEY_numbersign
)
{
gchar
*
sid
=
g_object_get_data
(
G_OBJECT
(
widget
),
"session-id"
);
purple_media_send_dtmf
(
gtkmedia
->
priv
->
media
,
sid
,
key
->
keyval
,
25
,
50
);
}
return
FALSE
;
}
static
GtkWidget
*
pidgin_media_add_dtmf_widget
(
PidginMedia
*
gtkmedia
,
PurpleMediaSessionType
type
,
const
gchar
*
_sid
)
{
GtkWidget
*
grid
=
gtk_grid_new
();
GtkWidget
*
button
;
gint
index
=
0
;
GtkApplicationWindow
*
win
=
&
gtkmedia
->
parent
;
gtk_grid_set_row_homogeneous
(
GTK_GRID
(
grid
),
TRUE
);
gtk_grid_set_column_homogeneous
(
GTK_GRID
(
grid
),
TRUE
);
/* Add buttons */
for
(
index
=
0
;
phone_labels
[
index
].
subtext
!=
NULL
;
index
++
)
{
button
=
phone_create_button
(
phone_labels
[
index
].
text
,
phone_labels
[
index
].
subtext
);
g_signal_connect
(
button
,
"pressed"
,
G_CALLBACK
(
phone_dtmf_pressed_cb
),
gtkmedia
);
g_object_set_data
(
G_OBJECT
(
button
),
"dtmf-digit"
,
GINT_TO_POINTER
(
phone_labels
[
index
].
chr
));
g_object_set_data_full
(
G_OBJECT
(
button
),
"session-id"
,
g_strdup
(
_sid
),
g_free
);
gtk_grid_attach
(
GTK_GRID
(
grid
),
button
,
index
%
3
,
index
/
3
,
1
,
1
);
g_object_set
(
button
,
"expand"
,
TRUE
,
"margin"
,
2
,
NULL
);
}
g_signal_connect
(
G_OBJECT
(
win
),
"key-press-event"
,
G_CALLBACK
(
pidgin_media_dtmf_key_press_event_cb
),
gtkmedia
);
g_object_set_data_full
(
G_OBJECT
(
win
),
"session-id"
,
g_strdup
(
_sid
),
g_free
);
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
;
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_box_pack_start
(
GTK_BOX
(
gtkmedia
->
priv
->
display
),
recv_widget
,
TRUE
,
TRUE
,
0
);
gtk_widget_show
(
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_pack_start
(
GTK_BOX
(
gtkmedia
->
priv
->
display
),
send_widget
,
FALSE
,
TRUE
,
0
);
button_widget
=
gtk_box_new
(
GTK_ORIENTATION_HORIZONTAL
,
6
);
gtk_box_pack_end
(
GTK_BOX
(
recv_widget
),
button_widget
,
FALSE
,
TRUE
,
0
);
gtk_widget_show
(
send_widget
);
/* Hold button */
gtkmedia
->
priv
->
hold
=
gtk_toggle_button_new_with_mnemonic
(
_
(
"_Hold"
));
gtk_box_pack_end
(
GTK_BOX
(
button_widget
),
gtkmedia
->
priv
->
hold
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
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
(
G_OBJECT
(
sink
),
"widget"
,
&
remote_video
,
NULL
);
gtk_widget_show
(
remote_video
);
gtk_box_pack_start
(
GTK_BOX
(
recv_widget
),
remote_video
,
TRUE
,
TRUE
,
0
);
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
(
G_OBJECT
(
sink
),
"widget"
,
&
local_video
,
NULL
);
gtk_widget_show
(
local_video
);
gtk_box_pack_start
(
GTK_BOX
(
send_widget
),
local_video
,
TRUE
,
TRUE
,
0
);
gtkmedia
->
priv
->
pause
=
gtk_toggle_button_new_with_mnemonic
(
_
(
"_Pause"
));
gtk_box_pack_end
(
GTK_BOX
(
button_widget
),
gtkmedia
->
priv
->
pause
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
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
)
{
gtk_box_pack_end
(
GTK_BOX
(
recv_widget
),
pidgin_media_add_audio_widget
(
gtkmedia
,
PURPLE_MEDIA_RECV_AUDIO
,
sid
),
FALSE
,
FALSE
,
0
);
}
if
(
type
&
PURPLE_MEDIA_SEND_AUDIO
)
{
gtkmedia
->
priv
->
mute
=
gtk_toggle_button_new_with_mnemonic
(
_
(
"_Mute"
));
gtk_box_pack_end
(
GTK_BOX
(
button_widget
),
gtkmedia
->
priv
->
mute
,
FALSE
,
FALSE
,
0
);
gtk_widget_show
(
gtkmedia
->
priv
->
mute
);
gtk_actionable_set_action_name
(
GTK_ACTIONABLE
(
gtkmedia
->
priv
->
mute
),
"win.Mute"
);
gtk_box_pack_end
(
GTK_BOX
(
recv_widget
),
pidgin_media_add_audio_widget
(
gtkmedia
,
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
&&
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
;
gtk_widget_show
(
GTK_WIDGET
(
button_widget
));
}
if
(
purple_media_is_initiator
(
media
,
sid
,
NULL
)
==
FALSE
)
{
if
(
gtkmedia
->
priv
->
timeout_id
!=
0
)
g_source_remove
(
gtkmedia
->
priv
->
timeout_id
);
gtkmedia
->
priv
->
request_type
|=
type
;
gtkmedia
->
priv
->
timeout_id
=
g_timeout_add
(
500
,
(
GSourceFunc
)
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"
);
}
gtk_widget_show
(
gtkmedia
->
priv
->
display
);
}
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_widget_destroy
(
GTK_WIDGET
(
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
(
PurpleMedia
*
media
,
PurpleMediaInfoType
type
,
gchar
*
sid
,
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
==
TRUE
)
purple_request_close_with_handle
(
gtkmedia
);
pidgin_media_set_state
(
gtkmedia
,
PIDGIN_MEDIA_ACCEPTED
);
pidgin_media_emit_message
(
gtkmedia
,
_
(
"Call in progress."
));
gtk_statusbar_push
(
GTK_STATUSBAR
(
gtkmedia
->
priv
->
statusbar
),
0
,
_
(
"Call in progress"
));
gtk_widget_show
(
GTK_WIDGET
(
gtkmedia
));
}
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
;
g_return_if_fail
(
PIDGIN_IS_MEDIA
(
object
));
media
=
PIDGIN_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
);
if
(
purple_media_is_initiator
(
media
->
priv
->
media
,
NULL
,
NULL
)
==
TRUE
)
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
;
g_return_if_fail
(
PIDGIN_IS_MEDIA
(
object
));
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
(
PurpleMediaManager
*
manager
,
PurpleMedia
*
media
,
PurpleAccount
*
account
,
gchar
*
screenname
,
gpointer
nul
)
{
PidginMedia
*
gtkmedia
=
PIDGIN_MEDIA
(
pidgin_media_new
(
media
,
screenname
));
PurpleBuddy
*
buddy
=
purple_blist_find_buddy
(
account
,
screenname
);
const
gchar
*
alias
=
buddy
?
purple_buddy_get_contact_alias
(
buddy
)
:
screenname
;
gtk_window_set_title
(
GTK_WINDOW
(
gtkmedia
),
alias
);
if
(
purple_media_is_initiator
(
media
,
NULL
,
NULL
)
==
TRUE
)
gtk_widget_show
(
GTK_WIDGET
(
gtkmedia
));
return
TRUE
;
}
#endif
/* USE_VV */
void
pidgin_medias_init
(
void
)
{
#ifdef USE_VV
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
);
#endif
}