source: mediastreamer2/linphone/gtk-glade/main.c @ 660:d015df1b9638

Last change on this file since 660:d015df1b9638 was 660:d015df1b9638, checked in by smorlat <smorlat@…>, 4 years ago

update it transation.
fix mute mode
repair --call when in login mode.

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@648 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 36.8 KB
Line 
1/*
2linphone, gtk-glade interface.
3Copyright (C) 2008  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#define USE_LIBGLADE 1
21
22#include "linphone.h"
23#include "lpconfig.h"
24
25
26
27#ifdef USE_LIBGLADE
28#include <glade/glade.h>
29#endif
30
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <unistd.h>
34
35#define LINPHONE_ICON "linphone2.png"
36
37const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION;
38
39static LinphoneCore *the_core=NULL;
40static GtkWidget *the_ui=NULL;
41
42static void linphone_gtk_show(LinphoneCore *lc);
43static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from);
44static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from);
45static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img);
46static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
47static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username);
48static void linphone_gtk_display_status(LinphoneCore *lc, const char *status);
49static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg);
50static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning);
51static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url);
52static void linphone_gtk_display_question(LinphoneCore *lc, const char *question);
53static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl);
54static void linphone_gtk_general_state(LinphoneCore *lc, LinphoneGeneralState *gstate);
55static void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to);
56static gboolean linphone_gtk_auto_answer(GtkWidget *incall_window);
57
58static LinphoneCoreVTable vtable={
59        .show=linphone_gtk_show,
60        .inv_recv=linphone_gtk_inv_recv,
61        .bye_recv=linphone_gtk_bye_recv,
62        .notify_recv=linphone_gtk_notify_recv,
63        .new_unknown_subscriber=linphone_gtk_new_unknown_subscriber,
64        .auth_info_requested=linphone_gtk_auth_info_requested,
65        .display_status=linphone_gtk_display_status,
66        .display_message=linphone_gtk_display_message,
67        .display_warning=linphone_gtk_display_warning,
68        .display_url=linphone_gtk_display_url,
69        .display_question=linphone_gtk_display_question,
70        .call_log_updated=linphone_gtk_call_log_updated,
71        .text_received=linphone_gtk_text_received,
72        .general_state=linphone_gtk_general_state,
73        .refer_received=linphone_gtk_refer_received
74};
75
76static gboolean verbose=0;
77static gboolean auto_answer = 0;
78static gchar * addr_to_call = NULL;
79static GOptionEntry linphone_options[]={
80        {
81                .long_name="verbose",
82                .short_name= '\0',
83                .arg=G_OPTION_ARG_NONE,
84                .arg_data= (gpointer)&verbose,
85                .description=N_("log to stdout some debug information while running.")
86        },
87        {                               /* zsd addition */
88            .long_name = "call",
89            .short_name = 'c',
90            .arg = G_OPTION_ARG_STRING,
91            .arg_data = &addr_to_call,
92            .description = N_("address to call right now")
93        },
94        {                               /* zsd addition */
95            .long_name = "auto-answer",
96            .short_name = 'a',
97            .arg = G_OPTION_ARG_NONE,
98            .arg_data = (gpointer) & auto_answer,
99            .description = N_("if set automatically answer incoming calls")
100        },
101        {0}
102};
103
104#define INSTALLED_XML_DIR PACKAGE_DATA_DIR "/linphone"
105#define BUILD_TREE_XML_DIR "gtk-glade"
106
107#ifndef WIN32
108#define CONFIG_FILE ".linphonerc"
109#else
110#define CONFIG_FILE "linphonerc"
111#endif
112
113
114
115static char _config_file[1024];
116
117const char *linphone_gtk_get_config_file(){
118        /*try accessing a local file first if exists*/
119        if (access(CONFIG_FILE,F_OK)==0){
120                snprintf(_config_file,sizeof(_config_file),"%s",CONFIG_FILE);
121        }else{
122#ifdef WIN32
123                const char *appdata=getenv("APPDATA");
124                if (appdata){
125                        snprintf(_config_file,sizeof(_config_file),"%s\\%s",appdata,LINPHONE_CONFIG_DIR);
126                        CreateDirectory(_config_file,NULL);
127                        snprintf(_config_file,sizeof(_config_file),"%s\\%s",appdata,LINPHONE_CONFIG_DIR "\\" CONFIG_FILE);
128                }
129#else
130                const char *home=getenv("HOME");
131                if (home==NULL) home=".";
132                snprintf(_config_file,sizeof(_config_file),"%s/%s",home,CONFIG_FILE);
133#endif
134        }
135        return _config_file;
136}
137
138static void linphone_gtk_init_liblinphone(const char *file){
139        linphone_core_set_user_agent("Linphone", LINPHONE_VERSION);
140        the_core=linphone_core_new(&vtable,file,NULL);
141        linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
142}
143
144
145
146LinphoneCore *linphone_gtk_get_core(void){
147        return the_core;
148}
149
150GtkWidget *linphone_gtk_get_main_window(){
151        return the_ui;
152}
153
154static void parse_item(const char *item, const char *window_name, GtkWidget *w){
155        char tmp[64];
156        char *dot;
157        strcpy(tmp,item);
158        dot=strchr(tmp,'.');
159        if (dot){
160                *dot='\0';
161                dot++;
162                if (strcmp(window_name,tmp)==0){
163                        GtkWidget *wd=linphone_gtk_get_widget(w,dot);
164                        if (wd) gtk_widget_hide(wd);
165                }
166        }
167}
168
169static void parse_hiddens(const char *hiddens, const char *window_name, GtkWidget *w){
170        char item[64];
171        const char *i;
172        const char *b;
173        int len;
174        for(b=i=hiddens;*i!='\0';++i){
175                if (*i==' '){
176                        len=MIN(i-b,sizeof(item)-1);
177                        strncpy(item,b,len);
178                        item[len]='\0';
179                        b=i+1;
180                        parse_item(item,window_name,w);
181                }
182        }
183        len=MIN(i-b,sizeof(item)-1);
184        if (len>0){
185                strncpy(item,b,len);
186                item[len]='\0';
187                parse_item(item,window_name,w);
188        }
189}
190
191static void linphone_gtk_configure_window(GtkWidget *w, const char *window_name){
192        static const char *icon_path=0;
193        static const char *hiddens=0;
194        static bool_t config_loaded=FALSE;
195        if (linphone_gtk_get_core()==NULL) return;
196        if (config_loaded==FALSE){
197                hiddens=linphone_gtk_get_ui_config("hidden_widgets",NULL);
198                icon_path=linphone_gtk_get_ui_config("icon",NULL);
199                config_loaded=TRUE;
200        }
201        if (hiddens){
202                parse_hiddens(hiddens,window_name,w);
203        }
204        if (icon_path) {
205                GdkPixbuf *pbuf=create_pixbuf(icon_path);
206                gtk_window_set_icon(GTK_WINDOW(w),pbuf);
207                g_object_unref(G_OBJECT(pbuf));
208        }
209}
210
211#ifdef USE_LIBGLADE
212
213GtkWidget *linphone_gtk_create_window(const char *window_name){
214        GtkWidget *w;
215        GladeXML *gxml;
216        char path[2048];
217        snprintf(path,sizeof(path),"%s/%s.glade",BUILD_TREE_XML_DIR,window_name);
218        if (access(path,F_OK)!=0){
219                snprintf(path,sizeof(path),"%s/%s.glade",INSTALLED_XML_DIR,window_name);
220                if (access(path,F_OK)!=0){
221                        g_error("Could not locate neither %s/%s.glade and %s/%s.glade .",BUILD_TREE_XML_DIR,window_name,
222                                INSTALLED_XML_DIR,window_name);
223                        return NULL;
224                }
225        }
226        gxml=glade_xml_new(path,NULL,NULL);
227        glade_xml_signal_autoconnect(gxml);
228        w=glade_xml_get_widget(gxml,window_name);
229        if (w==NULL) g_error("Could not retrieve '%s' window from xml file",window_name);
230        linphone_gtk_configure_window(w,window_name);
231        return w;
232}
233
234GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
235        GtkWidget *w;
236        GladeXML *gxml=glade_get_widget_tree(window);
237        if (gxml==NULL) g_error("Could not retrieve XML tree of window %s",name);
238        w=glade_xml_get_widget(gxml,name);
239        if (w==NULL) g_error("Could not retrieve widget %s",name);
240        return GTK_WIDGET(w);
241}
242
243#else
244
245GtkWidget *linphone_gtk_create_window(const char *window_name){
246       
247}
248
249GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
250        GObject *w=gtk_builder_get_object(the_ui,name);
251        if (w==NULL){
252                g_error("No widget named %s found in xml interface.",name);
253        }
254        return GTK_WIDGET(w);
255}
256
257#endif
258
259void linphone_gtk_display_something(GtkMessageType type,const gchar *message){
260        GtkWidget *dialog;
261        GtkWidget *main_window=linphone_gtk_get_main_window();
262       
263        gtk_widget_show(main_window);
264        if (type==GTK_MESSAGE_QUESTION)
265        {
266                /* draw a question box. link to dialog_click callback */
267                dialog = gtk_message_dialog_new (
268                                GTK_WINDOW(main_window),
269                                GTK_DIALOG_DESTROY_WITH_PARENT,
270                                GTK_MESSAGE_QUESTION,
271                                GTK_BUTTONS_YES_NO,
272                                "%s",
273                                (const gchar*)message);
274                /* connect to some callback : REVISIT */
275                /*
276                g_signal_connect_swapped (G_OBJECT (dialog), "response",
277                           G_CALLBACK (dialog_click),
278                           G_OBJECT (dialog));
279                */
280                /* actually show the box */
281                gtk_widget_show(dialog);
282        }
283        else
284        {
285                dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
286                                  GTK_DIALOG_DESTROY_WITH_PARENT,
287                                  type,
288                                  GTK_BUTTONS_CLOSE,
289                                  "%s",
290                                  (const gchar*)message);
291                /* Destroy the dialog when the user responds to it (e.g. clicks a button) */
292                g_signal_connect_swapped (G_OBJECT (dialog), "response",
293                           G_CALLBACK (gtk_widget_destroy),
294                           G_OBJECT (dialog));
295                gtk_widget_show(dialog);
296        }
297}
298
299void linphone_gtk_about_response(GtkDialog *dialog, gint id){
300        if (id==GTK_RESPONSE_CANCEL){
301                gtk_widget_destroy(GTK_WIDGET(dialog));
302        }
303}
304
305static void about_url_clicked(GtkAboutDialog *dialog, const char *url, gpointer data){
306        g_message("About url clicked");
307        linphone_gtk_open_browser(url);
308}
309
310void linphone_gtk_show_about(){
311        struct stat filestat;
312        const char *license_file=PACKAGE_DATA_DIR "/linphone/COPYING";
313        GtkWidget *about;
314       
315        about=linphone_gtk_create_window("about");
316        gtk_about_dialog_set_url_hook(about_url_clicked,NULL,NULL);
317        memset(&filestat,0,sizeof(filestat));
318        if (stat(license_file,&filestat)!=0){
319                license_file="COPYING";
320                stat(license_file,&filestat);
321        }
322        if (filestat.st_size>0){
323                char *license=g_malloc(filestat.st_size+1);
324                FILE *f=fopen(license_file,"r");
325                if (f && fread(license,filestat.st_size,1,f)==1){
326                        license[filestat.st_size]='\0';
327                        gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about),license);
328                }
329                g_free(license);
330        }
331        gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about),LINPHONE_VERSION);
332        gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about),linphone_gtk_get_ui_config("title","Linphone"));
333        gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about),linphone_gtk_get_ui_config("home","http://www.linphone.org"));
334        gtk_widget_show(about);
335}
336
337static void set_video_window_decorations(GdkWindow *w){
338        const char *title=linphone_gtk_get_ui_config("title","Linphone");
339        const char *icon_path=linphone_gtk_get_ui_config("icon","linphone2.png");
340        char video_title[256];
341        GdkPixbuf *pbuf=create_pixbuf(icon_path);
342        if (!linphone_core_in_call(linphone_gtk_get_core())){
343                snprintf(video_title,sizeof(video_title),"%s video",title);     
344        }else{
345                const char *uri=linphone_core_get_remote_uri(linphone_gtk_get_core());
346                gchar *display_name=linphone_gtk_get_display_name(uri);
347                snprintf(video_title,sizeof(video_title),"Call with %s",display_name);
348                g_free(display_name);
349        }
350        gdk_window_set_title(w,video_title);
351        /*gdk_window_set_urgency_hint(w,TRUE);*/
352        gdk_window_raise(w);
353        if (pbuf){
354                GList *l=NULL;
355                l=g_list_append(l,pbuf);
356                gdk_window_set_icon_list(w,l);
357                g_list_free(l);
358                g_object_unref(G_OBJECT(pbuf));
359        }
360}
361
362static gboolean video_needs_update=FALSE;
363
364static void update_video_title(){
365        video_needs_update=TRUE;
366}
367
368static gboolean linphone_gtk_iterate(LinphoneCore *lc){
369        static gboolean first_time=TRUE;
370        unsigned long id;
371        static unsigned long previd=0;
372        static gboolean in_iterate=FALSE;
373       
374        /*avoid reentrancy*/
375        if (in_iterate) return TRUE;
376        in_iterate=TRUE;
377        linphone_core_iterate(lc);
378        if (first_time){
379                /*after the first call to iterate, SipSetupContexts should be ready, so take actions:*/
380                linphone_gtk_show_directory_search();
381                first_time=FALSE;
382        }
383
384        id=linphone_core_get_native_video_window_id(lc);
385        if (id!=previd || video_needs_update){
386                GdkWindow *w;
387                previd=id;
388                if (id!=0){
389                        ms_message("Updating window decorations");
390#ifndef WIN32
391                        w=gdk_window_foreign_new(id);
392#else
393                        w=gdk_window_foreign_new((HANDLE)id);
394#endif
395                        if (w) {
396                                set_video_window_decorations(w);
397                                g_object_unref(G_OBJECT(w));
398                        }
399                        else ms_error("gdk_window_foreign_new() failed");
400                        if (video_needs_update) video_needs_update=FALSE;
401                }
402        }
403        if (addr_to_call!=NULL){
404                /*make sure we are not showing the login screen*/
405                GtkWidget *mw=linphone_gtk_get_main_window();
406                GtkWidget *login_frame=linphone_gtk_get_widget(mw,"login_frame");
407                if (!GTK_WIDGET_VISIBLE(login_frame)){
408                        GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar");
409                        gtk_entry_set_text(GTK_ENTRY(uri_bar),addr_to_call);
410                        addr_to_call=NULL;
411                        linphone_gtk_start_call(uri_bar);
412                }
413        }
414        in_iterate=FALSE;
415        return TRUE;
416}
417
418static void load_uri_history(){
419        GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"));
420        char key[20];
421        int i;
422        GtkEntryCompletion *gep=gtk_entry_completion_new();
423        GtkListStore *model=gtk_list_store_new(1,G_TYPE_STRING);
424        for (i=0;;i++){
425                const char *uri;
426                snprintf(key,sizeof(key),"uri%i",i);
427                uri=linphone_gtk_get_ui_config(key,NULL);
428                if (uri!=NULL) {
429                        GtkTreeIter iter;
430                        gtk_list_store_append(model,&iter);
431                        gtk_list_store_set(model,&iter,0,uri,-1);
432                        if (i==0) gtk_entry_set_text(uribar,uri);
433                }
434                else break;
435        }
436        gtk_entry_completion_set_model(gep,GTK_TREE_MODEL(model));
437        gtk_entry_completion_set_text_column(gep,0);
438        gtk_entry_set_completion(uribar,gep);
439}
440
441static void save_uri_history(){
442        LinphoneCore *lc=linphone_gtk_get_core();
443        LpConfig *cfg=linphone_core_get_config(lc);
444        GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"));
445        char key[20];
446        int i=0;
447        char *uri=NULL;
448        GtkTreeIter iter;
449        GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(uribar));
450
451        if (!gtk_tree_model_get_iter_first(model,&iter)) return;
452        do {
453                gtk_tree_model_get(model,&iter,0,&uri,-1);
454                if (uri) {
455                        snprintf(key,sizeof(key),"uri%i",i);
456                        lp_config_set_string(cfg,"GtkUi",key,uri);
457                        g_free(uri);
458                }else break;
459                i++;
460                if (i>5) break;
461        }while(gtk_tree_model_iter_next(model,&iter));
462        lp_config_sync(cfg);
463}
464
465static void completion_add_text(GtkEntry *entry, const char *text){
466        GtkTreeIter iter;
467        GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(entry));
468       
469        if (gtk_tree_model_get_iter_first(model,&iter)){ 
470                do {
471                        gchar *uri=NULL;
472                        gtk_tree_model_get(model,&iter,0,&uri,-1);
473                        if (uri!=NULL){
474                                if (strcmp(uri,text)==0) {
475                                        /*remove text */
476                                        gtk_list_store_remove(GTK_LIST_STORE(model),&iter);
477                                        g_free(uri);
478                                        break;
479                                }
480                                g_free(uri);
481                        }
482                }while (gtk_tree_model_iter_next(model,&iter));
483        }
484        /* and prepend it on top of the list */
485        gtk_list_store_prepend(GTK_LIST_STORE(model),&iter);
486        gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,text,-1);
487        save_uri_history();
488}
489
490void linphone_gtk_call_terminated(const char *error){
491        GtkWidget *mw=linphone_gtk_get_main_window();
492        gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),FALSE);
493        gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"start_call"),TRUE);
494        gtk_widget_hide_all(linphone_gtk_get_widget(mw,"go_to_call_view_box"));
495        linphone_gtk_in_call_view_terminate(error);
496        update_video_title();
497        g_object_set_data(G_OBJECT(mw),"incoming_call",NULL);
498       
499}
500
501static gboolean in_call_timer(){
502        if (linphone_core_in_call(linphone_gtk_get_core())){
503                linphone_gtk_in_call_view_update_duration(
504                        linphone_core_get_current_call_duration(linphone_gtk_get_core()));
505                return TRUE;
506        }
507        return FALSE;
508}
509
510static void linphone_gtk_call_started(GtkWidget *mw){
511        gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"start_call"),FALSE);
512        gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),TRUE);
513        gtk_widget_show_all(linphone_gtk_get_widget(mw,"go_to_call_view_box"));
514        update_video_title();
515        g_timeout_add(250,(GSourceFunc)in_call_timer,NULL);
516}
517
518static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){
519        const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar));
520        if (linphone_core_invite(linphone_gtk_get_core(),entered)==0) {
521                completion_add_text(GTK_ENTRY(uri_bar),entered);
522        }else{
523        }
524        return FALSE;
525}
526
527void linphone_gtk_start_call(GtkWidget *w){
528        LinphoneCore *lc=linphone_gtk_get_core();
529        if (linphone_core_inc_invite_pending(lc) || linphone_core_in_call(lc)) {
530                /*already in call */
531        }else{
532                /*change into in-call mode, then do the work later as it might block a bit */
533                GtkWidget *mw=gtk_widget_get_toplevel(w);
534                GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar");
535                const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar));
536                linphone_gtk_call_started(mw);
537                linphone_gtk_in_call_view_set_calling(entered);
538                linphone_gtk_show_in_call_view();
539                g_timeout_add(100,(GSourceFunc)linphone_gtk_start_call_do,uri_bar);
540        }
541}
542
543void linphone_gtk_uri_bar_activate(GtkWidget *w){
544        linphone_gtk_start_call(w);
545}
546
547
548void linphone_gtk_terminate_call(GtkWidget *button){
549        linphone_core_terminate_call(linphone_gtk_get_core(),NULL);
550}
551
552void linphone_gtk_decline_call(GtkWidget *button){
553        linphone_core_terminate_call(linphone_gtk_get_core(),NULL);
554        /* zsd note: there was a big here in 3.0.0 which caused an abort if
555         * someone clicked "decline"... the following line of code looks
556         * like a fix for that. */
557        gtk_widget_destroy(gtk_widget_get_toplevel(button));
558}
559
560void linphone_gtk_accept_call(GtkWidget *button){
561        LinphoneCore *lc=linphone_gtk_get_core();
562        linphone_core_accept_call(lc,NULL);
563        g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"incoming_call",NULL);
564        gtk_widget_destroy(gtk_widget_get_toplevel(button));
565        linphone_gtk_call_started(linphone_gtk_get_main_window());
566        linphone_gtk_in_call_view_set_in_call();
567        linphone_gtk_show_in_call_view();
568}
569
570static gboolean linphone_gtk_auto_answer(GtkWidget *incall_window){
571        linphone_gtk_accept_call(linphone_gtk_get_widget(incall_window,"accept_call"));
572        return FALSE;
573}
574
575void linphone_gtk_set_audio_video(){
576        linphone_core_enable_video(linphone_gtk_get_core(),TRUE,TRUE);
577        linphone_core_enable_video_preview(linphone_gtk_get_core(),TRUE);
578}
579
580void linphone_gtk_set_audio_only(){
581        linphone_core_enable_video(linphone_gtk_get_core(),FALSE,FALSE);
582        linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
583}
584
585void linphone_gtk_enable_self_view(GtkWidget *w){
586        linphone_core_enable_self_view(linphone_gtk_get_core(),
587                gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
588}
589
590void linphone_gtk_used_identity_changed(GtkWidget *w){
591        int active=gtk_combo_box_get_active(GTK_COMBO_BOX(w));
592        char *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w));
593        if (sel && strlen(sel)>0){ //avoid a dummy "changed" at gui startup
594                linphone_core_set_default_proxy_index(linphone_gtk_get_core(),(active==0) ? -1 : (active-1));
595                linphone_gtk_show_directory_search();
596        }
597}
598
599static void linphone_gtk_show_main_window(){
600        GtkWidget *w=linphone_gtk_get_main_window();
601        LinphoneCore *lc=linphone_gtk_get_core();
602        linphone_core_enable_video_preview(lc,linphone_core_video_enabled(lc));
603        gtk_widget_show(w);
604        gtk_window_present(GTK_WINDOW(w));
605}
606
607static void linphone_gtk_show(LinphoneCore *lc){
608        linphone_gtk_show_main_window();
609}
610
611static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from){
612        GtkWidget *w=linphone_gtk_create_window("incoming_call");
613        GtkWidget *label;
614        gchar *msg;
615
616        if (auto_answer){
617                g_timeout_add(2000,(GSourceFunc)linphone_gtk_auto_answer,w);
618        }
619
620        gtk_window_set_transient_for(GTK_WINDOW(w),GTK_WINDOW(linphone_gtk_get_main_window()));
621        gtk_window_set_position(GTK_WINDOW(w),GTK_WIN_POS_CENTER_ON_PARENT);
622
623        label=linphone_gtk_get_widget(w,"message");
624        msg=g_strdup_printf(_("Incoming call from %s"),from);
625        gtk_label_set_text(GTK_LABEL(label),msg);
626        gtk_window_set_title(GTK_WINDOW(w),msg);
627        gtk_widget_show(w);
628        gtk_window_present(GTK_WINDOW(w));
629        /*gtk_window_set_urgency_hint(GTK_WINDOW(w),TRUE);*/
630        g_free(msg);
631        g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"incoming_call",w);
632        gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),
633                        from);
634}
635
636static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from){
637        GtkWidget *icw=GTK_WIDGET(g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"incoming_call"));
638        if (icw!=NULL){
639                gtk_widget_destroy(icw);
640        }
641}
642
643static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img){
644}
645
646static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint response_id, LinphoneFriend *lf){
647        switch(response_id){
648                case GTK_RESPONSE_YES:
649                        linphone_gtk_show_contact(lf);
650                break;
651                default:
652                        linphone_core_reject_subscriber(linphone_gtk_get_core(),lf);
653        }
654        gtk_widget_destroy(dialog);
655}
656
657static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
658        GtkWidget *dialog;
659        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);
660        dialog = gtk_message_dialog_new (
661                                GTK_WINDOW(linphone_gtk_get_main_window()),
662                                GTK_DIALOG_DESTROY_WITH_PARENT,
663                                GTK_MESSAGE_QUESTION,
664                                GTK_BUTTONS_YES_NO,
665                                "%s",
666                                message);
667        g_free(message);
668        g_signal_connect(G_OBJECT (dialog), "response",
669                G_CALLBACK (linphone_gtk_new_subscriber_response),lf);
670        /* actually show the box */
671        gtk_widget_show(dialog);
672}
673
674typedef struct _AuthTimeout{
675        GtkWidget *w;
676} AuthTimeout;
677
678
679static void auth_timeout_clean(AuthTimeout *tout){
680        tout->w=NULL;
681}
682
683static gboolean auth_timeout_destroy(AuthTimeout *tout){
684        if (tout->w)  {
685                g_object_weak_unref(G_OBJECT(tout->w),(GWeakNotify)auth_timeout_clean,tout);
686                gtk_widget_destroy(tout->w);
687        }
688        g_free(tout);
689        return FALSE;
690}
691
692static AuthTimeout * auth_timeout_new(GtkWidget *w){
693        AuthTimeout *tout=g_new(AuthTimeout,1);
694        tout->w=w;
695        /*so that the timeout no more references the widget when it is destroyed:*/
696        g_object_weak_ref(G_OBJECT(w),(GWeakNotify)auth_timeout_clean,tout);
697        /*so that the widget is automatically destroyed after some time */
698        g_timeout_add(30000,(GtkFunction)auth_timeout_destroy,tout);
699        return tout;
700}
701
702void linphone_gtk_password_cancel(GtkWidget *w){
703        LinphoneAuthInfo *info;
704        GtkWidget *window=gtk_widget_get_toplevel(w);
705        info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info");
706        linphone_core_abort_authentication(linphone_gtk_get_core(),info);
707        gtk_widget_destroy(window);
708}
709
710void linphone_gtk_password_ok(GtkWidget *w){
711        GtkWidget *entry;
712        GtkWidget *window=gtk_widget_get_toplevel(w);
713        LinphoneAuthInfo *info;
714        info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info");
715        g_object_weak_unref(G_OBJECT(window),(GWeakNotify)linphone_auth_info_destroy,info);
716        entry=linphone_gtk_get_widget(window,"password_entry");
717        linphone_auth_info_set_passwd(info,gtk_entry_get_text(GTK_ENTRY(entry)));
718        linphone_auth_info_set_username(info,
719                gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(window,"username_entry"))));
720        linphone_core_add_auth_info(linphone_gtk_get_core(),info);
721        gtk_widget_destroy(window);
722}
723
724static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username){
725        GtkWidget *w=linphone_gtk_create_window("password");
726        GtkWidget *label=linphone_gtk_get_widget(w,"message");
727        LinphoneAuthInfo *info;
728        gchar *msg;
729        msg=g_strdup_printf(_("Please enter your password for domain %s:"),realm);
730        gtk_label_set_text(GTK_LABEL(label),msg);
731        g_free(msg);
732        gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"username_entry")),username);
733        info=linphone_auth_info_new(username, NULL, NULL, NULL,realm);
734        g_object_set_data(G_OBJECT(w),"auth_info",info);
735        g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_auth_info_destroy,info);
736        gtk_widget_show(w);
737        auth_timeout_new(w);
738}
739
740static void linphone_gtk_display_status(LinphoneCore *lc, const char *status){
741        GtkWidget *w=linphone_gtk_get_main_window();
742        GtkWidget *status_bar=linphone_gtk_get_widget(w,"status_bar");
743        gtk_statusbar_push(GTK_STATUSBAR(status_bar),
744                        gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar),""),
745                        status);
746}
747
748static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg){
749        linphone_gtk_display_something(GTK_MESSAGE_INFO,msg);
750}
751
752static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning){
753        linphone_gtk_display_something(GTK_MESSAGE_WARNING,warning);
754}
755
756static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url){
757        char richtext[4096];
758        snprintf(richtext,sizeof(richtext),"%s %s",msg,url);
759        linphone_gtk_display_something(GTK_MESSAGE_INFO,richtext);
760}
761
762static void linphone_gtk_display_question(LinphoneCore *lc, const char *question){
763        linphone_gtk_display_something(GTK_MESSAGE_QUESTION,question);
764}
765
766static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl){
767        GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"call_logs");
768        if (w) linphone_gtk_call_log_update(w);
769}
770
771static void linphone_gtk_general_state(LinphoneCore *lc, LinphoneGeneralState *gstate){
772        switch(gstate->new_state){
773                case GSTATE_CALL_OUT_CONNECTED:
774                case GSTATE_CALL_IN_CONNECTED:
775                        linphone_gtk_in_call_view_set_in_call();
776                break;
777                case GSTATE_CALL_ERROR:
778                        linphone_gtk_call_terminated(gstate->message);
779                break;
780                case GSTATE_CALL_END:
781                        linphone_gtk_call_terminated(NULL);
782                break;
783                default:
784                break;
785        }
786}
787
788static void icon_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data){
789        GtkWidget *menu=(GtkWidget*)g_object_get_data(G_OBJECT(status_icon),"menu");
790        gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time);
791}
792
793void linphone_gtk_open_browser(const char *url){
794        /*in gtk 2.16, gtk_show_uri does not work...*/
795        /*gtk_show_uri(NULL,url,GDK_CURRENT_TIME,NULL);*/
796#ifdef WIN32
797        ShellExecute(0,"open",url,NULL,NULL,1);
798#else
799        char cl[255];
800        snprintf(cl,sizeof(cl),"/usr/bin/x-www-browser %s",url);
801        g_spawn_command_line_async(cl,NULL);
802#endif
803}
804
805void linphone_gtk_link_to_website(GtkWidget *item){
806        const gchar *home=(const gchar*)g_object_get_data(G_OBJECT(item),"home");
807        linphone_gtk_open_browser(home);
808}
809
810static GtkWidget *create_icon_menu(){
811        GtkWidget *menu=gtk_menu_new();
812        GtkWidget *menu_item;
813        GtkWidget *image;
814        gchar *tmp;
815        const gchar *homesite;
816       
817        homesite=linphone_gtk_get_ui_config("home","http://www.linphone.org");
818        menu_item=gtk_image_menu_item_new_with_label(homesite);
819        tmp=g_strdup(homesite);
820        g_object_set_data(G_OBJECT(menu_item),"home",tmp);
821        g_object_weak_ref(G_OBJECT(menu_item),(GWeakNotify)g_free,tmp);
822       
823        image=gtk_image_new_from_stock(GTK_STOCK_HELP,GTK_ICON_SIZE_MENU);
824        gtk_widget_show(image);
825        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
826        //g_object_unref(G_OBJECT(image));
827        gtk_widget_show(menu_item);
828        gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
829        g_signal_connect(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_link_to_website,NULL);
830       
831        menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT,NULL);
832        gtk_widget_show(menu_item);
833        gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
834        g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_show_about,NULL);
835        menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,NULL);
836        gtk_widget_show(menu_item);
837        gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
838        g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)gtk_main_quit,NULL);
839        gtk_widget_show(menu);
840        return menu;
841}
842
843static GtkStatusIcon *icon=NULL;
844
845static void linphone_gtk_init_status_icon(){
846        const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
847        GdkPixbuf *pbuf=create_pixbuf(icon_path);
848        GtkWidget *menu=create_icon_menu();
849        const char *title;
850        icon=gtk_status_icon_new_from_pixbuf(pbuf);
851        g_object_unref(G_OBJECT(pbuf));
852        g_signal_connect_swapped(G_OBJECT(icon),"activate",(GCallback)linphone_gtk_show_main_window,linphone_gtk_get_main_window());
853        g_signal_connect(G_OBJECT(icon),"popup-menu",(GCallback)icon_popup_menu,NULL);
854        title=linphone_gtk_get_ui_config("title",_("Linphone - a video internet phone"));
855        gtk_status_icon_set_tooltip(icon,title);
856        gtk_status_icon_set_visible(icon,TRUE);
857        g_object_set_data(G_OBJECT(icon),"menu",menu);
858        g_object_weak_ref(G_OBJECT(icon),(GWeakNotify)gtk_widget_destroy,menu);
859}
860
861void linphone_gtk_load_identities(void){
862        const MSList *elem;
863        GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities"));
864        char *def_identity;
865        LinphoneProxyConfig *def=NULL;
866        int def_index=0,i;
867        GtkListStore *store;
868
869        store=GTK_LIST_STORE(gtk_combo_box_get_model(box));
870        gtk_list_store_clear(store);
871
872        linphone_core_get_default_proxy(linphone_gtk_get_core(),&def);
873        def_identity=g_strdup_printf(_("%s (Default)"),linphone_core_get_primary_contact(linphone_gtk_get_core()));
874        gtk_combo_box_append_text(box,def_identity);
875        g_free(def_identity);
876        for(i=1,elem=linphone_core_get_proxy_config_list(linphone_gtk_get_core());
877                        elem!=NULL;
878                        elem=ms_list_next(elem),i++){
879                LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
880                gtk_combo_box_append_text(box,linphone_proxy_config_get_identity(cfg));
881                if (cfg==def) {
882                        def_index=i;
883                }
884        }
885        gtk_combo_box_set_active(box,def_index);
886}
887
888static void linphone_gtk_dtmf_clicked(GtkButton *button){
889        const char *label=gtk_button_get_label(button);
890        if (linphone_core_in_call(linphone_gtk_get_core())){
891                linphone_core_send_dtmf(linphone_gtk_get_core(),label[0]);
892        }else{
893                GtkWidget *uri_bar=linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(button)),"uribar");
894                int pos=-1;
895                gtk_editable_insert_text(GTK_EDITABLE(uri_bar),label,1,&pos);
896        }
897}
898
899static void linphone_gtk_connect_digits(void){
900        GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"dtmf_table"));
901        GList *children=gtk_container_get_children(cont);
902        GList *elem;
903        for(elem=children;elem!=NULL;elem=elem->next){
904                GtkButton *button=GTK_BUTTON(elem->data);
905                g_signal_connect(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_dtmf_clicked,NULL);
906        }
907}
908
909static void linphone_gtk_check_menu_items(void){
910        bool_t audio_only=!linphone_core_video_enabled(linphone_gtk_get_core());
911        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(linphone_gtk_get_widget(
912                                        linphone_gtk_get_main_window(),
913                                        audio_only ? "audio_only_item" : "video_item")), TRUE);
914}
915
916static gboolean linphone_gtk_can_manage_accounts(){
917        LinphoneCore *lc=linphone_gtk_get_core();
918        const MSList *elem;
919        for(elem=linphone_core_get_sip_setups(lc);elem!=NULL;elem=elem->next){
920                SipSetup *ss=(SipSetup*)elem->data;
921                if (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_ACCOUNT_MANAGER){
922                        return TRUE;
923                }
924        }
925        return FALSE;
926}
927
928static void linphone_gtk_configure_main_window(){
929        static gboolean config_loaded=FALSE;
930        static const char *title;
931        static const char *home;
932        static const char *start_call_icon;
933        static const char *stop_call_icon;
934        GtkWidget *w=linphone_gtk_get_main_window();
935        if (!config_loaded){
936                title=linphone_gtk_get_ui_config("title","Linphone");
937                home=linphone_gtk_get_ui_config("home","http://www.linphone.org");
938                start_call_icon=linphone_gtk_get_ui_config("start_call_icon","green.png");
939                stop_call_icon=linphone_gtk_get_ui_config("stop_call_icon","red.png");
940                config_loaded=TRUE;
941        }
942        linphone_gtk_configure_window(w,"main_window");
943        if (title) {
944                gtk_window_set_title(GTK_WINDOW(w),title);
945#if GTK_CHECK_VERSION(2,16,0)
946                gtk_menu_item_set_label(GTK_MENU_ITEM(linphone_gtk_get_widget(w,"main_menu")),title);
947#endif
948        }
949        if (start_call_icon){
950                GdkPixbuf *pbuf=create_pixbuf(start_call_icon);
951                gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"start_call_icon")),pbuf);
952                g_object_unref(G_OBJECT(pbuf));
953        }
954        if (stop_call_icon){
955                GdkPixbuf *pbuf=create_pixbuf(stop_call_icon);
956                gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"terminate_call_icon")),pbuf);
957                gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"in_call_terminate_icon")),pbuf);
958                g_object_unref(G_OBJECT(pbuf));
959        }
960        if (home){
961                gchar *tmp;
962                GtkWidget *menu_item=linphone_gtk_get_widget(w,"home_item");
963                tmp=g_strdup(home);
964                g_object_set_data(G_OBJECT(menu_item),"home",tmp);
965        }
966        if (!linphone_gtk_can_manage_accounts())
967                gtk_widget_hide(linphone_gtk_get_widget(w,"run_assistant"));
968}
969
970void linphone_gtk_manage_login(void){
971        LinphoneCore *lc=linphone_gtk_get_core();
972        LinphoneProxyConfig *cfg=NULL;
973        linphone_core_get_default_proxy(lc,&cfg);
974        if (cfg){
975                SipSetup *ss=linphone_proxy_config_get_sip_setup(cfg);
976                if (ss && (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_LOGIN)){
977                        linphone_gtk_show_login_frame(cfg);
978                }
979        }
980}
981
982static void linphone_gtk_init_main_window(){
983        linphone_gtk_configure_main_window();
984        linphone_gtk_manage_login();
985        load_uri_history();
986        linphone_gtk_load_identities();
987        linphone_gtk_set_my_presence(linphone_core_get_presence_info(linphone_gtk_get_core()));
988        linphone_gtk_show_friends();
989        linphone_gtk_connect_digits();
990        linphone_gtk_check_menu_items();
991        if (linphone_core_in_call(linphone_gtk_get_core())) linphone_gtk_call_started(
992                linphone_gtk_get_main_window());/*hide the call button, show terminate button*/
993}
994
995void linphone_gtk_close(){
996        /* couldn't find a way to prevent closing to destroy the main window*/
997        LinphoneCore *lc=linphone_gtk_get_core();
998        the_ui=NULL;
999        the_ui=linphone_gtk_create_window("main");
1000        linphone_gtk_init_main_window();
1001        /*shutdown call if any*/
1002        if (linphone_core_in_call(lc)){
1003                linphone_core_terminate_call(lc,NULL);
1004                linphone_gtk_call_terminated(NULL);
1005        }
1006        linphone_core_enable_video_preview(lc,FALSE);
1007}
1008
1009void linphone_gtk_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
1010        if (verbose){
1011                const char *lname="undef";
1012                char *msg;
1013                #ifdef __linux
1014                va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/
1015                #endif
1016                switch(lev){
1017                        case ORTP_DEBUG:
1018                                lname="debug";
1019                                break;
1020                        case ORTP_MESSAGE:
1021                                lname="message";
1022                                break;
1023                        case ORTP_WARNING:
1024                                lname="warning";
1025                                break;
1026                        case ORTP_ERROR:
1027                                lname="error";
1028                                break;
1029                        case ORTP_FATAL:
1030                                lname="fatal";
1031                                break;
1032                        default:
1033                                g_error("Bad level !");
1034                }
1035#ifdef __linux
1036                va_copy(cap,args);
1037                msg=g_strdup_vprintf(fmt,cap);
1038                va_end(cap);
1039#else
1040                msg=g_strdup_vprintf(fmt,args);
1041#endif
1042                fprintf(stdout,"linphone-%s : %s\n",lname,msg);
1043                ortp_free(msg);
1044        }
1045        linphone_gtk_log_push(lev,fmt,args);
1046}
1047
1048
1049static void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to){
1050    GtkEntry * uri_bar =GTK_ENTRY(linphone_gtk_get_widget(
1051                linphone_gtk_get_main_window(), "uribar"));
1052        linphone_gtk_show_main_window();
1053        gtk_entry_set_text(uri_bar, refer_to);
1054        linphone_gtk_start_call(linphone_gtk_get_main_window());
1055}
1056
1057
1058int main(int argc, char *argv[]){
1059#ifdef ENABLE_NLS
1060        void *p;
1061#endif
1062        const char *config_file;
1063        const char *lang;
1064
1065        g_thread_init(NULL);
1066        gdk_threads_init();
1067       
1068        config_file=linphone_gtk_get_config_file();
1069
1070#ifdef WIN32
1071        /*workaround for windows: sometimes LANG is defined to an integer value, not understood by gtk */
1072        if ((lang=getenv("LANG"))!=NULL){
1073                if (atoi(lang)!=0){
1074                        char tmp[128];
1075                        snprintf(tmp,sizeof(tmp),"LANG=",lang);
1076                        _putenv(tmp);
1077                }
1078        }
1079#endif
1080       
1081        if ((lang=linphone_gtk_get_lang(config_file))!=NULL && lang[0]!='\0'){
1082#ifdef WIN32
1083                char tmp[128];
1084                snprintf(tmp,sizeof(tmp),"LANG=%s",lang);
1085                _putenv(tmp);
1086#else
1087                setenv("LANG",lang,1);
1088#endif
1089        }
1090
1091#ifdef ENABLE_NLS
1092        p=bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
1093        if (p==NULL) perror("bindtextdomain failed");
1094        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1095        textdomain (GETTEXT_PACKAGE);
1096#else
1097        g_message("NLS disabled.\n");
1098#endif
1099#ifdef WIN32
1100        gtk_rc_add_default_file("./gtkrc");
1101#endif
1102        gdk_threads_enter();
1103       
1104        if (!gtk_init_with_args(&argc,&argv,_("A free SIP video-phone"),
1105                                linphone_options,NULL,NULL)){
1106                gdk_threads_leave();
1107                return -1;
1108        }
1109        if (linphone_core_wake_up_possible_already_running_instance(
1110                config_file, addr_to_call) == 0){
1111                g_message("addr_to_call=%s",addr_to_call);
1112                g_warning("Another running instance of linphone has been detected. It has been woken-up.");
1113                g_warning("This instance is going to exit now.");
1114                gdk_threads_leave();
1115                return 0;
1116        }
1117
1118        add_pixmap_directory("pixmaps");
1119        add_pixmap_directory(PACKAGE_DATA_DIR "/pixmaps/linphone");
1120
1121        the_ui=linphone_gtk_create_window("main");
1122       
1123        linphone_gtk_create_log_window();
1124        linphone_core_enable_logs_with_cb(linphone_gtk_log_handler);
1125
1126        linphone_gtk_init_liblinphone(config_file);
1127        /* do not lower timeouts under 30 ms because it exhibits a bug on gtk+/win32, with cpu running 20% all the time...*/
1128        gtk_timeout_add(30,(GtkFunction)linphone_gtk_iterate,(gpointer)linphone_gtk_get_core());
1129        gtk_timeout_add(30,(GtkFunction)linphone_gtk_check_logs,(gpointer)NULL);
1130        linphone_gtk_init_main_window();
1131        linphone_gtk_init_status_icon();
1132        linphone_gtk_show_main_window();
1133        linphone_gtk_check_for_new_version();
1134
1135        gtk_main();
1136        gdk_threads_leave();
1137        linphone_gtk_destroy_log_window();
1138        linphone_core_destroy(the_core);
1139        /*workaround a bug on win32 that makes status icon still present in the systray even after program exit.*/
1140        gtk_status_icon_set_visible(icon,FALSE);
1141        return 0;
1142}
Note: See TracBrowser for help on using the repository browser.