]> sjero.net Git - linphone/commitdiff
Merge branch 'master' into dev_sal
authorSimon Morlat <simon.morlat@linphone.org>
Fri, 12 Feb 2010 10:48:08 +0000 (11:48 +0100)
committerSimon Morlat <simon.morlat@linphone.org>
Fri, 12 Feb 2010 10:48:08 +0000 (11:48 +0100)
Conflicts:
coreapi/authentication.c
coreapi/linphonecore.h
coreapi/misc.c
coreapi/proxy.c

1  2 
coreapi/authentication.c
coreapi/callbacks.c
coreapi/linphonecore.c
coreapi/linphonecore.h
coreapi/misc.c
gtk-glade/logging.c
gtk-glade/loginframe.c

index 6551b7121552e1141e2cdfdddb9ecd0ef405ef24,6185048849e5bc8baa79f5df6b2724ded46fcb98..24bed1c437dd22f3d9057d4c01e3879b97a6e949
@@@ -50,24 -54,19 +50,36 @@@ LinphoneAuthInfo *linphone_auth_info_ne
        return obj;
  }
  
 -      obj->first_time=TRUE;
+ static LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){
+       LinphoneAuthInfo *obj=ms_new0(LinphoneAuthInfo,1);
+       if (ai->username) obj->username=ms_strdup(ai->username);
+       if (ai->userid) obj->userid=ms_strdup(ai->userid);
+       if (ai->passwd) obj->passwd=ms_strdup(ai->passwd);
+       if (ai->ha1)    obj->ha1=ms_strdup(ai->ha1);
+       if (ai->realm)  obj->realm=ms_strdup(ai->realm);
+       obj->works=FALSE;
++      obj->usecount=0;
+       return obj;
+ }
 +/**
 + * Returns username.
 +**/
 +const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i){
 +      return i->username;
 +}
 +
 +/**
 + * Returns password.
 +**/
 +const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i){
 +      return i->passwd;
 +}
 +
 +const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i){
 +      return i->userid;
 +}
 +
  /**
   * Sets the password.
  **/
@@@ -230,41 -244,21 +242,35 @@@ const LinphoneAuthInfo *linphone_core_f
   * 
   * This information will be used during all SIP transacations that require authentication.
  **/
- void linphone_core_add_auth_info(LinphoneCore *lc, LinphoneAuthInfo *info)
+ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info)
  {
-       MSList *elem;
        LinphoneAuthInfo *ai;
++      MSList *elem;
        
        /* find if we are attempting to modify an existing auth info */
-       ai=linphone_core_find_auth_info(lc,info->realm,info->username);
+       ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username);
        if (ai!=NULL){
-               elem=ms_list_find(lc->auth_info,ai);
-               if (elem==NULL){
-                       ms_error("AuthInfo list corruption ?");
-                       return;
-               }
-               linphone_auth_info_destroy((LinphoneAuthInfo*)elem->data);
-               elem->data=(void *)info;
-       }else {
-               lc->auth_info=ms_list_append(lc->auth_info,(void *)info);
+               lc->auth_info=ms_list_remove(lc->auth_info,ai);
+               linphone_auth_info_destroy(ai);
        }
 -
 -      refresh_exosip_auth_info(lc);
 -      /* if the user was prompted, re-allow automatic_action */
 -      if (lc->automatic_action>0) lc->automatic_action--;
+       lc->auth_info=ms_list_append(lc->auth_info,linphone_auth_info_clone(info));
-               ai=linphone_core_find_auth_info(lc,realm,username);
 +      /* retry pending authentication operations */
 +      for(elem=sal_get_pending_auths(lc->sal);elem!=NULL;elem=elem->next){
 +              const char *username,*realm;
 +              SalOp *op=(SalOp*)elem->data;
 +              LinphoneAuthInfo *ai;
 +              sal_op_get_auth_requested(op,&realm,&username);
++              ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
 +              if (ai){
 +                      SalAuthInfo sai;
 +                      sai.username=ai->username;
 +                      sai.userid=ai->userid;
 +                      sai.realm=ai->realm;
 +                      sai.password=ai->passwd;
 +                      sal_op_authenticate(op,&sai);
 +                      ai->usecount++;
 +              }
 +      }
  }
  
  
@@@ -278,21 -273,21 +284,20 @@@ void linphone_core_abort_authentication
  /**
   * Removes an authentication information object.
  **/
- void linphone_core_remove_auth_info(LinphoneCore *lc, LinphoneAuthInfo *info){
-       int len=ms_list_size(lc->auth_info);
-       int newlen;
+ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){
        int i;
        MSList *elem;
-       lc->auth_info=ms_list_remove(lc->auth_info,info);
-       newlen=ms_list_size(lc->auth_info);
-       /*printf("len=%i newlen=%i\n",len,newlen);*/
-       linphone_auth_info_destroy(info);
-       for (i=0;i<len;i++){
+       LinphoneAuthInfo *r;
+       r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username);
+       if (r){
+               lc->auth_info=ms_list_remove(lc->auth_info,r);
+               /*printf("len=%i newlen=%i\n",len,newlen);*/
+               linphone_auth_info_destroy(r);
+               for (elem=lc->auth_info,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
+                       linphone_auth_info_write_config(lc->config,(LinphoneAuthInfo*)elem->data,i);
+               }
                linphone_auth_info_write_config(lc->config,NULL,i);
 -              refresh_exosip_auth_info(lc);
        }
-       for (elem=lc->auth_info,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
-               linphone_auth_info_write_config(lc->config,(LinphoneAuthInfo*)elem->data,i);
-       }
  }
  
  /**
index f6c5f034acbde14afe3766bdbea05e73d8c4921b,0000000000000000000000000000000000000000..cb0c7b48e561920fb187c232ccfc73da80516ed0
mode 100644,000000..100644
--- /dev/null
@@@ -1,442 -1,0 +1,442 @@@
-       LinphoneAuthInfo *ai=linphone_core_find_auth_info(lc,realm,username);
 +/*
 +linphone
 +Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
 +
 +This program is free software; you can redistribute it and/or
 +modify it under the terms of the GNU General Public License
 +as published by the Free Software Foundation; either version 2
 +of the License, or (at your option) any later version.
 +
 +This program is distributed in the hope that it will be useful,
 +but WITHOUT ANY WARRANTY; without even the implied warranty of
 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +GNU General Public License for more details.
 +
 +You should have received a copy of the GNU General Public License
 +along with this program; if not, write to the Free Software
 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 +*/
 +
 +
 +#include "sal.h"
 +
 +#include "linphonecore.h"
 +#include "private.h"
 +#include "mediastreamer2/mediastream.h"
 +
 +static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){
 +      if (lc->vtable.show)
 +              lc->vtable.show(lc);
 +      if (lc->vtable.display_status)
 +              lc->vtable.display_status(lc,_("Connected."));
 +      call->state=LCStateAVRunning;
 +      if (lc->ringstream!=NULL){
 +              ring_stop(lc->ringstream);
 +              lc->ringstream=NULL;
 +      }
 +      linphone_core_start_media_streams(lc,call);
 +}
 +
 +static void call_received(SalOp *h){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
 +      char *barmesg;
 +      LinphoneCall *call;
 +      const char *from,*to;
 +      char *tmp;
 +      LinphoneAddress *from_parsed;
 +
 +      /* first check if we can answer successfully to this invite */
 +      if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){
 +              ms_message("Not present !! presence mode : %d\n",lc->presence_mode);
 +              if (lc->presence_mode==LINPHONE_STATUS_BUSY)
 +                      sal_call_decline(h,SalReasonBusy,NULL);
 +              else if (lc->presence_mode==LINPHONE_STATUS_AWAY
 +                       ||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK
 +                       ||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE
 +                       ||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH
 +                       ||lc->presence_mode==LINPHONE_STATUS_OFFLINE)
 +                      sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
 +              else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB)
 +                      sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
 +              else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED)
 +                      sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
 +              else
 +                      sal_call_decline(h,SalReasonBusy,NULL);
 +              sal_op_release(h);
 +              return;
 +      }
 +      if (lc->call!=NULL){/*busy*/
 +              sal_call_decline(h,SalReasonBusy,NULL);
 +              sal_op_release(h);
 +              return;
 +      }
 +      from=sal_op_get_from(h);
 +      to=sal_op_get_to(h);
 +      
 +      call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),h);
 +      lc->call=call;
 +      sal_call_set_local_media_description(h,call->localdesc);
 +      call->resultdesc=sal_call_get_final_media_description(h);
 +      if (call->resultdesc)
 +              sal_media_description_ref(call->resultdesc);
 +      if (call->resultdesc && sal_media_description_empty(call->resultdesc)){
 +              sal_call_decline(h,SalReasonMedia,NULL);
 +              linphone_call_destroy(call);
 +              lc->call=NULL;
 +              return;
 +      }
 +      
 +      from_parsed=linphone_address_new(sal_op_get_from(h));
 +      linphone_address_clean(from_parsed);
 +      tmp=linphone_address_as_string(from_parsed);
 +      linphone_address_destroy(from_parsed);
 +      gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
 +      barmesg=ortp_strdup_printf(_("%s is contacting you"),tmp);
 +      if (lc->vtable.show) lc->vtable.show(lc);
 +      if (lc->vtable.display_status) 
 +          lc->vtable.display_status(lc,barmesg);
 +
 +      /* play the ring */
 +      if (lc->sound_conf.ring_sndcard!=NULL){
 +              ms_message("Starting local ring...");
 +              lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
 +      }
 +      linphone_call_set_state(call,LCStateRinging);
 +      sal_call_notify_ringing(h);
 +      linphone_core_init_media_streams(lc,lc->call);
 +      if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,tmp);
 +      ms_free(barmesg);
 +      ms_free(tmp);
 +}
 +
 +static void call_ringing(SalOp *h){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
 +      LinphoneCall *call=lc->call;
 +      SalMediaDescription *md;
 +      if (call==NULL) return;
 +      if (lc->vtable.display_status)
 +              lc->vtable.display_status(lc,_("Remote ringing."));
 +      md=sal_call_get_final_media_description(h);
 +      if (md==NULL){
 +              if (lc->ringstream!=NULL) return;       /*already ringing !*/
 +              if (lc->sound_conf.play_sndcard!=NULL){
 +                      ms_message("Remote ringing...");
 +                      lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,lc->sound_conf.play_sndcard);
 +              }
 +      }else{
 +              /*accept early media */
 +              if (lc->audiostream->ticker!=NULL){
 +                      /*streams already started */
 +                      ms_message("Early media already started.");
 +                      return;
 +              }
 +              sal_media_description_ref(md);
 +              call->resultdesc=md;
 +              if (lc->vtable.show) lc->vtable.show(lc);
 +              if (lc->vtable.display_status) 
 +                      lc->vtable.display_status(lc,_("Early media."));
 +              gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
 +              if (lc->ringstream!=NULL){
 +                      ring_stop(lc->ringstream);
 +                      lc->ringstream=NULL;
 +              }
 +              ms_message("Doing early media...");
 +              linphone_core_start_media_streams(lc,call);
 +              call->media_pending=TRUE;
 +      }
 +      call->state=LCStateRinging;
 +}
 +
 +static void call_accepted(SalOp *op){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      LinphoneCall *call=lc->call;
 +      if (call==NULL){
 +              ms_warning("No call to accept.");
 +              return ;
 +      }
 +      if (sal_op_get_user_pointer(op)!=lc->call){
 +              ms_warning("call_accepted: ignoring.");
 +              return;
 +      }
 +      if (call->state==LCStateAVRunning){
 +              return ; /*already accepted*/
 +      }
 +      if (lc->audiostream->ticker!=NULL){
 +              /*case where we accepted early media */
 +              linphone_core_stop_media_streams(lc,call);
 +              linphone_core_init_media_streams(lc,call);
 +      }
 +      if (call->resultdesc)
 +              sal_media_description_unref(call->resultdesc);
 +      call->resultdesc=sal_call_get_final_media_description(op);
 +      if (call->resultdesc){
 +              sal_media_description_ref(call->resultdesc);
 +              call->media_pending=FALSE;
 +      }
 +      if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
 +              gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
 +              linphone_connect_incoming(lc,call);
 +      }else{
 +              /*send a bye*/
 +              ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
 +              linphone_core_terminate_call(lc,NULL);
 +      }
 +}
 +
 +static void call_ack(SalOp *op){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      LinphoneCall *call=lc->call;
 +      if (call==NULL){
 +              ms_warning("No call to be ACK'd");
 +              return ;
 +      }
 +      if (sal_op_get_user_pointer(op)!=lc->call){
 +              ms_warning("call_ack: ignoring.");
 +              return;
 +      }
 +      if (call->media_pending){
 +              if (lc->audiostream->ticker!=NULL){
 +                      /*case where we accepted early media */
 +                      linphone_core_stop_media_streams(lc,call);
 +                      linphone_core_init_media_streams(lc,call);
 +              }
 +              if (call->resultdesc)
 +                      sal_media_description_unref(call->resultdesc);
 +              call->resultdesc=sal_call_get_final_media_description(op);
 +              if (call->resultdesc)
 +                      sal_media_description_ref(call->resultdesc);
 +              if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
 +                      gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL);
 +                      linphone_connect_incoming(lc,call);
 +              }else{
 +                      /*send a bye*/
 +                      ms_error("Incompatible SDP response received in ACK, need to abort the call");
 +                      linphone_core_terminate_call(lc,NULL);
 +              }
 +              call->media_pending=FALSE;
 +      }
 +}
 +
 +static void call_updated(SalOp *op){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
 +      linphone_core_stop_media_streams(lc,call);
 +      linphone_core_init_media_streams(lc,call);
 +      if (call->resultdesc)
 +              sal_media_description_unref(call->resultdesc);
 +      call->resultdesc=sal_call_get_final_media_description(op);
 +      if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
 +              linphone_connect_incoming(lc,call);
 +      }
 +}
 +
 +static void call_terminated(SalOp *op, const char *from){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      if (sal_op_get_user_pointer(op)!=lc->call){
 +              ms_warning("call_terminated: ignoring.");
 +              return;
 +      }
 +      ms_message("Current call terminated...");
 +      if (lc->ringstream!=NULL) {
 +              ring_stop(lc->ringstream);
 +              lc->ringstream=NULL;
 +      }
 +      linphone_core_stop_media_streams(lc,lc->call);
 +      lc->vtable.show(lc);
 +      lc->vtable.display_status(lc,_("Call terminated."));
 +      gstate_new_state(lc, GSTATE_CALL_END, NULL);
 +      if (lc->vtable.bye_recv!=NULL){
 +              LinphoneAddress *addr=linphone_address_new(from);
 +              char *tmp;
 +              linphone_address_clean(addr);
 +              tmp=linphone_address_as_string(addr);
 +              lc->vtable.bye_recv(lc,tmp);
 +              ms_free(tmp);
 +              linphone_address_destroy(addr);
 +      }
 +      linphone_call_destroy(lc->call);
 +      lc->call=NULL;
 +}
 +
 +static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      char *msg486=_("User is busy.");
 +      char *msg480=_("User is temporarily unavailable.");
 +      /*char *retrymsg=_("%s. Retry after %i minute(s).");*/
 +      char *msg600=_("User does not want to be disturbed.");
 +      char *msg603=_("Call declined.");
 +      LinphoneCall *call=lc->call;
 +
 +      if (sal_op_get_user_pointer(op)!=lc->call){
 +              ms_warning("call_failure: ignoring.");
 +              return;
 +      }
 +      if (lc->vtable.show) lc->vtable.show(lc);
 +
 +      if (error==SalErrorNoResponse){
 +              if (lc->vtable.display_status)
 +                      lc->vtable.display_status(lc,_("No response."));
 +      }else if (error==SalErrorProtocol){
 +              if (lc->vtable.display_status)
 +                      lc->vtable.display_status(lc, details ? details : _("Error."));
 +      }else if (error==SalErrorFailure){
 +              switch(sr){
 +                      case SalReasonDeclined:
 +                              if (lc->vtable.display_status)
 +                                      lc->vtable.display_status(lc,msg603);
 +                      break;
 +                      case SalReasonBusy:
 +                              if (lc->vtable.display_status)
 +                                      lc->vtable.display_status(lc,msg486);
 +                      break;
 +                      case SalReasonRedirect:
 +                              if (lc->vtable.display_status)
 +                                      lc->vtable.display_status(lc,_("Redirected"));
 +                      break;
 +                      case SalReasonTemporarilyUnavailable:
 +                              if (lc->vtable.display_status)
 +                                      lc->vtable.display_status(lc,msg480);
 +                      break;
 +                      case SalReasonNotFound:
 +                              if (lc->vtable.display_status)
 +                                      lc->vtable.display_status(lc,_("Not found"));
 +                      break;
 +                      case SalReasonDoNotDisturb:
 +                              if (lc->vtable.display_status)
 +                                      lc->vtable.display_status(lc,msg600);
 +                      break;
 +                      case SalReasonMedia:
 +                              if (lc->vtable.display_status)
 +                                      lc->vtable.display_status(lc,_("No common codecs"));
 +                      break;
 +                      default:
 +                              if (lc->vtable.display_status)
 +                                      lc->vtable.display_status(lc,_("Call failed."));
 +              }
 +      }
 +      if (lc->ringstream!=NULL) {
 +              ring_stop(lc->ringstream);
 +              lc->ringstream=NULL;
 +      }
 +      linphone_core_stop_media_streams(lc,call);
 +      if (call!=NULL) {
 +              linphone_call_destroy(call);
 +              gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
 +              lc->call=NULL;
 +      }
 +}
 +
 +static void auth_requested(SalOp *h, const char *realm, const char *username){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
-       LinphoneAuthInfo *ai=linphone_core_find_auth_info(lc,realm,username);
++      LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
 +      if (ai && (ai->works || ai->usecount<3)){
 +              SalAuthInfo sai;
 +              sai.username=ai->username;
 +              sai.userid=ai->userid;
 +              sai.realm=ai->realm;
 +              sai.password=ai->passwd;
 +              sal_op_authenticate(h,&sai);
 +              ai->usecount++;
 +      }else{
 +              if (lc->vtable.auth_info_requested)
 +                      lc->vtable.auth_info_requested(lc,realm,username);
 +      }
 +}
 +
 +static void auth_success(SalOp *h, const char *realm, const char *username){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
++      LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
 +      if (ai)
 +              ai->works=TRUE;
 +}
 +
 +static void register_success(SalOp *op, bool_t registered){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op);
 +      char *msg;
 +      gstate_new_state(lc, GSTATE_REG_OK, NULL);
 +      cfg->registered=registered;
 +      if (cfg->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));
 +      if (lc->vtable.display_status) 
 +              lc->vtable.display_status(lc,msg);
 +      ms_free(msg);
 +}
 +
 +static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op),(details!=NULL) ? details : _("no response timeout"));
 +      if (lc->vtable.display_status) lc->vtable.display_status(lc,msg);
 +      gstate_new_state(lc, GSTATE_REG_FAILED, msg);
 +      ms_free(msg);
 +}
 +
 +static void vfu_request(SalOp *op){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +#ifdef VIDEO_ENABLED
 +      if (lc->videostream)
 +              video_stream_send_vfu(lc->videostream);
 +#endif
 +}
 +
 +static void dtmf_received(SalOp *op, char dtmf){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      if (lc->vtable.dtmf_received != NULL)
 +              lc->vtable.dtmf_received(lc, dtmf);
 +}
 +
 +static void refer_received(Sal *sal, SalOp *op, const char *referto){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
 +      if (lc->vtable.refer_received)
 +              lc->vtable.refer_received(lc,referto);
 +}
 +
 +static void text_received(Sal *sal, const char *from, const char *msg){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
 +      linphone_core_text_received(lc,from,msg);
 +}
 +
 +static void notify(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      linphone_notify_recv(lc,op,ss,status);
 +}
 +
 +static void subscribe_received(SalOp *op, const char *from){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      linphone_subscription_new(lc,op,from);
 +}
 +
 +static void subscribe_closed(SalOp *op, const char *from){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
 +      linphone_subscription_closed(lc,op);
 +}
 +
 +static void internal_message(Sal *sal, const char *msg){
 +      LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
 +      if (lc->vtable.show)
 +              lc->vtable.show(lc);
 +}
 +
 +SalCallbacks linphone_sal_callbacks={
 +      call_received,
 +      call_ringing,
 +      call_accepted,
 +      call_ack,
 +      call_updated,
 +      call_terminated,
 +      call_failure,
 +      auth_requested,
 +      auth_success,
 +      register_success,
 +      register_failure,
 +      vfu_request,
 +      dtmf_received,
 +      refer_received,
 +      text_received,
 +      notify,
 +      subscribe_received,
 +      subscribe_closed,
 +      internal_message
 +};
 +
 +
Simple merge
Simple merge
diff --cc coreapi/misc.c
index f0cf871fd2d38fbcb8fad537f25cf77e00ffe273,db2c9393208bf5a864ed0cfb3a02f39bc5651962..70c75d82abe9debcc85b9dc2ba1369e27982ce78
@@@ -180,32 -185,6 +180,32 @@@ static bool_t payload_type_enabled(Payl
        return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0);
  }
  
-               return desc->text;
 +bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, PayloadType *pt){
 +      if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
 +              return payload_type_enabled(pt);
 +      }
 +      ms_error("Getting enablement status of codec not in audio or video list of PayloadType !");
 +      return FALSE;
 +}
 +
 +int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){
 +      if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
 +              payload_type_set_enable(pt,enabled);
 +              return 0;
 +      }
 +      ms_error("Enabling codec not in audio or video list of PayloadType !");
 +      return -1;
 +}
 +
 +const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt){
 +      if (ms_filter_codec_supported(pt->mime_type)){
 +              MSFilterDesc *desc=ms_filter_get_encoder(pt->mime_type);
++              return _(desc->text);
 +      }
 +      return NULL;
 +}
 +
 +
  /*this function makes a special case for speex/8000.
  This codec is variable bitrate. The 8kbit/s mode is interesting when having a low upload bandwidth, but its quality
  is not very good. We 'd better use its 15kbt/s mode when we have enough bandwidth*/
index a8211d1eabd9a76f893d1f57bf17d5784196a51b,85693734917e93ef6f8b3d040e6fe95e1833478d..4869beaac05a9fb3b212c2f69c14d898506a8d1e
@@@ -28,6 -34,186 +34,186 @@@ typedef struct _LinphoneGtkLog
        gchar *msg;
  }LinphoneGtkLog;
  
 -      if (lc->config == NULL) {
+ /******
+  * Module to log to a file
+  ******/
+ /* Marker to insert as a line at the start of every log file */
+ #define LOGFILE_MARKER_START  "----<start>----"
+ /* Marker to insert as a line at the end of every log file */
+ #define LOGFILE_MARKER_STOP  "----<end>----"
+ /* Number of files to keep in history, log file rotation will be
+    performed. */
+ #define LOGFILE_ROTATION 4
+ /* Pointer to opened log file */
+ static FILE *_logfile = NULL;
+ /* Called on exit, print out the marker, close the file and avoid to
+    continue logging. */
+ static void linphone_gtk_log_uninit()
+ {
+       if (_logfile != NULL) {
+               fprintf(_logfile, "%s\n", LOGFILE_MARKER_STOP);
+               fclose(_logfile);
+               _logfile = NULL;
+       }
+ }
+ /* Called when we start logging, find a good place for the log files,
+    perform rotation, insert the start marker and return the pointer to
+    the file that should be used for logging, or NULL on errors or if
+    disabled. */
+ static FILE *linphone_gtk_log_init()
+ {
+       static char _logdir[1024];
+       static char _logfname[1024];
+       static gboolean _log_init = FALSE;
+       const char *dst_fname;
+       dst_fname = linphone_gtk_get_ui_config("logfile",NULL);
+       /* For anything to happen, we need a logfile configuration variable,
+        this is our trigger */
+       if (dst_fname) {
+               /* If we haven't initialised yet, arrange for _logdir to contain a
+                directory that has been created and _logfname to contain the
+                path to a file to which we will log */
+               if (!_log_init) {
+ #ifdef WIN32
+                       const char *appdata=getenv("LOCALAPPDATA");
+                       if (appdata) {
+                               snprintf(_logdir, sizeof(_logdir),"%s\\Linphone", appdata);
+                               mkdir(_logdir);
+                       } else {
+                               _logdir[0] = '\0';
+                       }
+ #define PATH_SEPARATOR '\\'
+ #else
+                       const char *home=getenv("HOME");
+                       if (home) {
+                               snprintf(_logdir, sizeof(_logdir),"%s/.linphone", home);
+                               mkdir(_logdir,S_IRUSR | S_IWUSR | S_IRGRP);
+                       } else {
+                               _logdir[0] = '\0';
+                       }
+ #define PATH_SEPARATOR '/'
+ #endif
+                       /* We have a directory, fix the path to the log file in it and
+                        open the file so that we will be appending to it. */
+                       if (_logdir[0] != '\0') {
+                               snprintf(_logfname, sizeof(_logfname), "%s%c%s",
+                                   _logdir, PATH_SEPARATOR, dst_fname);
+                               /* If the constant LOGFILE_ROTATION is greater than zero, then
+                                we kick away a simple rotation that will ensure that there
+                                are never more than LOGFILE_ROTATION+1 old copies of the
+                                log file on the disk.  The oldest file is always rotated
+                                "away" as expected.  Rotated files have the same name as
+                                the main log file, though with a number 0..LOGFILE_ROTATION
+                                at the end, where the greater the number is, the older the
+                                file is. */
+                               if (ortp_file_exist(_logfname)==0 && LOGFILE_ROTATION > 0) {
+                                       int i;
+                                       char old_fname[1024];
+                                       char new_fname[1024];
+                                       /* Rotate away existing files.  We make sure to remove the
+                                        old files otherwise rename() would not work properly.  We
+                                        have to loop in reverse here. */
+                                       for (i=LOGFILE_ROTATION-1;i>=0;i--) {
+                                               snprintf(old_fname, sizeof(old_fname), "%s%c%s.%d",
+                                                   _logdir, PATH_SEPARATOR, dst_fname, i);
+                                               snprintf(new_fname, sizeof(new_fname), "%s%c%s.%d",
+                                                   _logdir, PATH_SEPARATOR, dst_fname, i+1);
+                                               if (ortp_file_exist(old_fname)==0) {
+                                                       if (ortp_file_exist(new_fname)==0)
+                                                               unlink(new_fname);
+                                                       rename(old_fname, new_fname);
+                                               }
+                                       }
+                                       /* Move current log file as the first of the rotation.  Make
+                                        sure to remove the old .0 also, since otherwise rename()
+                                        would not work as expected. */
+                                       snprintf(new_fname, sizeof(new_fname), "%s%c%s.%d",
+                                           _logdir, PATH_SEPARATOR, dst_fname, 0);
+                                       if (ortp_file_exist(new_fname)==0)
+                                               unlink(new_fname);
+                                       rename(_logfname, new_fname);
+                               }
+                               /* Start a new log file and mark that we have now initialised */
+                               _logfile = fopen(_logfname, "w");
+                               fprintf(_logfile, "%s\n", LOGFILE_MARKER_START);
+                               _log_init = TRUE;
+                       }
+               }
+       }
+       return _logfile;
+ }
+ static void linphone_gtk_log_file(OrtpLogLevel lev, const char *msg)
+ {
+       LinphoneCore *lc;
+       time_t now;
+       FILE *outlog;
+       lc = linphone_gtk_get_core();
+       /* Nothing to do until the core has initialised */
+       if (lc == NULL)
+               return;
+       /* lc->config will turn NULL at exit, close the file to flush and
+        return to stop logging */
++      if (linphone_core_get_config(lc) == NULL) {
+               linphone_gtk_log_uninit();
+               return;
+       }
+       outlog = linphone_gtk_log_init();
+       if (outlog != NULL) {
+               /* We have an opened file and we have initialised properly, it's
+                time to write all these log messages. We convert the log level
+                from oRTP into something readable and timestamp each log
+                message.  The format of the timestamp can be controlled by
+                logfile_date_format in the GtkUi section of the config file,
+                but it defaults to something compact, but yet readable. */
+               const char *lname="undef";
+               const char *dateformat=linphone_gtk_get_ui_config("logfile_date_format",
+                   "%Y%m%d-%H:%M:%S");
+               char date[256];
+               /* Convert level constant to text */
+               switch(lev){
+                       case ORTP_DEBUG:
+                               lname="debug";
+                               break;
+                       case ORTP_MESSAGE:
+                               lname="message";
+                               break;
+                       case ORTP_WARNING:
+                               lname="warning";
+                               break;
+                       case ORTP_ERROR:
+                               lname="error";
+                               break;
+                       case ORTP_FATAL:
+                               lname="fatal";
+                               break;
+                       default:
+                               lname="undef";
+                               break;
+               }
+               /* Get current time and format it properly */
+               now = time(NULL);
+               strftime(date, sizeof(date), dateformat, localtime(&now));
+               /* Now print out the message to the logfile.  We don't flush,
+                maybe we should do to ensure that we have all the messages in
+                case of a crash (which is one of the main reasons we have a
+                    log facility in the first place). */
+               fprintf(outlog, "[%s] [%s] %s\n", date, lname, msg);
+       }
+ }
  void linphone_gtk_create_log_window(void){
        GtkTextBuffer *b;
        log_window=linphone_gtk_create_window("log");
Simple merge