Commit 0b475524 authored by Simon Morlat's avatar Simon Morlat

add call statistics window to gtk

parent 3cd49ea4
......@@ -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
......
<?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">&lt;b&gt;Call statistics and information&lt;/b&gt;</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);
}
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.18"/>
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkWindow" id="dummy_conf_window">
<property name="can_focus">False</property>
<child>
<object class="GtkFrame" id="callee_frame">
<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="conf_alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkHBox" id="conf_hbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkHBox" id="conf_hbox1">
<property name="visible">True</property>
<child>
<object class="GtkButton" id="conference_control">
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="callee_name_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Callee name&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="justify">right</property>
<property name="ellipsize">end</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="conference_control">
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</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">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
......@@ -52,6 +63,7 @@
<property name="width_request">170</property>
<property name="height_request">30</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -71,21 +83,26 @@
</child>
</object>
<object class="GtkWindow" id="dummy_in_call_window">
<property name="can_focus">False</property>
<child>
<object class="GtkFrame" id="in_call_frame">
<property name="can_focus">False</property>
<property name="label_xalign">0.5</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>
<property name="right_padding">12</property>
<child>
<object class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkVBox" id="in_call_animation">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
......@@ -99,18 +116,23 @@
<child>
<object class="GtkLabel" id="in_call_uri">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="encryption_box">
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="image121">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-dialog-authentication</property>
<property name="icon-size">1</property>
</object>
......@@ -123,6 +145,7 @@
<child>
<object class="GtkImage" id="encryption_status_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-apply</property>
</object>
<packing>
......@@ -134,9 +157,12 @@
<child>
<object class="GtkLabel" id="encryption_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
......@@ -146,7 +172,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="linphone_gtk_auth_token_verified_clicked"/>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="linphone_gtk_auth_token_verified_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
......@@ -163,14 +190,17 @@
</child>
<child>
<object class="GtkHBox" id="incall_audioview">
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="incall_mute">
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="relief">half</property>
<signal name="clicked" handler="linphone_gtk_mute_clicked"/>
<signal name="clicked" handler="linphone_gtk_mute_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
......@@ -178,6 +208,7 @@
<child>
<object class="GtkProgressBar" id="mic_audiolevel">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -188,10 +219,12 @@
<child>
<object class="GtkImage" id="incall_spk_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-missing-image</property>
<property name="icon-size">1</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
......@@ -199,6 +232,7 @@
<child>
<object class="GtkProgressBar" id="spk_audiolevel">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -216,6 +250,7 @@
</child>
<child>
<object class="GtkHButtonBox" id="answer_decline_panel">
<property name="can_focus">False</property>
<property name="layout_style">spread</property>
<child>
<object class="GtkButton" id="accept_call">
......@@ -223,7 +258,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="linphone_gtk_answer_clicked"/>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="linphone_gtk_answer_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
......@@ -237,7 +273,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="linphone_gtk_decline_clicked"/>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="linphone_gtk_decline_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
......@@ -255,6 +292,7 @@
<child>
<object class="GtkHButtonBox" id="mute_pause_buttons">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="homogeneous">True</property>
<property name="layout_style">spread</property>
<child>
......@@ -262,7 +300,8 @@
<property name="label" translatable="yes">Pause</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="linphone_gtk_hold_clicked"/>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="linphone_gtk_hold_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
......@@ -276,6 +315,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="expand">False</property>
......@@ -297,34 +337,45 @@
<child type="label">
<object class="GtkHBox" id="heading_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel" id="in_call_status">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">In call</property>
<property name="use_markup">True</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="in_call_duration">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Duration</property>
<property name="justify">center</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkProgressBar" id="quality_indicator">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK</property>
<property name="tooltip_text" translatable="yes">Call quality rating</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
......@@ -335,173 +386,150 @@
</object>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-info</property>
</object>
<object class="GtkImage" id="image10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-add</property>
</object>
<object class="GtkImage" id="image11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-clear</property>
</object>
<object class="GtkImage" id="image12">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-connect</property>
</object>
<object class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-refresh</property>
</object>
<object class="GtkImage" id="image3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-properties</property>
</object>
<object class="GtkImage" id="image4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-home</property>
</object>
<object class="GtkImage" id="image5">
<property name="visible">True</property>
<