source: mediastreamer2/linphone/gtk-glade/main.c @ 218:c5e6ec0e7a20

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

translations and themes work on win32

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

File size: 29.1 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 "lpconfig.h"
23
24#include "linphone.h"
25
26#ifdef USE_LIBGLADE
27#include <glade/glade.h>
28#endif
29
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <unistd.h>
33
34#ifndef GETTEXT_PACKAGE
35#define GETTEXT_PACKAGE "linphone"
36#endif
37
38#ifndef PACKAGE_LOCALE_DIR
39#define PACKAGE_LOCALE_DIR "share/locale/"
40#endif
41
42#define LINPHONE_ICON "linphone2.png"
43
44static LinphoneCore *the_core=NULL;
45static GtkWidget *the_ui=NULL;
46
47static void linphone_gtk_show(LinphoneCore *lc);
48static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from);
49static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from);
50static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img);
51static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
52static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username);
53static void linphone_gtk_display_status(LinphoneCore *lc, const char *status);
54static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg);
55static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning);
56static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url);
57static void linphone_gtk_display_question(LinphoneCore *lc, const char *question);
58static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl);
59static void linphone_gtk_general_state(LinphoneCore *lc, LinphoneGeneralState *gstate);
60
61static LinphoneCoreVTable vtable={
62        .show=linphone_gtk_show,
63        .inv_recv=linphone_gtk_inv_recv,
64        .bye_recv=linphone_gtk_bye_recv,
65        .notify_recv=linphone_gtk_notify_recv,
66        .new_unknown_subscriber=linphone_gtk_new_unknown_subscriber,
67        .auth_info_requested=linphone_gtk_auth_info_requested,
68        .display_status=linphone_gtk_display_status,
69        .display_message=linphone_gtk_display_message,
70        .display_warning=linphone_gtk_display_warning,
71        .display_url=linphone_gtk_display_url,
72        .display_question=linphone_gtk_display_question,
73        .call_log_updated=linphone_gtk_call_log_updated,
74        .text_received=linphone_gtk_text_received,
75        .general_state=linphone_gtk_general_state
76};
77
78static gboolean verbose=0;
79static GOptionEntry linphone_options[2]={
80        {
81                .long_name="verbose",
82                .short_name= '\0',
83                .arg=G_OPTION_ARG_NONE,
84                .arg_data= (gpointer)&verbose,
85                .description="log to stdout some debug information while running."
86        }
87};
88
89#define INSTALLED_XML_DIR PACKAGE_DATA_DIR "/linphone"
90#define BUILD_TREE_XML_DIR "gtk-glade"
91#define CONFIG_FILE ".linphonerc"
92
93static char _config_file[1024];
94
95const char *linphone_gtk_get_config_file(){
96        const char *home;
97        /*try accessing a local file first if exists*/
98        if (access(CONFIG_FILE,F_OK)==0){
99                snprintf(_config_file,sizeof(_config_file),"%s",CONFIG_FILE);
100        }else{
101#ifdef WIN32
102                const char *appdata=getenv("APPDATA");
103                if (appdata){
104                        snprintf(_config_file,sizeof(_config_file),"%s\\%s",appdata,"Linphone\\");
105                        CreateDirectory(_config_file,NULL);
106                        snprintf(_config_file,sizeof(_config_file),"%s\\%s",appdata,"Linphone\\linphonerc");
107                }
108#else
109                home=getenv("HOME");
110                if (home==NULL) home="";
111                snprintf(_config_file,sizeof(_config_file),"%s/%s",home,CONFIG_FILE);
112#endif
113        }
114        return _config_file;
115}
116
117static void linphone_gtk_init_liblinphone(const char *file){
118        the_core=linphone_core_new(&vtable,file,NULL);
119}
120
121
122
123LinphoneCore *linphone_gtk_get_core(void){
124        return the_core;
125}
126
127GtkWidget *linphone_gtk_get_main_window(){
128        return the_ui;
129}
130
131#ifdef USE_LIBGLADE
132
133GtkWidget *linphone_gtk_create_window(const char *window_name){
134        GtkWidget *w;
135        GladeXML *gxml;
136        char path[2048];
137        snprintf(path,sizeof(path),"%s/%s.glade",BUILD_TREE_XML_DIR,window_name);
138        if (access(path,F_OK)!=0){
139                snprintf(path,sizeof(path),"%s/%s.glade",INSTALLED_XML_DIR,window_name);
140                if (access(path,F_OK)!=0){
141                        g_error("Could not locate neither %s/%s.glade and %s/%s.glade .",BUILD_TREE_XML_DIR,window_name,
142                                INSTALLED_XML_DIR,window_name);
143                        return NULL;
144                }
145        }
146        gxml=glade_xml_new(path,NULL,NULL);
147        glade_xml_signal_autoconnect(gxml);
148        w=glade_xml_get_widget(gxml,window_name);
149        if (w==NULL) g_error("Could not retrieve '%s' window from xml file",window_name);
150        return w;
151}
152
153GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
154        GtkWidget *w;
155        GladeXML *gxml=glade_get_widget_tree(window);
156        if (gxml==NULL) g_error("Could not retrieve XML tree of window %s",name);
157        w=glade_xml_get_widget(gxml,name);
158        if (w==NULL) g_error("Could not retrieve widget %s",name);
159        return GTK_WIDGET(w);
160}
161
162#else
163
164GtkWidget *linphone_gtk_create_window(const char *window_name){
165       
166}
167
168GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
169        GObject *w=gtk_builder_get_object(the_ui,name);
170        if (w==NULL){
171                g_error("No widget named %s found in xml interface.",name);
172        }
173        return GTK_WIDGET(w);
174}
175
176#endif
177
178void linphone_gtk_display_something(GtkMessageType type,const gchar *message){
179        GtkWidget *dialog;
180        GtkWidget *main_window=linphone_gtk_get_main_window();
181       
182        gtk_widget_show(main_window);
183        if (type==GTK_MESSAGE_QUESTION)
184        {
185                /* draw a question box. link to dialog_click callback */
186                dialog = gtk_message_dialog_new (
187                                GTK_WINDOW(main_window),
188                                GTK_DIALOG_DESTROY_WITH_PARENT,
189                                GTK_MESSAGE_QUESTION,
190                                GTK_BUTTONS_YES_NO,
191                                "%s",
192                                (const gchar*)message);
193                /* connect to some callback : REVISIT */
194                /*
195                g_signal_connect_swapped (G_OBJECT (dialog), "response",
196                           G_CALLBACK (dialog_click),
197                           G_OBJECT (dialog));
198                */
199                /* actually show the box */
200                gtk_widget_show(dialog);
201        }
202        else
203        {
204                dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
205                                  GTK_DIALOG_DESTROY_WITH_PARENT,
206                                  type,
207                                  GTK_BUTTONS_CLOSE,
208                                  "%s",
209                                  (const gchar*)message);
210                /* Destroy the dialog when the user responds to it (e.g. clicks a button) */
211                g_signal_connect_swapped (G_OBJECT (dialog), "response",
212                           G_CALLBACK (gtk_widget_destroy),
213                           G_OBJECT (dialog));
214                gtk_widget_show(dialog);
215        }
216}
217
218void linphone_gtk_about_response(GtkDialog *dialog, gint id){
219        if (id==GTK_RESPONSE_CANCEL){
220                gtk_widget_destroy(GTK_WIDGET(dialog));
221        }
222}
223
224void linphone_gtk_show_about(){
225        struct stat filestat;
226        const char *license_file=PACKAGE_DATA_DIR "/doc/COPYING";
227        GtkWidget *about;
228
229        about=linphone_gtk_create_window("about");
230        memset(&filestat,0,sizeof(filestat));
231        if (stat(license_file,&filestat)!=0){
232                license_file="COPYING";
233                stat(license_file,&filestat);
234        }
235        if (filestat.st_size>0){
236                char *license=g_malloc(filestat.st_size+1);
237                FILE *f=fopen(license_file,"r");
238                if (f && fread(license,filestat.st_size,1,f)==1){
239                        license[filestat.st_size]='\0';
240                        gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about),license);
241                }
242                g_free(license);
243        }
244        gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about),LINPHONE_VERSION);
245
246        gtk_widget_show(about);
247}
248
249static void set_video_window_decorations(GdkWindow *w){
250        const char *title=linphone_gtk_get_ui_config("title","Linphone");
251        const char *icon_path=linphone_gtk_get_ui_config("icon","linphone2.png");
252        char video_title[256];
253        GdkPixbuf *pbuf=create_pixbuf(icon_path);
254        snprintf(video_title,sizeof(video_title),"%s video",title);
255        gdk_window_set_title(w,video_title);
256        if (pbuf){
257                GList *l=NULL;
258                l=g_list_append(l,pbuf);
259                gdk_window_set_icon_list(w,l);
260                g_list_free(l);
261                g_object_unref(G_OBJECT(pbuf));
262        }
263}
264
265static gboolean linphone_gtk_iterate(LinphoneCore *lc){
266        unsigned long id;
267        static unsigned long previd=0;
268        linphone_core_iterate(lc);
269        id=linphone_core_get_native_video_window_id(lc);
270        if (id!=previd){
271                GdkWindow *w;
272                previd=id;
273                if (id!=0){
274                        w=gdk_window_foreign_new(id);
275                        if (w) {
276                                set_video_window_decorations(w);
277                                g_object_unref(G_OBJECT(w));
278                        }
279                        else ms_error("gdk_window_foreign_new() failed");
280                }
281        }
282        return TRUE;
283}
284
285static void load_uri_history(){
286        GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"));
287        LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core());
288        char key[20];
289        int i;
290        GtkEntryCompletion *gep=gtk_entry_completion_new();
291        GtkListStore *model=gtk_list_store_new(1,G_TYPE_STRING);
292        for (i=0;;i++){
293                const char *uri;
294                snprintf(key,sizeof(key),"uri%i",i);
295                uri=lp_config_get_string(cfg,"GtkUi",key,NULL);
296                if (uri!=NULL) {
297                        GtkTreeIter iter;
298                        gtk_list_store_append(model,&iter);
299                        gtk_list_store_set(model,&iter,0,uri,-1);
300                        if (i==0) gtk_entry_set_text(uribar,uri);
301                }
302                else break;
303        }
304        gtk_entry_completion_set_model(gep,GTK_TREE_MODEL(model));
305        gtk_entry_completion_set_text_column(gep,0);
306        gtk_entry_set_completion(uribar,gep);
307}
308
309static void save_uri_history(){
310        LinphoneCore *lc=linphone_gtk_get_core();
311        LpConfig *cfg=linphone_core_get_config(lc);
312        GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"));
313        char key[20];
314        int i=0;
315        char *uri=NULL;
316        GtkTreeIter iter;
317        GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(uribar));
318
319        if (!gtk_tree_model_get_iter_first(model,&iter)) return;
320        do {
321                gtk_tree_model_get(model,&iter,0,&uri,-1);
322                if (uri) {
323                        snprintf(key,sizeof(key),"uri%i",i);
324                        lp_config_set_string(cfg,"GtkUi",key,uri);
325                        g_free(uri);
326                }else break;
327                i++;
328                if (i>5) break;
329        }while(gtk_tree_model_iter_next(model,&iter));
330        lp_config_sync(cfg);
331}
332
333static void completion_add_text(GtkEntry *entry, const char *text){
334        GtkTreeIter iter;
335        GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(entry));
336       
337        if (gtk_tree_model_get_iter_first(model,&iter)){ 
338                do {
339                        gchar *uri=NULL;
340                        gtk_tree_model_get(model,&iter,0,&uri,-1);
341                        if (uri!=NULL){
342                                if (strcmp(uri,text)==0) {
343                                        /*remove text */
344                                        gtk_list_store_remove(GTK_LIST_STORE(model),&iter);
345                                        g_free(uri);
346                                        break;
347                                }
348                                g_free(uri);
349                        }
350                }while (gtk_tree_model_iter_next(model,&iter));
351        }
352        /* and prepend it on top of the list */
353        gtk_list_store_prepend(GTK_LIST_STORE(model),&iter);
354        gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,text,-1);
355        save_uri_history();
356}
357
358static void linphone_gtk_call_started(GtkWidget *mw){
359        gtk_widget_hide(linphone_gtk_get_widget(mw,"start_call"));
360        gtk_widget_show(linphone_gtk_get_widget(mw,"terminate_call"));
361}
362
363void linphone_gtk_start_call(GtkWidget *w){
364        LinphoneCore *lc=linphone_gtk_get_core();
365        if (linphone_core_inc_invite_pending(lc)){
366                /*already in call */
367        }else{
368                GtkWidget *uri_bar=linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"uribar");
369                const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar));
370                if (linphone_core_invite(lc,entered)==0) {
371                        linphone_gtk_call_started(linphone_gtk_get_main_window());
372                        completion_add_text(GTK_ENTRY(uri_bar),entered);
373                }
374        }
375}
376
377void linphone_gtk_uri_bar_activate(GtkWidget *w){
378        linphone_gtk_start_call(w);
379}
380
381
382static void linphone_gtk_call_terminated(GtkWidget *mw){
383        gtk_widget_hide(linphone_gtk_get_widget(mw,"terminate_call"));
384        gtk_widget_show(linphone_gtk_get_widget(mw,"start_call"));
385        g_object_set_data(G_OBJECT(mw),"incoming_call",NULL);
386}
387
388void linphone_gtk_terminate_call(GtkWidget *button){
389        linphone_core_terminate_call(linphone_gtk_get_core(),NULL);
390        linphone_gtk_call_terminated(gtk_widget_get_toplevel(button));
391}
392
393void linphone_gtk_decline_call(GtkWidget *button){
394        linphone_core_terminate_call(linphone_gtk_get_core(),NULL);
395        linphone_gtk_call_terminated(linphone_gtk_get_main_window());
396        gtk_widget_destroy(gtk_widget_get_toplevel(button));
397}
398
399void linphone_gtk_accept_call(GtkWidget *button){
400        linphone_core_accept_call(linphone_gtk_get_core(),NULL);
401        g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"incoming_call",NULL);
402        gtk_widget_destroy(gtk_widget_get_toplevel(button));
403        linphone_gtk_call_started(linphone_gtk_get_main_window());
404}
405
406void linphone_gtk_set_audio_video(){
407        linphone_core_enable_video(linphone_gtk_get_core(),TRUE,TRUE);
408        linphone_core_enable_video_preview(linphone_gtk_get_core(),TRUE);
409}
410
411void linphone_gtk_set_audio_only(){
412        linphone_core_enable_video(linphone_gtk_get_core(),FALSE,FALSE);
413        linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
414}
415
416void linphone_gtk_enable_self_view(GtkWidget *w){
417        linphone_core_enable_self_view(linphone_gtk_get_core(),
418                gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
419}
420
421void linphone_gtk_used_identity_changed(GtkWidget *w){
422        int active=gtk_combo_box_get_active(GTK_COMBO_BOX(w));
423        char *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w));
424        if (sel && strlen(sel)>0) //avoid a dummy "changed" at gui startup
425                linphone_core_set_default_proxy_index(linphone_gtk_get_core(),(active==0) ? -1 : (active-1));
426}
427
428static void linphone_gtk_show_main_window(){
429        GtkWidget *w=linphone_gtk_get_main_window();
430        LinphoneCore *lc=linphone_gtk_get_core();
431        linphone_core_enable_video_preview(lc,linphone_core_video_enabled(lc));
432        gtk_widget_show(w);
433        gtk_window_present(GTK_WINDOW(w));
434}
435
436static void linphone_gtk_show(LinphoneCore *lc){
437        linphone_gtk_show_main_window();
438}
439
440static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from){
441        GtkWidget *w=linphone_gtk_create_window("incoming_call");
442        GtkWidget *label;
443        gchar *msg;
444        gtk_window_set_transient_for(GTK_WINDOW(w),GTK_WINDOW(linphone_gtk_get_main_window()));
445        gtk_window_set_position(GTK_WINDOW(w),GTK_WIN_POS_CENTER_ON_PARENT);
446
447        label=linphone_gtk_get_widget(w,"message");
448        msg=g_strdup_printf(_("Incoming call from %s"),from);
449        gtk_label_set_text(GTK_LABEL(label),msg);
450        gtk_window_set_title(GTK_WINDOW(w),msg);
451        gtk_widget_show(w);
452        gtk_window_present(GTK_WINDOW(w));
453        /*gtk_window_set_urgency_hint(GTK_WINDOW(w),TRUE);*/
454        g_free(msg);
455        g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"incoming_call",w);
456        gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),
457                        from);
458}
459
460static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from){
461        GtkWidget *icw=GTK_WIDGET(g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"incoming_call"));
462        if (icw!=NULL){
463                gtk_widget_destroy(icw);
464        }
465        linphone_gtk_call_terminated(linphone_gtk_get_main_window());
466}
467
468static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid, const char *url, const char *status, const char *img){
469}
470
471static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint response_id, LinphoneFriend *lf){
472        switch(response_id){
473                case GTK_RESPONSE_YES:
474                        linphone_gtk_show_contact(lf);
475                break;
476                default:
477                        linphone_core_reject_subscriber(linphone_gtk_get_core(),lf);
478        }
479        gtk_widget_destroy(dialog);
480}
481
482static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
483        GtkWidget *dialog;
484        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);
485        dialog = gtk_message_dialog_new (
486                                GTK_WINDOW(linphone_gtk_get_main_window()),
487                                GTK_DIALOG_DESTROY_WITH_PARENT,
488                                GTK_MESSAGE_QUESTION,
489                                GTK_BUTTONS_YES_NO,
490                                "%s",
491                                message);
492        g_free(message);
493        g_signal_connect(G_OBJECT (dialog), "response",
494                G_CALLBACK (linphone_gtk_new_subscriber_response),lf);
495        /* actually show the box */
496        gtk_widget_show(dialog);
497}
498
499typedef struct _AuthTimeout{
500        GtkWidget *w;
501} AuthTimeout;
502
503
504static void auth_timeout_clean(AuthTimeout *tout){
505        tout->w=NULL;
506}
507
508static gboolean auth_timeout_destroy(AuthTimeout *tout){
509        if (tout->w)  {
510                g_object_weak_unref(G_OBJECT(tout->w),(GWeakNotify)auth_timeout_clean,tout);
511                gtk_widget_destroy(tout->w);
512        }
513        g_free(tout);
514        return FALSE;
515}
516
517static AuthTimeout * auth_timeout_new(GtkWidget *w){
518        AuthTimeout *tout=g_new(AuthTimeout,1);
519        tout->w=w;
520        /*so that the timeout no more references the widget when it is destroyed:*/
521        g_object_weak_ref(G_OBJECT(w),(GWeakNotify)auth_timeout_clean,tout);
522        /*so that the widget is automatically destroyed after some time */
523        g_timeout_add(30000,(GtkFunction)auth_timeout_destroy,tout);
524        return tout;
525}
526
527void linphone_gtk_password_cancel(GtkWidget *w){
528        LinphoneAuthInfo *info;
529        GtkWidget *window=gtk_widget_get_toplevel(w);
530        info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info");
531        linphone_core_abort_authentication(linphone_gtk_get_core(),info);
532        gtk_widget_destroy(window);
533}
534
535void linphone_gtk_password_ok(GtkWidget *w){
536        GtkWidget *entry;
537        GtkWidget *window=gtk_widget_get_toplevel(w);
538        LinphoneAuthInfo *info;
539        info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info");
540        g_object_weak_unref(G_OBJECT(window),(GWeakNotify)linphone_auth_info_destroy,info);
541        entry=linphone_gtk_get_widget(window,"password_entry");
542        linphone_auth_info_set_passwd(info,gtk_entry_get_text(GTK_ENTRY(entry)));
543        linphone_auth_info_set_username(info,
544                gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(window,"username_entry"))));
545        linphone_core_add_auth_info(linphone_gtk_get_core(),info);
546        gtk_widget_destroy(window);
547}
548
549static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username){
550        GtkWidget *w=linphone_gtk_create_window("password");
551        GtkWidget *label=linphone_gtk_get_widget(w,"message");
552        LinphoneAuthInfo *info;
553        gchar *msg;
554        msg=g_strdup_printf(_("Please enter your password for domain %s:"),realm);
555        gtk_label_set_text(GTK_LABEL(label),msg);
556        g_free(msg);
557        gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"username_entry")),username);
558        info=linphone_auth_info_new(username, NULL, NULL, NULL,realm);
559        g_object_set_data(G_OBJECT(w),"auth_info",info);
560        g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_auth_info_destroy,info);
561        gtk_widget_show(w);
562        auth_timeout_new(w);
563}
564
565static void linphone_gtk_display_status(LinphoneCore *lc, const char *status){
566        GtkWidget *w=linphone_gtk_get_main_window();
567        GtkWidget *status_bar=linphone_gtk_get_widget(w,"status_bar");
568        gtk_statusbar_push(GTK_STATUSBAR(status_bar),
569                        gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar),""),
570                        status);
571}
572
573static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg){
574        linphone_gtk_display_something(GTK_MESSAGE_INFO,msg);
575}
576
577static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning){
578        linphone_gtk_display_something(GTK_MESSAGE_WARNING,warning);
579}
580
581static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url){
582        char richtext[4096];
583        snprintf(richtext,sizeof(richtext),"%s %s",msg,url);
584        linphone_gtk_display_something(GTK_MESSAGE_INFO,richtext);
585}
586
587static void linphone_gtk_display_question(LinphoneCore *lc, const char *question){
588        linphone_gtk_display_something(GTK_MESSAGE_QUESTION,question);
589}
590
591static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl){
592        GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"call_logs");
593        if (w) linphone_gtk_call_log_update(w);
594}
595
596static void linphone_gtk_general_state(LinphoneCore *lc, LinphoneGeneralState *gstate){
597}
598
599const gchar *linphone_gtk_get_ui_config(const char *key, const char *def){
600        LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core());
601        return lp_config_get_string(cfg,"GtkUi",key,def);
602}
603
604int linphone_gtk_get_ui_config_int(const char *key, int def){
605        LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core());
606        return lp_config_get_int(cfg,"GtkUi",key,def);
607}
608
609static void icon_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data){
610        GtkWidget *menu=(GtkWidget*)g_object_get_data(G_OBJECT(status_icon),"menu");
611        gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time);
612}
613
614void linphone_gtk_open_browser(const char *url){
615#ifdef WIN32
616        ShellExecute(0,"open",url,NULL,NULL,1);
617#else
618        char cl[255];
619        snprintf(cl,sizeof(cl),"/usr/bin/x-www-browser %s",url);
620        g_spawn_command_line_async(cl,NULL);
621#endif
622}
623
624void linphone_gtk_link_to_website(GtkWidget *item){
625        const gchar *home=(const gchar*)g_object_get_data(G_OBJECT(item),"home");
626        linphone_gtk_open_browser(home);
627}
628
629static GtkWidget *create_icon_menu(){
630        GtkWidget *menu=gtk_menu_new();
631        GtkWidget *menu_item;
632        GtkWidget *image;
633        gchar *tmp;
634        const gchar *homesite;
635       
636        homesite=linphone_gtk_get_ui_config("home","http://www.linphone.org");
637        menu_item=gtk_image_menu_item_new_with_label(homesite);
638        tmp=g_strdup(homesite);
639        g_object_set_data(G_OBJECT(menu_item),"home",tmp);
640        g_object_weak_ref(G_OBJECT(menu_item),(GWeakNotify)g_free,tmp);
641       
642        image=gtk_image_new_from_stock(GTK_STOCK_HELP,GTK_ICON_SIZE_MENU);
643        gtk_widget_show(image);
644        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
645        //g_object_unref(G_OBJECT(image));
646        gtk_widget_show(menu_item);
647        gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
648        g_signal_connect(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_link_to_website,NULL);
649       
650        menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT,NULL);
651        gtk_widget_show(menu_item);
652        gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
653        g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_show_about,NULL);
654        menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,NULL);
655        gtk_widget_show(menu_item);
656        gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
657        g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)gtk_main_quit,NULL);
658        gtk_widget_show(menu);
659        return menu;
660}
661
662static GtkStatusIcon *icon=NULL;
663
664static void linphone_gtk_init_status_icon(){
665        const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
666        GdkPixbuf *pbuf=create_pixbuf(icon_path);
667        GtkWidget *menu=create_icon_menu();
668        const char *title;
669        icon=gtk_status_icon_new_from_pixbuf(pbuf);
670        g_object_unref(G_OBJECT(pbuf));
671        g_signal_connect_swapped(G_OBJECT(icon),"activate",(GCallback)linphone_gtk_show_main_window,linphone_gtk_get_main_window());
672        g_signal_connect(G_OBJECT(icon),"popup-menu",(GCallback)icon_popup_menu,NULL);
673        title=linphone_gtk_get_ui_config("title",_("Linphone - a video internet phone"));
674        gtk_status_icon_set_tooltip(icon,title);
675        g_object_set_data(G_OBJECT(icon),"menu",menu);
676        g_object_weak_ref(G_OBJECT(icon),(GWeakNotify)gtk_widget_destroy,menu);
677}
678
679void linphone_gtk_load_identities(void){
680        const MSList *elem;
681        GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities"));
682        char *def_identity;
683        LinphoneProxyConfig *def=NULL;
684        int def_index=0,i;
685        GtkListStore *store;
686
687        store=GTK_LIST_STORE(gtk_combo_box_get_model(box));
688        gtk_list_store_clear(store);
689
690        linphone_core_get_default_proxy(linphone_gtk_get_core(),&def);
691        def_identity=g_strdup_printf(_("%s (Default)"),linphone_core_get_primary_contact(linphone_gtk_get_core()));
692        gtk_combo_box_append_text(box,def_identity);
693        g_free(def_identity);
694        for(i=1,elem=linphone_core_get_proxy_config_list(linphone_gtk_get_core());
695                        elem!=NULL;
696                        elem=ms_list_next(elem),i++){
697                LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
698                gtk_combo_box_append_text(box,linphone_proxy_config_get_identity(cfg));
699                if (cfg==def) {
700                        def_index=i;
701                }
702        }
703        gtk_combo_box_set_active(box,def_index);
704}
705
706static void linphone_gtk_dtmf_clicked(GtkButton *button){
707        const char *label=gtk_button_get_label(button);
708        linphone_core_send_dtmf(linphone_gtk_get_core(),label[0]);
709}
710
711static void linphone_gtk_connect_digits(void){
712        GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"dtmf_table"));
713        GList *children=gtk_container_get_children(cont);
714        GList *elem;
715        for(elem=children;elem!=NULL;elem=elem->next){
716                GtkButton *button=GTK_BUTTON(elem->data);
717                g_signal_connect(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_dtmf_clicked,NULL);
718        }
719}
720
721static void linphone_gtk_check_menu_items(void){
722        bool_t audio_only=!linphone_core_video_enabled(linphone_gtk_get_core());
723        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(linphone_gtk_get_widget(
724                                        linphone_gtk_get_main_window(),
725                                        audio_only ? "audio_only_item" : "video_item")), TRUE);
726}
727
728static void linphone_gtk_configure_main_window(){
729        static gboolean config_loaded=FALSE;
730        static gboolean show_digits=1;
731        static gboolean show_identities=1;
732        static const char *title;
733        static const char *home;
734        static const char *icon_path;
735        GtkWidget *w=linphone_gtk_get_main_window();
736        if (!config_loaded){
737                show_digits=linphone_gtk_get_ui_config_int("show_digits",1);
738                show_identities=linphone_gtk_get_ui_config_int("identity_frame",1);
739                title=linphone_gtk_get_ui_config("title",NULL);
740                home=linphone_gtk_get_ui_config("home","http://www.linphone.org");
741                icon_path=linphone_gtk_get_ui_config("icon",NULL);
742                config_loaded=TRUE;
743        }
744        if (show_digits==FALSE) gtk_widget_hide(linphone_gtk_get_widget(w,"dialpad"));
745        if (show_identities==FALSE) gtk_widget_hide(linphone_gtk_get_widget(w,"identity_frame"));
746        if (title) gtk_window_set_title(GTK_WINDOW(w),title);
747        if (icon_path) {
748                GdkPixbuf *pbuf=create_pixbuf(icon_path);
749                gtk_window_set_icon(GTK_WINDOW(w),pbuf);
750                g_object_unref(G_OBJECT(pbuf));
751        }
752        if (home){
753                gchar *tmp;
754                GtkWidget *menu_item=linphone_gtk_get_widget(w,"home_item");
755                tmp=g_strdup(home);
756                g_object_set_data(G_OBJECT(menu_item),"home",tmp);
757        }
758}
759
760static void linphone_gtk_init_main_window(){
761        linphone_gtk_configure_main_window();
762        load_uri_history();
763        linphone_gtk_load_identities();
764        linphone_gtk_set_my_presence(linphone_core_get_presence_info(linphone_gtk_get_core()));
765        linphone_gtk_show_friends();
766        linphone_gtk_connect_digits();
767        linphone_gtk_check_menu_items();
768        if (linphone_core_in_call(linphone_gtk_get_core())) linphone_gtk_call_started(
769                linphone_gtk_get_main_window());/*hide the call button, show terminate button*/
770}
771
772void linphone_gtk_close(){
773        /* couldn't find a way to prevent closing to destroy the main window*/
774        LinphoneCore *lc=linphone_gtk_get_core();
775        the_ui=NULL;
776        the_ui=linphone_gtk_create_window("main");
777        linphone_gtk_init_main_window();
778        /*shutdown call if any*/
779        if (linphone_core_in_call(lc)){
780                linphone_core_terminate_call(lc,NULL);
781                linphone_gtk_call_terminated(the_ui);
782        }
783        linphone_core_enable_video_preview(lc,FALSE);
784}
785
786void linphone_gtk_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
787        if (verbose){
788                const char *lname="undef";
789                char *msg;
790                #ifdef __linux
791                va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/
792                #endif
793                switch(lev){
794                        case ORTP_DEBUG:
795                                lname="debug";
796                                break;
797                        case ORTP_MESSAGE:
798                                lname="message";
799                                break;
800                        case ORTP_WARNING:
801                                lname="warning";
802                                break;
803                        case ORTP_ERROR:
804                                lname="error";
805                                break;
806                        case ORTP_FATAL:
807                                lname="fatal";
808                                break;
809                        default:
810                                g_error("Bad level !");
811                }
812#ifdef __linux
813                va_copy(cap,args);
814                msg=g_strdup_vprintf(fmt,cap);
815                va_end(cap);
816#else
817                msg=g_strdup_vprintf(fmt,args);
818#endif
819                fprintf(stdout,"linphone-%s : %s\n",lname,msg);
820                ortp_free(msg);
821        }
822        linphone_gtk_log_push(lev,fmt,args);
823}
824
825int main(int argc, char *argv[]){
826        void *p;
827        const char *config_file;
828        g_thread_init(NULL);
829        gdk_threads_init();
830#ifdef ENABLE_NLS
831        p=bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
832        if (p==NULL) perror("bindtextdomain failed");
833        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
834        textdomain (GETTEXT_PACKAGE);
835#else
836        g_message("NLS disabled.\n");
837#endif
838        config_file=linphone_gtk_get_config_file();
839        if (linphone_core_wake_up_possible_already_running_instance(config_file)==0){
840                g_warning("Another running instance of linphone has been detected. It has been woken-up.");
841                g_warning("This instance is going to exit now.");
842                return 0;
843        }
844       
845#ifdef WIN32
846        gtk_rc_add_default_file("./gtkrc");
847#endif
848        gdk_threads_enter();
849        if (!gtk_init_with_args(&argc,&argv,_("A free SIP video-phone"),
850                                linphone_options,NULL,NULL)){
851                gdk_threads_leave();
852                return -1;
853        }
854       
855        add_pixmap_directory("pixmaps");
856        add_pixmap_directory(PACKAGE_DATA_DIR "/pixmaps/linphone");
857#ifdef WIN32
858        add_pixmap_directory("linphone");
859#endif
860
861        the_ui=linphone_gtk_create_window("main");
862       
863        linphone_gtk_create_log_window();
864        linphone_core_enable_logs_with_cb(linphone_gtk_log_handler);
865
866        linphone_gtk_init_liblinphone(config_file);
867        gtk_timeout_add(20,(GtkFunction)linphone_gtk_iterate,(gpointer)linphone_gtk_get_core());
868        gtk_timeout_add(20,(GtkFunction)linphone_gtk_check_logs,(gpointer)NULL);
869        linphone_gtk_init_main_window();
870        linphone_gtk_init_status_icon();
871        linphone_gtk_show_main_window();
872        linphone_gtk_check_for_new_version();
873        gtk_main();
874        gdk_threads_leave();
875        linphone_gtk_destroy_log_window();
876        linphone_core_destroy(the_core);
877        /*workaround a bug on win32 that makes status icon still present in the systray even after program exit.*/
878        gtk_status_icon_set_visible(icon,FALSE);
879        return 0;
880}
881
882
Note: See TracBrowser for help on using the repository browser.