forked from mirrors/linphone-iphone
add call statistics window to gtk
This commit is contained in:
parent
3cd49ea4bd
commit
0b475524e7
6 changed files with 1756 additions and 1173 deletions
|
|
@ -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\tvideo=%f",audio_load,video_load);
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
212
gtk/call_statistics.ui
Normal file
212
gtk/call_statistics.ui
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
<?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>
|
||||
|
|
@ -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\nupload: %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\nupload: %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);
|
||||
}
|
||||
|
||||
|
|
|
|||
2593
gtk/main.ui
2593
gtk/main.ui
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue