Commit 52040fc8 authored by Guillaume Beraudo's avatar Guillaume Beraudo
Browse files

Merge branch 'master' of git.linphone.org:linphone into tunnel

parents fdd53e63 173b02a2
......@@ -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
# <https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=2068410>
TAR_OPTIONS=--wildcards rpmbuild -ta --clean --rmsource --rmspec $(PACKAGE)-$(VERSION).tar.gz
rpm-novideo: rpm-base
# <https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=2068410>
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
......
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
......
......@@ -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.
......
......@@ -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.
......
......@@ -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\" \
......
......@@ -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);
......
......@@ -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);
}
......@@ -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
<b> GSM call interaction </b>
<br> 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 <AVAudioSessionDelegate> { [...] }
// 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
<br> 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
<b> Video </b>
<br>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.
<br> 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:
......
......@@ -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";
}
......
......@@ -202,6 +202,7 @@ enum _LinphoneReason{
LinphoneReasonNoResponse, /**<No response received from remote*/
LinphoneReasonBadCredentials, /**<Authentication failed due to bad or missing credentials*/
LinphoneReasonDeclined, /**<The call has been declined*/
LinphoneReasonNotFound,
};
typedef enum _LinphoneReason LinphoneReason;
......@@ -1077,7 +1078,7 @@ void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *para
/**
* True if tunnel support was compiled.
*/
bool_t linphone_core_tunnel_available();
bool_t linphone_core_tunnel_available(void);
/**
* Update tunnel using configuration.
......
......@@ -1574,6 +1574,10 @@ extern "C" void Java_org_linphone_core_LinphoneCallImpl_setAuthenticationTokenVe
linphone_call_set_authentication_token_verified(call, verified);
}
extern "C" jfloat Java_org_linphone_core_LinphoneCallImpl_getPlayVolume(JNIEnv* env, jobject thiz, jlong ptr) {
LinphoneCall *call = (LinphoneCall *) ptr;
return linphone_call_get_play_volume(call);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_soundResourcesLocked(JNIEnv* env,jobject thiz,jlong ptr){
return linphone_core_sound_resources_locked((LinphoneCore *) ptr);
......
......@@ -461,6 +461,7 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
struct sockaddr_storage ss;
socklen_t ss_len;
ortp_socket_t sock1=-1, sock2=-1;
int loops=0;
bool_t video_enabled=linphone_core_video_enabled(lc);
bool_t got_audio,got_video;
bool_t cone_audio=FALSE,cone_video=FALSE;
......@@ -479,16 +480,10 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
/*create the two audio and video RTP sockets, and send STUN message to our stun server */
sock1=create_socket(call->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);
}
}
......
......@@ -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;
......
......@@ -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);
}
}
......
......@@ -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){
......
......@@ -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);