pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Update to libadwaita 1.2
20 months ago, Gary Kramlich
cde17b22217f
Update to libadwaita 1.2
Fedora 36 updates finally has it and all of our build agents have it as well,
so it's time to move to it, so we can update a bunch of stuff.
Testing Done:
compiled
Reviewed at https://reviews.imfreedom.org/r/1988/
/*
* 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
<config.h>
#include
<glib/gi18n-lib.h>
#include
<purple.h>
#include
<gnt.h>
#include
"gntconv.h"
#include
"gntmedia.h"
#include
"libfinch.h"
/* An incredibly large part of the following is from gtkmedia.c */
#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
enum
_FinchMediaState
FinchMediaState
;
struct
_FinchMediaClass
{
GntBoxClass
parent_class
;
};
struct
_FinchMedia
{
GntBox
parent
;
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
(
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
->
calling
=
gnt_label_new
(
_
(
"Calling..."
));
media
->
hangup
=
gnt_button_new
(
_
(
"Hangup"
));
media
->
accept
=
gnt_button_new
(
_
(
"Accept"
));
media
->
reject
=
gnt_button_new
(
_
(
"Reject"
));
gnt_box_set_alignment
(
GNT_BOX
(
media
),
GNT_ALIGN_MID
);
gnt_box_add_widget
(
GNT_BOX
(
media
),
media
->
accept
);
gnt_box_add_widget
(
GNT_BOX
(
media
),
media
->
reject
);
}
static
void
finch_media_finalize
(
GObject
*
media
)
{
FinchMedia
*
gntmedia
=
FINCH_MEDIA
(
media
);
purple_debug_info
(
"gntmedia"
,
"finch_media_finalize"
);
g_clear_object
(
&
gntmedia
->
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
->
accept
);
gnt_box_remove
(
GNT_BOX
(
gntmedia
),
gntmedia
->
reject
);
gnt_box_remove
(
GNT_BOX
(
gntmedia
),
gntmedia
->
hangup
);
gnt_box_remove
(
GNT_BOX
(
gntmedia
),
gntmedia
->
calling
);
gnt_box_add_widget
(
GNT_BOX
(
gntmedia
),
gntmedia
->
hangup
);
g_clear_pointer
(
&
gntmedia
->
accept
,
gnt_widget_destroy
);
g_clear_pointer
(
&
gntmedia
->
reject
,
gnt_widget_destroy
);
g_clear_pointer
(
&
gntmedia
->
calling
,
gnt_widget_destroy
);
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
->
accept
);
gnt_box_remove
(
GNT_BOX
(
gntmedia
),
gntmedia
->
reject
);
gnt_box_remove
(
GNT_BOX
(
gntmedia
),
gntmedia
->
hangup
);
gnt_box_remove
(
GNT_BOX
(
gntmedia
),
gntmedia
->
calling
);
gnt_box_add_widget
(
GNT_BOX
(
gntmedia
),
gntmedia
->
calling
);
gnt_box_add_widget
(
GNT_BOX
(
gntmedia
),
gntmedia
->
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
->
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
->
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
:
g_set_object
(
&
media
->
media
,
g_value_get_object
(
value
));
g_signal_connect_swapped
(
G_OBJECT
(
media
->
accept
),
"activate"
,
G_CALLBACK
(
finch_media_accept_cb
),
media
->
media
);
g_signal_connect_swapped
(
G_OBJECT
(
media
->
reject
),
"activate"
,
G_CALLBACK
(
finch_media_reject_cb
),
media
->
media
);
g_signal_connect_swapped
(
G_OBJECT
(
media
->
hangup
),
"activate"
,
G_CALLBACK
(
finch_media_hangup_cb
),
media
->
media
);
if
(
purple_media_is_initiator
(
media
->
media
,
NULL
,
NULL
))
{
finch_media_wait_cb
(
media
->
media
,
media
);
}
g_signal_connect
(
G_OBJECT
(
media
->
media
),
"state-changed"
,
G_CALLBACK
(
finch_media_state_changed_cb
),
media
);
g_signal_connect
(
G_OBJECT
(
media
->
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
->
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
)
->
conv
=
conv
;
finch_conversation_set_info_widget
(
conv
,
gntmedia
);
return
TRUE
;
}
static
PurpleCmdRet
call_cmd_cb
(
PurpleConversation
*
conv
,
const
char
*
cmd
,
char
**
args
,
char
**
error
,
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
;
}
void
finch_media_manager_init
(
void
)
{
PurpleMediaManager
*
manager
=
purple_media_manager_get
();
PurpleMediaElementInfo
*
audio_src
=
NULL
;
PurpleMediaElementInfo
*
audio_sink
=
NULL
;
const
char
*
pref
;
purple_prefs_add_none
(
FINCH_PREFS_ROOT
"/vvconfig"
);
purple_prefs_add_none
(
FINCH_PREFS_ROOT
"/vvconfig/audio"
);
purple_prefs_add_none
(
FINCH_PREFS_ROOT
"/vvconfig/audio/src"
);
purple_prefs_add_none
(
FINCH_PREFS_ROOT
"/vvconfig/audio/sink"
);
purple_prefs_add_string
(
FINCH_PREFS_ROOT
"/vvconfig/audio/src/device"
,
""
);
purple_prefs_add_string
(
FINCH_PREFS_ROOT
"/vvconfig/audio/sink/device"
,
""
);
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
);
}
void
finch_media_manager_uninit
(
void
)
{
PurpleMediaManager
*
manager
=
purple_media_manager_get
();
g_signal_handlers_disconnect_by_func
(
G_OBJECT
(
manager
),
G_CALLBACK
(
finch_new_media
),
NULL
);
}