diff --git a/Makefile.am b/Makefile.am index a1cd5594e..15cf2a90d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,6 +53,7 @@ EXTRA_DIST = config.rpath BUGS linphone.kdevelop \ README.mingw \ README.macos \ autogen.sh \ + linphone.spec \ linphone.spec.in \ $(GTK_FILELIST) \ gen-gtkfilelist.sh \ @@ -69,20 +70,24 @@ all-local: linphone.spec linphone.iss linphone.spec: linphone.spec.in -.phony: rpm -rpm: +.phony: rpm rpm-novideo rpm-base +rpm-base: $(MAKE) dist - cd oRTP && $(MAKE) dist && mv -f ortp*.tar.gz ../ - cd mediastreamer2 && $(MAKE) dist && mv -f mediastreamer*.tar.gz ../ -# Create "Specfile" at the same level as the tarball content -rm -f $(PACKAGE)-$(VERSION).tar gunzip $(PACKAGE)-$(VERSION).tar.gz - cp $(PACKAGE).spec Specfile - tar --append --file=$(PACKAGE)-$(VERSION).tar Specfile +#remove ms2 and ortp spec file to make sure linphone spec file is used bu rpmbuild + tar --delete --file=$(PACKAGE)-$(VERSION).tar $(PACKAGE)-$(VERSION)/mediastreamer2/mediastreamer2.spec + tar --delete --file=$(PACKAGE)-$(VERSION).tar $(PACKAGE)-$(VERSION)/oRTP/ortp.spec gzip $(PACKAGE)-$(VERSION).tar + +rpm: rpm-base # TAR_OPTIONS=--wildcards rpmbuild -ta --clean --rmsource --rmspec $(PACKAGE)-$(VERSION).tar.gz +rpm-novideo: rpm-base +# + TAR_OPTIONS=--wildcards rpmbuild -ta --clean --rmsource --rmspec $(PACKAGE)-$(VERSION).tar.gz --without video + #a zip containing win32 binaries, suitable to generate an installer if BUILD_ZRTP diff --git a/NEWS b/NEWS index d7c8f5559..a4b134ddf 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ -linphone-3.5.0 -- future date +linphone-3.5.1 -- ?? + * gtk - implement friend search by typing into the friendlist, and friend sorting + +linphone-3.5.0 -- December 22, 2011 * added VP-8 video codec + * added G722 audio codec + * added SIP/TCP and SIP/TLS + * added SRTP media encryption + * Audio conferencing * UI: call history tab, menu simplified * UI: cosmetics for incall views * UI: integration with libnotify diff --git a/README.macos b/README.macos index 98b5b9fb6..d8c071590 100644 --- a/README.macos +++ b/README.macos @@ -15,26 +15,18 @@ You need: $ port install libosip2 $ port install libeXosip2 $ port install ffmpeg-devel - -- Install SDL (for video display) -Unfortunately the current (august 2011) version of sdl in macports crashes all the time. Fortunately these bugs are fixed in the development branch of SDL. -So we recommend to download SDL 1.3 with mercurial (hg) and compile it by yourself, like this: -First, make sure you have mercurial: - $ sudo port install mercurial -Fetch SDL: - $ hg clone http://hg.libsdl.org/SDL -Compile: - $ cd SDL - $ ./autogen.sh - $ ./configure --prefix=/opt/local && make -j4 + +- Install srtp (optional) for call encryption + $ port install srtp + If that fails, get from source: + $ git clone git://git.linphone.org/srtp.git + $ cd srtp && autoconf && ./configure --prefix=/opt/local && make libsrtp.a $ sudo make install When this version will be integrated into macports, only this will be necessary: $ port install libsdl-devel - Install gtk. It is recommended to use the quartz backend for better integration. - $ port install cairo +quartz +no_x11 - $ port install pango +quartz +no_x11 $ port install gtk2 +quartz +no_x11 $ port install ige-mac-integration $ port install hicolor-icon-theme @@ -45,7 +37,7 @@ If you got the source code from git, run ./autogen.sh first. Then or otherwise, do: - $ ./configure --prefix=/opt/local --with-readline=/opt/local --disable-strict --disable-x11 && make + $ ./configure --prefix=/opt/local --with-readline=/opt/local --disable-strict --disable-x11 --with-srtp=/opt/local && make Install to /opt/local @@ -58,6 +50,8 @@ Use git: $ git clone https://github.com/jralls/gtk-mac-bundler.git $ cd gtk-mac-bundler && make install $ export PATH=$PATH:~/.local/bin + #make this dummy charset.alias file for the bundler to be happy: + $ sudo touch touch /opt/local/lib/charset.alias Then run, inside linphone source tree: 1. Run configure as told before but with "--enable-relativeprefix" appended. diff --git a/README.mingw b/README.mingw index 0c84e250e..91fe0f9be 100644 --- a/README.mingw +++ b/README.mingw @@ -48,11 +48,8 @@ rm /include/stdint.h /include/inttypes.h #Remove libgcc specific libraries, only needed for MSVC: rm /lib/libgcc.a /lib/libmingw32.a /lib/libmingwex.a -#Remove libintl from gtk, we don't need it and it conflicts with the one supplied by mingw. -rm /lib/libintl.dll.a -rm /lib/libintl.la -rm /lib/libintl.a -rm /include/libintl.h +#To get the translations working, remove from C:/MinGW/lib : +libintl.a libintl.la libintl.dll.a * Download and install Inno Setup Compiler (required only if you run 'make setup.exe'). Add it to your windows Path environment variable. diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 659a9f78e..fdcaefdcf 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -74,8 +74,8 @@ endif AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \ $(ORTP_CFLAGS) \ - $(OSIP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ + $(OSIP_CFLAGS) \ $(EXOSIP_CFLAGS) \ -DENABLE_TRACE \ -DLOG_DOMAIN=\"LinphoneCore\" \ diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 7b79a78d6..a2dfffee3 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -374,7 +374,7 @@ static void call_accepted(SalOp *op){ }else{ /*send a bye*/ ms_error("Incompatible SDP offer received in 200Ok, need to abort the call"); - linphone_core_abort_call(lc,call,"No codec intersection"); + linphone_core_abort_call(lc,call,_("Incompatible, check codecs...")); } } @@ -523,7 +523,6 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de lc->vtable.display_status(lc,msg480); break; case SalReasonNotFound: - msg=_("Not found"); if (lc->vtable.display_status) lc->vtable.display_status(lc,msg); break; @@ -563,10 +562,14 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de lc->ringstream=NULL; } linphone_call_stop_media_streams (call); - if (sr!=SalReasonDeclined) linphone_call_set_state(call,LinphoneCallError,msg); - else{ + if (sr == SalReasonDeclined) { call->reason=LinphoneReasonDeclined; linphone_call_set_state(call,LinphoneCallEnd,"Call declined."); + } else if (sr == SalReasonNotFound) { + call->reason=LinphoneReasonNotFound; + linphone_call_set_state(call,LinphoneCallError,"User not found."); + } else { + linphone_call_set_state(call,LinphoneCallError,msg); } } @@ -623,12 +626,11 @@ static void register_success(SalOp *op, bool_t registered){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); char *msg; - cfg->registered=registered; linphone_proxy_config_set_error(cfg,LinphoneReasonNone); linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared , registered ? "Registration sucessful" : "Unregistration done"); if (lc->vtable.display_status){ - if (cfg->registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op)); + if (registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op)); else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op)); lc->vtable.display_status(lc,msg); ms_free(msg); diff --git a/coreapi/conference.c b/coreapi/conference.c index aafed5d60..d4abc1a91 100644 --- a/coreapi/conference.c +++ b/coreapi/conference.c @@ -298,5 +298,8 @@ int linphone_core_terminate_conference(LinphoneCore *lc) { } int linphone_core_get_conference_size(LinphoneCore *lc) { + if (lc->conf_ctx.conf == NULL) { + return 0; + } return ms_audio_conference_get_size(lc->conf_ctx.conf); } diff --git a/coreapi/help/doxygen.dox b/coreapi/help/doxygen.dox index 0ddb4e76f..d1ec25b9c 100644 --- a/coreapi/help/doxygen.dox +++ b/coreapi/help/doxygen.dox @@ -316,6 +316,38 @@ void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReach linphone_core_set_ringer_device(lc, "AQ: Audio Queue Device"); linphone_core_set_capture_device(lc, "AU: Audio Unit Receiver"); \endcode + GSM call interaction +
To ensure gentle interaction with GSM calls, it is recommended to register an AudioSession delegate. This allows the application to be notified when its audio session is interrupted/resumed (presumably by a GSM call). +\code + // declare a class handling the AVAudioSessionDelegate protocol + @interface MyClass : NSObject { [...] } + // implement 2 methods : here's an example implementation + -(void) beginInterruption { + LinphoneCall* c = linphone_core_get_current_call(theLinphoneCore); + ms_message("Sound interruption detected!"); + if (c) { + linphone_core_pause_call(theLinphoneCore, c); + } + } + + -(void) endInterruption { + ms_message("Sound interruption ended!"); + const MSList* c = linphone_core_get_calls(theLinphoneCore); + + if (c) { + ms_message("Auto resuming call"); + linphone_core_resume_call(theLinphoneCore, (LinphoneCall*) c->data); + } + } +\endcode +@see http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVAudioSessionDelegate_ProtocolReference/Reference/Reference.html + +
Declare an instance of your class as AudioSession's delegate : +\code + [audioSession setDelegate:myClassInstance]; +\endcode +@see http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVAudioSession_ClassReference/Reference/Reference.html + Video
Since 3.5 video support has been added to liblinphone for IOS. It requires the application to provide liblinphone with pointers to IOS's views hosting video display and video previous.
These 2 UIView objects must be passed to the core using functions #linphone_core_set_native_video_window_id() and #linphone_core_set_native_preview_window_id(). here under speudo code: diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 30f599762..33c168522 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -4164,7 +4164,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data; if (linphone_proxy_config_register_enabled(cfg) ) { if (!isReachable) { - cfg->registered=0; + linphone_proxy_config_set_state(cfg, LinphoneRegistrationNone,"Registration impossible (network down)"); }else{ cfg->commit=TRUE; } @@ -4365,6 +4365,8 @@ const char *linphone_reason_to_string(LinphoneReason err){ return "Bad credentials"; case LinphoneReasonDeclined: return "Call declined"; + case LinphoneReasonNotFound: + return "User not found"; } return "unknown error"; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index b9cd9cae5..14c850de8 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -202,6 +202,7 @@ enum _LinphoneReason{ LinphoneReasonNoResponse, /**audio_port); - if (sock1<0) return; + if (sock1==-1) return; if (video_enabled){ sock2=create_socket(call->video_port); - if (sock2<0) return ; - } - sendStunRequest(sock1,(struct sockaddr*)&ss,ss_len,11,TRUE); - sendStunRequest(sock1,(struct sockaddr*)&ss,ss_len,1,FALSE); - if (sock2>=0){ - sendStunRequest(sock2,(struct sockaddr*)&ss,ss_len,22,TRUE); - sendStunRequest(sock2,(struct sockaddr*)&ss,ss_len,2,FALSE); + if (sock2==-1) return ; } got_audio=FALSE; got_video=FALSE; @@ -496,6 +491,15 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ do{ double elapsed; int id; + if (loops%20==0){ + ms_message("Sending stun requests..."); + sendStunRequest(sock1,(struct sockaddr*)&ss,ss_len,11,TRUE); + sendStunRequest(sock1,(struct sockaddr*)&ss,ss_len,1,FALSE); + if (sock2!=-1){ + sendStunRequest(sock2,(struct sockaddr*)&ss,ss_len,22,TRUE); + sendStunRequest(sock2,(struct sockaddr*)&ss,ss_len,2,FALSE); + } + } #ifdef WIN32 Sleep(10); #else @@ -522,29 +526,25 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ } gettimeofday(&cur,NULL); elapsed=((cur.tv_sec-init.tv_sec)*1000.0) + ((cur.tv_usec-init.tv_usec)/1000.0); - if (elapsed>2000) break; - }while(!(got_audio && (got_video||sock2<0) ) ); + if (elapsed>2000) { + ms_message("Stun responses timeout, going ahead."); + break; + } + loops++; + }while(!(got_audio && (got_video||sock2==-1) ) ); if (!got_audio){ ms_error("No stun server response for audio port."); }else{ if (!cone_audio) { - ms_warning("NAT is symmetric for audio port"); - /* - ac->addr[0]='\0'; - ac->port=0; - */ + ms_message("NAT is symmetric for audio port"); } } - if (sock2>=0){ + if (sock2!=-1){ if (!got_video){ ms_error("No stun server response for video port."); }else{ if (!cone_video) { - ms_warning("NAT is symmetric for video port."); - /* - vc->addr[0]='\0'; - vc->port=0; - */ + ms_message("NAT is symmetric for video port."); } } } @@ -553,7 +553,7 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ strcpy(call->localdesc->addr,ac->addr); } close_socket(sock1); - if (sock2>=0) close_socket(sock2); + if (sock2!=-1) close_socket(sock2); } } diff --git a/coreapi/private.h b/coreapi/private.h index a21fc8b20..77f62c334 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -255,7 +255,6 @@ struct _LinphoneProxyConfig SalOp *publish_op; bool_t commit; bool_t reg_sendregister; - bool_t registered; bool_t publish; bool_t dial_escape_plus; void* user_data; diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 011be6706..959c321b6 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -84,7 +84,7 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ * Returns a boolean indicating that the user is sucessfully registered on the proxy. **/ bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj){ - return obj->registered; + return obj->state == LinphoneRegistrationOk; } /** @@ -232,9 +232,8 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){ void linphone_proxy_config_edit(LinphoneProxyConfig *obj){ if (obj->reg_sendregister){ /* unregister */ - if (obj->registered) { + if (obj->state != LinphoneRegistrationNone && obj->state != LinphoneRegistrationCleared) { sal_unregister(obj->op); - obj->registered=FALSE; } } } @@ -301,7 +300,7 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ **/ void linphone_proxy_config_refresh_register(LinphoneProxyConfig *obj){ if (obj->reg_sendregister && obj->op){ - obj->registered=FALSE; + linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress, "Refresh registration"); sal_register_refresh(obj->op,obj->expires); } } diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index 533fa860a..7a2f3e051 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -374,17 +374,14 @@ int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int i memset(&tlsCtx, 0, sizeof(tlsCtx)); snprintf(tlsCtx.root_ca_cert, sizeof(tlsCtx.client.cert), "%s", ctx->rootCa); eXosip_set_tls_ctx(&tlsCtx); - } + } +#ifdef HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE eXosip_tls_verify_certificate(ctx->verify_server_certs); +#endif break; default: ms_warning("unexpected proto, using datagram"); } -#if 0 - /* it does not work, exosip does not implement this option correctly*/ - err=0; - eXosip_set_option(EXOSIP_OPT_DNS_CAPABILITIES,&err); /*0=no NAPTR */ -#endif /*see if it looks like an IPv6 address*/ int use_rports = ctx->use_rports; // Copy char to int to avoid bad alignment eXosip_set_option(EXOSIP_OPT_USE_RPORT,&use_rports); @@ -399,10 +396,6 @@ int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int i return -1; } err=eXosip_listen_addr(proto, addr, port, ipv6 ? PF_INET6 : PF_INET, is_secure); -#ifdef HAVE_EXOSIP_GET_SOCKET - ms_message("Exosip has socket number %i",eXosip_get_socket(proto)); -#endif - ctx->running=TRUE; return err; } @@ -451,7 +444,9 @@ void sal_set_root_ca(Sal* ctx, const char* rootCa) { void sal_verify_server_certificates(Sal *ctx, bool_t verify){ ctx->verify_server_certs=verify; +#ifdef HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE eXosip_tls_verify_certificate(verify); +#endif } static int extract_received_rport(osip_message_t *msg, const char **received, int *rportval,SalTransport* transport){ diff --git a/gtk/friendlist.c b/gtk/friendlist.c index 9dacac717..d5a056fef 100644 --- a/gtk/friendlist.c +++ b/gtk/friendlist.c @@ -239,6 +239,119 @@ static void linphone_gtk_init_bookmark_icon(void){ g_signal_connect(G_OBJECT(GTK_EDITABLE(entry)),"changed",(GCallback)check_contact,linphone_gtk_get_core()); } +static gboolean friend_search_func(GtkTreeModel *model, gint column, + const gchar *key, + GtkTreeIter *iter, + gpointer search_data){ + char *name=NULL; + gboolean ret=TRUE; + gtk_tree_model_get(model,iter,FRIEND_NAME,&name,-1); + if (name!=NULL){ + ret=strstr(name,key)==NULL; + g_free(name); + } + return ret; +} + +static gint friend_sort(GtkTreeModel *model, GtkTreeIter *a,GtkTreeIter *b,gpointer user_data){ + char *n1=NULL,*n2=NULL; + int ret; + gtk_tree_model_get(model,a,FRIEND_NAME,&n1,-1); + gtk_tree_model_get(model,b,FRIEND_NAME,&n2,-1); + if (n1 && n2) { + ret=strcmp(n1,n2); + g_free(n1); + g_free(n2); + }else if (n1){ + g_free(n1); + ret=-1; + }else if (n2){ + g_free(n2); + ret=1; + }else ret=0; + return ret; +} + +static void on_name_column_clicked(GtkTreeModel *model){ + GtkSortType st; + gint column; + + gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model),&column,&st); + if (column==FRIEND_NAME){ + if (st==GTK_SORT_ASCENDING) st=GTK_SORT_DESCENDING; + else st=GTK_SORT_ASCENDING; + }else st=GTK_SORT_ASCENDING; + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),FRIEND_NAME,st); +} + + +static int get_friend_weight(const LinphoneFriend *lf){ + int w=0; + switch(linphone_friend_get_status(lf)){ + case LinphoneStatusOnline: + w+=1000; + break; + case LinphoneStatusOffline: + if (linphone_friend_get_send_subscribe(lf)) + w+=100; + break; + default: + w+=500; + break; + } + return w; +} + +static int friend_compare_func(const LinphoneFriend *lf1, const LinphoneFriend *lf2){ + int w1,w2; + w1=get_friend_weight(lf1); + w2=get_friend_weight(lf2); + if (w1==w2){ + const char *u1,*u2; + const LinphoneAddress *addr1,*addr2; + addr1=linphone_friend_get_address(lf1); + addr2=linphone_friend_get_address(lf2); + u1=linphone_address_get_username(addr1); + u2=linphone_address_get_username(addr2); + if (u1 && u2) return strcasecmp(u1,u2); + if (u1) return 1; + else return -1; + } + return w2-w1; +} + +static gint friend_sort_with_presence(GtkTreeModel *model, GtkTreeIter *a,GtkTreeIter *b,gpointer user_data){ + LinphoneFriend *lf1=NULL,*lf2=NULL; + gtk_tree_model_get(model,a,FRIEND_ID,&lf1,-1); + gtk_tree_model_get(model,b,FRIEND_ID,&lf2,-1); + return friend_compare_func(lf1,lf2); +} + + +static MSList *sort_friend_list(const MSList *friends){ + MSList *ret=NULL; + const MSList *elem; + LinphoneFriend *lf; + + for(elem=friends;elem!=NULL;elem=elem->next){ + lf=(LinphoneFriend*)elem->data; + ret=ms_list_insert_sorted(ret,lf,(MSCompareFunc)friend_compare_func); + } + return ret; +} + +static void on_presence_column_clicked(GtkTreeModel *model){ + GtkSortType st; + gint column; + + gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model),&column,&st); + if (column==FRIEND_ID){ + if (st==GTK_SORT_ASCENDING) st=GTK_SORT_DESCENDING; + else st=GTK_SORT_ASCENDING; + }else st=GTK_SORT_ASCENDING; + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),FRIEND_ID,st); +} + static void linphone_gtk_friend_list_init(GtkWidget *friendlist) { GtkListStore *store; @@ -254,12 +367,21 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist) gtk_tree_view_set_model(GTK_TREE_VIEW(friendlist),GTK_TREE_MODEL(store)); g_object_unref(G_OBJECT(store)); + gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(friendlist),friend_search_func,NULL,NULL); + gtk_tree_view_set_search_column(GTK_TREE_VIEW(friendlist),FRIEND_NAME); + + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_NAME,friend_sort,NULL,NULL); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_ID,friend_sort_with_presence,NULL,NULL); + renderer = gtk_cell_renderer_pixbuf_new (); column = gtk_tree_view_column_new_with_attributes (_("Name"), renderer, "pixbuf", FRIEND_ICON, NULL); g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); + g_signal_connect_swapped(G_OBJECT(column),"clicked",(GCallback)on_name_column_clicked,GTK_TREE_MODEL(store)); + gtk_tree_view_column_set_clickable(column,TRUE); + renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start(column,renderer,FALSE); gtk_tree_view_column_add_attribute (column,renderer, @@ -273,6 +395,8 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist) "text", FRIEND_PRESENCE_STATUS, NULL); g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); + g_signal_connect_swapped(G_OBJECT(column),"clicked",(GCallback)on_presence_column_clicked,GTK_TREE_MODEL(store)); + gtk_tree_view_column_set_clickable(column,TRUE); gtk_tree_view_column_set_visible(column,linphone_gtk_get_ui_config_int("friendlist_status",1)); renderer = gtk_cell_renderer_pixbuf_new(); @@ -344,52 +468,6 @@ void linphone_gtk_directory_search_button_clicked(GtkWidget *button){ linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"directory_search_entry")); } -static int get_friend_weight(const LinphoneFriend *lf){ - int w=0; - switch(linphone_friend_get_status(lf)){ - case LinphoneStatusOnline: - w+=1000; - break; - case LinphoneStatusOffline: - if (linphone_friend_get_send_subscribe(lf)) - w+=100; - break; - default: - w+=500; - break; - } - return w; -} - -static int friend_compare_func(const LinphoneFriend *lf1, const LinphoneFriend *lf2){ - int w1,w2; - w1=get_friend_weight(lf1); - w2=get_friend_weight(lf2); - if (w1==w2){ - const char *u1,*u2; - const LinphoneAddress *addr1,*addr2; - addr1=linphone_friend_get_address(lf1); - addr2=linphone_friend_get_address(lf2); - u1=linphone_address_get_username(addr1); - u2=linphone_address_get_username(addr2); - if (u1 && u2) return strcasecmp(u1,u2); - if (u1) return 1; - else return -1; - } - return w2-w1; -} - -static MSList *sort_friend_list(const MSList *friends){ - MSList *ret=NULL; - const MSList *elem; - LinphoneFriend *lf; - - for(elem=friends;elem!=NULL;elem=elem->next){ - lf=(LinphoneFriend*)elem->data; - ret=ms_list_insert_sorted(ret,lf,(MSCompareFunc)friend_compare_func); - } - return ret; -} void linphone_gtk_show_friends(void){ GtkWidget *mw=linphone_gtk_get_main_window(); diff --git a/gtk/incall_view.c b/gtk/incall_view.c index 75060da9a..5674d5544 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -94,6 +94,7 @@ static void linphone_gtk_in_call_set_animation_image(GtkWidget *callview, const } static void linphone_gtk_in_call_set_animation_spinner(GtkWidget *callview){ +#if GTK_CHECK_VERSION(2,20,0) GtkWidget *container=linphone_gtk_get_widget(callview,"in_call_animation"); GList *elem=gtk_container_get_children(GTK_CONTAINER(container)); GtkWidget *spinner=gtk_spinner_new(); @@ -103,6 +104,7 @@ static void linphone_gtk_in_call_set_animation_spinner(GtkWidget *callview){ gtk_container_add(GTK_CONTAINER(container),spinner); gtk_widget_set_size_request(spinner, 20,20); gtk_spinner_start(GTK_SPINNER(spinner)); +#endif } diff --git a/gtk/main.c b/gtk/main.c index 73e99cc96..88f2807fd 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1208,7 +1208,9 @@ static void linphone_gtk_init_status_icon(){ const char *title; title=linphone_gtk_get_ui_config("title",_("Linphone - a video internet phone")); icon=gtk_status_icon_new_from_pixbuf(pbuf); +#if GTK_CHECK_VERSION(2,20,0) gtk_status_icon_set_name(icon,title); +#endif g_signal_connect_swapped(G_OBJECT(icon),"activate",(GCallback)handle_icon_click,NULL); g_signal_connect(G_OBJECT(icon),"popup-menu",(GCallback)icon_popup_menu,NULL); gtk_status_icon_set_tooltip(icon,title); @@ -1583,14 +1585,19 @@ static void linphone_gtk_check_soundcards(){ } static void linphone_gtk_quit(void){ - linphone_gtk_uninit_instance(); - linphone_gtk_destroy_log_window(); - linphone_core_destroy(the_core); - linphone_gtk_log_uninit(); + static gboolean quit_done=FALSE; + if (!quit_done){ + quit_done=TRUE; + g_source_remove_by_user_data(linphone_gtk_get_core()); + linphone_gtk_uninit_instance(); + linphone_gtk_destroy_log_window(); + linphone_core_destroy(the_core); + linphone_gtk_log_uninit(); #ifdef HAVE_NOTIFY - notify_uninit(); + notify_uninit(); #endif - gdk_threads_leave(); + gdk_threads_leave(); + } } #ifdef HAVE_GTK_OSX diff --git a/gtk/main.ui b/gtk/main.ui index 2cfe555e7..fde3a794a 100644 --- a/gtk/main.ui +++ b/gtk/main.ui @@ -1,7 +1,6 @@ - - + False @@ -652,8 +651,6 @@ False False - True - True @@ -745,8 +742,6 @@ True False False - True - True @@ -808,10 +803,15 @@ True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + 0 + + + @@ -837,8 +837,6 @@ True False False - True - True @@ -1037,6 +1035,9 @@ False + + + @@ -1540,8 +1541,6 @@ False False - True - True 1 @@ -1556,8 +1555,6 @@ False False - True - True 1 diff --git a/gtk/parameters.ui b/gtk/parameters.ui index 2403b3316..153b5bdde 100644 --- a/gtk/parameters.ui +++ b/gtk/parameters.ui @@ -1,6 +1,6 @@ - + 500 diff --git a/gtk/propertybox.c b/gtk/propertybox.c index 30890c765..c45f34e31 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -989,7 +989,7 @@ void linphone_gtk_show_parameters(void){ g_signal_connect(G_OBJECT(linphone_gtk_get_widget(pb,"proto_combo")),"changed",(GCallback)linphone_gtk_proto_changed,NULL); - if (linphone_core_tunnel_available(lc)){ + if (linphone_core_tunnel_available()){ gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_edit_button")), TRUE); gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_label")), TRUE); } diff --git a/java/common/org/linphone/core/LinphoneCall.java b/java/common/org/linphone/core/LinphoneCall.java index 3d1c9696f..d0f97130d 100644 --- a/java/common/org/linphone/core/LinphoneCall.java +++ b/java/common/org/linphone/core/LinphoneCall.java @@ -240,4 +240,6 @@ public interface LinphoneCall { void setAuthenticationTokenVerified(boolean verified); boolean isInConference(); + + float getPlayVolume(); } diff --git a/linphone.spec.in b/linphone.spec.in index e4a7c3075..171cb5e39 100644 --- a/linphone.spec.in +++ b/linphone.spec.in @@ -23,10 +23,9 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildArch: i686 %endif -BuildRequires: gnome-panel-devel libgnomeui-devel glib2-devel alsa-lib-devel -BuildRequires: libosip2-devel speex-devel gettext desktop-file-utils -BuildRequires: readline-devel ncurses-devel -BuildRequires: intltool gettext-devel +BuildRequires: gtk2-devel +BuildRequires: libeXosip2-devel speex-devel gettext +BuildRequires: intltool gettext-devel %if %{video} BuildRequires: ffmpeg-devel SDL-devel %endif @@ -40,58 +39,12 @@ Summary: Development libraries for linphone Group: Development/Libraries Requires: %{name} = %{version}-%{release} Requires: ortp-devel = @ORTP_VERSION@ +Requires: mediastreamer2-devel = @MS2_VERSION@ Requires: glib2-devel %description devel Libraries and headers required to develop software with linphone. -%package -n ortp -Summary: A C library implementing the RTP protocol (rfc1889) -Group: System Environment/Libraries -Version: @ORTP_VERSION@ - -%description -n ortp -oRTP is a LGPL licensed C library implementing the RTP protocol (rfc1889). It -is available for most *nix clones (primilarly Linux and HP-UX), and Win32. - -%package -n ortp-devel -Summary: Development libraries for ortp -Group: Development/Libraries -Version: @ORTP_VERSION@ -Requires: ortp = @ORTP_VERSION@ - -%description -n ortp-devel -oRTP is a LGPL licensed C library implementing the RTP protocol (rfc1889). It -is available for most *nix clones (primilarly Linux and HP-UX), and Win32. - -This package contains header files and development libraries needed to -develop programs using the oRTP library. - -%package -n mediastreamer2 -Summary: Audio/Video real-time streaming -Group: Development/Libraries -Version: @MS2_VERSION@ - -%description -n mediastreamer2 -Mediastreamer2 is a GPL licensed library to make audio and video -real-time streaming and processing. Written in pure C, it is based -upon the oRTP library. - -%package -n mediastreamer2-devel -Summary: Headers, libraries and docs for the mediastreamer2 library -Group: Development/Libraries -Version: @MS2_VERSION@ -Requires: mediastreamer2 = @MS2_VERSION@ -Requires: ortp-devel = @ORTP_VERSION@ - -%description -n mediastreamer2-devel -Mediastreamer2 is a GPL licensed library to make audio and video -real-time streaming and processing. Written in pure C, it is based -upon the ortp library. - -This package contains header files and development libraries needed to -develop programs using the mediastreamer2 library. - %prep %setup -q #%patch -p 1 -b .pkgconfig @@ -100,25 +53,19 @@ develop programs using the mediastreamer2 library. %build %configure \ - --with-osip=/usr \ - --with-speex=/usr \ - --with-readline=/usr \ -%if %{video} - --enable-video \ - --with-ffmpeg=/usr \ - --with-sdl=/usr \ +%if !%{video} + --disable-video \ %endif - --enable-ipv6 + --docdir=%{_docdir} --enable-ipv6 --enable-static --enable-external-mediastreamer --enable-external-ortp %__make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT -install -p -m 0644 pixmaps/linphone2.png $RPM_BUILD_ROOT%{_datadir}/pixmaps +install -p -m 0644 pixmaps/linphone.png $RPM_BUILD_ROOT%{_datadir}/pixmaps %find_lang %{name} -rm $RPM_BUILD_ROOT%{_datadir}/gnome/apps/Internet/linphone.desktop -desktop-file-install --vendor=fedora \ +desktop-file-install \ --delete-original \ --dir $RPM_BUILD_ROOT%{_datadir}/applications \ --add-category X-Fedora \ @@ -133,28 +80,17 @@ rm -rf $RPM_BUILD_ROOT %postun -p /sbin/ldconfig -%post -n ortp -p /sbin/ldconfig - -%postun -n ortp -p /sbin/ldconfig - -%post -n mediastreamer2 -p /sbin/ldconfig - -%postun -n mediastreamer2 -p /sbin/ldconfig %files -f %{name}.lang %defattr(-,root,root) %doc AUTHORS ChangeLog COPYING NEWS README TODO %{_bindir}/* -%{_libdir}/bonobo/servers/*.server %{_libdir}/liblinphone.so.* -%exclude %{_libdir}/libortp* -%{_libexecdir}/* %{_mandir}/* -%{_datadir}/applications/*%{name}.desktop -%{_datadir}/gnome/help/linphone -%{_datadir}/gnome-2.0/ui/*.xml +%{_datadir}/applications/%{name}.desktop %{_datadir}/pixmaps/linphone -%{_datadir}/pixmaps/linphone2.png +%{_datadir}/linphone +%{_datadir}/pixmaps/linphone.png %{_datadir}/sounds/linphone %files devel @@ -164,33 +100,7 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/liblinphone.la %{_libdir}/liblinphone.so %{_libdir}/pkgconfig/linphone.pc - -%files -n ortp -%defattr(-,root,root) -%doc oRTP/AUTHORS oRTP/ChangeLog oRTP/COPYING oRTP/NEWS oRTP/README oRTP/TODO -%{_libdir}/libortp.so.* -%exclude %{_libdir}/liblinphone* - -%files -n ortp-devel -%defattr(-,root,root) -%{_includedir}/ortp -%{_libdir}/pkgconfig/ortp.pc -%{_libdir}/libortp.a -%{_libdir}/libortp.la -%{_libdir}/libortp.so -%{_datadir}/gtk-doc/html/ortp - -%files -n mediastreamer2 -%defattr(-,root,root) -%doc mediastreamer2/AUTHORS mediastreamer2/ChangeLog mediastreamer2/COPYING -%doc mediastreamer2/NEWS mediastreamer2/README -%{_libdir}/libmediastreamer.so.* - -%files -n mediastreamer2-devel -%{_includedir}/mediastreamer2 -%{_libdir}/pkgconfig/mediastreamer.pc -%{_libdir}/libmediastreamer.so -%{_libdir}/libmediastreamer.*a +%{_docdir} %changelog * Wed Sep 28 2005 Francois-Xavier 'FiX' KOWALSKI - 1.2.0pre3 diff --git a/m4/exosip.m4 b/m4/exosip.m4 index 921e3353b..9be357f71 100644 --- a/m4/exosip.m4 +++ b/m4/exosip.m4 @@ -42,6 +42,10 @@ AC_CHECK_LIB([eXosip2],[eXosip_get_version], [AC_DEFINE([HAVE_EXOSIP_GET_VERSION],[1],[Defined when eXosip_get_version is available])], [], [-losipparser2 -losip2 ]) +AC_CHECK_LIB([eXosip2],[eXosip_tls_verify_certificate], + [AC_DEFINE([HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE],[1],[Defined when eXosip_tls_verify_certificate is available])], + [AC_MSG_WARN([Could not find eXosip_tls_verify_certificate in eXosip2 !])], + [-losipparser2 -losip2 ]) AC_CHECK_LIB([eXosip2],[eXosip_get_socket], [AC_DEFINE([HAVE_EXOSIP_GET_SOCKET],[1],[Defined when eXosip_get_socket is available])], [AC_MSG_WARN([Could not find eXosip_get_socket in eXosip2 !])], diff --git a/mediastreamer2 b/mediastreamer2 index c1f6d3e6d..4aaab3296 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit c1f6d3e6d4f36928fffd2e7380759544bcd23d84 +Subproject commit 4aaab3296337eb313d9b554dff1860cd23b3dbc9 diff --git a/oRTP b/oRTP index 73dff1e14..a936749fa 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 73dff1e14c73e76e5d46f617a320389e29606ffd +Subproject commit a936749fac4d3e2f788a0c03b3c4ea2021b3ae13