2 linphone, gtk-glade interface.
3 Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org)
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #define VIDEOSELFVIEW_DEFAULT 1
27 #include <sys/types.h>
32 #include <gtkosxapplication.h>
39 #define LINPHONE_ICON "linphone.png"
41 const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION;
43 static LinphoneCore *the_core=NULL;
44 static GtkWidget *the_ui=NULL;
46 static void linphone_gtk_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState rs, const char *msg);
47 static void linphone_gtk_show(LinphoneCore *lc);
48 static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid);
49 static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
50 static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username);
51 static void linphone_gtk_display_status(LinphoneCore *lc, const char *status);
52 static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg);
53 static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning);
54 static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url);
55 static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl);
56 static void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to);
57 static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg);
58 static gboolean linphone_gtk_auto_answer(LinphoneCall *call);
61 static gboolean verbose=0;
62 static gboolean auto_answer = 0;
63 static gchar * addr_to_call = NULL;
64 static gboolean iconified=FALSE;
65 static gchar *workingdir=NULL;
66 static char *progpath=NULL;
68 static GOptionEntry linphone_options[]={
72 .arg=G_OPTION_ARG_NONE,
73 .arg_data= (gpointer)&verbose,
74 .description=N_("log to stdout some debug information while running.")
77 .long_name="iconified",
79 .arg=G_OPTION_ARG_NONE,
80 .arg_data= (gpointer)&iconified,
81 .description=N_("Start only in the system tray, do not show the main interface.")
86 .arg = G_OPTION_ARG_STRING,
87 .arg_data = &addr_to_call,
88 .description = N_("address to call right now")
91 .long_name = "auto-answer",
93 .arg = G_OPTION_ARG_NONE,
94 .arg_data = (gpointer) & auto_answer,
95 .description = N_("if set automatically answer incoming calls")
98 .long_name = "workdir",
100 .arg = G_OPTION_ARG_STRING,
101 .arg_data = (gpointer) & workingdir,
102 .description = N_("Specifiy a working directory (should be the base of the installation, eg: c:\\Program Files\\Linphone)")
107 #define INSTALLED_XML_DIR PACKAGE_DATA_DIR "/linphone"
108 #define BUILD_TREE_XML_DIR "gtk"
111 #define CONFIG_FILE ".linphonerc"
113 #define CONFIG_FILE "linphonerc"
118 static char _config_file[1024];
121 const char *linphone_gtk_get_config_file(){
122 /*try accessing a local file first if exists*/
123 if (access(CONFIG_FILE,F_OK)==0){
124 snprintf(_config_file,sizeof(_config_file),"%s",CONFIG_FILE);
127 const char *appdata=getenv("APPDATA");
129 snprintf(_config_file,sizeof(_config_file),"%s\\%s",appdata,LINPHONE_CONFIG_DIR);
130 CreateDirectory(_config_file,NULL);
131 snprintf(_config_file,sizeof(_config_file),"%s\\%s",appdata,LINPHONE_CONFIG_DIR "\\" CONFIG_FILE);
134 const char *home=getenv("HOME");
135 if (home==NULL) home=".";
136 snprintf(_config_file,sizeof(_config_file),"%s/%s",home,CONFIG_FILE);
143 #define FACTORY_CONFIG_FILE "linphonerc.factory"
144 static char _factory_config_file[1024];
145 static const char *linphone_gtk_get_factory_config_file(){
146 /*try accessing a local file first if exists*/
147 if (access(FACTORY_CONFIG_FILE,F_OK)==0){
148 snprintf(_factory_config_file,sizeof(_factory_config_file),
149 "%s",FACTORY_CONFIG_FILE);
153 if (progpath != NULL) {
155 progdir = strdup(progpath);
157 basename = strrchr(progdir, '\\');
158 if (basename != NULL) {
161 snprintf(_factory_config_file, sizeof(_factory_config_file),
162 "%s\\..\\%s", progdir, FACTORY_CONFIG_FILE);
164 if (workingdir!=NULL) {
165 snprintf(_factory_config_file, sizeof(_factory_config_file),
166 "%s\\%s", workingdir, FACTORY_CONFIG_FILE);
173 basename = strrchr(progdir, '/');
174 if (basename != NULL) {
177 snprintf(_factory_config_file, sizeof(_factory_config_file),
178 "%s/../share/Linphone/%s", progdir, FACTORY_CONFIG_FILE);
187 return _factory_config_file;
190 static void linphone_gtk_init_liblinphone(const char *config_file,
191 const char *factory_config_file) {
192 LinphoneCoreVTable vtable={0};
194 vtable.call_state_changed=linphone_gtk_call_state_changed;
195 vtable.registration_state_changed=linphone_gtk_registration_state_changed;
196 vtable.show=linphone_gtk_show;
197 vtable.notify_presence_recv=linphone_gtk_notify_recv;
198 vtable.new_subscription_request=linphone_gtk_new_unknown_subscriber;
199 vtable.auth_info_requested=linphone_gtk_auth_info_requested;
200 vtable.display_status=linphone_gtk_display_status;
201 vtable.display_message=linphone_gtk_display_message;
202 vtable.display_warning=linphone_gtk_display_warning;
203 vtable.display_url=linphone_gtk_display_url;
204 vtable.call_log_updated=linphone_gtk_call_log_updated;
205 vtable.text_received=linphone_gtk_text_received;
206 vtable.refer_received=linphone_gtk_refer_received;
207 vtable.buddy_info_updated=linphone_gtk_buddy_info_updated;
209 linphone_core_set_user_agent("Linphone", LINPHONE_VERSION);
210 the_core=linphone_core_new(&vtable,config_file,factory_config_file,NULL);
211 linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
216 LinphoneCore *linphone_gtk_get_core(void){
220 GtkWidget *linphone_gtk_get_main_window(){
224 static void linphone_gtk_configure_window(GtkWidget *w, const char *window_name){
225 static const char *icon_path=NULL;
226 static const char *hiddens=NULL;
227 static const char *shown=NULL;
228 static bool_t config_loaded=FALSE;
229 if (linphone_gtk_get_core()==NULL) return;
230 if (config_loaded==FALSE){
231 hiddens=linphone_gtk_get_ui_config("hidden_widgets",NULL);
232 shown=linphone_gtk_get_ui_config("shown_widgets",NULL);
233 icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
237 linphone_gtk_visibility_set(hiddens,window_name,w,FALSE);
239 linphone_gtk_visibility_set(shown,window_name,w,TRUE);
241 GdkPixbuf *pbuf=create_pixbuf(icon_path);
242 gtk_window_set_icon(GTK_WINDOW(w),pbuf);
243 g_object_unref(G_OBJECT(pbuf));
247 static int get_ui_file(const char *name, char *path, int pathsize){
248 snprintf(path,pathsize,"%s/%s.ui",BUILD_TREE_XML_DIR,name);
249 if (access(path,F_OK)!=0){
250 snprintf(path,pathsize,"%s/%s.ui",INSTALLED_XML_DIR,name);
251 if (access(path,F_OK)!=0){
252 g_error("Could not locate neither %s/%s.ui and %s/%s.ui .",BUILD_TREE_XML_DIR,name,
253 INSTALLED_XML_DIR,name);
260 GtkWidget *linphone_gtk_create_window(const char *window_name){
261 GError* error = NULL;
262 GtkBuilder* builder = gtk_builder_new ();
266 if (get_ui_file(window_name,path,sizeof(path))==-1) return NULL;
268 if (!gtk_builder_add_from_file (builder, path, &error)){
269 g_error("Couldn't load builder file: %s", error->message);
270 g_error_free (error);
273 w=GTK_WIDGET(gtk_builder_get_object (builder,window_name));
275 g_error("Could not retrieve '%s' window from xml file",window_name);
278 g_object_set_data(G_OBJECT(w),"builder",builder);
279 gtk_builder_connect_signals(builder,w);
280 linphone_gtk_configure_window(w,window_name);
284 GtkWidget *linphone_gtk_create_widget(const char *filename, const char *widget_name){
287 GtkBuilder* builder = gtk_builder_new ();
289 gchar *object_ids[2];
290 object_ids[0]=g_strdup(widget_name);
293 if (get_ui_file(filename,path,sizeof(path))==-1) return NULL;
294 if (!gtk_builder_add_objects_from_file(builder,path,object_ids,&error)){
295 g_error("Couldn't load %s from builder file %s: %s", widget_name,path,error->message);
296 g_error_free (error);
297 g_free(object_ids[0]);
300 g_free(object_ids[0]);
301 w=GTK_WIDGET(gtk_builder_get_object (builder,widget_name));
303 g_error("Could not retrieve '%s' window from xml file",widget_name);
306 g_object_set_data(G_OBJECT(w),"builder",builder);
307 gtk_builder_connect_signals(builder,w);
311 GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
312 GtkBuilder *builder=(GtkBuilder*)g_object_get_data(G_OBJECT(window),"builder");
315 g_error("Fail to retrieve builder from window !");
318 w=gtk_builder_get_object(builder,name);
320 g_error("No widget named %s found in xml interface.",name);
322 return GTK_WIDGET(w);
326 void linphone_gtk_display_something(GtkMessageType type,const gchar *message){
328 GtkWidget *main_window=linphone_gtk_get_main_window();
330 gtk_widget_show(main_window);
331 if (type==GTK_MESSAGE_QUESTION)
333 /* draw a question box. link to dialog_click callback */
334 dialog = gtk_message_dialog_new (
335 GTK_WINDOW(main_window),
336 GTK_DIALOG_DESTROY_WITH_PARENT,
337 GTK_MESSAGE_QUESTION,
340 (const gchar*)message);
341 /* connect to some callback : REVISIT */
343 g_signal_connect_swapped (G_OBJECT (dialog), "response",
344 G_CALLBACK (dialog_click),
347 /* actually show the box */
348 gtk_widget_show(dialog);
352 dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
353 GTK_DIALOG_DESTROY_WITH_PARENT,
357 (const gchar*)message);
358 /* Destroy the dialog when the user responds to it (e.g. clicks a button) */
359 g_signal_connect_swapped (G_OBJECT (dialog), "response",
360 G_CALLBACK (gtk_widget_destroy),
362 gtk_widget_show(dialog);
366 void linphone_gtk_about_response(GtkDialog *dialog, gint id){
367 if (id==GTK_RESPONSE_CANCEL){
368 gtk_widget_destroy(GTK_WIDGET(dialog));
372 static void about_url_clicked(GtkAboutDialog *dialog, const char *url, gpointer data){
373 g_message("About url clicked");
374 linphone_gtk_open_browser(url);
377 void linphone_gtk_show_about(){
378 struct stat filestat;
379 const char *license_file=PACKAGE_DATA_DIR "/linphone/COPYING";
382 GdkPixbuf *logo=create_pixbuf(
383 linphone_gtk_get_ui_config("logo","linphone-banner.png"));
384 static const char *defcfg="defcfg";
386 about=linphone_gtk_create_window("about");
387 gtk_about_dialog_set_url_hook(about_url_clicked,NULL,NULL);
388 memset(&filestat,0,sizeof(filestat));
389 if (stat(license_file,&filestat)!=0){
390 license_file="COPYING";
391 stat(license_file,&filestat);
393 if (filestat.st_size>0){
394 char *license=g_malloc(filestat.st_size+1);
395 FILE *f=fopen(license_file,"r");
396 if (f && fread(license,filestat.st_size,1,f)==1){
397 license[filestat.st_size]='\0';
398 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about),license);
402 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about),LINPHONE_VERSION);
403 gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about),linphone_gtk_get_ui_config("title","Linphone"));
404 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about),linphone_gtk_get_ui_config("home","http://www.linphone.org"));
405 if (logo) gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about),logo);
406 tmp=linphone_gtk_get_ui_config("artists",defcfg);
411 gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(about),tmp2);
413 tmp=linphone_gtk_get_ui_config("translators",defcfg);
415 gtk_about_dialog_set_translator_credits (GTK_ABOUT_DIALOG(about),tmp);
416 tmp=linphone_gtk_get_ui_config("comments",defcfg);
418 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about),tmp);
419 gtk_widget_show(about);
422 static void set_video_window_decorations(GdkWindow *w){
423 const char *title=linphone_gtk_get_ui_config("title","Linphone");
424 const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
425 char video_title[256];
426 GdkPixbuf *pbuf=create_pixbuf(icon_path);
427 if (!linphone_core_in_call(linphone_gtk_get_core())){
428 snprintf(video_title,sizeof(video_title),"%s video",title);
429 /* When not in call, treat the video as a normal window */
430 gdk_window_set_keep_above(w, FALSE);
432 LinphoneAddress *uri =
433 linphone_address_clone(linphone_core_get_current_call_remote_address(linphone_gtk_get_core()));
436 linphone_address_clean(uri);
437 if (linphone_address_get_display_name(uri)!=NULL){
438 display_name=ms_strdup(linphone_address_get_display_name(uri));
440 display_name=linphone_address_as_string(uri);
442 snprintf(video_title,sizeof(video_title),_("Call with %s"),display_name);
443 linphone_address_destroy(uri);
444 ms_free(display_name);
446 /* During calls, bring up the video window, arrange so that
447 it is above all the other windows */
448 gdk_window_deiconify(w);
449 gdk_window_set_keep_above(w,TRUE);
450 /* Maybe we should have the following, but then we want to
451 have a timer that turns it off after a little while. */
452 /* gdk_window_set_urgency_hint(w,TRUE); */
454 gdk_window_set_title(w,video_title);
455 /* Refrain the video window to be closed at all times. */
456 gdk_window_set_functions(w,
457 GDK_FUNC_RESIZE|GDK_FUNC_MOVE|
458 GDK_FUNC_MINIMIZE|GDK_FUNC_MAXIMIZE);
461 l=g_list_append(l,pbuf);
462 gdk_window_set_icon_list(w,l);
464 g_object_unref(G_OBJECT(pbuf));
468 static gboolean video_needs_update=FALSE;
470 static void update_video_title(){
471 video_needs_update=TRUE;
474 static gboolean linphone_gtk_iterate(LinphoneCore *lc){
475 static gboolean first_time=TRUE;
477 static unsigned long previd=0;
478 static unsigned long preview_previd=0;
479 static gboolean in_iterate=FALSE;
482 if (in_iterate) return TRUE;
484 linphone_core_iterate(lc);
486 /*after the first call to iterate, SipSetupContexts should be ready, so take actions:*/
487 linphone_gtk_show_directory_search();
491 id=linphone_core_get_native_video_window_id(lc);
492 if (id!=previd || video_needs_update){
496 ms_message("Updating window decorations");
498 w=gdk_window_foreign_new(id);
500 w=gdk_window_foreign_new((HANDLE)id);
503 set_video_window_decorations(w);
504 g_object_unref(G_OBJECT(w));
506 else ms_error("gdk_window_foreign_new() failed");
507 if (video_needs_update) video_needs_update=FALSE;
510 id=linphone_core_get_native_preview_window_id (lc);
511 if (id!=preview_previd ){
515 ms_message("Updating window decorations for preview");
517 w=gdk_window_foreign_new(id);
519 w=gdk_window_foreign_new((HANDLE)id);
522 set_video_window_decorations(w);
523 g_object_unref(G_OBJECT(w));
525 else ms_error("gdk_window_foreign_new() failed");
526 if (video_needs_update) video_needs_update=FALSE;
529 if (addr_to_call!=NULL){
530 /*make sure we are not showing the login screen*/
531 GtkWidget *mw=linphone_gtk_get_main_window();
532 GtkWidget *login_frame=linphone_gtk_get_widget(mw,"login_frame");
533 if (!GTK_WIDGET_VISIBLE(login_frame)){
534 GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar");
535 gtk_entry_set_text(GTK_ENTRY(uri_bar),addr_to_call);
537 linphone_gtk_start_call(uri_bar);
544 static void load_uri_history(){
545 GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"));
548 GtkEntryCompletion *gep=gtk_entry_completion_new();
549 GtkListStore *model=gtk_list_store_new(1,G_TYPE_STRING);
552 snprintf(key,sizeof(key),"uri%i",i);
553 uri=linphone_gtk_get_ui_config(key,NULL);
556 gtk_list_store_append(model,&iter);
557 gtk_list_store_set(model,&iter,0,uri,-1);
558 if (i==0) gtk_entry_set_text(uribar,uri);
562 gtk_entry_completion_set_model(gep,GTK_TREE_MODEL(model));
563 gtk_entry_completion_set_text_column(gep,0);
564 gtk_entry_set_completion(uribar,gep);
567 static void save_uri_history(){
568 LinphoneCore *lc=linphone_gtk_get_core();
569 LpConfig *cfg=linphone_core_get_config(lc);
570 GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"));
575 GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(uribar));
577 if (!gtk_tree_model_get_iter_first(model,&iter)) return;
579 gtk_tree_model_get(model,&iter,0,&uri,-1);
581 snprintf(key,sizeof(key),"uri%i",i);
582 lp_config_set_string(cfg,"GtkUi",key,uri);
587 }while(gtk_tree_model_iter_next(model,&iter));
591 static void completion_add_text(GtkEntry *entry, const char *text){
593 GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(entry));
595 if (gtk_tree_model_get_iter_first(model,&iter)){
598 gtk_tree_model_get(model,&iter,0,&uri,-1);
600 if (strcmp(uri,text)==0) {
602 gtk_list_store_remove(GTK_LIST_STORE(model),&iter);
608 }while (gtk_tree_model_iter_next(model,&iter));
610 /* and prepend it on top of the list */
611 gtk_list_store_prepend(GTK_LIST_STORE(model),&iter);
612 gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,text,-1);
616 void linphone_gtk_call_terminated(LinphoneCall *call, const char *error){
617 GtkWidget *mw=linphone_gtk_get_main_window();
618 gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),FALSE);
619 gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"start_call"),TRUE);
621 if (linphone_gtk_use_in_call_view() && call)
622 linphone_gtk_in_call_view_terminate(call,error);
623 update_video_title();
626 static gboolean in_call_timer(){
627 LinphoneCall *call=linphone_core_get_current_call(linphone_gtk_get_core());
629 linphone_gtk_in_call_view_update_duration(call);
635 static bool_t all_other_calls_paused(LinphoneCall *refcall, const MSList *calls){
636 for(;calls!=NULL;calls=calls->next){
637 LinphoneCall *call=(LinphoneCall*)calls->data;
638 LinphoneCallState cs=linphone_call_get_state(call);
640 if (cs!=LinphoneCallPaused && cs!=LinphoneCallPausing)
647 static void linphone_gtk_update_call_buttons(LinphoneCall *call){
648 LinphoneCore *lc=linphone_gtk_get_core();
649 GtkWidget *mw=linphone_gtk_get_main_window();
650 const MSList *calls=linphone_core_get_calls(lc);
652 bool_t start_active=TRUE;
653 bool_t stop_active=FALSE;
654 bool_t add_call=FALSE;
655 int call_list_size=ms_list_size(calls);
662 if (all_other_calls_paused(NULL,calls)){
665 }else if (call!=NULL && linphone_call_get_state(call)==LinphoneCallIncomingReceived && all_other_calls_paused(call,calls)){
666 if (call_list_size>1){
677 button=linphone_gtk_get_widget(mw,"start_call");
678 gtk_widget_set_sensitive(button,start_active);
679 gtk_widget_set_visible(button,!add_call);
681 button=linphone_gtk_get_widget(mw,"add_call");
682 gtk_widget_set_sensitive(button,start_active);
683 gtk_widget_set_visible(button,add_call);
685 gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),stop_active);
686 if (linphone_core_get_calls(lc)==NULL){
687 linphone_gtk_enable_mute_button(
688 GTK_BUTTON(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"main_mute")),
691 linphone_gtk_enable_transfer_button(lc,call_list_size>1);
692 update_video_title();
695 static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){
696 const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar));
697 if (linphone_core_invite(linphone_gtk_get_core(),entered)!=NULL) {
698 completion_add_text(GTK_ENTRY(uri_bar),entered);
700 linphone_gtk_call_terminated(NULL,NULL);
705 static gboolean linphone_gtk_auto_answer(LinphoneCall *call){
706 if (linphone_call_get_state(call)==LinphoneCallIncomingReceived){
707 linphone_core_accept_call (linphone_gtk_get_core(),call);
708 linphone_call_unref(call);
714 void linphone_gtk_start_call(GtkWidget *w){
715 LinphoneCore *lc=linphone_gtk_get_core();
717 /*change into in-call mode, then do the work later as it might block a bit */
718 GtkWidget *mw=gtk_widget_get_toplevel(w);
719 GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar");
721 call=linphone_gtk_get_currently_displayed_call ();
722 if (call!=NULL && linphone_call_get_state(call)==LinphoneCallIncomingReceived){
723 linphone_core_accept_call(lc,call);
725 /*immediately disable the button and delay a bit the execution the linphone_core_invite()
726 so that we don't freeze the button. linphone_core_invite() might block for some hundreds of milliseconds*/
727 gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"start_call"),FALSE);
728 g_timeout_add(100,(GSourceFunc)linphone_gtk_start_call_do,uri_bar);
733 void linphone_gtk_uri_bar_activate(GtkWidget *w){
734 linphone_gtk_start_call(w);
738 void linphone_gtk_terminate_call(GtkWidget *button){
739 LinphoneCall *call=linphone_gtk_get_currently_displayed_call ();
741 linphone_core_terminate_call(linphone_gtk_get_core(),call);
744 void linphone_gtk_decline_clicked(GtkWidget *button){
745 LinphoneCall *call=linphone_gtk_get_currently_displayed_call ();
747 linphone_core_terminate_call(linphone_gtk_get_core(),call);
750 void linphone_gtk_answer_clicked(GtkWidget *button){
751 LinphoneCall *call=linphone_gtk_get_currently_displayed_call ();
753 linphone_core_pause_all_calls(linphone_gtk_get_core());
754 linphone_core_accept_call(linphone_gtk_get_core(),call);
758 void linphone_gtk_set_audio_video(){
759 linphone_core_enable_video(linphone_gtk_get_core(),TRUE,TRUE);
760 linphone_core_enable_video_preview(linphone_gtk_get_core(),
761 linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT));
764 void linphone_gtk_set_audio_only(){
765 linphone_core_enable_video(linphone_gtk_get_core(),FALSE,FALSE);
766 linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
769 void linphone_gtk_enable_self_view(GtkWidget *w){
770 gboolean val=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
771 LinphoneCore *lc=linphone_gtk_get_core();
772 linphone_core_enable_video_preview(lc,val);
773 linphone_core_enable_self_view(lc,val);
774 linphone_gtk_set_ui_config_int("videoselfview",val);
777 void linphone_gtk_used_identity_changed(GtkWidget *w){
778 int active=gtk_combo_box_get_active(GTK_COMBO_BOX(w));
779 char *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w));
780 if (sel && strlen(sel)>0){ //avoid a dummy "changed" at gui startup
781 linphone_core_set_default_proxy_index(linphone_gtk_get_core(),(active==0) ? -1 : (active-1));
782 linphone_gtk_show_directory_search();
784 if (sel) g_free(sel);
787 static void linphone_gtk_show_main_window(){
788 GtkWidget *w=linphone_gtk_get_main_window();
789 LinphoneCore *lc=linphone_gtk_get_core();
790 if (linphone_core_video_enabled(lc)){
791 linphone_core_enable_video_preview(lc,linphone_gtk_get_ui_config_int("videoselfview",
792 VIDEOSELFVIEW_DEFAULT));
795 gtk_window_present(GTK_WINDOW(w));
798 static void linphone_gtk_show(LinphoneCore *lc){
799 linphone_gtk_show_main_window();
802 static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid){
803 linphone_gtk_show_friends();
806 static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint response_id, LinphoneFriend *lf){
808 case GTK_RESPONSE_YES:
809 linphone_gtk_show_contact(lf);
812 linphone_core_reject_subscriber(linphone_gtk_get_core(),lf);
814 gtk_widget_destroy(dialog);
817 static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
820 if (linphone_gtk_get_ui_config_int("subscribe_deny_all",0)){
821 linphone_core_reject_subscriber(linphone_gtk_get_core(),lf);
825 gchar *message=g_strdup_printf(_("%s would like to add you to his contact list.\nWould you allow him to see your presence status or add him to your contact list ?\nIf you answer no, this person will be temporarily blacklisted."),url);
826 dialog = gtk_message_dialog_new (
827 GTK_WINDOW(linphone_gtk_get_main_window()),
828 GTK_DIALOG_DESTROY_WITH_PARENT,
829 GTK_MESSAGE_QUESTION,
834 g_signal_connect(G_OBJECT (dialog), "response",
835 G_CALLBACK (linphone_gtk_new_subscriber_response),lf);
836 /* actually show the box */
837 gtk_widget_show(dialog);
840 typedef struct _AuthTimeout{
845 static void auth_timeout_clean(AuthTimeout *tout){
849 static gboolean auth_timeout_destroy(AuthTimeout *tout){
851 g_object_weak_unref(G_OBJECT(tout->w),(GWeakNotify)auth_timeout_clean,tout);
852 gtk_widget_destroy(tout->w);
858 static AuthTimeout * auth_timeout_new(GtkWidget *w){
859 AuthTimeout *tout=g_new(AuthTimeout,1);
861 /*so that the timeout no more references the widget when it is destroyed:*/
862 g_object_weak_ref(G_OBJECT(w),(GWeakNotify)auth_timeout_clean,tout);
863 /*so that the widget is automatically destroyed after some time */
864 g_timeout_add(30000,(GtkFunction)auth_timeout_destroy,tout);
868 void linphone_gtk_password_cancel(GtkWidget *w){
869 LinphoneAuthInfo *info;
870 GtkWidget *window=gtk_widget_get_toplevel(w);
871 info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info");
872 linphone_core_abort_authentication(linphone_gtk_get_core(),info);
873 gtk_widget_destroy(window);
876 void linphone_gtk_password_ok(GtkWidget *w){
878 GtkWidget *window=gtk_widget_get_toplevel(w);
879 LinphoneAuthInfo *info;
880 info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info");
881 g_object_weak_unref(G_OBJECT(window),(GWeakNotify)linphone_auth_info_destroy,info);
882 entry=linphone_gtk_get_widget(window,"password_entry");
883 linphone_auth_info_set_passwd(info,gtk_entry_get_text(GTK_ENTRY(entry)));
884 linphone_auth_info_set_userid(info,
885 gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(window,"userid_entry"))));
886 linphone_core_add_auth_info(linphone_gtk_get_core(),info);
887 gtk_widget_destroy(window);
890 static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username){
891 GtkWidget *w=linphone_gtk_create_window("password");
892 GtkWidget *label=linphone_gtk_get_widget(w,"message");
893 LinphoneAuthInfo *info;
895 GtkWidget *mw=linphone_gtk_get_main_window();
897 if (mw && GTK_WIDGET_VISIBLE(linphone_gtk_get_widget(mw,"login_frame"))){
898 /*don't prompt for authentication when login frame is visible*/
899 linphone_core_abort_authentication(lc,NULL);
903 msg=g_strdup_printf(_("Please enter your password for username <i>%s</i>\n at domain <i>%s</i>:"),
905 gtk_label_set_markup(GTK_LABEL(label),msg);
907 gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"userid_entry")),username);
908 info=linphone_auth_info_new(username, NULL, NULL, NULL,realm);
909 g_object_set_data(G_OBJECT(w),"auth_info",info);
910 g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_auth_info_destroy,info);
915 static void linphone_gtk_display_status(LinphoneCore *lc, const char *status){
916 GtkWidget *w=linphone_gtk_get_main_window();
917 GtkWidget *status_bar=linphone_gtk_get_widget(w,"status_bar");
918 gtk_statusbar_push(GTK_STATUSBAR(status_bar),
919 gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar),""),
923 static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg){
924 linphone_gtk_display_something(GTK_MESSAGE_INFO,msg);
927 static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning){
928 linphone_gtk_display_something(GTK_MESSAGE_WARNING,warning);
931 static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url){
933 snprintf(richtext,sizeof(richtext),"%s %s",msg,url);
934 linphone_gtk_display_something(GTK_MESSAGE_INFO,richtext);
937 static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl){
938 GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"call_logs");
939 if (w) linphone_gtk_call_log_update(w);
942 static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg){
944 case LinphoneCallOutgoingInit:
945 linphone_gtk_create_in_call_view (call);
947 case LinphoneCallOutgoingProgress:
948 linphone_gtk_in_call_view_set_calling (call);
950 case LinphoneCallStreamsRunning:
951 linphone_gtk_in_call_view_set_in_call(call);
952 linphone_gtk_enable_mute_button(
953 GTK_BUTTON(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"main_mute")),
955 g_timeout_add(250,(GSourceFunc)in_call_timer,NULL);
957 case LinphoneCallError:
958 linphone_gtk_in_call_view_terminate (call,msg);
960 case LinphoneCallEnd:
961 linphone_gtk_in_call_view_terminate(call,NULL);
963 case LinphoneCallIncomingReceived:
964 linphone_gtk_create_in_call_view (call);
965 linphone_gtk_in_call_view_set_incoming(call,!all_other_calls_paused (call,linphone_core_get_calls(lc)));
967 linphone_call_ref(call);
968 g_timeout_add(2000,(GSourceFunc)linphone_gtk_auto_answer ,call);
971 case LinphoneCallResuming:
972 linphone_gtk_enable_hold_button(call,TRUE,TRUE);
973 linphone_gtk_in_call_view_set_in_call (call);
975 case LinphoneCallPausing:
976 linphone_gtk_enable_hold_button(call,TRUE,FALSE);
977 case LinphoneCallPausedByRemote:
978 linphone_gtk_in_call_view_set_paused(call);
980 case LinphoneCallConnected:
981 linphone_gtk_enable_hold_button (call,TRUE,TRUE);
986 linphone_gtk_update_call_buttons (call);
989 static void linphone_gtk_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg,
990 LinphoneRegistrationState rs, const char *msg){
992 case LinphoneRegistrationOk:
994 SipSetup *ss=linphone_proxy_config_get_sip_setup(cfg);
995 if (ss && (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_LOGIN)){
996 linphone_gtk_exit_login_frame();
1006 static void icon_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data){
1007 GtkWidget *menu=(GtkWidget*)g_object_get_data(G_OBJECT(status_icon),"menu");
1008 gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time);
1011 void linphone_gtk_open_browser(const char *url){
1012 /*in gtk 2.16, gtk_show_uri does not work...*/
1014 #if GTK_CHECK_VERSION(2,18,3)
1015 gtk_show_uri(NULL,url,GDK_CURRENT_TIME,NULL);
1018 snprintf(cl,sizeof(cl),"/usr/bin/x-www-browser %s",url);
1019 g_spawn_command_line_async(cl,NULL);
1022 ShellExecute(0,"open",url,NULL,NULL,1);
1026 void linphone_gtk_link_to_website(GtkWidget *item){
1027 const gchar *home=(const gchar*)g_object_get_data(G_OBJECT(item),"home");
1028 linphone_gtk_open_browser(home);
1031 static GtkWidget *create_icon_menu(){
1032 GtkWidget *menu=gtk_menu_new();
1033 GtkWidget *menu_item;
1036 const gchar *homesite;
1038 homesite=linphone_gtk_get_ui_config("home","http://www.linphone.org");
1039 menu_item=gtk_image_menu_item_new_with_label(_("Website link"));
1040 tmp=g_strdup(homesite);
1041 g_object_set_data(G_OBJECT(menu_item),"home",tmp);
1042 g_object_weak_ref(G_OBJECT(menu_item),(GWeakNotify)g_free,tmp);
1044 image=gtk_image_new_from_stock(GTK_STOCK_HELP,GTK_ICON_SIZE_MENU);
1045 gtk_widget_show(image);
1046 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
1047 //g_object_unref(G_OBJECT(image));
1048 gtk_widget_show(menu_item);
1049 gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
1050 g_signal_connect(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_link_to_website,NULL);
1052 menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT,NULL);
1053 gtk_widget_show(menu_item);
1054 gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
1055 g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_show_about,NULL);
1056 menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,NULL);
1057 gtk_widget_show(menu_item);
1058 gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
1059 g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)gtk_main_quit,NULL);
1060 gtk_widget_show(menu);
1064 static GtkStatusIcon *icon=NULL;
1066 static void linphone_gtk_init_status_icon(){
1067 const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
1068 GdkPixbuf *pbuf=create_pixbuf(icon_path);
1069 GtkWidget *menu=create_icon_menu();
1071 icon=gtk_status_icon_new_from_pixbuf(pbuf);
1072 g_object_unref(G_OBJECT(pbuf));
1073 g_signal_connect_swapped(G_OBJECT(icon),"activate",(GCallback)linphone_gtk_show_main_window,linphone_gtk_get_main_window());
1074 g_signal_connect(G_OBJECT(icon),"popup-menu",(GCallback)icon_popup_menu,NULL);
1075 title=linphone_gtk_get_ui_config("title",_("Linphone - a video internet phone"));
1076 gtk_status_icon_set_tooltip(icon,title);
1077 gtk_status_icon_set_visible(icon,TRUE);
1078 g_object_set_data(G_OBJECT(icon),"menu",menu);
1079 g_object_weak_ref(G_OBJECT(icon),(GWeakNotify)gtk_widget_destroy,menu);
1082 void linphone_gtk_load_identities(void){
1084 GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities"));
1086 LinphoneProxyConfig *def=NULL;
1088 GtkListStore *store;
1090 store=GTK_LIST_STORE(gtk_combo_box_get_model(box));
1091 gtk_list_store_clear(store);
1093 linphone_core_get_default_proxy(linphone_gtk_get_core(),&def);
1094 def_identity=g_strdup_printf(_("%s (Default)"),linphone_core_get_primary_contact(linphone_gtk_get_core()));
1095 gtk_combo_box_append_text(box,def_identity);
1096 g_free(def_identity);
1097 for(i=1,elem=linphone_core_get_proxy_config_list(linphone_gtk_get_core());
1099 elem=ms_list_next(elem),i++){
1100 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
1101 gtk_combo_box_append_text(box,linphone_proxy_config_get_identity(cfg));
1106 gtk_combo_box_set_active(box,def_index);
1109 static void linphone_gtk_dtmf_pressed(GtkButton *button){
1110 const char *label=gtk_button_get_label(button);
1111 GtkWidget *uri_bar=linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(button)),"uribar");
1113 gtk_editable_insert_text(GTK_EDITABLE(uri_bar),label,1,&pos);
1114 linphone_core_play_dtmf (linphone_gtk_get_core(),label[0],-1);
1115 if (linphone_core_in_call(linphone_gtk_get_core())){
1116 linphone_core_send_dtmf(linphone_gtk_get_core(),label[0]);
1120 static void linphone_gtk_dtmf_released(GtkButton *button){
1121 linphone_core_stop_dtmf (linphone_gtk_get_core());
1124 static void linphone_gtk_connect_digits(void){
1125 GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"dtmf_table"));
1126 GList *children=gtk_container_get_children(cont);
1128 for(elem=children;elem!=NULL;elem=elem->next){
1129 GtkButton *button=GTK_BUTTON(elem->data);
1130 g_signal_connect(G_OBJECT(button),"pressed",(GCallback)linphone_gtk_dtmf_pressed,NULL);
1131 g_signal_connect(G_OBJECT(button),"released",(GCallback)linphone_gtk_dtmf_released,NULL);
1135 static void linphone_gtk_check_menu_items(void){
1136 bool_t audio_only=!linphone_core_video_enabled(linphone_gtk_get_core());
1137 bool_t selfview=linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT);
1138 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(linphone_gtk_get_widget(
1139 linphone_gtk_get_main_window(),
1140 audio_only ? "audio_only_item" : "video_item")), TRUE);
1141 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(linphone_gtk_get_widget(
1142 linphone_gtk_get_main_window(),"selfview_item")),selfview);
1145 static gboolean linphone_gtk_can_manage_accounts(){
1146 LinphoneCore *lc=linphone_gtk_get_core();
1148 for(elem=linphone_core_get_sip_setups(lc);elem!=NULL;elem=elem->next){
1149 SipSetup *ss=(SipSetup*)elem->data;
1150 if (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_ACCOUNT_MANAGER){
1157 static void linphone_gtk_configure_main_window(){
1158 static gboolean config_loaded=FALSE;
1159 static const char *title;
1160 static const char *home;
1161 static const char *start_call_icon;
1162 static const char *add_call_icon;
1163 static const char *stop_call_icon;
1164 static const char *search_icon;
1165 static gboolean update_check_menu;
1166 static gboolean buttons_have_borders;
1167 static gboolean show_abcd;
1168 GtkWidget *w=linphone_gtk_get_main_window();
1169 if (!config_loaded){
1170 title=linphone_gtk_get_ui_config("title","Linphone");
1171 home=linphone_gtk_get_ui_config("home","http://www.linphone.org");
1172 start_call_icon=linphone_gtk_get_ui_config("start_call_icon","startcall-green.png");
1173 add_call_icon=linphone_gtk_get_ui_config("add_call_icon","addcall-green.png");
1174 stop_call_icon=linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png");
1175 search_icon=linphone_gtk_get_ui_config("directory_search_icon",NULL);
1176 update_check_menu=linphone_gtk_get_ui_config_int("update_check_menu",0);
1177 buttons_have_borders=linphone_gtk_get_ui_config_int("buttons_border",1);
1178 show_abcd=linphone_gtk_get_ui_config_int("show_abcd",1);
1181 linphone_gtk_configure_window(w,"main_window");
1183 gtk_window_set_title(GTK_WINDOW(w),title);
1184 #if GTK_CHECK_VERSION(2,16,0)
1186 gtk_menu_item_set_label(GTK_MENU_ITEM(linphone_gtk_get_widget(w,"main_menu")),_("Windows"));
1188 gtk_menu_item_set_label(GTK_MENU_ITEM(linphone_gtk_get_widget(w,"main_menu")),title);
1192 if (start_call_icon){
1193 gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(w,"start_call")),
1194 create_pixmap (start_call_icon));
1195 if (!buttons_have_borders)
1196 gtk_button_set_relief(GTK_BUTTON(linphone_gtk_get_widget(w,"start_call")),GTK_RELIEF_NONE);
1199 gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(w,"add_call")),
1200 create_pixmap (add_call_icon));
1201 if (!buttons_have_borders)
1202 gtk_button_set_relief(GTK_BUTTON(linphone_gtk_get_widget(w,"add_call")),GTK_RELIEF_NONE);
1204 if (stop_call_icon){
1205 gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(w,"terminate_call")),
1206 create_pixmap (stop_call_icon));
1207 if (!buttons_have_borders)
1208 gtk_button_set_relief(GTK_BUTTON(linphone_gtk_get_widget(w,"terminate_call")),GTK_RELIEF_NONE);
1211 GdkPixbuf *pbuf=create_pixbuf(search_icon);
1212 gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"directory_search_button_icon")),pbuf);
1213 g_object_unref(G_OBJECT(pbuf));
1217 GtkWidget *menu_item=linphone_gtk_get_widget(w,"home_item");
1219 g_object_set_data(G_OBJECT(menu_item),"home",tmp);
1222 GdkPixbuf *pbuf=create_pixbuf("contact-orange.png");
1224 gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"contact_tab_icon")),pbuf);
1225 g_object_unref(G_OBJECT(pbuf));
1229 GdkPixbuf *pbuf=create_pixbuf("dialer-orange.png");
1231 gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"keypad_tab_icon")),pbuf);
1232 g_object_unref(G_OBJECT(pbuf));
1235 if (linphone_gtk_can_manage_accounts())
1236 gtk_widget_show(linphone_gtk_get_widget(w,"assistant_item"));
1237 if (update_check_menu){
1238 gtk_widget_show(linphone_gtk_get_widget(w,"versioncheck_item"));
1241 gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_A"));
1242 gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_B"));
1243 gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_C"));
1244 gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_D"));
1245 gtk_table_resize(GTK_TABLE(linphone_gtk_get_widget(w,"dtmf_table")),4,3);
1249 void linphone_gtk_manage_login(void){
1250 LinphoneCore *lc=linphone_gtk_get_core();
1251 LinphoneProxyConfig *cfg=NULL;
1252 linphone_core_get_default_proxy(lc,&cfg);
1254 SipSetup *ss=linphone_proxy_config_get_sip_setup(cfg);
1255 if (ss && (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_LOGIN)){
1256 linphone_gtk_show_login_frame(cfg);
1262 gboolean linphone_gtk_close(GtkWidget *mw){
1263 /*shutdown calls if any*/
1264 LinphoneCore *lc=linphone_gtk_get_core();
1265 if (linphone_core_in_call(lc)){
1266 linphone_core_terminate_all_calls(lc);
1268 linphone_core_enable_video_preview(lc,FALSE);
1270 gtk_window_iconify(GTK_WINDOW(mw));
1272 gtk_widget_hide(mw);
1277 static void linphone_gtk_init_main_window(){
1278 GtkWidget *main_window;
1280 linphone_gtk_configure_main_window();
1281 linphone_gtk_manage_login();
1283 linphone_gtk_load_identities();
1284 linphone_gtk_set_my_presence(linphone_core_get_presence_info(linphone_gtk_get_core()));
1285 linphone_gtk_show_friends();
1286 linphone_gtk_connect_digits();
1287 linphone_gtk_check_menu_items();
1288 main_window=linphone_gtk_get_main_window();
1289 linphone_gtk_enable_mute_button(GTK_BUTTON(linphone_gtk_get_widget(main_window,
1290 "main_mute")),FALSE);
1291 if (!linphone_gtk_use_in_call_view()) {
1292 gtk_widget_show(linphone_gtk_get_widget(main_window, "main_mute"));
1294 linphone_gtk_update_call_buttons (NULL);
1295 /*prevent the main window from being destroyed by a user click on WM controls, instead we hide it*/
1296 g_signal_connect (G_OBJECT (main_window), "delete-event",
1297 G_CALLBACK (linphone_gtk_close), main_window);
1300 GtkWidget *menubar=linphone_gtk_get_widget(main_window,"menubar1");
1301 gtk_widget_destroy(linphone_gtk_get_widget(main_window,"imagemenuitem5"));
1302 GtkOSXApplication *theMacApp = (GtkOSXApplication*)g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1303 gtk_osxapplication_set_menu_bar(theMacApp,GTK_MENU_SHELL(menubar));
1304 gtk_widget_hide(menubar);
1305 gtk_osxapplication_ready(theMacApp);
1311 void linphone_gtk_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
1313 const char *lname="undef";
1315 #if defined(__linux) || defined(__APPLE__)
1316 va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/
1335 g_error("Bad level !");
1337 #if defined(__linux) || defined(__APPLE__)
1339 msg=g_strdup_vprintf(fmt,cap);
1342 msg=g_strdup_vprintf(fmt,args);
1344 fprintf(stdout,"linphone-%s : %s\n",lname,msg);
1347 linphone_gtk_log_push(lev,fmt,args);
1351 static void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to){
1352 GtkEntry * uri_bar =GTK_ENTRY(linphone_gtk_get_widget(
1353 linphone_gtk_get_main_window(), "uribar"));
1354 linphone_gtk_show_main_window();
1355 gtk_entry_set_text(uri_bar, refer_to);
1356 linphone_gtk_start_call(linphone_gtk_get_main_window());
1359 static void linphone_gtk_check_soundcards(){
1360 const char **devices=linphone_core_get_sound_devices(linphone_gtk_get_core());
1361 if (devices==NULL || devices[0]==NULL){
1362 linphone_gtk_display_something(GTK_MESSAGE_WARNING,
1363 _("No sound cards have been detected on this computer.\n"
1364 "You won't be able to send or receive audio calls."));
1368 int main(int argc, char *argv[]){
1372 const char *config_file;
1373 const char *factory_config_file;
1375 GtkSettings *settings;
1378 g_thread_init(NULL);
1381 progpath = strdup(argv[0]);
1383 config_file=linphone_gtk_get_config_file();
1386 /*workaround for windows: sometimes LANG is defined to an integer value, not understood by gtk */
1387 if ((lang=getenv("LANG"))!=NULL){
1390 snprintf(tmp,sizeof(tmp),"LANG=",lang);
1396 g_setenv("PULSE_PROP_media.role", "phone", TRUE);
1399 if ((lang=linphone_gtk_get_lang(config_file))!=NULL && lang[0]!='\0'){
1402 snprintf(tmp,sizeof(tmp),"LANG=%s",lang);
1405 setenv("LANG",lang,1);
1410 p=bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
1411 if (p==NULL) perror("bindtextdomain failed");
1412 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1413 textdomain (GETTEXT_PACKAGE);
1415 g_message("NLS disabled.\n");
1418 gtk_rc_add_default_file("./gtkrc");
1420 gdk_threads_enter();
1422 if (!gtk_init_with_args(&argc,&argv,_("A free SIP video-phone"),
1423 linphone_options,NULL,NULL)){
1424 gdk_threads_leave();
1428 settings=gtk_settings_get_default();
1429 g_type_class_unref (g_type_class_ref (GTK_TYPE_IMAGE_MENU_ITEM));
1430 g_type_class_unref (g_type_class_ref (GTK_TYPE_BUTTON));
1431 g_object_set(settings, "gtk-menu-images", TRUE, NULL);
1432 g_object_set(settings, "gtk-button-images", TRUE, NULL);
1434 if (workingdir!=NULL)
1437 /* Now, look for the factory configuration file, we do it this late
1438 since we want to have had time to change directory and to parse
1439 the options, in case we needed to access the working directory */
1440 factory_config_file = linphone_gtk_get_factory_config_file();
1442 if (linphone_core_wake_up_possible_already_running_instance(
1443 config_file, addr_to_call) == 0){
1444 g_message("addr_to_call=%s",addr_to_call);
1445 g_warning("Another running instance of linphone has been detected. It has been woken-up.");
1446 g_warning("This instance is going to exit now.");
1447 gdk_threads_leave();
1451 add_pixmap_directory("pixmaps");
1452 add_pixmap_directory(PACKAGE_DATA_DIR "/pixmaps/linphone");
1455 GtkOSXApplication *theMacApp = (GtkOSXApplication*)g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1456 g_signal_connect(G_OBJECT(theMacApp),"NSApplicationDidBecomeActive",(GCallback)linphone_gtk_show_main_window,NULL);
1457 g_signal_connect(G_OBJECT(theMacApp),"NSApplicationWillTerminate",(GCallback)gtk_main_quit,NULL);
1460 the_ui=linphone_gtk_create_window("main");
1462 linphone_gtk_create_log_window();
1463 linphone_core_enable_logs_with_cb(linphone_gtk_log_handler);
1465 linphone_gtk_init_liblinphone(config_file, factory_config_file);
1467 g_set_application_name(linphone_gtk_get_ui_config("title","Linphone"));
1468 pbuf=create_pixbuf(linphone_gtk_get_ui_config("icon",LINPHONE_ICON));
1469 if (pbuf!=NULL) gtk_window_set_default_icon(pbuf);
1471 /* do not lower timeouts under 30 ms because it exhibits a bug on gtk+/win32, with cpu running 20% all the time...*/
1472 gtk_timeout_add(30,(GtkFunction)linphone_gtk_iterate,(gpointer)linphone_gtk_get_core());
1473 gtk_timeout_add(30,(GtkFunction)linphone_gtk_check_logs,(gpointer)NULL);
1474 linphone_gtk_init_main_window();
1476 linphone_gtk_init_status_icon();
1479 linphone_gtk_show_main_window();
1480 linphone_gtk_check_soundcards();
1482 if (linphone_gtk_get_ui_config_int("update_check_menu",0)==0)
1483 linphone_gtk_check_for_new_version();
1486 gdk_threads_leave();
1487 linphone_gtk_destroy_log_window();
1488 linphone_core_destroy(the_core);
1490 /*workaround a bug on win32 that makes status icon still present in the systray even after program exit.*/
1491 gtk_status_icon_set_visible(icon,FALSE);