incall_view.c 40.1 KB
Newer Older
smorlat's avatar
smorlat committed
1
/*
smorlat's avatar
smorlat committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
linphone, gtk-glade interface.
Copyright (C) 2009  Simon MORLAT (simon.morlat@linphone.org)

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
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
smorlat's avatar
smorlat committed
18 19
*/
/*
smorlat's avatar
smorlat committed
20 21
*  C Implementation: incall_frame
*
22
* Description:
smorlat's avatar
smorlat committed
23 24 25 26 27 28 29 30 31
*
*
* Author: Simon Morlat <simon.morlat@linphone.org>, (C) 2009
*
*
*/

#include "linphone.h"

32
gboolean linphone_gtk_use_in_call_view(void){
smorlat's avatar
smorlat committed
33 34 35 36 37
	static int val=-1;
	if (val==-1) val=linphone_gtk_get_ui_config_int("use_incall_view",1);
	return val;
}

38
LinphoneCall *linphone_gtk_get_currently_displayed_call(gboolean *is_conf){
39 40
	LinphoneCore *lc=linphone_gtk_get_core();
	GtkWidget *main_window=linphone_gtk_get_main_window ();
41
	GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch");
42
	const bctbx_list_t *calls=linphone_core_get_calls(lc);
43
	if (is_conf) *is_conf=FALSE;
44
	if (!linphone_gtk_use_in_call_view() || bctbx_list_size(calls)==1){
45 46 47 48 49 50
		if (calls) return (LinphoneCall*)calls->data;
	}else{
		int idx=gtk_notebook_get_current_page (notebook);
		GtkWidget *page=gtk_notebook_get_nth_page(notebook,idx);
		if (page!=NULL){
			LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(page),"call");
51
			if (call==NULL){
52 53
				GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(main_window),"conf_frame");
				if (conf_frame==page){
54 55 56 57 58
					if (is_conf)
						*is_conf=TRUE;
					return NULL;
				}
			}
59 60
			return call;
		}
61
	}
62
	return NULL;
smorlat's avatar
smorlat committed
63 64
}

65
static GtkWidget *make_tab_header(int number){
66 67 68
	gchar text[20];
	g_snprintf(text, sizeof(text), _("Call #%i"), number);
	return linphone_gtk_make_tab_header(text, "linphone-start-call", FALSE, NULL, NULL);
69 70
}

Margaux Clerc's avatar
Margaux Clerc committed
71
void linphone_gtk_call_update_tab_header(LinphoneCall *call,gboolean pause){
72 73 74 75 76 77
	GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *main_window=linphone_gtk_get_main_window();
	GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(main_window,"viewswitch"));
	gint call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"call_index"));
	GtkWidget *new_label=gtk_hbox_new (FALSE,0);
	GtkWidget *i=NULL;
78
	GtkWidget *l;
79
	gchar *text;
80

81
	if(pause){
82
		i=gtk_image_new_from_icon_name("linphone-hold-off",GTK_ICON_SIZE_BUTTON);
83
	} else {
84
		i=gtk_image_new_from_icon_name("linphone-start-call", GTK_ICON_SIZE_BUTTON);
85
	}
86

87
	text=g_strdup_printf(_("Call #%i"),call_index);
88 89 90 91
	l=gtk_label_new (text);
	gtk_box_pack_start (GTK_BOX(new_label),i,FALSE,FALSE,0);
	gtk_box_pack_end(GTK_BOX(new_label),l,TRUE,TRUE,0);

92 93
	gtk_notebook_set_tab_label(notebook,w,new_label);
	gtk_widget_show_all(new_label);
94
	g_free(text);
95 96
}

97
static void linphone_gtk_in_call_set_animation_image(GtkWidget *callview, const char *image_name){
98 99 100
	GtkWidget *container=linphone_gtk_get_widget(callview,"in_call_animation");
	GList *elem=gtk_container_get_children(GTK_CONTAINER(container));
	GtkWidget *image;
101

102 103 104 105
	if (image_name==NULL){
		gtk_widget_hide(container);
	}
	image=gtk_image_new_from_icon_name(image_name,GTK_ICON_SIZE_DIALOG);
106 107 108 109
	if (elem)
		gtk_widget_destroy((GtkWidget*)elem->data);
	gtk_widget_show(image);
	gtk_container_add(GTK_CONTAINER(container),image);
110
	gtk_widget_show_all(container);
111 112 113
}

static void linphone_gtk_in_call_set_animation_spinner(GtkWidget *callview){
jehan's avatar
jehan committed
114
#if GTK_CHECK_VERSION(2,20,0)
115 116 117 118 119 120 121
	GtkWidget *container=linphone_gtk_get_widget(callview,"in_call_animation");
	GList *elem=gtk_container_get_children(GTK_CONTAINER(container));
	GtkWidget *spinner=gtk_spinner_new();
	if (elem)
		gtk_widget_destroy((GtkWidget*)elem->data);
	gtk_widget_show(spinner);
	gtk_container_add(GTK_CONTAINER(container),spinner);
122
	gtk_widget_set_size_request(spinner, 20,20);
123
	gtk_spinner_start(GTK_SPINNER(spinner));
jehan's avatar
jehan committed
124
#endif
125 126
}

127
static void linphone_gtk_transfer_call(LinphoneCall *dest_call){
128 129
	LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
	if (call) linphone_core_transfer_call_to_another(linphone_gtk_get_core(),call,dest_call);
130 131
}

132
void transfer_button_clicked(GtkWidget *button, gpointer call_ref){
133 134 135 136
	GtkWidget *menu_item;
	GtkWidget *menu=gtk_menu_new();
	LinphoneCall *call=(LinphoneCall*)call_ref;
	LinphoneCore *lc=linphone_gtk_get_core();
137
	const bctbx_list_t *elem=linphone_core_get_calls(lc);
138

139 140 141 142 143
	for(;elem!=NULL;elem=elem->next){
		LinphoneCall *other_call=(LinphoneCall*)elem->data;
		GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(other_call);
		if (other_call!=call){
			int call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(call_view),"call_index"));
144
			char *remote_uri=linphone_call_get_remote_address_as_string (other_call);
145
			char *text=g_strdup_printf(_("Transfer to call #%i with %s"),call_index,remote_uri);
146
			GtkWidget *image = gtk_image_new_from_icon_name("linphone-start-call", GTK_ICON_SIZE_MENU);
147 148 149
			menu_item=gtk_image_menu_item_new_with_label(text);
			ms_free(remote_uri);
			g_free(text);
150
			gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image);
151 152 153 154 155
			gtk_widget_show(menu_item);
			gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
			g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_transfer_call,other_call);
		}
	}
156
	gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
157 158 159 160
	gtk_widget_show(menu);
}

void linphone_gtk_enable_transfer_button(LinphoneCore *lc, gboolean value){
161
	const bctbx_list_t *elem=linphone_core_get_calls(lc);
162 163 164
	for(;elem!=NULL;elem=elem->next){
		LinphoneCall *call=(LinphoneCall*)elem->data;
		GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call);
165 166 167
		GtkWidget *button=linphone_gtk_get_widget (call_view,"transfer_button");
		if(button != NULL){
			gtk_widget_set_sensitive(button,value);
168 169 170 171
		}
	}
}

172
static void conference_button_clicked(GtkWidget *button, gpointer call_ref){
173 174
	gtk_widget_set_sensitive(button,FALSE);
	g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame",NULL);
175
	linphone_core_add_all_to_conference(linphone_gtk_get_core());
176

177 178 179
}

void linphone_gtk_enable_conference_button(LinphoneCore *lc, gboolean value){
180
	const bctbx_list_t *elem=linphone_core_get_calls(lc);
181 182 183
	for(;elem!=NULL;elem=elem->next){
		LinphoneCall *call=(LinphoneCall*)elem->data;
		GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call);
184 185 186
		GtkWidget *button=linphone_gtk_get_widget (call_view,"conference_button");
		if (button != NULL){
			gtk_widget_set_sensitive(button,value);
187 188 189 190
		}
	}
}

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
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:
212 213 214
			return _("ICE not activated");
		case LinphoneIceStateFailed:
			return _("ICE failed");
215 216 217 218 219 220 221 222 223 224 225 226
		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";
}

Yann Diorcet's avatar
Yann Diorcet committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
static const char *upnp_state_to_string(LinphoneUpnpState ice_state){
	switch(ice_state){
		case LinphoneUpnpStateIdle:
			return _("uPnP not activated");
		case LinphoneUpnpStatePending:
			return _("uPnP in progress");
		case LinphoneUpnpStateNotAvailable:
			return _("uPnp not available");
		case LinphoneUpnpStateOk:
			return _("uPnP is running");
		case LinphoneUpnpStateKo:
			return _("uPnP failed");
		default:
			break;
	}
	return "invalid";
}

245 246 247
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);
248 249
	const char *audio_media_connectivity = _("Direct or through server");
	const char *video_media_connectivity = _("Direct or through server");
250 251 252 253 254
	const LinphoneCallParams *curparams=linphone_call_get_current_params(call);
	gboolean has_video=linphone_call_params_video_enabled(curparams);
	MSVideoSize size_received = linphone_call_params_get_received_video_size(curparams);
	MSVideoSize size_sent = linphone_call_params_get_sent_video_size(curparams);
	const char *rtp_profile = linphone_call_params_get_rtp_profile(curparams);
255 256 257 258
	gchar *tmp = g_strdup_printf("%s", rtp_profile);
	gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"rtp_profile")),tmp);
	g_free(tmp);
	tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),
259 260 261
		as->download_bandwidth,as->upload_bandwidth);
	gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp);
	g_free(tmp);
262
	if (has_video){
263
		gchar *size_r=g_strdup_printf(_("%ix%i @ %f fps"),size_received.width,size_received.height,
264 265 266
					      linphone_call_params_get_received_framerate(curparams));
		gchar *size_s=g_strdup_printf(_("%ix%i @ %f fps"),size_sent.width,size_sent.height,
			linphone_call_params_get_sent_framerate(curparams));
267 268
		gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_size_recv")),size_r);
		gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_size_sent")),size_s);
269

270
		tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),vs->download_bandwidth,vs->upload_bandwidth);
271 272 273 274 275
		g_free(size_r);
		g_free(size_s);
	} else {
		tmp=NULL;
	}
276
	gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp);
277
	if (tmp) g_free(tmp);
Yann Diorcet's avatar
Yann Diorcet committed
278 279 280 281 282 283
	if(as->upnp_state != LinphoneUpnpStateNotAvailable && as->upnp_state != LinphoneUpnpStateIdle) {
		audio_media_connectivity = upnp_state_to_string(as->upnp_state);
	} else if(as->ice_state != LinphoneIceStateNotActivated) {
		audio_media_connectivity = ice_state_to_string(as->ice_state);
	}
	gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_media_connectivity")),audio_media_connectivity);
284

285 286 287 288 289 290 291
	if (has_video){
		if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) {
				video_media_connectivity = upnp_state_to_string(vs->upnp_state);
		} else if(vs->ice_state != LinphoneIceStateNotActivated) {
			video_media_connectivity = ice_state_to_string(vs->ice_state);
		}
	}else video_media_connectivity=NULL;
Yann Diorcet's avatar
Yann Diorcet committed
292
	gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_media_connectivity")),video_media_connectivity);
293

294 295 296 297 298
	if (as->round_trip_delay>0){
		tmp=g_strdup_printf(_("%.3f seconds"),as->round_trip_delay);
		gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"round_trip_time")),tmp);
		g_free(tmp);
	}
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
}

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;
332
		call_stats=linphone_gtk_create_window("call_statistics", NULL);
333 334 335 336 337 338 339 340 341
		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);
	}
342 343 344 345 346 347 348 349 350 351

}

void linphone_gtk_enable_video_button(LinphoneCall *call, gboolean sensitive, gboolean holdon){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer (call);
	GtkWidget *button;
	g_return_if_fail(callview!=NULL);
	button=linphone_gtk_get_widget(callview,"video_button");
	gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive);
	gtk_widget_set_visible(GTK_WIDGET(button),sensitive);
352 353
}

354 355 356 357 358

typedef enum { VOLUME_CTRL_PLAYBACK, VOLUME_CTRL_RECORD } VolumeControlType;

static void volume_control_value_changed(GtkScaleButton *button, gdouble value, gpointer user_data) {
	LinphoneCall *call = (LinphoneCall *)g_object_get_data(G_OBJECT(button), "call");
359
	VolumeControlType type = (VolumeControlType)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "type"));
360 361

	if(type == VOLUME_CTRL_PLAYBACK) {
362
		linphone_call_set_speaker_volume_gain(call, (float)value);
363
	} else if(type == VOLUME_CTRL_RECORD) {
364
		linphone_call_set_microphone_volume_gain(call, (float)value);
365 366 367
	}
}

368
static gboolean volume_control_button_update_value(GtkWidget *widget) {
369
	LinphoneCall *call = (LinphoneCall *)g_object_get_data(G_OBJECT(widget), "call");
370
	VolumeControlType type = (VolumeControlType)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "type"));
Simon Morlat's avatar
Simon Morlat committed
371
	float gain = -1;
372 373

	if(type == VOLUME_CTRL_PLAYBACK) {
374
		gain = linphone_call_get_speaker_volume_gain(call);
375
	} else if(type == VOLUME_CTRL_RECORD) {
376 377 378 379 380 381 382
		gain = linphone_call_get_microphone_volume_gain(call);
	}
	if(gain >= 0.0f) {
		gtk_scale_button_set_value(GTK_SCALE_BUTTON(widget), gain);
		return TRUE;
	} else {
		return FALSE;
383 384 385 386 387 388 389 390 391 392
	}
}

static gboolean volume_control_button_enter_event_handler(GtkWidget *widget) {
	volume_control_button_update_value(widget);
	return FALSE;
}

static void volume_control_init(GtkWidget *vol_ctrl, VolumeControlType type, LinphoneCall *call) {
	g_object_set_data(G_OBJECT(vol_ctrl), "call", call);
393 394 395 396 397 398 399 400
	g_object_set_data(G_OBJECT(vol_ctrl), "type", GINT_TO_POINTER(type));
	if(!volume_control_button_update_value(vol_ctrl)) {
		gtk_widget_set_sensitive(vol_ctrl, FALSE);
	} else {
		gtk_widget_set_sensitive(vol_ctrl, TRUE);
		g_signal_connect(G_OBJECT(vol_ctrl), "enter-notify-event", G_CALLBACK(volume_control_button_enter_event_handler), NULL);
		g_signal_connect(G_OBJECT(vol_ctrl), "value-changed", G_CALLBACK(volume_control_value_changed), NULL);
	}
401 402
}

403
void linphone_gtk_create_in_call_view(LinphoneCall *call){
404
	GtkWidget *call_view=linphone_gtk_create_widget("in_call_frame");
405
	GtkWidget *main_window=linphone_gtk_get_main_window ();
406
	GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch");
407
	GtkWidget *audio_bar = linphone_gtk_get_widget(call_view, "incall_audioview");
408 409
	static int call_index=1;
	int idx;
410
	GtkWidget *record;
411 412 413 414 415
	GtkWidget *transfer;
	GtkWidget *conf;
	GtkWidget *button;
	GtkWidget *image;

416
	if (bctbx_list_size(linphone_core_get_calls(linphone_gtk_get_core()))==1){
417 418 419
		/*this is the only call at this time */
		call_index=1;
	}
420
	g_object_set_data(G_OBJECT(call_view),"call",call);
421 422
	g_object_set_data(G_OBJECT(call_view),"call_index",GINT_TO_POINTER(call_index));

423 424 425 426 427 428 429
	linphone_call_set_user_pointer (call,call_view);
	linphone_call_ref(call);
	gtk_notebook_append_page (notebook,call_view,make_tab_header(call_index));
	gtk_widget_show(call_view);
	idx = gtk_notebook_page_num(notebook, call_view);
	gtk_notebook_set_current_page(notebook, idx);
	call_index++;
Simon Morlat's avatar
Simon Morlat committed
430
	linphone_gtk_enable_hold_button (call,FALSE,TRUE);
431
	linphone_gtk_enable_video_button (call,FALSE,TRUE);
Simon Morlat's avatar
Simon Morlat committed
432 433
	linphone_gtk_enable_mute_button(
					GTK_BUTTON(linphone_gtk_get_widget(call_view,"incall_mute")),FALSE);
434

435 436 437
	record = linphone_gtk_get_widget(call_view, "record_button");
	gtk_button_set_image(GTK_BUTTON(record), gtk_image_new_from_icon_name("linphone-record", GTK_ICON_SIZE_BUTTON));
	gtk_widget_hide(record);
438
	transfer = linphone_gtk_get_widget(call_view,"transfer_button");
439
	gtk_button_set_image(GTK_BUTTON(transfer),gtk_image_new_from_icon_name("linphone-call-transfer",GTK_ICON_SIZE_BUTTON));
440 441 442
	g_signal_connect(G_OBJECT(transfer),"clicked",(GCallback)transfer_button_clicked,call);
	gtk_widget_hide(transfer);

443
	conf = linphone_gtk_get_widget(call_view,"conference_button");
444
	gtk_button_set_image(GTK_BUTTON(conf),gtk_image_new_from_icon_name("linphone-conference-start",GTK_ICON_SIZE_BUTTON));
445 446 447
	g_signal_connect(G_OBJECT(conf),"clicked",(GCallback)conference_button_clicked,call);
	gtk_widget_hide(conf);

448
	button=linphone_gtk_get_widget(call_view,"terminate_call");
449 450 451 452
	image=gtk_image_new_from_icon_name(
		linphone_gtk_get_ui_config("stop_call_icon_name","linphone-stop-call"),
		GTK_ICON_SIZE_BUTTON
	);
453
	gtk_button_set_label(GTK_BUTTON(button),_("Hang up"));
454 455
	gtk_button_set_image(GTK_BUTTON(button),image);
	gtk_widget_show(image);
456
	g_signal_connect_swapped(G_OBJECT(linphone_gtk_get_widget(call_view,"quality_indicator")),"button-press-event",(GCallback)linphone_gtk_show_call_stats,call);
457
	
458
	gtk_widget_hide(audio_bar);
459
}
460

461 462
static void video_button_clicked(GtkWidget *button, LinphoneCall *call){
	gboolean adding=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"adding_video"));
463
	LinphoneCore *lc=linphone_call_get_core(call);
464
	LinphoneCallParams *params = linphone_core_create_call_params(lc, call);
465
	gtk_widget_set_sensitive(button,FALSE);
466
	linphone_call_params_enable_video(params, adding);
467
	linphone_core_update_call(lc,call,params);
Simon Morlat's avatar
Simon Morlat committed
468
	linphone_call_params_unref(params);
469 470 471 472
}

void linphone_gtk_update_video_button(LinphoneCall *call){
	GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call);
473
	GtkWidget *button;
474
	GtkWidget *conf_frame;
475 476
	const LinphoneCallParams *params=linphone_call_get_current_params(call);
	gboolean has_video=linphone_call_params_video_enabled(params);
Simon Morlat's avatar
Simon Morlat committed
477
	gboolean button_sensitive=FALSE;
478
	if (call_view==NULL) return;
479

480
	button=linphone_gtk_get_widget(call_view,"video_button");
481 482

	gtk_button_set_image(GTK_BUTTON(button),
483
	gtk_image_new_from_icon_name(has_video ? "linphone-camera-disabled" : "linphone-camera-enabled",GTK_ICON_SIZE_BUTTON));
484 485 486 487 488
	g_object_set_data(G_OBJECT(button),"adding_video",GINT_TO_POINTER(!has_video));
	if (!linphone_core_video_supported(linphone_call_get_core(call))){
		gtk_widget_set_sensitive(button,FALSE);
		return;
	}
Simon Morlat's avatar
Simon Morlat committed
489 490 491 492 493 494 495 496 497
	switch(linphone_call_get_state(call)){
		case LinphoneCallStreamsRunning:
			button_sensitive=!linphone_call_media_in_progress(call);
		break;
		default:
			button_sensitive=FALSE;
		break;
	}
	gtk_widget_set_sensitive(button,button_sensitive);
498 499 500 501
	if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"signal_connected"))==0){
		g_signal_connect(G_OBJECT(button),"clicked",(GCallback)video_button_clicked,call);
		g_object_set_data(G_OBJECT(button),"signal_connected",GINT_TO_POINTER(1));
	}
502
	conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame");
503 504 505
	if(conf_frame!=NULL){
		gtk_widget_set_sensitive(button,FALSE);
	}
506 507
}

508 509 510 511
void linphone_gtk_remove_in_call_view(LinphoneCall *call){
	GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer (call);
	GtkWidget *main_window=linphone_gtk_get_main_window ();
	GtkWidget *nb=linphone_gtk_get_widget(main_window,"viewswitch");
512
	int idx,id_current_page;
513 514
	g_return_if_fail(w!=NULL);
	idx=gtk_notebook_page_num(GTK_NOTEBOOK(nb),w);
515
	if (linphone_gtk_call_is_in_conference_view(call)){
516 517
		linphone_gtk_unset_from_conference(call);
	}
518 519
	linphone_call_set_user_pointer (call,NULL);
	linphone_call_unref(call);
520
	call=linphone_core_get_current_call(linphone_gtk_get_core());
521 522 523 524 525 526 527 528 529 530 531 532
	id_current_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(nb));
	if (id_current_page == idx) {
		if (call==NULL){
			if (linphone_core_is_in_conference(linphone_gtk_get_core())){
				/*show the conference*/
				gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),
								g_object_get_data(G_OBJECT(main_window),"conf_frame")));
			} else {
				gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),0);
			}
		}else{
			/*show the active call*/
533
			gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),
534 535
							linphone_call_get_user_pointer(call)));
		}
536
	}
537 538
	gtk_notebook_remove_page (GTK_NOTEBOOK(nb),idx);
	gtk_widget_destroy(w);
smorlat's avatar
smorlat committed
539 540
}

541
static void display_peer_name_in_label(GtkWidget *label, const LinphoneAddress *from){
542
	const char *displayname=NULL;
543
	char *id;
smorlat's avatar
smorlat committed
544
	char *uri_label;
545 546
	displayname=linphone_address_get_display_name(from);
	id=linphone_address_as_string_uri_only(from);
547

548
	if (displayname!=NULL){
549
		uri_label=g_markup_printf_escaped("<span size=\"large\">%s</span>\n<i>%s</i>",
smorlat's avatar
smorlat committed
550
			displayname,id);
551
	}else
smorlat's avatar
smorlat committed
552 553 554
		uri_label=g_markup_printf_escaped("<span size=\"large\"><i>%s</i></span>\n",id);
	gtk_label_set_markup(GTK_LABEL(label),uri_label);
	g_free(uri_label);
555
	ms_free(id);
smorlat's avatar
smorlat committed
556 557
}

558 559 560 561 562
void linphone_gtk_in_call_view_set_calling(LinphoneCall *call){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
	GtkWidget *callee=linphone_gtk_get_widget(callview,"in_call_uri");
	GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration");
563

smorlat's avatar
smorlat committed
564
	gtk_label_set_markup(GTK_LABEL(status),_("<b>Calling...</b>"));
565
	display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
566

567
	gtk_label_set_text(GTK_LABEL(duration),_("00:00:00"));
568
	linphone_gtk_in_call_set_animation_spinner(callview);
smorlat's avatar
smorlat committed
569 570
}

571
void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call){
572 573 574
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
	GtkWidget *callee=linphone_gtk_get_widget(callview,"in_call_uri");
575
	GtkWidget *answer_button;
Simon Morlat's avatar
Simon Morlat committed
576
	GtkWidget *image;
577 578 579

	gtk_label_set_markup(GTK_LABEL(status),_("<b>Incoming call</b>"));
	gtk_widget_show_all(linphone_gtk_get_widget(callview,"answer_decline_panel"));
580
	gtk_widget_hide(linphone_gtk_get_widget(callview,"buttons_panel"));
581 582
	display_peer_name_in_label(callee,linphone_call_get_remote_address (call));

583
	answer_button=linphone_gtk_get_widget(callview,"accept_call");
584
	image=gtk_image_new_from_icon_name("linphone-start-call", GTK_ICON_SIZE_BUTTON);
585
	gtk_button_set_label(GTK_BUTTON(answer_button),_("Answer"));
Simon Morlat's avatar
Simon Morlat committed
586 587
	gtk_button_set_image(GTK_BUTTON(answer_button),image);
	gtk_widget_show(image);
588

589
	image=gtk_image_new_from_icon_name("linphone-stop-call", GTK_ICON_SIZE_BUTTON);
Simon Morlat's avatar
Simon Morlat committed
590 591
	gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(callview,"decline_call")),image);
	gtk_widget_show(image);
592

593
	linphone_gtk_in_call_set_animation_image(callview,"linphone-call-status-incoming");
594 595
}

596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
static void rating_to_color(float rating, GdkColor *color){
	const char *colorname="grey";
	if (rating>=4.0)
		colorname="green";
	else if (rating>=3.0)
		colorname="white";
	else if (rating>=2.0)
		colorname="yellow";
	else if (rating>=1.0)
		colorname="orange";
	else if (rating>=0)
		colorname="red";
	if (!gdk_color_parse(colorname,color)){
		g_warning("Fail to parse color %s",colorname);
	}
}

static const char *rating_to_text(float rating){
	if (rating>=4.0)
		return _("good");
	if (rating>=3.0)
		return _("average");
	if (rating>=2.0)
		return _("poor");
	if (rating>=1.0)
		return _("very poor");
	if (rating>=0)
		return _("too bad");
	return _("unavailable");
}

static gboolean linphone_gtk_in_call_view_refresh(LinphoneCall *call){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *qi=linphone_gtk_get_widget(callview,"quality_indicator");
	float rating=linphone_call_get_current_quality(call);
	GdkColor color;
	gchar tmp[50];
	linphone_gtk_in_call_view_update_duration(call);
	if (rating>=0){
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(qi),rating/5.0);
		snprintf(tmp,sizeof(tmp),"%.1f (%s)",rating,rating_to_text(rating));
		gtk_progress_bar_set_text(GTK_PROGRESS_BAR(qi),tmp);
	}else{
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(qi),0);
		gtk_progress_bar_set_text(GTK_PROGRESS_BAR(qi),_("unavailable"));
	}
	rating_to_color(rating,&color);
	gtk_widget_modify_bg(qi,GTK_STATE_NORMAL,&color);
644 645
	
	linphone_gtk_update_video_button(call); /*in case of no ice re-invite, video button status shall be checked by polling*/
646 647 648
	return TRUE;
}

649
#define UNSIGNIFICANT_VOLUME (-23)
650
#define SMOOTH 0.15f
651 652 653

static gboolean update_audio_meter(volume_ctx_t *ctx){
	float volume_db=ctx->get_volume(ctx->data);
654
	float frac=(volume_db-UNSIGNIFICANT_VOLUME)/(float)(-UNSIGNIFICANT_VOLUME-3.0);
655 656 657 658 659 660 661 662 663 664 665
	if (frac<0) frac=0;
	if (frac>1.0) frac=1.0;
	if (frac<ctx->last_value){
		frac=(frac*SMOOTH)+(ctx->last_value*(1-SMOOTH));
	}
	ctx->last_value=frac;
	//g_message("volume_db=%f, frac=%f",volume_db,frac);
	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ctx->widget),frac);
	return TRUE;
}

666 667
static void on_audio_meter_destroy(GtkWidget *w, gpointer data){
	guint task_id = GPOINTER_TO_INT(data);
668 669 670
	g_source_remove(task_id);
}

671

672 673 674 675 676 677 678 679 680 681
void linphone_gtk_init_audio_meter(GtkWidget *w, get_volume_t get_volume, void *data){
	guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id"));
	if (task_id==0){
		volume_ctx_t *ctx=g_new(volume_ctx_t,1);
		ctx->widget=w;
		ctx->get_volume=get_volume;
		ctx->data=data;
		ctx->last_value=0;
		g_object_set_data_full(G_OBJECT(w),"ctx",ctx,g_free);
		task_id=g_timeout_add(50,(GSourceFunc)update_audio_meter,ctx);
682 683
		g_object_set_data(G_OBJECT(w), "task_id", GINT_TO_POINTER(task_id));
		g_signal_connect(G_OBJECT(w), "destroy", (GCallback)on_audio_meter_destroy, GINT_TO_POINTER(task_id));
684 685 686
	}
}

687 688 689 690 691
void linphone_gtk_uninit_audio_meter(GtkWidget *w){
	guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id"));
	if (task_id!=0){
		g_object_set_data(G_OBJECT(w),"ctx",NULL);
		g_object_set_data(G_OBJECT(w),"task_id",NULL);
692
		g_source_remove(task_id);
693 694 695 696
	}
}

void linphone_gtk_in_call_view_enable_audio_view(LinphoneCall *call, gboolean val){
697 698 699 700
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *audio_view=linphone_gtk_get_widget(callview,"incall_audioview");
	GtkWidget *mic_level=linphone_gtk_get_widget(callview,"mic_audiolevel");
	GtkWidget *spk_level=linphone_gtk_get_widget(callview,"spk_audiolevel");
701 702
	GtkWidget *mic_ctrl = linphone_gtk_get_widget(callview, "incall_mic_vol_ctrl_button");
	GtkWidget *spk_ctrl = linphone_gtk_get_widget(callview, "incall_spk_vol_ctrl_button");
703

704 705 706
	if (val){
		linphone_gtk_init_audio_meter(mic_level,(get_volume_t)linphone_call_get_record_volume,call);
		linphone_gtk_init_audio_meter(spk_level,(get_volume_t)linphone_call_get_play_volume,call);
707 708
		volume_control_init(mic_ctrl, VOLUME_CTRL_RECORD, call);
		volume_control_init(spk_ctrl, VOLUME_CTRL_PLAYBACK, call);
709 710 711 712
		gtk_widget_show_all(audio_view);
	}else{
		linphone_gtk_uninit_audio_meter(mic_level);
		linphone_gtk_uninit_audio_meter(spk_level);
713
		gtk_widget_hide(audio_view);
714
	}
715 716
}

717 718 719 720 721 722 723 724
void linphone_gtk_auth_token_verified_clicked(GtkButton *button){
	LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
	if (call){
		linphone_call_set_authentication_token_verified(call,!linphone_call_get_authentication_token_verified(call));
	}
}

void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call){
725 726 727 728 729 730 731 732 733 734
	GtkWidget *callview = (GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *encryption_status_box = linphone_gtk_get_widget(callview, "encryption_status_box");
	GtkWidget *encryption_status_label = linphone_gtk_get_widget(callview, "encryption_status_label");
	GtkWidget *encryption_status_icon = linphone_gtk_get_widget(callview, "encryption_status_icon");
	GtkWidget *zrtp_box = linphone_gtk_get_widget(callview, "zrtp_box");
	GtkWidget *zrtp_button = linphone_gtk_get_widget(callview, "zrtp_button");
	GtkWidget *zrtp_status_icon = gtk_button_get_image(GTK_BUTTON(zrtp_button));
	LinphoneMediaEncryption me = linphone_call_params_get_media_encryption(linphone_call_get_current_params(call));

	switch (me) {
735
		case LinphoneMediaEncryptionSRTP:
736 737 738 739 740
			gtk_widget_hide_all(zrtp_box);
			gtk_widget_show_all(encryption_status_box);
			gtk_label_set_markup(GTK_LABEL(encryption_status_label), _("Secured by SRTP"));
			gtk_image_set_from_icon_name(GTK_IMAGE(encryption_status_icon), "linphone-security-ok", GTK_ICON_SIZE_MENU);
			break;
johan's avatar
johan committed
741
		case LinphoneMediaEncryptionDTLS:
742 743 744 745 746
			gtk_widget_hide_all(zrtp_box);
			gtk_widget_show_all(encryption_status_box);
			gtk_label_set_markup(GTK_LABEL(encryption_status_label), _("Secured by DTLS"));
			gtk_image_set_from_icon_name(GTK_IMAGE(encryption_status_icon), "linphone-security-ok", GTK_ICON_SIZE_MENU);
			break;
747 748
		case LinphoneMediaEncryptionZRTP:
		{
749 750 751
			bool_t verified = linphone_call_get_authentication_token_verified(call);
			gchar *text = g_strdup_printf(_("Secured by ZRTP - [auth token: %s]"), linphone_call_get_authentication_token(call));
			gtk_button_set_label(GTK_BUTTON(zrtp_button), text);
752
			g_free(text);
753 754 755 756
			gtk_image_set_from_icon_name(GTK_IMAGE(zrtp_status_icon), verified ? "linphone-security-ok" : "linphone-security-pending", GTK_ICON_SIZE_MENU);
			gtk_widget_set_tooltip_text(zrtp_button, verified ? _("Set unverified") : _("Set verified"));
			gtk_widget_hide_all(encryption_status_box);
			gtk_widget_show_all(zrtp_box);
757
		}
758 759
		break;
		default:
760 761 762
			gtk_widget_hide_all(encryption_status_box);
			gtk_widget_hide_all(zrtp_box);
			break;
763 764 765
	}
}

766 767
void linphone_gtk_in_call_view_hide_encryption(LinphoneCall *call) {
	GtkWidget *callview = (GtkWidget*)linphone_call_get_user_pointer(call);
768 769 770 771
	GtkWidget *encryption_status_box = linphone_gtk_get_widget(callview, "encryption_status_box");
	GtkWidget *zrtp_box = linphone_gtk_get_widget(callview, "zrtp_box");
	gtk_widget_hide_all(encryption_status_box);
	gtk_widget_hide_all(zrtp_box);
772 773
}

774 775 776 777 778 779
char *linphone_gtk_address(const LinphoneAddress *addr){
	const char *displayname=linphone_address_get_display_name(addr);
	if (!displayname) return linphone_address_as_string_uri_only(addr);
	return ms_strdup(displayname);
}

780 781 782 783 784
void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
	GtkWidget *callee=linphone_gtk_get_widget(callview,"in_call_uri");
	GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration");
785
	guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
786
	gboolean in_conf=(linphone_call_get_conference(call) != NULL);
787
	GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"call_stats");
788

789
	linphone_gtk_in_call_show_video(call);
790

791
	display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
792

793
	gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
794
	gtk_label_set_markup(GTK_LABEL(status),in_conf ? _("In conference") : _("<b>In call</b>"));
795

796 797 798
	gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"conference_button"),!in_conf);
	gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"transfer_button"),!in_conf);

799
	gtk_label_set_text(GTK_LABEL(duration),_("00:00:00"));
800
	linphone_gtk_in_call_set_animation_image(callview,"linphone-media-play");
Margaux Clerc's avatar
Margaux Clerc committed
801
	linphone_gtk_call_update_tab_header(call,FALSE);
smorlat's avatar
smorlat committed
802
	linphone_gtk_enable_mute_button(
803
					GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),TRUE);
804

805 806 807 808
	if (taskid==0){
		taskid=g_timeout_add(250,(GSourceFunc)linphone_gtk_in_call_view_refresh,call);
		g_object_set_data(G_OBJECT(callview),"taskid",GINT_TO_POINTER(taskid));
	}
809
	linphone_gtk_in_call_view_enable_audio_view(call, !in_conf);
810
	linphone_gtk_in_call_view_show_encryption(call);
811 812 813
	if (in_conf){
		linphone_gtk_set_in_conference(call);
		gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),FALSE);
814
		gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"hold_call"),FALSE);
815 816 817
	}else{
		linphone_gtk_unset_from_conference(call); /*in case it was previously*/
		gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),TRUE);
818
		gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"hold_call"),TRUE);
819
	}
820
	gtk_widget_show_all(linphone_gtk_get_widget(callview,"buttons_panel"));
Simon Morlat's avatar
Simon Morlat committed
821 822
	if (!in_conf) gtk_widget_show_all(linphone_gtk_get_widget(callview,"record_hbox"));
	else gtk_widget_hide(linphone_gtk_get_widget(callview,"record_hbox"));
823
	if (call_stats) show_used_codecs(call_stats,call);
smorlat's avatar
smorlat committed
824 825
}

826 827 828
void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
829
	GtkWidget *record_bar = linphone_gtk_get_widget(callview, "record_hbox");
830
	gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
Simon Morlat's avatar
Simon Morlat committed
831
	gtk_label_set_markup(GTK_LABEL(status),_("<b>Paused call</b>"));
832
	linphone_gtk_in_call_show_video(call);
833
	linphone_gtk_in_call_set_animation_image(callview,"linphone-media-pause");
834
	gtk_widget_show_all(record_bar);
835 836
}

837 838 839 840
void linphone_gtk_in_call_view_update_duration(LinphoneCall *call){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
	GtkWidget *duration_label=linphone_gtk_get_widget(callview,"in_call_duration");
	int duration=linphone_call_get_duration(call);
smorlat's avatar
smorlat committed
841 842 843 844
	char tmp[256]={0};
	int seconds=duration%60;
	int minutes=(duration/60)%60;
	int hours=duration/3600;
845
	snprintf(tmp,sizeof(tmp)-1,"%02i:%02i:%02i",hours,minutes,seconds);
smorlat's avatar
smorlat committed
846 847 848
	gtk_label_set_text(GTK_LABEL(duration_label),tmp);
}

849 850
static gboolean in_call_view_terminated(LinphoneCall *call){
	linphone_gtk_remove_in_call_view(call);
smorlat's avatar
smorlat committed
851 852 853
	return FALSE;
}

854 855
void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
856
	GtkWidget *status;
857
	GtkWidget *video_window;
858 859
	gboolean in_conf;
	guint taskid;
Margaux Clerc's avatar
Margaux Clerc committed
860
	if(callview==NULL) return;
861
	video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window");
862 863
	status=linphone_gtk_get_widget(callview,"in_call_status");
	taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
864
	in_conf=(linphone_call_get_conference(call) != NULL);
865
	if (video_window) gtk_widget_destroy(video_window);
Margaux Clerc's avatar
Margaux Clerc committed
866
	if (status==NULL) return;
smorlat's avatar
smorlat committed
867 868 869 870 871 872 873
	if (error_msg==NULL)
		gtk_label_set_markup(GTK_LABEL(status),_("<b>Call ended.</b>"));
	else{
		char *msg=g_markup_printf_escaped("<span color=\"red\"><b>%s</b></span>",error_msg);
		gtk_label_set_markup(GTK_LABEL(status),msg);
		g_free(msg);
	}
874
	
875
	linphone_gtk_in_call_set_animation_image(callview, linphone_gtk_get_ui_config("stop_call_icon_name","linphone-stop-call"));
876
	linphone_gtk_in_call_view_hide_encryption(call);
877

878
	gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
Simon Morlat's avatar
Simon Morlat committed
879 880
	gtk_widget_hide(linphone_gtk_get_widget(callview,"record_hbox"));
	gtk_widget_hide(linphone_gtk_get_widget(callview,"buttons_panel"));
881
	gtk_widget_hide(linphone_gtk_get_widget(callview,"incall_audioview"));
Margaux Clerc's avatar
Margaux Clerc committed
882
	gtk_widget_hide(linphone_gtk_get_widget(callview,"quality_indicator"));
smorlat's avatar
smorlat committed
883
	linphone_gtk_enable_mute_button(
Simon Morlat's avatar
Simon Morlat committed
884 885
		GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),FALSE);
	linphone_gtk_enable_hold_button(call,FALSE,TRUE);
886

887
	if (taskid!=0) g_source_remove(taskid);
888
	g_timeout_add_seconds(2,(GSourceFunc)in_call_view_terminated,call);
889 890
	if (in_conf)
		linphone_gtk_terminate_conference_participant(call);
smorlat's avatar
smorlat committed
891
}
smorlat's avatar
smorlat committed
892

893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914
void linphone_gtk_in_call_view_set_transfer_status(LinphoneCall *call,LinphoneCallState cstate){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
	if (callview){
		GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration");
		const char *transfer_status="unknown";
		switch(cstate){
			case LinphoneCallOutgoingProgress:
				transfer_status=_("Transfer in progress");
			break;
			case LinphoneCallConnected:
				transfer_status=_("Transfer done.");
			break;
			case LinphoneCallError:
				transfer_status=_("Transfer failed.");
			break;
			default:
			break;
		}
		gtk_label_set_text(GTK_LABEL(duration),transfer_status);
	}
}

Simon Morlat's avatar
Simon Morlat committed
915
void linphone_gtk_draw_mute_button(GtkButton *button, gboolean active){
916 917 918 919
	const char *icon_name = active ? "linphone-micro-muted" : "linphone-micro-enabled";
	GtkWidget *image = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_BUTTON);
	gtk_button_set_image(button, image);
	gtk_widget_show(image);
Simon Morlat's avatar
Simon Morlat committed
920
	g_object_set_data(G_OBJECT(button),"active",GINT_TO_POINTER(active));
smorlat's avatar
smorlat committed
921 922
}

Simon Morlat's avatar
Simon Morlat committed
923 924
void linphone_gtk_mute_clicked(GtkButton *button){
	int active=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"active"));
925
	linphone_core_enable_mic(linphone_gtk_get_core(),active);
Simon Morlat's avatar
Simon Morlat committed
926
	linphone_gtk_draw_mute_button(button,!active);
smorlat's avatar
smorlat committed
927 928
}

929
void linphone_gtk_enable_mute_button(GtkButton *button, gboolean sensitive){
930 931
	/*gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive);*/
	gtk_widget_set_visible(GTK_WIDGET(button),sensitive);
smorlat's avatar
smorlat committed
932
	linphone_gtk_draw_mute_button(button,FALSE);
smorlat's avatar
smorlat committed
933
}
934

Simon Morlat's avatar
Simon Morlat committed
935
void linphone_gtk_draw_hold_button(GtkButton *button, gboolean active){
François Grisez's avatar
François Grisez committed
936 937 938
	const gchar *icon_name = active ? "linphone-hold-on" : "linphone-hold-off";
	const gchar *label = active ? _("Resume") : _("Pause");
	GtkWidget *image = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_BUTTON);
Simon Morlat's avatar
Simon Morlat committed
939
	g_object_set_data(G_OBJECT(button),"active",GINT_TO_POINTER(active));
François Grisez's avatar
François Grisez committed
940 941 942
	gtk_button_set_label(GTK_BUTTON(button),label);
	gtk_button_set_image(GTK_BUTTON(button),image);
	gtk_widget_show(image);
943 944
}

Simon Morlat's avatar
Simon Morlat committed
945 946
void linphone_gtk_hold_clicked(GtkButton *button){
	int active=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"active"));
947
	LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
Margaux Clerc's avatar
Margaux Clerc committed
948
	linphone_gtk_call_update_tab_header(call,active);
949
	if (!call) return;
Simon Morlat's avatar
Simon Morlat committed
950
	if(!active)
951
	{
Simon Morlat's avatar
Simon Morlat committed
952
		linphone_core_pause_call(linphone_gtk_get_core(),call);
953 954 955
	}
	else
	{
956
		linphone_core_resume_call(linphone_gtk_get_core(),call);
957 958 959
	}
}

Simon Morlat's avatar
Simon Morlat committed
960 961 962 963
void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gboolean holdon){
	GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer (call);
	GtkWidget *button;
	g_return_if_fail(callview!=NULL);
Margaux Clerc's avatar
Margaux Clerc committed
964
	linphone_gtk_call_update_tab_header(call,!holdon);
Simon Morlat's avatar
Simon Morlat committed
965
	button=linphone_gtk_get_widget(callview,"hold_call");
966
	gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive);
967
	gtk_widget_set_visible(GTK_WIDGET(button),sensitive);
Simon Morlat's avatar
Simon Morlat committed
968
	linphone_gtk_draw_hold_button(GTK_BUTTON(button),!holdon);
969
}
970 971 972 973 974

void linphone_gtk_call_statistics_closed(GtkWidget *call_stats){
	gtk_widget_destroy(call_stats);
}

Simon Morlat's avatar
Simon Morlat committed
975 976
void linphone_gtk_record_call_toggled(GtkWidget *button){
	gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
977 978 979 980 981 982 983 984
	gboolean is_conf=FALSE;
	const char *filepath;
	gchar *message;
	LinphoneCore *lc=linphone_gtk_get_core();
	LinphoneCall *call=linphone_gtk_get_currently_displayed_call(&is_conf);
	GtkWidget *callview;
	GtkWidget *label;
	if (call){
985
		const LinphoneCallParams *params;
986
		callview=(GtkWidget*)linphone_call_get_user_pointer (call);
987
		params=linphone_call_get_current_params(call);
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
		filepath=linphone_call_params_get_record_file(params);
		label=linphone_gtk_get_widget(callview,"record_status");
	}else if (is_conf){
		GtkWidget *mw=linphone_gtk_get_main_window();
		callview=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame");
		label=linphone_gtk_get_widget(callview,"conf_record_status");
		filepath=(const char*)g_object_get_data(G_OBJECT(mw),"conf_record_path");
		if (filepath==NULL){
			filepath=linphone_gtk_get_record_path(NULL,TRUE);
			g_object_set_data_full(G_OBJECT(mw),"conf_record_path",(char*)filepath,g_free);
		}
	}else{
		g_warning("linphone_gtk_record_call_toggled(): bug.");
		return;
	}
	message=g_strdup_printf(_("<small><i>Recording into\n%s %s</i></small>"),filepath,active ? "" : _("(Paused)"));
1004

Simon Morlat's avatar
Simon Morlat committed
1005
	if (active){
1006 1007 1008 1009
		if (call)
			linphone_call_start_recording(call);
		else
			linphone_core_start_conference_recording(lc,filepath);
Simon Morlat's avatar
Simon Morlat committed
1010
	}else {
1011 1012 1013 1014
		if (call)
			linphone_call_stop_recording(call);
		else
			linphone_core_stop_conference_recording(lc);
1015

Simon Morlat's avatar
Simon Morlat committed
1016
	}
1017
	gtk_label_set_markup(GTK_LABEL(label),message);
Simon Morlat's avatar
Simon Morlat committed
1018 1019 1020
	g_free(message);
}