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.
20 #define USE_LIBGLADE 1
22 #define VIDEOSELFVIEW_DEFAULT 1
30 #include <glade/glade.h>
33 #include <sys/types.h>
37 #define LINPHONE_ICON "linphone.png"
39 const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION;
41 static LinphoneCore *the_core=NULL;
42 static GtkWidget *the_ui=NULL;
44 static void linphone_gtk_show(LinphoneCore *lc);
45 static void linphone_gtk_inv_recv(LinphoneCore *lc, LinphoneCall *call);
46 static void linphone_gtk_bye_recv(LinphoneCore *lc, LinphoneCall *call);
47 static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid);
48 static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
49 static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username);
50 static void linphone_gtk_display_status(LinphoneCore *lc, const char *status);
51 static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg);
52 static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning);
53 static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url);
54 static void linphone_gtk_display_question(LinphoneCore *lc, const char *question);
55 static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl);
56 static void linphone_gtk_general_state(LinphoneCore *lc, LinphoneGeneralState *gstate);
57 static void linphone_gtk_refer_received(LinphoneCore *lc, LinphoneCall *call, const char *refer_to);
58 static gboolean linphone_gtk_auto_answer(GtkWidget *incall_window);
60 static LinphoneCoreVTable vtable={
61 .show=linphone_gtk_show,
62 .inv_recv=linphone_gtk_inv_recv,
63 .bye_recv=linphone_gtk_bye_recv,
64 .notify_presence_recv=linphone_gtk_notify_recv,
65 .new_unknown_subscriber=linphone_gtk_new_unknown_subscriber,
66 .auth_info_requested=linphone_gtk_auth_info_requested,
67 .display_status=linphone_gtk_display_status,
68 .display_message=linphone_gtk_display_message,
69 .display_warning=linphone_gtk_display_warning,
70 .display_url=linphone_gtk_display_url,
71 .display_question=linphone_gtk_display_question,
72 .call_log_updated=linphone_gtk_call_log_updated,
73 .text_received=linphone_gtk_text_received,
74 .general_state=linphone_gtk_general_state,
75 .refer_received=linphone_gtk_refer_received,
76 .buddy_info_updated=linphone_gtk_buddy_info_updated
79 static gboolean verbose=0;
80 static gboolean auto_answer = 0;
81 static gchar * addr_to_call = NULL;
82 static gboolean iconified=FALSE;
84 static gchar *workingdir=NULL;
86 static char *progpath=NULL;
88 static GOptionEntry linphone_options[]={
92 .arg=G_OPTION_ARG_NONE,
93 .arg_data= (gpointer)&verbose,
94 .description=N_("log to stdout some debug information while running.")
97 .long_name="iconified",
99 .arg=G_OPTION_ARG_NONE,
100 .arg_data= (gpointer)&iconified,
101 .description=N_("Start only in the system tray, do not show the main interface.")
106 .arg = G_OPTION_ARG_STRING,
107 .arg_data = &addr_to_call,
108 .description = N_("address to call right now")
111 .long_name = "auto-answer",
113 .arg = G_OPTION_ARG_NONE,
114 .arg_data = (gpointer) & auto_answer,
115 .description = N_("if set automatically answer incoming calls")
119 .long_name = "workdir",
121 .arg = G_OPTION_ARG_STRING,
122 .arg_data = (gpointer) & workingdir,
123 .description = N_("Specifiy a working directory (should be the base of the installation, eg: c:\\Program Files\\Linphone)")
129 #define INSTALLED_XML_DIR PACKAGE_DATA_DIR "/linphone"
130 #define BUILD_TREE_XML_DIR "gtk-glade"
133 #define CONFIG_FILE ".linphonerc"
135 #define CONFIG_FILE "linphonerc"
140 static char _config_file[1024];
143 const char *linphone_gtk_get_config_file(){
144 /*try accessing a local file first if exists*/
145 if (access(CONFIG_FILE,F_OK)==0){
146 snprintf(_config_file,sizeof(_config_file),"%s",CONFIG_FILE);
149 const char *appdata=getenv("APPDATA");
151 snprintf(_config_file,sizeof(_config_file),"%s\\%s",appdata,LINPHONE_CONFIG_DIR);
152 CreateDirectory(_config_file,NULL);
153 snprintf(_config_file,sizeof(_config_file),"%s\\%s",appdata,LINPHONE_CONFIG_DIR "\\" CONFIG_FILE);
156 const char *home=getenv("HOME");
157 if (home==NULL) home=".";
158 snprintf(_config_file,sizeof(_config_file),"%s/%s",home,CONFIG_FILE);
165 #define FACTORY_CONFIG_FILE "linphonerc.factory"
166 static char _factory_config_file[1024];
167 static const char *linphone_gtk_get_factory_config_file(){
168 /*try accessing a local file first if exists*/
169 if (access(FACTORY_CONFIG_FILE,F_OK)==0){
170 snprintf(_factory_config_file,sizeof(_factory_config_file),
171 "%s",FACTORY_CONFIG_FILE);
175 if (progpath != NULL) {
177 progdir = strdup(progpath);
179 basename = strrchr(progdir, '\\');
180 if (basename != NULL) {
183 snprintf(_factory_config_file, sizeof(_factory_config_file),
184 "%s\\..\\%s", progdir, FACTORY_CONFIG_FILE);
186 if (workingdir!=NULL) {
187 snprintf(_factory_config_file, sizeof(_factory_config_file),
188 "%s\\%s", workingdir, FACTORY_CONFIG_FILE);
195 basename = strrchr(progdir, '/');
196 if (basename != NULL) {
199 snprintf(_factory_config_file, sizeof(_factory_config_file),
200 "%s/../share/Linphone/%s", progdir, FACTORY_CONFIG_FILE);
209 return _factory_config_file;
212 static void linphone_gtk_init_liblinphone(const char *config_file,
213 const char *factory_config_file) {
214 linphone_core_set_user_agent("Linphone", LINPHONE_VERSION);
215 the_core=linphone_core_new(&vtable,config_file,factory_config_file,NULL);
216 linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
221 LinphoneCore *linphone_gtk_get_core(void){
225 GtkWidget *linphone_gtk_get_main_window(){
229 static void linphone_gtk_configure_window(GtkWidget *w, const char *window_name){
230 static const char *icon_path=NULL;
231 static const char *hiddens=NULL;
232 static const char *shown=NULL;
233 static bool_t config_loaded=FALSE;
234 if (linphone_gtk_get_core()==NULL) return;
235 if (config_loaded==FALSE){
236 hiddens=linphone_gtk_get_ui_config("hidden_widgets",NULL);
237 shown=linphone_gtk_get_ui_config("shown_widgets",NULL);
238 icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
242 linphone_gtk_visibility_set(hiddens,window_name,w,FALSE);
244 linphone_gtk_visibility_set(shown,window_name,w,TRUE);
246 GdkPixbuf *pbuf=create_pixbuf(icon_path);
247 gtk_window_set_icon(GTK_WINDOW(w),pbuf);
248 g_object_unref(G_OBJECT(pbuf));
254 GtkWidget *linphone_gtk_create_window(const char *window_name){
258 snprintf(path,sizeof(path),"%s/%s.glade",BUILD_TREE_XML_DIR,window_name);
259 if (access(path,F_OK)!=0){
260 snprintf(path,sizeof(path),"%s/%s.glade",INSTALLED_XML_DIR,window_name);
261 if (access(path,F_OK)!=0){
262 g_error("Could not locate neither %s/%s.glade and %s/%s.glade .",BUILD_TREE_XML_DIR,window_name,
263 INSTALLED_XML_DIR,window_name);
267 gxml=glade_xml_new(path,NULL,NULL);
268 glade_xml_signal_autoconnect(gxml);
269 w=glade_xml_get_widget(gxml,window_name);
270 if (w==NULL) g_error("Could not retrieve '%s' window from xml file",window_name);
271 linphone_gtk_configure_window(w,window_name);
275 GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
277 GladeXML *gxml=glade_get_widget_tree(window);
278 if (gxml==NULL) g_error("Could not retrieve XML tree of window %s",name);
279 w=glade_xml_get_widget(gxml,name);
280 if (w==NULL) g_error("Could not retrieve widget %s",name);
281 return GTK_WIDGET(w);
286 GtkWidget *linphone_gtk_create_window(const char *window_name){
290 GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
291 GObject *w=gtk_builder_get_object(the_ui,name);
293 g_error("No widget named %s found in xml interface.",name);
295 return GTK_WIDGET(w);
300 void linphone_gtk_display_something(GtkMessageType type,const gchar *message){
302 GtkWidget *main_window=linphone_gtk_get_main_window();
304 gtk_widget_show(main_window);
305 if (type==GTK_MESSAGE_QUESTION)
307 /* draw a question box. link to dialog_click callback */
308 dialog = gtk_message_dialog_new (
309 GTK_WINDOW(main_window),
310 GTK_DIALOG_DESTROY_WITH_PARENT,
311 GTK_MESSAGE_QUESTION,
314 (const gchar*)message);
315 /* connect to some callback : REVISIT */
317 g_signal_connect_swapped (G_OBJECT (dialog), "response",
318 G_CALLBACK (dialog_click),
321 /* actually show the box */
322 gtk_widget_show(dialog);
326 dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
327 GTK_DIALOG_DESTROY_WITH_PARENT,
331 (const gchar*)message);
332 /* Destroy the dialog when the user responds to it (e.g. clicks a button) */
333 g_signal_connect_swapped (G_OBJECT (dialog), "response",
334 G_CALLBACK (gtk_widget_destroy),
336 gtk_widget_show(dialog);
340 void linphone_gtk_about_response(GtkDialog *dialog, gint id){
341 if (id==GTK_RESPONSE_CANCEL){
342 gtk_widget_destroy(GTK_WIDGET(dialog));
346 static void about_url_clicked(GtkAboutDialog *dialog, const char *url, gpointer data){
347 g_message("About url clicked");
348 linphone_gtk_open_browser(url);
351 void linphone_gtk_show_about(){
352 struct stat filestat;
353 const char *license_file=PACKAGE_DATA_DIR "/linphone/COPYING";
355 GdkPixbuf *logo=create_pixbuf(
356 linphone_gtk_get_ui_config("logo","linphone-banner.png"));
358 about=linphone_gtk_create_window("about");
359 gtk_about_dialog_set_url_hook(about_url_clicked,NULL,NULL);
360 memset(&filestat,0,sizeof(filestat));
361 if (stat(license_file,&filestat)!=0){
362 license_file="COPYING";
363 stat(license_file,&filestat);
365 if (filestat.st_size>0){
366 char *license=g_malloc(filestat.st_size+1);
367 FILE *f=fopen(license_file,"r");
368 if (f && fread(license,filestat.st_size,1,f)==1){
369 license[filestat.st_size]='\0';
370 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about),license);
374 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about),LINPHONE_VERSION);
375 gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about),linphone_gtk_get_ui_config("title","Linphone"));
376 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about),linphone_gtk_get_ui_config("home","http://www.linphone.org"));
377 if (logo) gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about),logo);
379 gtk_widget_show(about);
382 static void set_video_window_decorations(GdkWindow *w){
383 const char *title=linphone_gtk_get_ui_config("title","Linphone");
384 const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
385 char video_title[256];
386 GdkPixbuf *pbuf=create_pixbuf(icon_path);
387 if (!linphone_core_in_call(linphone_gtk_get_core())){
388 snprintf(video_title,sizeof(video_title),"%s video",title);
389 /* When not in call, treat the video as a normal window */
390 gdk_window_set_keep_above(w, FALSE);
392 LinphoneAddress *uri =
393 linphone_address_clone(linphone_core_get_current_call_remote_address(linphone_gtk_get_core()));
396 linphone_address_clean(uri);
397 if (linphone_address_get_display_name(uri)!=NULL){
398 display_name=linphone_address_get_display_name_unquoted (uri);
400 display_name=linphone_address_as_string(uri);
402 snprintf(video_title,sizeof(video_title),_("Call with %s"),display_name);
403 linphone_address_destroy(uri);
404 ms_free(display_name);
406 /* During calls, bring up the video window, arrange so that
407 it is above all the other windows */
408 gdk_window_deiconify(w);
409 gdk_window_set_keep_above(w,TRUE);
410 /* Maybe we should have the following, but then we want to
411 have a timer that turns it off after a little while. */
412 /* gdk_window_set_urgency_hint(w,TRUE); */
414 gdk_window_set_title(w,video_title);
415 /* Refrain the video window to be closed at all times. */
416 gdk_window_set_functions(w,
417 GDK_FUNC_RESIZE|GDK_FUNC_MOVE|
418 GDK_FUNC_MINIMIZE|GDK_FUNC_MAXIMIZE);
421 l=g_list_append(l,pbuf);
422 gdk_window_set_icon_list(w,l);
424 g_object_unref(G_OBJECT(pbuf));
428 static gboolean video_needs_update=FALSE;
430 static void update_video_title(){
431 video_needs_update=TRUE;
434 static gboolean linphone_gtk_iterate(LinphoneCore *lc){
435 static gboolean first_time=TRUE;
437 static unsigned long previd=0;
438 static gboolean in_iterate=FALSE;
441 if (in_iterate) return TRUE;
443 linphone_core_iterate(lc);
445 /*after the first call to iterate, SipSetupContexts should be ready, so take actions:*/
446 linphone_gtk_show_directory_search();
450 id=linphone_core_get_native_video_window_id(lc);
451 if (id!=previd || video_needs_update){
455 ms_message("Updating window decorations");
457 w=gdk_window_foreign_new(id);
459 w=gdk_window_foreign_new((HANDLE)id);
462 set_video_window_decorations(w);
463 g_object_unref(G_OBJECT(w));
465 else ms_error("gdk_window_foreign_new() failed");
466 if (video_needs_update) video_needs_update=FALSE;
469 if (addr_to_call!=NULL){
470 /*make sure we are not showing the login screen*/
471 GtkWidget *mw=linphone_gtk_get_main_window();
472 GtkWidget *login_frame=linphone_gtk_get_widget(mw,"login_frame");
473 if (!GTK_WIDGET_VISIBLE(login_frame)){
474 GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar");
475 gtk_entry_set_text(GTK_ENTRY(uri_bar),addr_to_call);
477 linphone_gtk_start_call(uri_bar);
484 static void load_uri_history(){
485 GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"));
488 GtkEntryCompletion *gep=gtk_entry_completion_new();
489 GtkListStore *model=gtk_list_store_new(1,G_TYPE_STRING);
492 snprintf(key,sizeof(key),"uri%i",i);
493 uri=linphone_gtk_get_ui_config(key,NULL);
496 gtk_list_store_append(model,&iter);
497 gtk_list_store_set(model,&iter,0,uri,-1);
498 if (i==0) gtk_entry_set_text(uribar,uri);
502 gtk_entry_completion_set_model(gep,GTK_TREE_MODEL(model));
503 gtk_entry_completion_set_text_column(gep,0);
504 gtk_entry_set_completion(uribar,gep);
507 static void save_uri_history(){
508 LinphoneCore *lc=linphone_gtk_get_core();
509 LpConfig *cfg=linphone_core_get_config(lc);
510 GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"));
515 GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(uribar));
517 if (!gtk_tree_model_get_iter_first(model,&iter)) return;
519 gtk_tree_model_get(model,&iter,0,&uri,-1);
521 snprintf(key,sizeof(key),"uri%i",i);
522 lp_config_set_string(cfg,"GtkUi",key,uri);
527 }while(gtk_tree_model_iter_next(model,&iter));
531 static void completion_add_text(GtkEntry *entry, const char *text){
533 GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(entry));
535 if (gtk_tree_model_get_iter_first(model,&iter)){
538 gtk_tree_model_get(model,&iter,0,&uri,-1);
540 if (strcmp(uri,text)==0) {
542 gtk_list_store_remove(GTK_LIST_STORE(model),&iter);
548 }while (gtk_tree_model_iter_next(model,&iter));
550 /* and prepend it on top of the list */
551 gtk_list_store_prepend(GTK_LIST_STORE(model),&iter);
552 gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,text,-1);
556 void linphone_gtk_call_terminated(const char *error){
557 GtkWidget *mw=linphone_gtk_get_main_window();
559 gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),FALSE);
560 gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"start_call"),TRUE);
561 linphone_gtk_enable_mute_button(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(mw,"main_mute")),FALSE);
562 if (linphone_gtk_use_in_call_view())
563 linphone_gtk_in_call_view_terminate(error);
564 update_video_title();
565 icw=GTK_WIDGET(g_object_get_data(G_OBJECT(mw),"incoming_call"));
567 g_object_set_data(G_OBJECT(mw),"incoming_call",NULL);
568 gtk_widget_destroy(icw);
572 static gboolean in_call_timer(){
573 if (linphone_core_in_call(linphone_gtk_get_core())){
574 linphone_gtk_in_call_view_update_duration(
575 linphone_core_get_current_call_duration(linphone_gtk_get_core()));
581 static void linphone_gtk_call_started(GtkWidget *mw){
582 gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"start_call"),FALSE);
583 gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),TRUE);
584 update_video_title();
585 if (linphone_gtk_use_in_call_view())
586 g_timeout_add(250,(GSourceFunc)in_call_timer,NULL);
589 static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){
590 const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar));
591 if (linphone_core_invite(linphone_gtk_get_core(),entered)!=NULL) {
592 completion_add_text(GTK_ENTRY(uri_bar),entered);
594 linphone_gtk_call_terminated(NULL);
599 static void _linphone_gtk_accept_call(){
600 LinphoneCore *lc=linphone_gtk_get_core();
601 GtkWidget *mw=linphone_gtk_get_main_window();
602 GtkWidget *icw=GTK_WIDGET(g_object_get_data(G_OBJECT(mw),"incoming_call"));
604 g_object_set_data(G_OBJECT(mw),"incoming_call",NULL);
605 gtk_widget_destroy(icw);
608 linphone_core_accept_call(lc,NULL);
609 linphone_gtk_call_started(linphone_gtk_get_main_window());
610 if (linphone_gtk_use_in_call_view()){
611 linphone_gtk_in_call_view_set_in_call();
612 linphone_gtk_show_in_call_view();
614 linphone_gtk_enable_mute_button(
615 GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"main_mute"))
619 void linphone_gtk_start_call(GtkWidget *w){
620 LinphoneCore *lc=linphone_gtk_get_core();
621 if (linphone_core_inc_invite_pending(lc)){
623 _linphone_gtk_accept_call();
624 }else if (linphone_core_in_call(lc)) {
627 /*change into in-call mode, then do the work later as it might block a bit */
628 GtkWidget *mw=gtk_widget_get_toplevel(w);
629 GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar");
630 const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar));
631 linphone_gtk_call_started(mw);
632 if (linphone_gtk_use_in_call_view()){
633 linphone_gtk_in_call_view_set_calling(entered);
634 linphone_gtk_show_in_call_view();
636 g_timeout_add(100,(GSourceFunc)linphone_gtk_start_call_do,uri_bar);
640 void linphone_gtk_uri_bar_activate(GtkWidget *w){
641 linphone_gtk_start_call(w);
645 void linphone_gtk_terminate_call(GtkWidget *button){
646 linphone_core_terminate_call(linphone_gtk_get_core(),NULL);
649 void linphone_gtk_decline_call(GtkWidget *button){
650 linphone_core_terminate_call(linphone_gtk_get_core(),NULL);
651 gtk_widget_destroy(gtk_widget_get_toplevel(button));
654 void linphone_gtk_accept_call(GtkWidget *button){
655 _linphone_gtk_accept_call();
658 static gboolean linphone_gtk_auto_answer(GtkWidget *incall_window){
659 linphone_gtk_accept_call(linphone_gtk_get_widget(incall_window,"accept_call"));
663 void linphone_gtk_set_audio_video(){
664 linphone_core_enable_video(linphone_gtk_get_core(),TRUE,TRUE);
665 linphone_core_enable_video_preview(linphone_gtk_get_core(),
666 linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT));
669 void linphone_gtk_set_audio_only(){
670 linphone_core_enable_video(linphone_gtk_get_core(),FALSE,FALSE);
671 linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
674 void linphone_gtk_enable_self_view(GtkWidget *w){
675 gboolean val=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
676 LinphoneCore *lc=linphone_gtk_get_core();
677 linphone_core_enable_video_preview(lc,val);
678 linphone_core_enable_self_view(lc,val);
679 linphone_gtk_set_ui_config_int("videoselfview",val);
682 void linphone_gtk_used_identity_changed(GtkWidget *w){
683 int active=gtk_combo_box_get_active(GTK_COMBO_BOX(w));
684 char *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w));
685 if (sel && strlen(sel)>0){ //avoid a dummy "changed" at gui startup
686 linphone_core_set_default_proxy_index(linphone_gtk_get_core(),(active==0) ? -1 : (active-1));
687 linphone_gtk_show_directory_search();
689 if (sel) g_free(sel);
692 static void linphone_gtk_show_main_window(){
693 GtkWidget *w=linphone_gtk_get_main_window();
694 LinphoneCore *lc=linphone_gtk_get_core();
695 if (linphone_core_video_enabled(lc)){
696 linphone_core_enable_video_preview(lc,linphone_gtk_get_ui_config_int("videoselfview",
697 VIDEOSELFVIEW_DEFAULT));
700 gtk_window_present(GTK_WINDOW(w));
703 static void linphone_gtk_show(LinphoneCore *lc){
704 linphone_gtk_show_main_window();
707 static void linphone_gtk_inv_recv(LinphoneCore *lc, LinphoneCall *call){
708 GtkWidget *w=linphone_gtk_create_window("incoming_call");
711 char *from=linphone_call_get_remote_address_as_string(call);
714 g_timeout_add(2000,(GSourceFunc)linphone_gtk_auto_answer,w);
717 gtk_window_set_transient_for(GTK_WINDOW(w),GTK_WINDOW(linphone_gtk_get_main_window()));
718 gtk_window_set_position(GTK_WINDOW(w),GTK_WIN_POS_CENTER_ON_PARENT);
720 label=linphone_gtk_get_widget(w,"message");
721 msg=g_strdup_printf(_("Incoming call from %s"),from);
722 gtk_label_set_text(GTK_LABEL(label),msg);
723 gtk_window_set_title(GTK_WINDOW(w),msg);
725 gtk_window_present(GTK_WINDOW(w));
726 /*gtk_window_set_urgency_hint(GTK_WINDOW(w),TRUE);*/
728 g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"incoming_call",w);
729 gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),
734 static void linphone_gtk_bye_recv(LinphoneCore *lc, LinphoneCall *call){
738 static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid){
739 linphone_gtk_show_friends();
742 static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint response_id, LinphoneFriend *lf){
744 case GTK_RESPONSE_YES:
745 linphone_gtk_show_contact(lf);
748 linphone_core_reject_subscriber(linphone_gtk_get_core(),lf);
750 gtk_widget_destroy(dialog);
753 static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
756 if (linphone_gtk_get_ui_config_int("subscribe_deny_all",0)){
757 linphone_core_reject_subscriber(linphone_gtk_get_core(),lf);
761 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);
762 dialog = gtk_message_dialog_new (
763 GTK_WINDOW(linphone_gtk_get_main_window()),
764 GTK_DIALOG_DESTROY_WITH_PARENT,
765 GTK_MESSAGE_QUESTION,
770 g_signal_connect(G_OBJECT (dialog), "response",
771 G_CALLBACK (linphone_gtk_new_subscriber_response),lf);
772 /* actually show the box */
773 gtk_widget_show(dialog);
776 typedef struct _AuthTimeout{
781 static void auth_timeout_clean(AuthTimeout *tout){
785 static gboolean auth_timeout_destroy(AuthTimeout *tout){
787 g_object_weak_unref(G_OBJECT(tout->w),(GWeakNotify)auth_timeout_clean,tout);
788 gtk_widget_destroy(tout->w);
794 static AuthTimeout * auth_timeout_new(GtkWidget *w){
795 AuthTimeout *tout=g_new(AuthTimeout,1);
797 /*so that the timeout no more references the widget when it is destroyed:*/
798 g_object_weak_ref(G_OBJECT(w),(GWeakNotify)auth_timeout_clean,tout);
799 /*so that the widget is automatically destroyed after some time */
800 g_timeout_add(30000,(GtkFunction)auth_timeout_destroy,tout);
804 void linphone_gtk_password_cancel(GtkWidget *w){
805 LinphoneAuthInfo *info;
806 GtkWidget *window=gtk_widget_get_toplevel(w);
807 info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info");
808 linphone_core_abort_authentication(linphone_gtk_get_core(),info);
809 gtk_widget_destroy(window);
812 void linphone_gtk_password_ok(GtkWidget *w){
814 GtkWidget *window=gtk_widget_get_toplevel(w);
815 LinphoneAuthInfo *info;
816 info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info");
817 g_object_weak_unref(G_OBJECT(window),(GWeakNotify)linphone_auth_info_destroy,info);
818 entry=linphone_gtk_get_widget(window,"password_entry");
819 linphone_auth_info_set_passwd(info,gtk_entry_get_text(GTK_ENTRY(entry)));
820 linphone_auth_info_set_userid(info,
821 gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(window,"userid_entry"))));
822 linphone_core_add_auth_info(linphone_gtk_get_core(),info);
823 gtk_widget_destroy(window);
826 static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username){
827 GtkWidget *w=linphone_gtk_create_window("password");
828 GtkWidget *label=linphone_gtk_get_widget(w,"message");
829 LinphoneAuthInfo *info;
831 GtkWidget *mw=linphone_gtk_get_main_window();
833 if (mw && GTK_WIDGET_VISIBLE(linphone_gtk_get_widget(mw,"login_frame"))){
834 /*don't prompt for authentication when login frame is visible*/
835 linphone_core_abort_authentication(lc,NULL);
839 msg=g_strdup_printf(_("Please enter your password for username <i>%s</i>\n at domain <i>%s</i>:"),
841 gtk_label_set_markup(GTK_LABEL(label),msg);
843 gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"userid_entry")),username);
844 info=linphone_auth_info_new(username, NULL, NULL, NULL,realm);
845 g_object_set_data(G_OBJECT(w),"auth_info",info);
846 g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_auth_info_destroy,info);
851 static void linphone_gtk_display_status(LinphoneCore *lc, const char *status){
852 GtkWidget *w=linphone_gtk_get_main_window();
853 GtkWidget *status_bar=linphone_gtk_get_widget(w,"status_bar");
854 gtk_statusbar_push(GTK_STATUSBAR(status_bar),
855 gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar),""),
859 static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg){
860 linphone_gtk_display_something(GTK_MESSAGE_INFO,msg);
863 static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning){
864 linphone_gtk_display_something(GTK_MESSAGE_WARNING,warning);
867 static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url){
869 snprintf(richtext,sizeof(richtext),"%s %s",msg,url);
870 linphone_gtk_display_something(GTK_MESSAGE_INFO,richtext);
873 static void linphone_gtk_display_question(LinphoneCore *lc, const char *question){
874 linphone_gtk_display_something(GTK_MESSAGE_QUESTION,question);
877 static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl){
878 GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"call_logs");
879 if (w) linphone_gtk_call_log_update(w);
882 static void linphone_gtk_general_state(LinphoneCore *lc, LinphoneGeneralState *gstate){
883 switch(gstate->new_state){
884 case GSTATE_CALL_OUT_CONNECTED:
885 case GSTATE_CALL_IN_CONNECTED:
886 if (linphone_gtk_use_in_call_view())
887 linphone_gtk_in_call_view_set_in_call();
888 linphone_gtk_enable_mute_button(
889 GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"main_mute")),
892 case GSTATE_CALL_ERROR:
893 linphone_gtk_call_terminated(gstate->message);
895 case GSTATE_CALL_END:
896 linphone_gtk_call_terminated(NULL);
903 static void icon_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data){
904 GtkWidget *menu=(GtkWidget*)g_object_get_data(G_OBJECT(status_icon),"menu");
905 gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time);
908 void linphone_gtk_open_browser(const char *url){
909 /*in gtk 2.16, gtk_show_uri does not work...*/
911 #if GTK_CHECK_VERSION(2,18,3)
912 gtk_show_uri(NULL,url,GDK_CURRENT_TIME,NULL);
915 snprintf(cl,sizeof(cl),"/usr/bin/x-www-browser %s",url);
916 g_spawn_command_line_async(cl,NULL);
919 ShellExecute(0,"open",url,NULL,NULL,1);
923 void linphone_gtk_link_to_website(GtkWidget *item){
924 const gchar *home=(const gchar*)g_object_get_data(G_OBJECT(item),"home");
925 linphone_gtk_open_browser(home);
928 static GtkWidget *create_icon_menu(){
929 GtkWidget *menu=gtk_menu_new();
930 GtkWidget *menu_item;
933 const gchar *homesite;
935 homesite=linphone_gtk_get_ui_config("home","http://www.linphone.org");
936 menu_item=gtk_image_menu_item_new_with_label(_("Website link"));
937 tmp=g_strdup(homesite);
938 g_object_set_data(G_OBJECT(menu_item),"home",tmp);
939 g_object_weak_ref(G_OBJECT(menu_item),(GWeakNotify)g_free,tmp);
941 image=gtk_image_new_from_stock(GTK_STOCK_HELP,GTK_ICON_SIZE_MENU);
942 gtk_widget_show(image);
943 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
944 //g_object_unref(G_OBJECT(image));
945 gtk_widget_show(menu_item);
946 gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
947 g_signal_connect(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_link_to_website,NULL);
949 menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT,NULL);
950 gtk_widget_show(menu_item);
951 gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
952 g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_show_about,NULL);
953 menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,NULL);
954 gtk_widget_show(menu_item);
955 gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
956 g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)gtk_main_quit,NULL);
957 gtk_widget_show(menu);
961 static GtkStatusIcon *icon=NULL;
963 static void linphone_gtk_init_status_icon(){
964 const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
965 GdkPixbuf *pbuf=create_pixbuf(icon_path);
966 GtkWidget *menu=create_icon_menu();
968 icon=gtk_status_icon_new_from_pixbuf(pbuf);
969 g_object_unref(G_OBJECT(pbuf));
970 g_signal_connect_swapped(G_OBJECT(icon),"activate",(GCallback)linphone_gtk_show_main_window,linphone_gtk_get_main_window());
971 g_signal_connect(G_OBJECT(icon),"popup-menu",(GCallback)icon_popup_menu,NULL);
972 title=linphone_gtk_get_ui_config("title",_("Linphone - a video internet phone"));
973 gtk_status_icon_set_tooltip(icon,title);
974 gtk_status_icon_set_visible(icon,TRUE);
975 g_object_set_data(G_OBJECT(icon),"menu",menu);
976 g_object_weak_ref(G_OBJECT(icon),(GWeakNotify)gtk_widget_destroy,menu);
979 void linphone_gtk_load_identities(void){
981 GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities"));
983 LinphoneProxyConfig *def=NULL;
987 store=GTK_LIST_STORE(gtk_combo_box_get_model(box));
988 gtk_list_store_clear(store);
990 linphone_core_get_default_proxy(linphone_gtk_get_core(),&def);
991 def_identity=g_strdup_printf(_("%s (Default)"),linphone_core_get_primary_contact(linphone_gtk_get_core()));
992 gtk_combo_box_append_text(box,def_identity);
993 g_free(def_identity);
994 for(i=1,elem=linphone_core_get_proxy_config_list(linphone_gtk_get_core());
996 elem=ms_list_next(elem),i++){
997 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
998 gtk_combo_box_append_text(box,linphone_proxy_config_get_identity(cfg));
1003 gtk_combo_box_set_active(box,def_index);
1006 static void linphone_gtk_dtmf_clicked(GtkButton *button){
1007 const char *label=gtk_button_get_label(button);
1008 if (linphone_core_in_call(linphone_gtk_get_core())){
1009 linphone_core_send_dtmf(linphone_gtk_get_core(),label[0]);
1011 GtkWidget *uri_bar=linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(button)),"uribar");
1013 gtk_editable_insert_text(GTK_EDITABLE(uri_bar),label,1,&pos);
1017 static void linphone_gtk_connect_digits(void){
1018 GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"dtmf_table"));
1019 GList *children=gtk_container_get_children(cont);
1021 for(elem=children;elem!=NULL;elem=elem->next){
1022 GtkButton *button=GTK_BUTTON(elem->data);
1023 g_signal_connect(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_dtmf_clicked,NULL);
1027 static void linphone_gtk_check_menu_items(void){
1028 bool_t audio_only=!linphone_core_video_enabled(linphone_gtk_get_core());
1029 bool_t selfview=linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT);
1030 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(linphone_gtk_get_widget(
1031 linphone_gtk_get_main_window(),
1032 audio_only ? "audio_only_item" : "video_item")), TRUE);
1033 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(linphone_gtk_get_widget(
1034 linphone_gtk_get_main_window(),"selfview_item")),selfview);
1037 static gboolean linphone_gtk_can_manage_accounts(){
1038 LinphoneCore *lc=linphone_gtk_get_core();
1040 for(elem=linphone_core_get_sip_setups(lc);elem!=NULL;elem=elem->next){
1041 SipSetup *ss=(SipSetup*)elem->data;
1042 if (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_ACCOUNT_MANAGER){
1049 static void linphone_gtk_configure_main_window(){
1050 static gboolean config_loaded=FALSE;
1051 static const char *title;
1052 static const char *home;
1053 static const char *start_call_icon;
1054 static const char *stop_call_icon;
1055 static const char *search_icon;
1056 static gboolean update_check_menu;
1057 static gboolean buttons_have_borders;
1058 GtkWidget *w=linphone_gtk_get_main_window();
1059 if (!config_loaded){
1060 title=linphone_gtk_get_ui_config("title","Linphone");
1061 home=linphone_gtk_get_ui_config("home","http://www.linphone.org");
1062 start_call_icon=linphone_gtk_get_ui_config("start_call_icon","startcall-green.png");
1063 stop_call_icon=linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png");
1064 search_icon=linphone_gtk_get_ui_config("directory_search_icon",NULL);
1065 update_check_menu=linphone_gtk_get_ui_config_int("update_check_menu",0);
1066 buttons_have_borders=linphone_gtk_get_ui_config_int("buttons_border",1);
1069 linphone_gtk_configure_window(w,"main_window");
1071 gtk_window_set_title(GTK_WINDOW(w),title);
1072 #if GTK_CHECK_VERSION(2,16,0)
1073 gtk_menu_item_set_label(GTK_MENU_ITEM(linphone_gtk_get_widget(w,"main_menu")),title);
1076 if (start_call_icon){
1077 GdkPixbuf *pbuf=create_pixbuf(start_call_icon);
1078 gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"start_call_icon")),pbuf);
1079 if (buttons_have_borders)
1080 gtk_button_set_relief(GTK_BUTTON(linphone_gtk_get_widget(w,"start_call")),GTK_RELIEF_NORMAL);
1081 g_object_unref(G_OBJECT(pbuf));
1083 if (stop_call_icon){
1084 GdkPixbuf *pbuf=create_pixbuf(stop_call_icon);
1085 gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"terminate_call_icon")),pbuf);
1086 if (buttons_have_borders)
1087 gtk_button_set_relief(GTK_BUTTON(linphone_gtk_get_widget(w,"terminate_call")),GTK_RELIEF_NORMAL);
1088 g_object_unref(G_OBJECT(pbuf));
1091 GdkPixbuf *pbuf=create_pixbuf(search_icon);
1092 gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"directory_search_button_icon")),pbuf);
1093 g_object_unref(G_OBJECT(pbuf));
1097 GtkWidget *menu_item=linphone_gtk_get_widget(w,"home_item");
1099 g_object_set_data(G_OBJECT(menu_item),"home",tmp);
1102 GdkPixbuf *pbuf=create_pixbuf("contact-orange.png");
1104 gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"contact_tab_icon")),pbuf);
1105 g_object_unref(G_OBJECT(pbuf));
1109 GdkPixbuf *pbuf=create_pixbuf("dialer-orange.png");
1111 gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"keypad_tab_icon")),pbuf);
1112 g_object_unref(G_OBJECT(pbuf));
1115 if (!linphone_gtk_can_manage_accounts())
1116 gtk_widget_hide(linphone_gtk_get_widget(w,"run_assistant"));
1117 if (update_check_menu){
1118 gtk_widget_show(linphone_gtk_get_widget(w,"versioncheck"));
1122 void linphone_gtk_manage_login(void){
1123 LinphoneCore *lc=linphone_gtk_get_core();
1124 LinphoneProxyConfig *cfg=NULL;
1125 linphone_core_get_default_proxy(lc,&cfg);
1127 SipSetup *ss=linphone_proxy_config_get_sip_setup(cfg);
1128 if (ss && (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_LOGIN)){
1129 linphone_gtk_show_login_frame(cfg);
1134 static void linphone_gtk_init_main_window(){
1135 GtkWidget *main_window;
1137 linphone_gtk_configure_main_window();
1138 linphone_gtk_manage_login();
1140 linphone_gtk_load_identities();
1141 linphone_gtk_set_my_presence(linphone_core_get_presence_info(linphone_gtk_get_core()));
1142 linphone_gtk_show_friends();
1143 linphone_gtk_connect_digits();
1144 linphone_gtk_check_menu_items();
1145 main_window=linphone_gtk_get_main_window();
1146 linphone_gtk_enable_mute_button(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,
1147 "main_mute")),FALSE);
1148 linphone_gtk_enable_mute_button(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,
1149 "incall_mute")),FALSE);
1150 linphone_gtk_enable_hold_button(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,
1151 "hold_call")),FALSE);
1152 if (!linphone_gtk_use_in_call_view()) {
1153 gtk_widget_show(linphone_gtk_get_widget(main_window, "main_mute"));
1155 if (linphone_core_in_call(linphone_gtk_get_core())) linphone_gtk_call_started(
1156 linphone_gtk_get_main_window());/*hide the call button, show terminate button*/
1159 void linphone_gtk_close(){
1160 /* couldn't find a way to prevent closing to destroy the main window*/
1161 LinphoneCore *lc=linphone_gtk_get_core();
1163 the_ui=linphone_gtk_create_window("main");
1164 linphone_gtk_init_main_window();
1165 /*shutdown call if any*/
1166 if (linphone_core_in_call(lc)){
1167 linphone_core_terminate_call(lc,NULL);
1168 linphone_gtk_call_terminated(NULL);
1170 linphone_core_enable_video_preview(lc,FALSE);
1173 void linphone_gtk_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
1175 const char *lname="undef";
1178 va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/
1197 g_error("Bad level !");
1201 msg=g_strdup_vprintf(fmt,cap);
1204 msg=g_strdup_vprintf(fmt,args);
1206 fprintf(stdout,"linphone-%s : %s\n",lname,msg);
1209 linphone_gtk_log_push(lev,fmt,args);
1213 static void linphone_gtk_refer_received(LinphoneCore *lc, LinphoneCall *call, const char *refer_to){
1214 GtkEntry * uri_bar =GTK_ENTRY(linphone_gtk_get_widget(
1215 linphone_gtk_get_main_window(), "uribar"));
1216 linphone_gtk_show_main_window();
1217 gtk_entry_set_text(uri_bar, refer_to);
1218 linphone_gtk_start_call(linphone_gtk_get_main_window());
1221 static void linphone_gtk_check_soundcards(){
1222 const char **devices=linphone_core_get_sound_devices(linphone_gtk_get_core());
1223 if (devices==NULL || devices[0]==NULL){
1224 linphone_gtk_display_something(GTK_MESSAGE_WARNING,
1225 _("No sound cards have been detected on this computer.\n"
1226 "You won't be able to send or receive audio calls."));
1230 int main(int argc, char *argv[]){
1234 const char *config_file;
1235 const char *factory_config_file;
1237 GtkSettings *settings;
1240 g_thread_init(NULL);
1243 progpath = strdup(argv[0]);
1245 config_file=linphone_gtk_get_config_file();
1248 /*workaround for windows: sometimes LANG is defined to an integer value, not understood by gtk */
1249 if ((lang=getenv("LANG"))!=NULL){
1252 snprintf(tmp,sizeof(tmp),"LANG=",lang);
1258 g_setenv("PULSE_PROP_media.role", "phone", TRUE);
1261 if ((lang=linphone_gtk_get_lang(config_file))!=NULL && lang[0]!='\0'){
1264 snprintf(tmp,sizeof(tmp),"LANG=%s",lang);
1267 setenv("LANG",lang,1);
1272 p=bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
1273 if (p==NULL) perror("bindtextdomain failed");
1274 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1275 textdomain (GETTEXT_PACKAGE);
1277 g_message("NLS disabled.\n");
1280 gtk_rc_add_default_file("./gtkrc");
1282 gdk_threads_enter();
1284 if (!gtk_init_with_args(&argc,&argv,_("A free SIP video-phone"),
1285 linphone_options,NULL,NULL)){
1286 gdk_threads_leave();
1290 settings=gtk_settings_get_default();
1291 g_object_set(settings, "gtk-menu-images", TRUE, NULL);
1292 g_object_set(settings, "gtk-button-images", TRUE, NULL);
1294 if (workingdir!=NULL)
1297 /* Now, look for the factory configuration file, we do it this late
1298 since we want to have had time to change directory and to parse
1299 the options, in case we needed to access the working directory */
1300 factory_config_file = linphone_gtk_get_factory_config_file();
1302 if (linphone_core_wake_up_possible_already_running_instance(
1303 config_file, addr_to_call) == 0){
1304 g_message("addr_to_call=%s",addr_to_call);
1305 g_warning("Another running instance of linphone has been detected. It has been woken-up.");
1306 g_warning("This instance is going to exit now.");
1307 gdk_threads_leave();
1311 add_pixmap_directory("pixmaps");
1312 add_pixmap_directory(PACKAGE_DATA_DIR "/pixmaps/linphone");
1315 g_set_application_name("Linphone");
1316 pbuf=create_pixbuf(linphone_gtk_get_ui_config("icon",LINPHONE_ICON));
1317 if (pbuf!=NULL) gtk_window_set_default_icon(pbuf);
1319 the_ui=linphone_gtk_create_window("main");
1321 linphone_gtk_create_log_window();
1322 linphone_core_enable_logs_with_cb(linphone_gtk_log_handler);
1324 linphone_gtk_init_liblinphone(config_file, factory_config_file);
1325 /* do not lower timeouts under 30 ms because it exhibits a bug on gtk+/win32, with cpu running 20% all the time...*/
1326 gtk_timeout_add(30,(GtkFunction)linphone_gtk_iterate,(gpointer)linphone_gtk_get_core());
1327 gtk_timeout_add(30,(GtkFunction)linphone_gtk_check_logs,(gpointer)NULL);
1328 linphone_gtk_init_main_window();
1329 linphone_gtk_init_status_icon();
1331 linphone_gtk_show_main_window();
1332 linphone_gtk_check_soundcards();
1334 if (linphone_gtk_get_ui_config_int("update_check_menu",0)==0)
1335 linphone_gtk_check_for_new_version();
1338 gdk_threads_leave();
1339 linphone_gtk_destroy_log_window();
1340 linphone_core_destroy(the_core);
1341 /*workaround a bug on win32 that makes status icon still present in the systray even after program exit.*/
1342 gtk_status_icon_set_visible(icon,FALSE);