Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
liblinphone
Commits
0b475524
Commit
0b475524
authored
Sep 19, 2012
by
Simon Morlat
Browse files
add call statistics window to gtk
parent
3cd49ea4
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
717 additions
and
134 deletions
+717
-134
coreapi/linphonecall.c
coreapi/linphonecall.c
+11
-6
coreapi/linphonecore.h
coreapi/linphonecore.h
+2
-0
gtk/Makefile.am
gtk/Makefile.am
+2
-1
gtk/call_statistics.ui
gtk/call_statistics.ui
+212
-0
gtk/incall_view.c
gtk/incall_view.c
+102
-0
gtk/main.ui
gtk/main.ui
+388
-127
No files found.
coreapi/linphonecall.c
View file @
0b475524
...
...
@@ -1732,12 +1732,17 @@ const LinphoneCallStats *linphone_call_get_video_stats(const LinphoneCall *call)
* @}
**/
static
void
display_bandwidth
(
RtpSession
*
as
,
RtpSession
*
vs
){
static
void
report_bandwidth
(
LinphoneCall
*
call
,
RtpSession
*
as
,
RtpSession
*
vs
){
call
->
stats
[
LINPHONE_CALL_STATS_AUDIO
].
download_bandwidth
=
(
as
!=
NULL
)
?
(
rtp_session_compute_recv_bandwidth
(
as
)
*
1e-3
)
:
0
;
call
->
stats
[
LINPHONE_CALL_STATS_AUDIO
].
upload_bandwidth
=
(
as
!=
NULL
)
?
(
rtp_session_compute_send_bandwidth
(
as
)
*
1e-3
)
:
0
;
call
->
stats
[
LINPHONE_CALL_STATS_VIDEO
].
download_bandwidth
=
(
vs
!=
NULL
)
?
(
rtp_session_compute_recv_bandwidth
(
vs
)
*
1e-3
)
:
0
;
call
->
stats
[
LINPHONE_CALL_STATS_VIDEO
].
upload_bandwidth
=
(
vs
!=
NULL
)
?
(
rtp_session_compute_send_bandwidth
(
vs
)
*
1e-3
)
:
0
;
ms_message
(
"bandwidth usage: audio=[d=%.1f,u=%.1f] video=[d=%.1f,u=%.1f] kbit/sec"
,
(
as
!=
NULL
)
?
(
rtp_session_compute_recv_bandwidth
(
as
)
*
1e-3
)
:
0
,
(
as
!=
NULL
)
?
(
rtp_session_compute_send_bandwidth
(
as
)
*
1e-3
)
:
0
,
(
vs
!=
NULL
)
?
(
rtp_session_compute_recv_bandwidth
(
vs
)
*
1e-3
)
:
0
,
(
vs
!=
NULL
)
?
(
rtp_session_compute_send_bandwidth
(
vs
)
*
1e-3
)
:
0
);
call
->
stats
[
LINPHONE_CALL_STATS_AUDIO
].
download_bandwidth
,
call
->
stats
[
LINPHONE_CALL_STATS_AUDIO
].
upload_bandwidth
,
call
->
stats
[
LINPHONE_CALL_STATS_VIDEO
].
download_bandwidth
,
call
->
stats
[
LINPHONE_CALL_STATS_VIDEO
].
upload_bandwidth
);
}
static
void
linphone_core_disconnected
(
LinphoneCore
*
lc
,
LinphoneCall
*
call
){
...
...
@@ -1848,7 +1853,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
video_load
=
ms_ticker_get_average_load
(
call
->
videostream
->
ticker
);
vs
=
call
->
videostream
->
session
;
}
display
_bandwidth
(
as
,
vs
);
report
_bandwidth
(
call
,
as
,
vs
);
ms_message
(
"Thread processing load: audio=%f
\t
video=%f"
,
audio_load
,
video_load
);
}
#ifdef VIDEO_ENABLED
...
...
coreapi/linphonecore.h
View file @
0b475524
...
...
@@ -304,6 +304,8 @@ struct _LinphoneCallStats {
mblk_t
*
sent_rtcp
;
/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float
round_trip_delay
;
/**<Round trip propagation time in seconds if known, -1 if unknown.*/
LinphoneIceState
ice_state
;
/**< State of ICE processing. */
float
download_bandwidth
;
/**<Download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float
upload_bandwidth
;
/**<Download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
};
/**
...
...
gtk/Makefile.am
View file @
0b475524
...
...
@@ -10,7 +10,8 @@ UI_FILES= about.ui \
buddylookup.ui
\
tunnel_config.ui
\
waiting.ui
\
dscp_settings.ui
dscp_settings.ui
\
call_statistics.ui
PIXMAPS
=
\
stock_people.png
...
...
gtk/call_statistics.ui
0 → 100644
View file @
0b475524
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires
lib=
"gtk+"
version=
"2.24"
/>
<!-- interface-naming-policy project-wide -->
<object
class=
"GtkDialog"
id=
"call_statistics"
>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"border_width"
>
5
</property>
<property
name=
"title"
translatable=
"yes"
>
Call statistics
</property>
<property
name=
"type_hint"
>
dialog
</property>
<signal
name=
"response"
handler=
"linphone_gtk_call_statistics_closed"
swapped=
"no"
/>
<child
internal-child=
"vbox"
>
<object
class=
"GtkVBox"
id=
"dialog-vbox1"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"spacing"
>
2
</property>
<child
internal-child=
"action_area"
>
<object
class=
"GtkHButtonBox"
id=
"dialog-action_area1"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"layout_style"
>
end
</property>
<child>
<placeholder/>
</child>
<child>
<object
class=
"GtkButton"
id=
"button1"
>
<property
name=
"label"
>
gtk-close
</property>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
True
</property>
<property
name=
"receives_default"
>
True
</property>
<property
name=
"use_action_appearance"
>
False
</property>
<property
name=
"use_stock"
>
True
</property>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
False
</property>
<property
name=
"position"
>
1
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"pack_type"
>
end
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
<child>
<object
class=
"GtkFrame"
id=
"frame1"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"label_xalign"
>
0
</property>
<property
name=
"shadow_type"
>
none
</property>
<child>
<object
class=
"GtkAlignment"
id=
"alignment1"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"left_padding"
>
12
</property>
<child>
<object
class=
"GtkTable"
id=
"table1"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"n_rows"
>
6
</property>
<property
name=
"n_columns"
>
2
</property>
<property
name=
"homogeneous"
>
True
</property>
<child>
<object
class=
"GtkLabel"
id=
"audio_codec_label"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
Audio codec
</property>
</object>
<packing>
<property
name=
"x_options"
></property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"video_codec_label"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
Video codec
</property>
</object>
<packing>
<property
name=
"top_attach"
>
1
</property>
<property
name=
"bottom_attach"
>
2
</property>
<property
name=
"x_options"
></property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"label3"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
Audio IP bandwidth usage
</property>
</object>
<packing>
<property
name=
"top_attach"
>
2
</property>
<property
name=
"bottom_attach"
>
3
</property>
<property
name=
"x_options"
></property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"audio_codec"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
</object>
<packing>
<property
name=
"left_attach"
>
1
</property>
<property
name=
"right_attach"
>
2
</property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"video_codec"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
</object>
<packing>
<property
name=
"left_attach"
>
1
</property>
<property
name=
"right_attach"
>
2
</property>
<property
name=
"top_attach"
>
1
</property>
<property
name=
"bottom_attach"
>
2
</property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"audio_bandwidth_usage"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
</object>
<packing>
<property
name=
"left_attach"
>
1
</property>
<property
name=
"right_attach"
>
2
</property>
<property
name=
"top_attach"
>
2
</property>
<property
name=
"bottom_attach"
>
3
</property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"label4"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
Media connectivity
</property>
</object>
<packing>
<property
name=
"top_attach"
>
4
</property>
<property
name=
"bottom_attach"
>
5
</property>
<property
name=
"x_options"
></property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object
class=
"GtkLabel"
id=
"media_connectivity"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
</object>
<packing>
<property
name=
"left_attach"
>
1
</property>
<property
name=
"right_attach"
>
2
</property>
<property
name=
"top_attach"
>
4
</property>
<property
name=
"bottom_attach"
>
5
</property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"label1"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
Video IP bandwidth usage
</property>
</object>
<packing>
<property
name=
"top_attach"
>
3
</property>
<property
name=
"bottom_attach"
>
4
</property>
<property
name=
"x_options"
></property>
</packing>
</child>
<child>
<object
class=
"GtkLabel"
id=
"video_bandwidth_usage"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
</object>
<packing>
<property
name=
"left_attach"
>
1
</property>
<property
name=
"right_attach"
>
2
</property>
<property
name=
"top_attach"
>
3
</property>
<property
name=
"bottom_attach"
>
4
</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child
type=
"label"
>
<object
class=
"GtkLabel"
id=
"call_statistics_label"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
<
b
>
Call statistics and information
<
/b
>
</property>
<property
name=
"use_markup"
>
True
</property>
</object>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
False
</property>
<property
name=
"position"
>
1
</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget
response=
"0"
>
button1
</action-widget>
</action-widgets>
</object>
</interface>
gtk/incall_view.c
View file @
0b475524
...
...
@@ -193,6 +193,100 @@ void linphone_gtk_enable_conference_button(LinphoneCore *lc, gboolean value){
}
}
static
void
show_used_codecs
(
GtkWidget
*
callstats
,
LinphoneCall
*
call
){
const
LinphoneCallParams
*
params
=
linphone_call_get_current_params
(
call
);
if
(
params
){
const
PayloadType
*
acodec
=
linphone_call_params_get_used_audio_codec
(
params
);
const
PayloadType
*
vcodec
=
linphone_call_params_get_used_video_codec
(
params
);
GtkWidget
*
acodec_ui
=
linphone_gtk_get_widget
(
callstats
,
"audio_codec"
);
GtkWidget
*
vcodec_ui
=
linphone_gtk_get_widget
(
callstats
,
"video_codec"
);
if
(
acodec
){
char
tmp
[
64
]
=
{
0
};
snprintf
(
tmp
,
sizeof
(
tmp
)
-
1
,
"%s/%i/%i"
,
acodec
->
mime_type
,
acodec
->
clock_rate
,
acodec
->
channels
);
gtk_label_set_label
(
GTK_LABEL
(
acodec_ui
),
tmp
);
}
else
gtk_label_set_label
(
GTK_LABEL
(
acodec_ui
),
_
(
"Not used"
));
if
(
vcodec
){
gtk_label_set_label
(
GTK_LABEL
(
vcodec_ui
),
vcodec
->
mime_type
);
}
else
gtk_label_set_label
(
GTK_LABEL
(
vcodec_ui
),
_
(
"Not used"
));
}
}
static
const
char
*
ice_state_to_string
(
LinphoneIceState
ice_state
){
switch
(
ice_state
){
case
LinphoneIceStateNotActivated
:
return
_
(
"Ice not activated"
);
case
LinphoneIceStateInProgress
:
return
_
(
"ICE in progress"
);
case
LinphoneIceStateReflexiveConnection
:
return
_
(
"Going through one or more NATs"
);
case
LinphoneIceStateHostConnection
:
return
_
(
"Direct"
);
case
LinphoneIceStateRelayConnection
:
return
_
(
"Through a relay server"
);
}
return
"invalid"
;
}
static
void
_refresh_call_stats
(
GtkWidget
*
callstats
,
LinphoneCall
*
call
){
const
LinphoneCallStats
*
as
=
linphone_call_get_audio_stats
(
call
);
const
LinphoneCallStats
*
vs
=
linphone_call_get_video_stats
(
call
);
LinphoneIceState
ice_state
=
as
->
ice_state
;
gchar
*
tmp
=
g_strdup_printf
(
_
(
"download: %f
\n
upload: %f (kbit/s)"
),
as
->
download_bandwidth
,
as
->
upload_bandwidth
);
gtk_label_set_markup
(
GTK_LABEL
(
linphone_gtk_get_widget
(
callstats
,
"audio_bandwidth_usage"
)),
tmp
);
g_free
(
tmp
);
tmp
=
g_strdup_printf
(
_
(
"download: %f
\n
upload: %f (kbit/s)"
),
vs
->
download_bandwidth
,
vs
->
upload_bandwidth
);
gtk_label_set_markup
(
GTK_LABEL
(
linphone_gtk_get_widget
(
callstats
,
"video_bandwidth_usage"
)),
tmp
);
g_free
(
tmp
);
gtk_label_set_text
(
GTK_LABEL
(
linphone_gtk_get_widget
(
callstats
,
"media_connectivity"
)),
ice_state_to_string
(
ice_state
));
}
static
gboolean
refresh_call_stats
(
GtkWidget
*
callstats
){
LinphoneCall
*
call
=
(
LinphoneCall
*
)
g_object_get_data
(
G_OBJECT
(
callstats
),
"call"
);
switch
(
linphone_call_get_state
(
call
)){
case
LinphoneCallError
:
case
LinphoneCallEnd
:
case
LinphoneCallReleased
:
gtk_widget_destroy
(
callstats
);
return
FALSE
;
break
;
case
LinphoneCallStreamsRunning
:
_refresh_call_stats
(
callstats
,
call
);
break
;
default:
break
;
}
return
TRUE
;
}
static
void
on_call_stats_destroyed
(
GtkWidget
*
call_view
){
GtkWidget
*
call_stats
=
(
GtkWidget
*
)
g_object_get_data
(
G_OBJECT
(
call_view
),
"call_stats"
);
LinphoneCall
*
call
=
(
LinphoneCall
*
)
g_object_get_data
(
G_OBJECT
(
call_stats
),
"call"
);
g_source_remove
(
GPOINTER_TO_INT
(
g_object_get_data
(
G_OBJECT
(
call_stats
),
"tid"
)));
g_object_set_data
(
G_OBJECT
(
call_view
),
"call_stats"
,
NULL
);
linphone_call_unref
(
call
);
}
static
void
linphone_gtk_show_call_stats
(
LinphoneCall
*
call
){
GtkWidget
*
w
=
(
GtkWidget
*
)
linphone_call_get_user_pointer
(
call
);
GtkWidget
*
call_stats
=
(
GtkWidget
*
)
g_object_get_data
(
G_OBJECT
(
w
),
"call_stats"
);
if
(
call_stats
==
NULL
){
guint
tid
;
call_stats
=
linphone_gtk_create_window
(
"call_statistics"
);
g_object_set_data
(
G_OBJECT
(
w
),
"call_stats"
,
call_stats
);
g_object_set_data
(
G_OBJECT
(
call_stats
),
"call"
,
linphone_call_ref
(
call
));
tid
=
g_timeout_add
(
1000
,(
GSourceFunc
)
refresh_call_stats
,
call_stats
);
g_object_set_data
(
G_OBJECT
(
call_stats
),
"tid"
,
GINT_TO_POINTER
(
tid
));
g_signal_connect_swapped
(
G_OBJECT
(
call_stats
),
"destroy"
,(
GCallback
)
on_call_stats_destroyed
,(
gpointer
)
w
);
show_used_codecs
(
call_stats
,
call
);
refresh_call_stats
(
call_stats
);
gtk_widget_show
(
call_stats
);
}
}
void
linphone_gtk_create_in_call_view
(
LinphoneCall
*
call
){
GtkWidget
*
call_view
=
linphone_gtk_create_widget
(
"main"
,
"in_call_frame"
);
GtkWidget
*
main_window
=
linphone_gtk_get_main_window
();
...
...
@@ -217,6 +311,7 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){
linphone_gtk_enable_hold_button
(
call
,
FALSE
,
TRUE
);
linphone_gtk_enable_mute_button
(
GTK_BUTTON
(
linphone_gtk_get_widget
(
call_view
,
"incall_mute"
)),
FALSE
);
g_signal_connect_swapped
(
G_OBJECT
(
linphone_gtk_get_widget
(
call_view
,
"quality_indicator"
)),
"button-press-event"
,(
GCallback
)
linphone_gtk_show_call_stats
,
call
);
}
static
void
video_button_clicked
(
GtkWidget
*
button
,
LinphoneCall
*
call
){
...
...
@@ -506,6 +601,7 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
GtkWidget
*
duration
=
linphone_gtk_get_widget
(
callview
,
"in_call_duration"
);
guint
taskid
=
GPOINTER_TO_INT
(
g_object_get_data
(
G_OBJECT
(
callview
),
"taskid"
));
gboolean
in_conf
=
linphone_call_params_local_conference_mode
(
linphone_call_get_current_params
(
call
));
GtkWidget
*
call_stats
=
(
GtkWidget
*
)
g_object_get_data
(
G_OBJECT
(
callview
),
"call_stats"
);
display_peer_name_in_label
(
callee
,
linphone_call_get_remote_address
(
call
));
...
...
@@ -524,6 +620,7 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
linphone_gtk_in_call_view_enable_audio_view
(
call
,
!
in_conf
);
linphone_gtk_in_call_view_show_encryption
(
call
);
if
(
in_conf
)
linphone_gtk_set_in_conference
(
call
);
if
(
call_stats
)
show_used_codecs
(
call_stats
,
call
);
}
void
linphone_gtk_in_call_view_set_paused
(
LinphoneCall
*
call
){
...
...
@@ -676,3 +773,8 @@ void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gbo
gtk_widget_set_visible
(
GTK_WIDGET
(
button
),
sensitive
);
linphone_gtk_draw_hold_button
(
GTK_BUTTON
(
button
),
!
holdon
);
}
void
linphone_gtk_call_statistics_closed
(
GtkWidget
*
call_stats
){
gtk_widget_destroy
(
call_stats
);
}
gtk/main.ui
View file @
0b475524
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment