[Pkg-voip-commits] r4700 - in /linphone/trunk/debian: changelog patches/00list patches/fix_segfault.dpatch

kilian at alioth.debian.org kilian at alioth.debian.org
Sat Oct 6 23:48:04 UTC 2007


Author: kilian
Date: Sat Oct  6 23:48:04 2007
New Revision: 4700

URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=4700
Log:
backport full diff until today's CVS HEAD to start narrowing down proper fix.

Added:
    linphone/trunk/debian/patches/fix_segfault.dpatch   (with props)
Modified:
    linphone/trunk/debian/changelog
    linphone/trunk/debian/patches/00list

Modified: linphone/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-voip/linphone/trunk/debian/changelog?rev=4700&op=diff
==============================================================================
--- linphone/trunk/debian/changelog (original)
+++ linphone/trunk/debian/changelog Sat Oct  6 23:48:04 2007
@@ -1,8 +1,9 @@
 linphone (1.99.0-3) UNRELEASED; urgency=low
 
   * Fix wrong menu section (Closes: #444898)
-
- -- Kilian Krause <kilian at debian.org>  Mon,  1 Oct 2007 21:23:10 +0200
+  * Backport segfault fix from CVS. (Closes: #445462)
+
+ -- Kilian Krause <kilian at debian.org>  Sun, 07 Oct 2007 01:46:24 +0200
 
 linphone (1.99.0-2) unstable; urgency=low
 

Modified: linphone/trunk/debian/patches/00list
URL: http://svn.debian.org/wsvn/pkg-voip/linphone/trunk/debian/patches/00list?rev=4700&op=diff
==============================================================================
--- linphone/trunk/debian/patches/00list (original)
+++ linphone/trunk/debian/patches/00list Sat Oct  6 23:48:04 2007
@@ -1,1 +1,2 @@
 hide_manual_menu
+fix_segfault

Added: linphone/trunk/debian/patches/fix_segfault.dpatch
URL: http://svn.debian.org/wsvn/pkg-voip/linphone/trunk/debian/patches/fix_segfault.dpatch?rev=4700&op=file
==============================================================================
--- linphone/trunk/debian/patches/fix_segfault.dpatch (added)
+++ linphone/trunk/debian/patches/fix_segfault.dpatch Sat Oct  6 23:48:04 2007
@@ -1,0 +1,2391 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## fix_segfault.dpatch by Kilian Krause <kilian at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad linphone-1.99.0~/ChangeLog linphone-1.99.0/ChangeLog
+--- linphone-1.99.0~/ChangeLog	2007-08-04 22:13:18.000000000 +0200
++++ linphone-1.99.0/ChangeLog	2007-10-07 01:42:50.000000000 +0200
+@@ -1,3 +1,15 @@
++2007-09-26  Francois-Xavier Kowalski  <fix at hp.com>
++
++	* m4/exosip.m4: 1.3
++	  make Linphone buildable with  the eXosip/osip version that ships
++	  with Fedora.
++
++	* oRTP/include/ortp/stun_udp.h: 1.9 
++	* mediastreamer2/include/mediastreamer2/msvideo.h: 1.7 
++	* mediastreamer2/include/mediastreamer2/msticker.h: 1.6 
++	* mediastreamer2/include/mediastreamer2/msqueue.h: 1.3
++	  Clean ANSI/C vs. ANSI/C++ differences
++
+ 2007-08-01 Sandro Santilli <strk at keybit.net>
+ 
+ 	* console/commands.c: Clean up commands 'nat', 'stun'
+diff -urNad linphone-1.99.0~/console/linphonec.c linphone-1.99.0/console/linphonec.c
+--- linphone-1.99.0~/console/linphonec.c	2007-02-13 22:31:01.000000000 +0100
++++ linphone-1.99.0/console/linphonec.c	2007-10-07 01:42:50.000000000 +0200
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+  *
+- *  $Id: linphonec.c,v 1.53 2007/02/13 21:31:01 smorlat Exp $
++ *  $Id: linphonec.c,v 1.56 2007/09/26 14:07:27 fixkowalski Exp $
+  *
+  *  Copyright (C) 2006  Sandro Santilli <strk at keybit.net>
+  *  Copyright (C) 2002  Florian Winterstein <flox at gmx.net>
+@@ -93,6 +93,8 @@
+ static void linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr,
+ 		const char *from, const char *msg);
+ static void linphonec_display_status (LinphoneCore * lc, const char *something);
++static void linphonec_general_state (LinphoneCore * lc, LinphoneGeneralState *gstate);
++static void print_prompt(LinphoneCore *opm);
+ 
+ /***************************************************************************
+  *
+@@ -108,6 +110,7 @@
+ static bool_t auto_answer=FALSE;
+ static bool_t answer_call=FALSE;
+ static bool_t video_enabled=FALSE;
++static bool_t show_general_state=FALSE;
+ LPC_AUTH_STACK auth_stack;
+ static int trace_level = 0;
+ static char *logfile_name = NULL;
+@@ -130,9 +133,9 @@
+ #endif
+ 	display_warning:linphonec_display_warning,
+ 	display_url:linphonec_display_url,
+-	display_question:stub,
++	display_question:(DisplayQuestionCb)stub,
+ 	text_received:linphonec_text_received,
+-        general_state:NULL
++        general_state:linphonec_general_state
+ };
+ 
+ /***************************************************************************
+@@ -147,7 +150,8 @@
+ static void
+ linphonec_display_something (LinphoneCore * lc, const char *something)
+ {
+-	fprintf (stdout, "%s\n", something);
++	fprintf (stdout, "%s\n%s", something,prompt);
++	fflush(stdout);
+ }
+ 
+ /*
+@@ -156,7 +160,8 @@
+ static void
+ linphonec_display_status (LinphoneCore * lc, const char *something)
+ {
+-	fprintf (stdout, "%s\n", something);
++	fprintf (stdout, "%s\n%s", something,prompt);
++	fflush(stdout);
+ }
+ 
+ /*
+@@ -165,7 +170,8 @@
+ static void
+ linphonec_display_warning (LinphoneCore * lc, const char *something)
+ {
+-	fprintf (stdout, "Warning: %s\n", something);
++	fprintf (stdout, "Warning: %s\n%s", something,prompt);
++	fflush(stdout);
+ }
+ 
+ /*
+@@ -260,7 +266,60 @@
+ }
+ 
+ 
+-
++static void 
++linphonec_general_state (LinphoneCore * lc, LinphoneGeneralState *gstate)
++{
++        if (show_general_state) {
++          switch(gstate->new_state) {
++           case GSTATE_POWER_OFF:
++             printf("GSTATE_POWER_OFF");
++             break;
++           case GSTATE_POWER_STARTUP:
++             printf("GSTATE_POWER_STARTUP");
++             break;
++           case GSTATE_POWER_ON:
++             printf("GSTATE_POWER_ON");
++             break;
++           case GSTATE_POWER_SHUTDOWN:
++             printf("GSTATE_POWER_SHUTDOWN");
++             break;
++           case GSTATE_REG_NONE:
++             printf("GSTATE_REG_NONE");
++             break;
++           case GSTATE_REG_OK:
++             printf("GSTATE_REG_OK");
++             break;
++           case GSTATE_REG_FAILED:
++             printf("GSTATE_REG_FAILED");
++             break;
++           case GSTATE_CALL_IDLE:
++             printf("GSTATE_CALL_IDLE");
++             break;
++           case GSTATE_CALL_OUT_INVITE:
++             printf("GSTATE_CALL_OUT_INVITE");
++             break;
++           case GSTATE_CALL_OUT_CONNECTED:
++             printf("GSTATE_CALL_OUT_CONNECTED");
++             break;
++           case GSTATE_CALL_IN_INVITE:
++             printf("GSTATE_CALL_IN_INVITE");
++             break;
++           case GSTATE_CALL_IN_CONNECTED:
++             printf("GSTATE_CALL_IN_CONNECTED");
++             break;
++           case GSTATE_CALL_END:
++             printf("GSTATE_CALL_END");
++             break;
++           case GSTATE_CALL_ERROR:
++             printf("GSTATE_CALL_ERROR");
++             break;
++           default:
++              printf("GSTATE_UNKNOWN_%d",gstate->new_state);   
++          }
++          if (gstate->message) printf(" %s", gstate->message);
++          printf("\n");
++        }  
++}
+ 
+ 
+ /***************************************************************************/
+@@ -496,6 +555,7 @@
+   -s  sipaddress       specify the sip call to do at startup\n\
+   -a                   enable auto answering for incoming calls\n\
+   -V                   enable video (disabled by default)\n\
++  -S                   show general state messages (disabled by default)\n\
+   -v or --version      display version and exits.\n");
+ 
+   	exit(exit_status);
+@@ -579,7 +639,7 @@
+ 	rl_attempted_completion_function = linephonec_readline_completion;
+ 
+ 	/* printf("Readline initialized.\n"); */
+-
++        setlinebuf(stdout); 
+ 	return 0;
+ }
+ 
+@@ -601,6 +661,15 @@
+ 	return 0;
+ }
+ 
++static void print_prompt(LinphoneCore *opm){
++#ifdef IDENTITY_AS_PROMPT
++	snprintf(prompt, PROMPT_MAX_LEN, "%s> ",
++		linphone_core_get_primary_contact(opm));
++#else
++	snprintf(prompt, PROMPT_MAX_LEN, "linphonec> ");
++#endif
++}
++
+ static int
+ linphonec_main_loop (LinphoneCore * opm, char * sipAddr)
+ {
+@@ -608,13 +677,8 @@
+ 	bool_t run=TRUE;
+ 	char *input;
+ 
++	print_prompt(opm);
+ 
+-#ifdef IDENTITY_AS_PROMPT
+-	snprintf(prompt, PROMPT_MAX_LEN, "%s> ",
+-		linphone_core_get_primary_contact(opm));
+-#else
+-	snprintf(prompt, PROMPT_MAX_LEN, "linphonec> ");
+-#endif
+ 
+ 	/* auto call handling */
+ 	if (sipAddr != NULL )
+@@ -730,6 +794,10 @@
+ 			printf ("version: " LINPHONE_VERSION "\n");
+ 			exit (EXIT_SUCCESS);
+ 		}
++		else if (strncmp ("-S", argv[arg_num], 2) == 0)
++		{
++			show_general_state = TRUE;
++		}
+ 		else if (old_arg_num == arg_num)
+ 		{
+ 			fprintf (stderr, "ERROR: bad arguments\n");
+@@ -929,6 +997,17 @@
+ /****************************************************************************
+  *
+  * $Log: linphonec.c,v $
++ * Revision 1.56  2007/09/26 14:07:27  fixkowalski
++ * - ANSI/C++ compilation issues with non-GCC compilers
++ * - Faster epm-based packaging
++ * - Ability to build & run on FC6's eXosip/osip
++ *
++ * Revision 1.55  2007/09/24 16:01:58  smorlat
++ * fix bugs.
++ *
++ * Revision 1.54  2007/08/22 14:06:11  smorlat
++ * authentication bugs fixed.
++ *
+  * Revision 1.53  2007/02/13 21:31:01  smorlat
+  * added patch for general state.
+  * new doxygen for oRTP
+diff -urNad linphone-1.99.0~/coreapi/authentication.c linphone-1.99.0/coreapi/authentication.c
+--- linphone-1.99.0~/coreapi/authentication.c	2007-05-08 15:04:24.000000000 +0200
++++ linphone-1.99.0/coreapi/authentication.c	2007-10-07 01:42:50.000000000 +0200
+@@ -41,6 +41,8 @@
+ 	if (passwd!=NULL && (strlen(passwd)>0)) obj->passwd=ms_strdup(passwd);
+ 	if (ha1!=NULL && (strlen(ha1)>0)) obj->ha1=ms_strdup(ha1);
+ 	if (realm!=NULL && (strlen(realm)>0)) obj->realm=ms_strdup(realm);
++	obj->works=FALSE;
++	obj->first_time=TRUE;
+ 	return obj;
+ }
+ 
+@@ -190,41 +192,47 @@
+ }
+ 
+ void linphone_authentication_ok(LinphoneCore *lc, eXosip_event_t *ev){
+-	AuthState *as=&lc->authstate;
+-	if (as->tid==ev->tid){
+-		as->tid=0;
+-		if (as->username!=NULL)
+-			ms_free(as->username);
+-		as->username=NULL;
+-		if (as->realm!=NULL)
+-			ms_free(as->realm);
+-		as->realm=NULL;
+-	}
+-}
++	char *prx_realm=NULL,*www_realm=NULL;
++	osip_proxy_authorization_t *prx_auth;
++	osip_authorization_t *www_auth;
++	osip_message_t *msg=ev->request;
++	char *username;
++	LinphoneAuthInfo *as=NULL;
+ 
+-static bool_t last_auth_failed(AuthState *as, const char *username, const char *realm, int tid){
+-	bool_t ret=FALSE;
+-	if (as->username!=NULL && strcmp(as->username,username)==0
+-		&& as->realm!=NULL && strcmp(as->realm,realm)==0
+-		&& tid!=as->tid){
+-		ret=TRUE;
++	username=osip_uri_get_username(msg->from->url);
++	osip_message_get_proxy_authorization(msg,0,&prx_auth);
++	osip_message_get_authorization(msg,0,&www_auth);
++	if (prx_auth!=NULL)
++		prx_realm=osip_proxy_authorization_get_realm(prx_auth);
++	if (www_auth!=NULL)
++		www_realm=osip_authorization_get_realm(www_auth);
++	
++	if (prx_realm==NULL && www_realm==NULL){
++		ms_message("No authentication info in the request, ignoring");
++		return;
++	}
++	/* see if we already have this auth information , not to ask it everytime to the user */
++	if (prx_realm!=NULL)
++		as=linphone_core_auth_info_find(lc,prx_realm,username);
++	if (www_realm!=NULL) 
++		as=linphone_core_auth_info_find(lc,www_realm,username);
++	if (as){
++		ms_message("Authentication for user=%s realm=%s is working.",username,prx_realm ? prx_realm : www_realm);
++		as->works=TRUE;
+ 	}
+-	if (as->username!=NULL)
+-		ms_free(as->username);
+-	as->username=ms_strdup(username);
+-	if (as->realm!=NULL)
+-		ms_free(as->realm);
+-	as->realm=ms_strdup(realm);
+-	return ret;
+ }
+ 
++
+ void linphone_core_find_or_ask_for_auth_info(LinphoneCore *lc,const char *username,const char* realm, int tid)
+ {
+-	if (linphone_core_auth_info_find(lc,realm,username)==NULL ||
+-		last_auth_failed(&lc->authstate,username,realm,tid)){
++	LinphoneAuthInfo *as;
++	if ((as=linphone_core_auth_info_find(lc,realm,username))==NULL || 
++		(as->works==FALSE && as->first_time==FALSE) ) {
+ 		if (lc->vtable.auth_info_requested!=NULL) {
+ 			lc->vtable.auth_info_requested(lc,realm,username);
+ 			lc->automatic_action++;/*suspends eXosip_automatic_action until the user supplies a password */
++		}else{
++			if (as) as->first_time=FALSE;
+ 		}
+ 	}
+ }
+diff -urNad linphone-1.99.0~/coreapi/chat.c linphone-1.99.0/coreapi/chat.c
+--- linphone-1.99.0~/coreapi/chat.c	2007-05-07 18:23:19.000000000 +0200
++++ linphone-1.99.0/coreapi/chat.c	2007-10-07 01:42:50.000000000 +0200
+@@ -26,34 +26,35 @@
+  #include "private.h"
+  #include <eXosip2/eXosip.h>
+  
+- LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to)
+- {
+-	 char *real_url=NULL;
+-	 osip_from_t *parsed_url=NULL;
+-	 if (linphone_core_interpret_url(lc,to,&real_url,&parsed_url)){
+-	 	LinphoneChatRoom *cr=ms_new0(LinphoneChatRoom,1);
+-	 	cr->lc=lc;
+-	 	cr->peer=real_url;
++ LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
++	char *real_url=NULL;
++	osip_from_t *parsed_url=NULL;
++	char *route;
++	if (linphone_core_interpret_url(lc,to,&real_url,&parsed_url,&route)){
++		LinphoneChatRoom *cr=ms_new0(LinphoneChatRoom,1);
++		cr->lc=lc;
++		cr->peer=real_url;
+ 		cr->peer_url=parsed_url;
+-	 	lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr);
+-	 	return cr;
+-	 }
+-	 return NULL;
++		cr->route=route;
++		lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr);
++		return cr;
++	}
++	return NULL;
+  }
+  
+  
+  void linphone_chat_room_destroy(LinphoneChatRoom *cr){
+-	 LinphoneCore *lc=cr->lc;
+-	 lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
+-	 osip_from_free(cr->peer_url);
+-	 ms_free(cr->peer);
++	LinphoneCore *lc=cr->lc;
++	lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
++	osip_from_free(cr->peer_url);
++	ms_free(cr->peer);
++	ms_free(cr->route);
+  }
+  
+ void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg){
+ 	const char *identity=linphone_core_get_identity(cr->lc);
+ 	osip_message_t *sip=NULL;
+-	eXosip_message_build_request(&sip,"MESSAGE",cr->peer,identity,
+-		linphone_core_get_route(cr->lc));
++	eXosip_message_build_request(&sip,"MESSAGE",cr->peer,identity,cr->route);
+ 	osip_message_set_content_type(sip,"text/plain");
+ 	osip_message_set_body(sip,msg,strlen(msg));
+ 	eXosip_message_send_request(sip);
+diff -urNad linphone-1.99.0~/coreapi/exevents.c linphone-1.99.0/coreapi/exevents.c
+--- linphone-1.99.0~/coreapi/exevents.c	2007-06-28 12:15:57.000000000 +0200
++++ linphone-1.99.0/coreapi/exevents.c	2007-10-07 01:42:50.000000000 +0200
+@@ -24,38 +24,61 @@
+ #include <eXosip2/eXosip.h>
+ #include <osipparser2/osip_message.h>
+ 
++int linphone_answer_sdp(LinphoneCore *lc, eXosip_event_t *ev, sdp_message_t *sdp);
+ 
++static void linphone_connect_incoming(LinphoneCore *lc){
++	lc->vtable.show(lc);
++	lc->vtable.display_status(lc,_("Connected."));
++	lc->call->state=LCStateAVRunning;
++	if (lc->ringstream!=NULL){
++		ring_stop(lc->ringstream);
++		lc->ringstream=NULL;
++	}
++	if (lc->audiostream->ticker!=NULL){
++		/*case where we accepted early media */
++		linphone_core_stop_media_streams(lc);
++		linphone_core_init_media_streams(lc);
++	}
++	linphone_core_start_media_streams(lc,lc->call);
++}
+ 
+-int linphone_call_accepted(LinphoneCore *lc,int id, sdp_message_t *sdpbody)
++int linphone_call_accepted(LinphoneCore *lc, eXosip_event_t *ev)
+ {
+-	StreamParams *audio_params;
+ 	LinphoneCall *call=lc->call;
++	sdp_message_t *sdp=eXosip_get_sdp_info(ev->response);
++	const char *sdpanswer=NULL;
++	osip_message_t *msg=NULL;
++	int err;
+ 	if (call==NULL){
+ 		ms_warning("No call to accept.");
+ 		return 0;
+ 	}
+-	audio_params=&call->audio_params;
+ 	call->auth_pending=FALSE;
+ 	if (call->state==LCStateAVRunning){
+ 		return 0; /*already accepted*/
+ 	}
+ 	linphone_call_init_media_params(call);
+-	sdp_context_read_answer(call->sdpctx,sdpbody);
+-	lc->vtable.show(lc);
+-	lc->vtable.display_status(lc,_("Connected."));
+-	gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
+-	lc->call->state=LCStateAVRunning;
+-	if (lc->ringstream!=NULL){
+-		ring_stop(lc->ringstream);
+-		lc->ringstream=NULL;
++	if (!lc->sip_conf.sdp_200_ack){
++		err=0;
++		sdp_context_read_answer(call->sdpctx,sdp);
++	}else{
++		/*we receive a 200OK with an sdp offer*/
++		err=linphone_answer_sdp(lc,ev,sdp);
++		if (err==0) sdpanswer=call->sdpctx->answerstr;
+ 	}
+-	if (lc->audiostream->ticker!=NULL){
+-		/*case where we accepted early media */
+-		linphone_core_stop_media_streams(lc);
+-		linphone_core_init_media_streams(lc);
++	if (err==0){
++		gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
++		linphone_connect_incoming(lc);
++	}
++	/*send the ack once streams are started*/
++	eXosip_call_build_ack(ev->did,&msg);
++	if (sdpanswer!=NULL) linphone_set_sdp(msg,sdpanswer);
++	eXosip_call_send_ack(ev->did,msg);
++	if (err!=0){
++		/*send a bye*/
++		ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
++		linphone_core_terminate_call(lc,NULL);
+ 	}
+-	linphone_core_start_media_streams(lc,call);
+-	
+ 	return 0;
+ }
+ 
+@@ -193,167 +216,126 @@
+ 
+ extern sdp_handler_t linphone_sdphandler;
+ 
+-int linphone_inc_new_call(LinphoneCore *lc, eXosip_event_t *ev)
+-{
+-	char *barmesg,*answer;
++int linphone_answer_sdp(LinphoneCore *lc, eXosip_event_t *ev, sdp_message_t *sdp){
+ 	int status=200;
+ 	sdp_context_t *ctx=NULL;
++	
++	ctx=lc->call->sdpctx;
++	/* get the result of the negociation */
++	sdp_context_get_answer(ctx,sdp);
++	status=sdp_context_get_status(ctx);
++
++	if (status==200){
++		linphone_core_init_media_streams(lc);
++		return 0;
++	}else{
++		if (status==-1) status=415;
++	}
++	return -1;
++}
++
++int linphone_inc_new_call(LinphoneCore *lc, eXosip_event_t *ev)
++{
++	sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
+ 	osip_from_t *from_url=ev->request->from;
+-	int cid=ev->cid;
+-	int did=ev->did;
+-	int tid=ev->tid;
++	char *barmesg;
+ 	char *from;
+ 	char *to;
+-	sdp_message_t *sdp=eXosip_get_remote_sdp(ev->did);
+-#ifdef VINCENT_MAURY_RSVP
+-	char *textinfo=ev->textinfo;
+- #endif
+-	
++	int err;
++
+ 	osip_from_to_str(ev->request->from,&from);
+-	osip_to_to_str(ev->request->to,&to);
++	osip_to_to_str(ev->request->to,&to);	
++	
+ 	/* 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);
+ 		eXosip_lock();
+ 		if (lc->presence_mode==LINPHONE_STATUS_BUSY)
+-			eXosip_call_send_answer(tid,486,NULL);
++			eXosip_call_send_answer(ev->tid,486,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)
+-		  eXosip_call_send_answer(tid,480,NULL);
++		  eXosip_call_send_answer(ev->tid,480,NULL);
+ 		else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB)
+-		  eXosip_call_send_answer(tid,480,NULL);
++		  eXosip_call_send_answer(ev->tid,480,NULL);
+ 		else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED)
+ 		  {
+ 			osip_message_t *msg;
+-			eXosip_call_build_answer(tid,302,&msg);
++			eXosip_call_build_answer(ev->tid,302,&msg);
+ 			osip_message_set_contact(msg,lc->alt_contact);
+-			eXosip_call_send_answer(tid,302,msg);
++			eXosip_call_send_answer(ev->tid,302,msg);
+ 		  }
+ 		else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_ALT_SERVICE)
+ 		  {
+ 			osip_message_t *msg;
+-			eXosip_call_build_answer(tid,380,&msg);
++			eXosip_call_build_answer(ev->tid,380,&msg);
+ 			osip_message_set_contact(msg,lc->alt_contact);
+-			eXosip_call_send_answer(tid,380,msg);
++			eXosip_call_send_answer(ev->tid,380,msg);
+ 		  }
+ 		else
+-		  eXosip_call_send_answer(tid,486,NULL);
++		  eXosip_call_send_answer(ev->tid,486,NULL);
+ 		eXosip_unlock();
+ 		goto end;
+ 	}
+-	/* not busy */
+-#ifdef VINCENT_MAURY_RSVP
+-	/* in qos mode, call already exists at the end of resource reservation */
+-	if (lc->call!=NULL && lc->rsvp_enable && strcmp(textinfo,"New Call")!=0){
+-#else
+-	if (lc->call!=NULL){
+-#endif
++	if (lc->call!=NULL){/*busy*/
+ 		eXosip_lock();
+-		eXosip_call_send_answer(tid,486,NULL);
++		eXosip_call_send_answer(ev->tid,486,NULL);
+ 		eXosip_unlock();
+ 		goto end;
+ 	}
++	lc->call=linphone_call_new_incoming(lc,from,to,ev->cid,ev->did,ev->tid);
++	gstate_new_state(lc, GSTATE_CALL_IN_INVITE, NULL);
+ 	if (sdp==NULL){
+-		ms_warning("No sdp body !");
+-		eXosip_lock();
+-		eXosip_call_send_answer(tid,603,NULL);
+-		eXosip_unlock();
+-		goto end;
++		ms_message("No sdp body in invite, 200-ack scheme");
++		err=0;
++	}else{
++		err=linphone_answer_sdp(lc,ev,sdp);
+ 	}
+-#ifdef VINCENT_MAURY_RSVP
+-	/* make the negotiation only once at the first invite received */
+-	if (strcmp(textinfo,"New Call")!=0)
+-	{
++	if (!err){
++		char *tmp;
++		if (from_2char_without_params(from_url,&tmp)!=0){
++			tmp=ms_strdup("Unknown user");
++		}
++		barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you."));
++		lc->vtable.show(lc);
++		lc->vtable.display_status(lc,barmesg);
++		lc->vtable.inv_recv(lc,tmp);
++		ms_free(barmesg);
++		osip_free(tmp);
+ 		
+-		lc->call=linphone_call_new_incoming(lc,from,ev->local_uri,cid,did);
+-		ctx=lc->call->sdpctx;
+-		/* get the result of the negociation */
+-		answer=sdp_context_get_answer(ctx,sdp_body);
+-		status=sdp_context_get_status(ctx);
+-	}
+-#else
+-	lc->call=linphone_call_new_incoming(lc,from,to,cid,did,ev->tid);
+-	ctx=lc->call->sdpctx;
+-	/* get the result of the negociation */
+-	answer=sdp_context_get_answer(ctx,sdp);
+-	status=sdp_context_get_status(ctx);
+-
+-#endif
+-	switch(status)
+-	{
+-		case 200:
+-			/* vérification de la qos */
+-#ifdef VINCENT_MAURY_RSVP
+-			if (strcmp(textinfo,"With QoS")==0 && !lc->rsvp_enable)
+-				/* caller has QoS, we don't */
+-				lc->vtable.display_yes_no(lc,strdup(textinfo));
+-			else if (strcmp(textinfo,"Without QoS")==0 && lc->rsvp_enable)
+-				/* caller doesn't have QoS, we do ! */
+-				lc->vtable.display_yes_no(lc,strdup(textinfo));
+-			else if (strcmp(textinfo,"With QoS")==0 && lc->rsvp_enable)
+-			{
+-				/* we agree on With QoS */
+-				eXosip_lock();
+-				eXosip_answer_call_with_body(did,183,"application/sdp",answer);
+-				eXosip_unlock();
+-			}
+-			else if (strcmp(textinfo,"Without QoS")==0 && !lc->rsvp_enable ||
+-					strcmp(textinfo,"New Call")==0)
+-			{
+-				/* we agree on Without QoS */
+-				eXosip_lock();
+-				eXosip_answer_call(did,180,NULL);
+-				eXosip_unlock();
+-				/* play the ring */
+-				lc->ringstream=ring_start(lc->sound_conf.local_ring,
+-							2000,lc->sound_conf.ring_sndcard);
+-			}
+-#else
+-			eXosip_lock();
+-			eXosip_call_send_answer(tid,180,NULL);
+-			eXosip_unlock();
+-			/* 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);
+-			}
+-#endif
+-			linphone_call_set_state(lc->call,LCStateRinging);
+-			{
+-				char *tmp;
+-				if (from_2char_without_params(from_url,&tmp)!=0){
+-					tmp=ms_strdup("Unknown user");
+-				}
+-				linphone_core_init_media_streams(lc);
+-				barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you."));
+-				lc->vtable.show(lc);
+-				lc->vtable.display_status(lc,barmesg);
+-				gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
+-				lc->vtable.inv_recv(lc,tmp);
+-				ms_free(barmesg);
+-				osip_free(tmp);
+-				
+-				gstate_new_state(lc, GSTATE_CALL_IN_INVITE, NULL);
+-			}
+-		break;
+-		default:	
+-			if (status==-1) status=415;
+-			ms_warning("Error during sdp negociation. status : %d\n",status);
+-			eXosip_lock();
+-			eXosip_call_send_answer(tid,status,NULL);
+-			eXosip_unlock();
+-			linphone_call_destroy(lc->call);
+-			lc->call=NULL;
++		linphone_call_set_state(lc->call,LCStateRinging);
++		eXosip_lock();
++		eXosip_call_send_answer(ev->tid,180,NULL);
++		eXosip_unlock();
++		/* 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);
++		}
++	}else{
++		ms_error("Error during sdp negociation. ");
++		eXosip_lock();
++		eXosip_call_send_answer(ev->tid,415,NULL);
++		eXosip_unlock();
++		linphone_call_destroy(lc->call);
++		lc->call=NULL;
+ 	}
+ 	end:
+-		osip_free(from);
+-		osip_free(to);
++	osip_free(from);
++	osip_free(to);
+ 	return 0;
+ }
+ 
++void linphone_handle_ack(LinphoneCore *lc, eXosip_event_t *ev){
++	sdp_message_t *sdp=eXosip_get_sdp_info(ev->ack);
++	if (sdp){
++		sdp_context_read_answer(lc->call->sdpctx,sdp);
++		linphone_connect_incoming(lc);
++	}
++}
++
+ void linphone_handle_reinvite(LinphoneCore *lc, eXosip_event_t *ev){
+ 	sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
+ 	sdp_context_t *ctx;
+@@ -823,16 +805,10 @@
+ 
+ void linphone_core_process_event(LinphoneCore *lc,eXosip_event_t *ev)
+ {
+-	sdp_message_t *sdp=NULL;
+-	osip_message_t *msg=NULL;
+ 	switch(ev->type){
+ 		case EXOSIP_CALL_ANSWERED:
+ 			ms_message("CALL_ANSWERED\n");
+-			sdp=eXosip_get_sdp_info(ev->response);
+-			linphone_call_accepted(lc,ev->did,sdp);
+-			/*send the ack once streams are started*/
+-			eXosip_call_build_ack(ev->did,&msg);
+-			eXosip_call_send_ack(ev->did,msg);
++			linphone_call_accepted(lc,ev);
+ 			linphone_authentication_ok(lc,ev);
+ 			break;
+ 		case EXOSIP_CALL_CLOSED:
+@@ -863,6 +839,7 @@
+ 			break;
+ 		case EXOSIP_CALL_ACK:
+ 			ms_message("CALL_ACK");
++			linphone_handle_ack(lc,ev);
+ 			break;
+ 		case EXOSIP_CALL_REDIRECTED:
+ 			ms_message("CALL_REDIRECTED");
+@@ -916,6 +893,5 @@
+ 		default:
+ 			break;
+ 	}
+-	if (sdp) sdp_message_free(sdp);
+ 	eXosip_event_free(ev);
+ }
+diff -urNad linphone-1.99.0~/coreapi/linphonecore.c linphone-1.99.0/coreapi/linphonecore.c
+--- linphone-1.99.0~/coreapi/linphonecore.c	2007-08-07 12:19:44.000000000 +0200
++++ linphone-1.99.0/coreapi/linphonecore.c	2007-10-07 01:42:50.000000000 +0200
+@@ -98,7 +98,6 @@
+ 	call->core=lc;
+ 	linphone_core_get_local_ip(lc,to->url->host,localip);
+ 	call->sdpctx=sdp_handler_create_context(&linphone_sdphandler,localip,from->url->username);
+-	call->profile=lc->local_profile; /*use the readonly local profile*/
+ 	osip_from_to_str(from,&fromstr);
+ 	osip_to_to_str(to,&tostr);
+ 	linphone_call_init_common(call,fromstr,tostr);
+@@ -433,6 +432,8 @@
+ 		}
+ 	}
+ 	
++	/*for test*/
++	lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
+ }
+ 
+ void rtp_config_read(LinphoneCore *lc)
+@@ -878,7 +879,13 @@
+ 	eXosip_set_rsvp_mode (lc->rsvp_enable);
+ 	eXosip_set_rpc_mode (lc->rpc_enable);
+ #endif
+-	snprintf(ua_string,sizeof(ua_string),"Linphone-%s/eXosip2-%s",LINPHONE_VERSION, eXosip_get_version());
++	snprintf(ua_string,sizeof(ua_string),"Linphone-%s/eXosip2-%s",LINPHONE_VERSION,
++#ifdef HAVE_EXOSIP_GET_VERSION
++		 eXosip_get_version()
++#else
++		 "unknown"
++#endif
++);
+ 	eXosip_set_user_agent(ua_string);
+ 	exosip_running=TRUE;
+ }
+@@ -976,15 +983,17 @@
+ 	return ret;
+ }
+ 
+-bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, char **real_url, osip_to_t **real_parsed_url){
++bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, char **real_url, osip_to_t **real_parsed_url, char **route){
+ 	enum_lookup_res_t *enumres=NULL;
+ 	osip_to_t *parsed_url=NULL;
+ 	char *enum_domain=NULL;
+ 	LinphoneProxyConfig *proxy;
+ 	char *tmpurl;
+-	
++	const char *tmproute;
+ 	if (real_url!=NULL) *real_url=NULL;
+ 	if (real_parsed_url!=NULL) *real_parsed_url=NULL;
++	*route=NULL;
++	tmproute=linphone_core_get_route(lc);
+ 	
+ 	if (is_enum(url,&enum_domain)){
+ 		lc->vtable.display_status(lc,_("Looking for telephone number destination..."));
+@@ -998,6 +1007,7 @@
+ 		if (real_url!=NULL) *real_url=ms_strdup(tmpurl);
+ 		if (real_parsed_url!=NULL) *real_parsed_url=osip_to_create(tmpurl);
+ 		enum_lookup_res_free(enumres);
++		if (tmproute) *route=ms_strdup(tmproute);
+ 		return TRUE;
+ 	}
+ 	/* check if we have a "sip:" */
+@@ -1005,22 +1015,25 @@
+ 		/* this doesn't look like a true sip uri */
+ 		proxy=lc->default_proxy;
+ 		if (proxy!=NULL){
+-			/* append the proxy suffix */
+-			osip_uri_t *proxy_uri;
++			/* append the proxy domain suffix */
++			osip_from_t *uri;
+ 			char *sipaddr;
+-			const char *proxy_addr=linphone_proxy_config_get_addr(proxy);
+-			osip_uri_init(&proxy_uri);
+-			if (osip_uri_parse(proxy_uri,proxy_addr)<0){
+-				osip_uri_free(proxy_uri);
++			const char *identity=linphone_proxy_config_get_identity(proxy);
++			osip_from_init(&uri);
++			if (osip_from_parse(uri,identity)<0){
++				osip_from_free(uri);
+ 				return FALSE;
+ 			}
+-			if (proxy_uri->port!=NULL)
+-				sipaddr=ortp_strdup_printf("sip:%s@%s:%s",url,proxy_uri->host,proxy_uri->port);
+-			else
+-				sipaddr=ortp_strdup_printf("sip:%s@%s",url,proxy_uri->host);
++			sipaddr=ortp_strdup_printf("sip:%s@%s",url,uri->url->host);
+ 			if (real_parsed_url!=NULL) *real_parsed_url=osip_to_create(sipaddr);
+ 			if (real_url!=NULL) *real_url=sipaddr;
+ 			else ms_free(sipaddr);
++			/*if the prompted uri was auto-suffixed with proxy domain,
++			then automatically set a route so that the request goes
++			through the proxy*/
++			if (tmproute==NULL) 
++				*route=ms_strdup(linphone_proxy_config_get_addr(proxy));
++			else *route=ms_strdup(tmproute);
+ 			return TRUE;
+ 		}
+ 	}
+@@ -1029,6 +1042,7 @@
+ 		if (real_url!=NULL) *real_url=ms_strdup(url);
+ 		if (real_parsed_url!=NULL) *real_parsed_url=parsed_url;
+ 		else osip_to_free(parsed_url);
++		if (tmproute) *route=ms_strdup(tmproute);
+ 		return TRUE;
+ 	}
+ 	/* else we could not do anything with url given by user, so display an error */
+@@ -1083,11 +1097,12 @@
+ 	
+ 	if (lc->call!=NULL){
+ 		lc->vtable.display_warning(lc,_("Sorry, having multiple simultaneous calls is not supported yet !"));
++		return -1;
+ 	}
+ 
+ 	gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, url);
+ 	linphone_core_get_default_proxy(lc,&proxy);
+-	if (!linphone_core_interpret_url(lc,url,&real_url,&real_parsed_url)){
++	if (!linphone_core_interpret_url(lc,url,&real_url,&real_parsed_url,&route)){
+ 		/* bad url */
+ 		gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
+ 		return -1;
+@@ -1096,8 +1111,8 @@
+ 	lc->vtable.display_status(lc,barmsg);
+ 	ms_free(barmsg);
+ 	if (proxy!=NULL) {
+-		route=linphone_proxy_config_get_route(proxy);
+ 		from=linphone_proxy_config_get_identity(proxy);
++		
+ 	}
+ 	/* if no proxy or no identity defined for this proxy, default to primary contact*/
+ 	if (from==NULL) from=linphone_core_get_primary_contact(lc);
+@@ -1109,16 +1124,20 @@
+ 		ms_warning("Could not build initial invite");
+ 		goto end;
+ 	}
++	
+ 	/* make sdp message */
+ 	
+ 	osip_from_init(&parsed_url2);
+ 	osip_from_parse(parsed_url2,from);
+ 	
+ 	lc->call=linphone_call_new_outgoing(lc,parsed_url2,real_parsed_url);
+-	ctx=lc->call->sdpctx;
+-	sdpmesg=sdp_context_get_offer(ctx);
+-	linphone_set_sdp(invite,sdpmesg);
+-	linphone_core_init_media_streams(lc);
++	if (!lc->sip_conf.sdp_200_ack){
++		ctx=lc->call->sdpctx;
++		lc->call->profile=lc->local_profile;
++		sdpmesg=sdp_context_get_offer(ctx);
++		linphone_set_sdp(invite,sdpmesg);
++		linphone_core_init_media_streams(lc);
++	}
+ 	eXosip_lock();
+ 	err=eXosip_call_send_initial_invite(invite);
+ 	lc->call->cid=err;
+@@ -1138,6 +1157,7 @@
+ 		if (parsed_url2!=NULL) osip_from_free(parsed_url2);
+ 		if (err<0)
+ 			gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
++		if (route!=NULL) ms_free(route);
+ 	return (err<0) ? -1 : 0;
+ }
+ 
+@@ -1147,10 +1167,12 @@
+ 	osip_to_t *real_parsed_url=NULL;
+ 	LinphoneCall *call;
+ 	osip_message_t *msg=NULL;
+-	if (!linphone_core_interpret_url(lc,url,&real_url,&real_parsed_url)){
++	char *route;
++	if (!linphone_core_interpret_url(lc,url,&real_url,&real_parsed_url, &route)){
+ 		/* bad url */
+ 		return -1;
+ 	}
++	if (route!=NULL) ms_free(route);
+ 	call=lc->call;
+ 	if (call==NULL){
+ 		ms_warning("No established call to refer.");
+@@ -1346,6 +1368,7 @@
+ 	char *sdpmesg;
+ 	osip_message_t *msg=NULL;
+ 	LinphoneCall *call=lc->call;
++	bool_t offering=FALSE;
+ 	if (call==NULL){
+ 		return -1;
+ 	}
+@@ -1362,15 +1385,24 @@
+ 	}
+ 	/* sends a 200 OK */
+ 	eXosip_call_build_answer(call->tid,200,&msg);
+-	sdpmesg=call->sdpctx->answerstr;	/* takes the sdp already computed*/
+-	linphone_set_sdp(msg,sdpmesg);
++	/*if a sdp answer is computed, send it, else send an offer */
++	sdpmesg=call->sdpctx->answerstr;
++	if (sdpmesg==NULL){
++		offering=TRUE;
++		call->profile=lc->local_profile;
++		sdpmesg=sdp_context_get_offer(call->sdpctx);
++		linphone_set_sdp(msg,sdpmesg);
++		linphone_core_init_media_streams(lc);
++	}else{
++		linphone_set_sdp(msg,sdpmesg);
++	}
+ 	eXosip_lock();
+ 	eXosip_call_send_answer(call->tid,200,msg);
+ 	eXosip_unlock();
+ 	lc->vtable.display_status(lc,_("Connected."));
+ 	gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL);
+ 	
+-	linphone_core_start_media_streams(lc, lc->call);
++	if (!offering) linphone_core_start_media_streams(lc, lc->call);
+ 	return 0;
+ }
+ 
+@@ -1485,27 +1517,34 @@
+ 	if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_CAPTURE,level);
+ }
+ 
+-static MSSndCard *get_card_from_string_id(const char *devid){
++static MSSndCard *get_card_from_string_id(const char *devid, unsigned int cap){
+ 	MSSndCard *sndcard=NULL;
+ 	if (devid!=NULL){
+ 		sndcard=ms_snd_card_manager_get_card(ms_snd_card_manager_get(),devid);
++		if (sndcard!=NULL && 
++			(ms_snd_card_get_capabilities(sndcard) & cap)==0 ){
++			ms_warning("%s card does not have the %s capability, ignoring.",
++				devid,
++				cap==MS_SND_CARD_CAP_CAPTURE ? "capture" : "playback");
++			sndcard=NULL;
++		}
+ 	}
+ 	if (sndcard==NULL) sndcard=ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
+ 	return sndcard;
+ }
+ 
+ int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid){
+-	lc->sound_conf.ring_sndcard=get_card_from_string_id(devid);
++	lc->sound_conf.ring_sndcard=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK);
+ 	return 0;
+ }
+ 
+ int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid){
+-	lc->sound_conf.play_sndcard=get_card_from_string_id(devid);
++	lc->sound_conf.play_sndcard=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK);
+ 	return 0;
+ }
+ 
+ int linphone_core_set_capture_device(LinphoneCore *lc, const char * devid){
+-	lc->sound_conf.capt_sndcard=get_card_from_string_id(devid);
++	lc->sound_conf.capt_sndcard=get_card_from_string_id(devid,MS_SND_CARD_CAP_CAPTURE);
+ 	return 0;
+ }
+ 
+diff -urNad linphone-1.99.0~/coreapi/linphonecore.h linphone-1.99.0/coreapi/linphonecore.h
+--- linphone-1.99.0~/coreapi/linphonecore.h	2007-06-27 10:36:46.000000000 +0200
++++ linphone-1.99.0/coreapi/linphonecore.h	2007-10-07 01:42:50.000000000 +0200
+@@ -55,6 +55,7 @@
+ 	bool_t guess_hostname;
+ 	bool_t loopback_only;
+ 	bool_t ipv6_enabled;
++	bool_t sdp_200_ack;
+ } sip_config_t;
+ 
+ typedef struct rtp_config
+@@ -277,6 +278,7 @@
+ 	char *passwd;
+ 	char *ha1;
+ 	bool_t works;
++	bool_t first_time;
+ }LinphoneAuthInfo;
+ 
+ LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid,
+@@ -289,6 +291,7 @@
+ struct _LinphoneChatRoom{
+ 	struct _LinphoneCore *lc;
+ 	char  *peer;
++	char *route;
+ 	osip_from_t *peer_url;
+ 	void * user_data;
+ };
+@@ -410,12 +413,6 @@
+ 	LINPHONE_POLICY_USE_STUN
+ } LinphoneFirewallPolicy;
+ 
+-typedef struct _AuthState{
+-	int tid;
+-	char *username;
+-	char *realm;
+-}AuthState;
+-
+ typedef struct _LinphoneCore
+ {
+ 	LinphoneCoreVTable vtable;
+@@ -460,7 +457,6 @@
+ 	int dw_video_bw;
+ 	int up_video_bw;
+ 	int automatic_action;
+-	AuthState authstate;
+ 	bool_t use_files;
+ 	bool_t apply_nat_settings;
+ #ifdef VINCENT_MAURY_RSVP
+@@ -669,7 +665,7 @@
+ void linphone_core_stop_media_streams(LinphoneCore *lc);
+ const char * linphone_core_get_identity(LinphoneCore *lc);
+ const char * linphone_core_get_route(LinphoneCore *lc);
+-bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, char **real_url, osip_to_t **real_parsed_url);
++bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, char **real_url, osip_to_t **real_parsed_url, char **route);
+ 
+ #ifdef __cplusplus
+ }
+diff -urNad linphone-1.99.0~/coreapi/private.h linphone-1.99.0/coreapi/private.h
+--- linphone-1.99.0~/coreapi/private.h	2007-06-01 14:47:21.000000000 +0200
++++ linphone-1.99.0/coreapi/private.h	2007-10-07 01:42:50.000000000 +0200
+@@ -33,7 +33,7 @@
+ #endif
+ 
+ #ifndef LINPHONE_VERSION
+-#define LINPHONE_VERSION "1.7.0"
++#define LINPHONE_VERSION "1.99.1"
+ #endif
+ 
+ #ifndef LIBLINPHONE_VERSION 
+diff -urNad linphone-1.99.0~/gtk/linphone.c linphone-1.99.0/gtk/linphone.c
+--- linphone-1.99.0~/gtk/linphone.c	2007-05-23 15:21:33.000000000 +0200
++++ linphone-1.99.0/gtk/linphone.c	2007-10-07 01:42:50.000000000 +0200
+@@ -39,8 +39,6 @@
+ 
+ void linphone_gnome_ui_init(LinphoneGnomeUI *ui,LinphoneCore *core)
+ {
+-	g_thread_init(NULL);
+-	gdk_threads_init();
+ 	memset(ui,0,sizeof(LinphoneGnomeUI));
+ 	ui->core=core;
+ 	uiobj=ui;
+diff -urNad linphone-1.99.0~/gtk/main.c linphone-1.99.0/gtk/main.c
+--- linphone-1.99.0~/gtk/main.c	2007-05-23 11:18:36.000000000 +0200
++++ linphone-1.99.0/gtk/main.c	2007-10-07 01:42:50.000000000 +0200
+@@ -35,7 +35,8 @@
+ main (int argc, char *argv[])
+ {
+ 	void *p;
+-	
++
++	g_thread_init(NULL);
+ 	//g_log_set_fatal_mask("GLib",G_LOG_LEVEL_WARNING);
+ 	//g_mem_set_vtable(glib_mem_profiler_table);
+ 	//g_mem_set_vtable(&dbgtable);
+diff -urNad linphone-1.99.0~/m4/exosip.m4 linphone-1.99.0/m4/exosip.m4
+--- linphone-1.99.0~/m4/exosip.m4	2007-05-23 11:32:18.000000000 +0200
++++ linphone-1.99.0/m4/exosip.m4	2007-10-07 01:42:50.000000000 +0200
+@@ -1,3 +1,4 @@
++dnl -*- autoconf -*-
+ AC_DEFUN([LP_SETUP_EXOSIP],[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_REQUIRE([LP_CHECK_OSIP2])
+@@ -16,7 +17,14 @@
+ LDFLAGS_save=$LDFLAGS
+ LDFLAGS=$OSIP_LIBS
+ LIBS_save=$LIBS
+-AC_CHECK_LIB(eXosip2,eXosip_subscribe_remove, , AC_MSG_ERROR([Could not find eXosip2 library with version >= 3.0.2 !]),[-losipparser2 -losip2 -lpthread])
++AC_CHECK_LIB([eXosip2],[eXosip_subscribe_remove],
++	[],
++	[AC_MSG_ERROR([Could not find eXosip2 library with version >= 3.0.2 !])],
++	[-losipparser2 -losip2 -lpthread])
++AC_CHECK_LIB([eXosip2],[eXosip_get_version],
++	[AC_DEFINE([HAVE_EXOSIP_GET_VERSION],[1],[Defined when eXosip_get_version is available])],
++	[],
++	[-losipparser2 -losip2 -lpthread])
+ LIBS=$LIBS_save
+ LDFLAGS=$LDFLAGS_save
+ 
+diff -urNad linphone-1.99.0~/mediastreamer2/include/mediastreamer2/msfileplayer.h linphone-1.99.0/mediastreamer2/include/mediastreamer2/msfileplayer.h
+--- linphone-1.99.0~/mediastreamer2/include/mediastreamer2/msfileplayer.h	2006-11-08 18:52:45.000000000 +0100
++++ linphone-1.99.0/mediastreamer2/include/mediastreamer2/msfileplayer.h	2007-10-07 01:42:54.000000000 +0200
+@@ -34,6 +34,7 @@
+ */
+ #define MS_FILE_PLAYER_LOOP	MS_FILTER_METHOD(MS_FILE_PLAYER_ID,4,int)
+ #define MS_FILE_PLAYER_DONE	MS_FILTER_METHOD(MS_FILE_PLAYER_ID,5,int)
++#define MS_FILE_PLAYER_BIG_BUFFER	MS_FILTER_METHOD(MS_FILE_PLAYER_ID,6,int)
+ 
+ /*events*/
+ #define MS_FILE_PLAYER_EOF	MS_FILTER_EVENT_NO_ARG(MS_FILE_PLAYER_ID,0)
+diff -urNad linphone-1.99.0~/mediastreamer2/include/mediastreamer2/msqueue.h linphone-1.99.0/mediastreamer2/include/mediastreamer2/msqueue.h
+--- linphone-1.99.0~/mediastreamer2/include/mediastreamer2/msqueue.h	2006-11-29 14:50:49.000000000 +0100
++++ linphone-1.99.0/mediastreamer2/include/mediastreamer2/msqueue.h	2007-10-07 01:42:54.000000000 +0200
+@@ -44,13 +44,17 @@
+ 
+ static inline void ms_queue_put(MSQueue *q, mblk_t *m){
+ 	putq(&q->q,m);
+-    return;
++	return;
+ }
+ 
+ static inline mblk_t * ms_queue_peek_last(MSQueue *q){
+ 	return qlast(&q->q);
+ }
+ 
++static inline bool_t ms_queue_empty(MSQueue *q){
++	return qempty(&q->q);
++}
++
+ void ms_queue_flush(MSQueue *q);
+ 
+ void ms_queue_destroy(MSQueue *q);
+@@ -72,7 +76,7 @@
+ typedef struct _MSBufferizer MSBufferizer;
+ 
+ /*allocates and initialize */
+-MSBufferizer * ms_bufferizer_new();
++MSBufferizer * ms_bufferizer_new(void);
+ 
+ /*initialize in memory */
+ void ms_bufferizer_init(MSBufferizer *obj);
+diff -urNad linphone-1.99.0~/mediastreamer2/include/mediastreamer2/msticker.h linphone-1.99.0/mediastreamer2/include/mediastreamer2/msticker.h
+--- linphone-1.99.0~/mediastreamer2/include/mediastreamer2/msticker.h	2007-02-07 21:36:18.000000000 +0100
++++ linphone-1.99.0/mediastreamer2/include/mediastreamer2/msticker.h	2007-10-07 01:42:54.000000000 +0200
+@@ -50,7 +50,7 @@
+ typedef struct _MSTicker MSTicker;
+ 	
+ 
+-MSTicker *ms_ticker_new();
++MSTicker *ms_ticker_new(void);
+ 
+ /**
+  * function_name:ms_ticker_attach
+diff -urNad linphone-1.99.0~/mediastreamer2/include/mediastreamer2/msvideo.h linphone-1.99.0/mediastreamer2/include/mediastreamer2/msvideo.h
+--- linphone-1.99.0~/mediastreamer2/include/mediastreamer2/msvideo.h	2007-06-12 15:18:01.000000000 +0200
++++ linphone-1.99.0/mediastreamer2/include/mediastreamer2/msvideo.h	2007-10-07 01:42:54.000000000 +0200
+@@ -68,7 +68,7 @@
+ 
+ int ms_pix_fmt_to_ffmpeg(MSPixFmt fmt);
+ MSPixFmt ffmpeg_pix_fmt_to_ms(int fmt);
+-void ms_ffmpeg_check_init();
++void ms_ffmpeg_check_init(void);
+ 
+ #define MS_FILTER_SET_VIDEO_SIZE	MS_FILTER_BASE_METHOD(100,MSVideoSize)
+ #define MS_FILTER_GET_VIDEO_SIZE	MS_FILTER_BASE_METHOD(101,MSVideoSize)
+diff -urNad linphone-1.99.0~/mediastreamer2/src/msconf.c linphone-1.99.0/mediastreamer2/src/msconf.c
+--- linphone-1.99.0~/mediastreamer2/src/msconf.c	2007-03-09 21:56:35.000000000 +0100
++++ linphone-1.99.0/mediastreamer2/src/msconf.c	2007-10-07 01:42:54.000000000 +0200
+@@ -211,7 +211,7 @@
+ 	chan=&s->channels[0];
+ 	if (s->adaptative_msconf_buf*s->conf_gran<ms_bufferizer_get_avail(&chan->buff))
+ 	{
+-		int i = ms_bufferizer_get_avail(&chan->buff)/s->conf_gran;
++		i = ms_bufferizer_get_avail(&chan->buff)/s->conf_gran;
+ 		if (i>5)
+ 			ms_message("Increasing buffer because sound card is late. (nb_buf=%i /old=%i)", i, s->adaptative_msconf_buf);
+ 		s->adaptative_msconf_buf=i;
+diff -urNad linphone-1.99.0~/mediastreamer2/src/msfileplayer.c linphone-1.99.0/mediastreamer2/src/msfileplayer.c
+--- linphone-1.99.0~/mediastreamer2/src/msfileplayer.c	2007-07-22 11:47:57.000000000 +0200
++++ linphone-1.99.0/mediastreamer2/src/msfileplayer.c	2007-10-07 01:42:54.000000000 +0200
+@@ -160,10 +160,19 @@
+ 			}else freemsg(om);
+ 			if (err<bytes){
+ 				ms_filter_notify_no_arg(f,MS_FILE_PLAYER_EOF);
++				lseek(d->fd,d->hsize,SEEK_SET);
++
++				/* special value for playing file only once */
++				if (d->loop_after==-2)
++				{
++					d->state=STOPPED;
++					ms_filter_unlock(f);
++					return;
++				}
++
+ 				if (d->loop_after>=0){
+-					lseek(d->fd,d->hsize,SEEK_SET);
+ 					d->pause_time=d->loop_after;
+-				}else d->state=STOPPED;
++				}
+ 			}
+ 		}else{
+ 			ms_warning("Fail to read %i bytes: %s",bytes,strerror(errno));
+diff -urNad linphone-1.99.0~/mediastreamer2/src/msfileplayer_win.c linphone-1.99.0/mediastreamer2/src/msfileplayer_win.c
+--- linphone-1.99.0~/mediastreamer2/src/msfileplayer_win.c	2006-11-08 18:52:45.000000000 +0100
++++ linphone-1.99.0/mediastreamer2/src/msfileplayer_win.c	2007-10-07 01:42:54.000000000 +0200
+@@ -37,6 +37,9 @@
+ 	int loop_after;
+ 	int pause_time;
+ 	bool_t swap;
++
++	int stat;
++	int big_buffer; /* ouput less & bigger buffer. (default => no change) */
+ };
+ 
+ typedef struct _PlayerData PlayerData;
+@@ -51,6 +54,8 @@
+ 	d->hsize=0;
+ 	d->loop_after=-1;
+ 	d->pause_time=0;
++	d->stat=-1;
++	d->big_buffer=1;
+ 	f->data=d;	
+ }
+ 
+@@ -99,6 +104,7 @@
+ 	if (d->fd!=INVALID_HANDLE_VALUE)	CloseHandle(d->fd);
+ 	d->fd=NULL;
+ 	d->state=CLOSED;
++	d->stat=-1;
+ 	return 0;
+ }
+ 
+@@ -113,6 +119,7 @@
+ 	PlayerData *d=(PlayerData*)f->data;
+ 	if (d->state==STARTED){
+ 		d->state=STOPPED;
++		d->stat=-1;
+         SetFilePointer(d->fd, d->hsize, NULL, FILE_BEGIN);
+ 	}
+ 	return 0;
+@@ -156,6 +163,8 @@
+ 				}
+ 
+ 				if (d->loop_after>0)
++				{
++					d->stat=-1;
+ 					d->pause_time=d->loop_after;
+ 			}
+ 		}else{
+@@ -180,6 +189,12 @@
+ 	return 0;
+ }
+ 
++static int player_set_big_buffer(MSFilter *f, void *arg){
++	PlayerData *d=(PlayerData*)f->data;
++	d->big_buffer=*((int*)arg);
++	return 0;
++}
++
+ static int player_eof(MSFilter *f, void *arg){
+ 	PlayerData *d=(PlayerData*)f->data;
+ 	if (d->fd==NULL && d->state==CLOSED)
+@@ -204,6 +219,7 @@
+ 	{	MS_FILTER_GET_NCHANNELS, player_get_nch	},
+ 	{	MS_FILE_PLAYER_LOOP,	player_loop	},
+ 	{	MS_FILE_PLAYER_DONE,	player_eof	},
++	{	MS_FILE_PLAYER_BIG_BUFFER,	player_set_big_buffer	},
+ 	{	0,			NULL		}
+ };
+ 
+diff -urNad linphone-1.99.0~/mediastreamer2/src/mssndcard.c linphone-1.99.0/mediastreamer2/src/mssndcard.c
+--- linphone-1.99.0~/mediastreamer2/src/mssndcard.c	2007-02-02 11:42:15.000000000 +0100
++++ linphone-1.99.0/mediastreamer2/src/mssndcard.c	2007-10-07 01:42:54.000000000 +0200
+@@ -51,7 +51,13 @@
+ }
+ 
+ MSSndCard * ms_snd_card_manager_get_default_card(MSSndCardManager *m){
+-	if (m->cards!=NULL) return (MSSndCard*)m->cards->data;
++	/*return the first card that has the capture+playback capability */
++	MSList *elem;
++	for (elem=m->cards;elem!=NULL;elem=elem->next){
++		MSSndCard *card=(MSSndCard*)elem->data;
++		if (card->capabilities==(MS_SND_CARD_CAP_CAPTURE|MS_SND_CARD_CAP_PLAYBACK))
++			return card;
++	}
+ 	return NULL;
+ }
+ 
+diff -urNad linphone-1.99.0~/mediastreamer2/src/msticker.c linphone-1.99.0/mediastreamer2/src/msticker.c
+--- linphone-1.99.0~/mediastreamer2/src/msticker.c	2007-07-22 11:47:57.000000000 +0200
++++ linphone-1.99.0/mediastreamer2/src/msticker.c	2007-10-07 01:42:54.000000000 +0200
+@@ -1,294 +1,294 @@
+-/*
+-mediastreamer2 library - modular sound and video processing and streaming
+-Copyright (C) 2006  Simon MORLAT (simon.morlat at linphone.org)
+-
+-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 "mediastreamer2/msticker.h"
+-
+-
+-void * ms_ticker_run(void *s);
+-static uint64_t get_cur_time(void *);
+-
+-void ms_ticker_start(MSTicker *s){
+-	s->run=TRUE;
+-	ms_thread_create(&s->thread,NULL,ms_ticker_run,s);
+-}
+-
+-
+-void ms_ticker_init(MSTicker *ticker)
+-{
+-	ms_mutex_init(&ticker->lock,NULL);
+-	ms_cond_init(&ticker->cond,NULL);
+-	ticker->execution_list=NULL;
+-	ticker->ticks=1;
+-	ticker->time=0;
+-	ticker->interval=10;
+-	ticker->run=FALSE;
+-	ticker->exec_id=0;
+-	ticker->get_cur_time_ptr=&get_cur_time;
+-	ticker->get_cur_time_data=NULL;
+-#ifdef WIN32_TIMERS
+-	ticker->TimeEvent=NULL;
+-#endif
+-	ms_ticker_start(ticker);
+-}
+-
+-MSTicker *ms_ticker_new(){
+-	MSTicker *obj=ms_new(MSTicker,1);
+-	ms_ticker_init(obj);
+-	return obj;
+-}
+-
+-void ms_ticker_stop(MSTicker *s){
+-	ms_mutex_lock(&s->lock);
+-	s->run=FALSE;
+-	ms_cond_wait(&s->cond,&s->lock);
+-	ms_mutex_unlock(&s->lock);
+-	ms_thread_join(s->thread,NULL);
+-}
+-
+-
+-void ms_ticker_uninit(MSTicker *ticker)
+-{
+-	ms_ticker_stop(ticker);
+-	ms_mutex_destroy(&ticker->lock);
+-	ms_cond_destroy(&ticker->cond);
+-}
+-
+-void ms_ticker_destroy(MSTicker *ticker){
+-	ms_ticker_uninit(ticker);
+-	ms_free(ticker);
+-}
+-
+-static void find_filters(MSList **filters, MSFilter *f ){
+-	int i;
+-	MSQueue *link;
+-	if (f==NULL) ms_fatal("Bad graph.");
+-	/*ms_message("seeing %s, seen=%i",f->desc->name,f->seen);*/
+-	if (f->seen){
+-		return;
+-	}
+-	f->seen=TRUE;
+-	*filters=ms_list_append(*filters,f);
+-	/* go upstream */
+-	for(i=0;i<f->desc->ninputs;i++){
+-		link=f->inputs[i];
+-		if (link!=NULL) find_filters(filters,link->prev.filter);
+-	}
+-	/* go downstream */
+-	for(i=0;i<f->desc->noutputs;i++){
+-		link=f->outputs[i];
+-		if (link!=NULL) find_filters(filters,link->next.filter);
+-	}
+-}
+-
+-static MSList *get_sources(MSList *filters){
+-	MSList *sources=NULL;
+-	MSFilter *f;
+-	for(;filters!=NULL;filters=filters->next){
+-		f=(MSFilter*)filters->data;
+-		if (f->desc->ninputs==0){
+-			sources=ms_list_append(sources,f);
+-		}
+-	}
+-	return sources;
+-}
+-
+-int ms_ticker_attach(MSTicker *ticker,MSFilter *f)
+-{
+-	MSList *sources=NULL;
+-	MSList *filters=NULL;
+-	MSList *it;
+-	
+-	if (f->ticker!=NULL) {
+-		ms_message("Filter %s is already being scheduled; nothing to do.",f->desc->name);
+-		return 0;
+-	}
+-
+-	find_filters(&filters,f);
+-	sources=get_sources(filters);
+-	if (sources==NULL){
+-		ms_fatal("No sources found around filter %s",f->desc->name);
+-		ms_list_free(filters);
+-		return -1;
+-	}
+-	/*run preprocess on each filter: */
+-	for(it=filters;it!=NULL;it=it->next)
+-		ms_filter_preprocess((MSFilter*)it->data,ticker);
+-	ms_mutex_lock(&ticker->lock);
+-	ticker->execution_list=ms_list_concat(ticker->execution_list,sources);
+-	ms_mutex_unlock(&ticker->lock);
+-	ms_list_free(filters);
+-	return 0;
+-}
+-
+-
+-
+-int ms_ticker_detach(MSTicker *ticker,MSFilter *f){
+-	MSList *sources=NULL;
+-	MSList *filters=NULL;
+-	MSList *it;
+-
+-	if (f->ticker==NULL) {
+-		ms_message("Filter %s is not scheduled; nothing to do.",f->desc->name);
+-		return 0;
+-	}
+-
+-	find_filters(&filters,f);
+-	sources=get_sources(filters);
+-	if (sources==NULL){
+-		ms_mutex_unlock(&ticker->lock);
+-		ms_fatal("No sources found around filter %s",f->desc->name);
+-		return -1;
+-	}
+-	ms_mutex_lock(&ticker->lock);
+-	for(it=sources;it!=NULL;it=ms_list_next(it)){
+-		ticker->execution_list=ms_list_remove(ticker->execution_list,it->data);
+-	}
+-	ms_mutex_unlock(&ticker->lock);
+-	ms_list_for_each(filters,(void (*)(void*))ms_filter_postprocess);
+-	ms_list_free(filters);
+-	ms_list_free(sources);
+-	return 0;
+-}
+-
+-
+-static bool_t filter_can_process(MSFilter *f, int tick){
+-	/* look if filters before this one have run */
+-	int i;
+-	MSQueue *l;
+-	for(i=0;i<f->desc->ninputs;i++){
+-		l=f->inputs[i];
+-		if (l!=NULL){
+-			if (l->prev.filter->last_tick!=tick) return FALSE;
+-		}
+-	}
+-	return TRUE;
+-}
+-
+-static void call_process(MSFilter *f){
+-	bool_t process_done=FALSE;
+-	if (f->desc->ninputs==0){
+-		ms_filter_process(f);
+-	}else{
+-		while (ms_filter_inputs_have_data(f)) {
+-			if (process_done){
+-				ms_warning("Re-scheduling filter %s: all data should be consumed in one process call, so fix it.",f->desc->name);
+-			}
+-			ms_filter_process(f);
+-			process_done=TRUE;
+-		}
+-	}
+-}
+-
+-static void run_graph(MSFilter *f, MSTicker *s, MSList **unschedulable, bool_t force_schedule){
+-	int i;
+-	MSQueue *l;
+-	if (f->last_tick!=s->ticks ){
+-		if (filter_can_process(f,s->ticks) || force_schedule) {
+-			/* this is a candidate */
+-			f->last_tick=s->ticks;
+-			call_process(f);	
+-			/* now recurse to next filters */		
+-			for(i=0;i<f->desc->noutputs;i++){
+-				l=f->outputs[i];
+-				if (l!=NULL){
+-					run_graph(l->next.filter,s,unschedulable, force_schedule);
+-				}
+-			}
+-		}else{
+-			/* this filter has not all inputs that have been filled by filters before it. */
+-			*unschedulable=ms_list_prepend(*unschedulable,f);
+-		}
+-	}
+-}
+-
+-static void run_graphs(MSTicker *s, MSList *execution_list, bool_t force_schedule){
+-	MSList *it;
+-	MSList *unschedulable=NULL;
+-	for(it=execution_list;it!=NULL;it=it->next){
+-		run_graph((MSFilter*)it->data,s,&unschedulable,force_schedule);
+-	}
+-	/* filters that are part of a loop haven't been called in process() because one of their input refers to a filter that could not be scheduled (because they could not be scheduled themselves)... Do you understand ?*/
+-	/* we resolve this by simply assuming that they must be called anyway 
+-	for the loop to run correctly*/
+-	/* we just recall run_graphs on them, as if they were source filters */
+-	if (unschedulable!=NULL) {
+-		run_graphs(s,unschedulable,TRUE);
+-		ms_list_free(unschedulable);
+-	}
+-}
+-
+-#ifdef __MACH__
+-#include <sys/types.h>
+-#include <sys/timeb.h>
+-#endif
+-
+-static uint64_t get_cur_time(void *unused){
+-#if defined(_WIN32_WCE)
+-	DWORD timemillis = GetTickCount();
+-	return timemillis;
+-#elif defined(WIN32)
+-	return timeGetTime() ;
+-#elif defined(__MACH__) && defined(__GNUC__) && (__GNUC__ >= 3)
+-	struct timeval tv;
+-	gettimeofday(&tv, NULL);
+-	return (tv.tv_sec*1000LL) + (tv.tv_usec/1000LL);
+-#elif defined(__MACH__)
+-	struct timespec ts;
+-	struct timeb time_val;
+-	
+-	ftime (&time_val);
+-	ts.tv_sec = time_val.time;
+-	ts.tv_nsec = time_val.millitm * 1000000;
+-	return (ts.tv_sec*1000LL) + (ts.tv_nsec/1000000LL);
+-#else
+-	struct timespec ts;
+-	if (clock_gettime(CLOCK_REALTIME,&ts)<0){
+-		ms_fatal("clock_gettime() doesn't work: %s",strerror(errno));
+-	}
+-	return (ts.tv_sec*1000LL) + (ts.tv_nsec/1000000LL);
+-#endif
+-}
++/*
++mediastreamer2 library - modular sound and video processing and streaming
++Copyright (C) 2006  Simon MORLAT (simon.morlat at linphone.org)
+ 
+-static void sleepMs(int ms){
+-#ifdef WIN32
+-	Sleep(ms);
+-#else
+-	struct timespec ts;
+-	ts.tv_sec=0;
+-	ts.tv_nsec=ms*1000000LL;
+-	nanosleep(&ts,NULL);
+-#endif
+-}
+-
+-static int set_high_prio(void){
++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 "mediastreamer2/msticker.h"
++
++
++void * ms_ticker_run(void *s);
++static uint64_t get_cur_time(void *);
++
++void ms_ticker_start(MSTicker *s){
++	s->run=TRUE;
++	ms_thread_create(&s->thread,NULL,ms_ticker_run,s);
++}
++
++
++void ms_ticker_init(MSTicker *ticker)
++{
++	ms_mutex_init(&ticker->lock,NULL);
++	ms_cond_init(&ticker->cond,NULL);
++	ticker->execution_list=NULL;
++	ticker->ticks=1;
++	ticker->time=0;
++	ticker->interval=10;
++	ticker->run=FALSE;
++	ticker->exec_id=0;
++	ticker->get_cur_time_ptr=&get_cur_time;
++	ticker->get_cur_time_data=NULL;
++#ifdef WIN32_TIMERS
++	ticker->TimeEvent=NULL;
++#endif
++	ms_ticker_start(ticker);
++}
++
++MSTicker *ms_ticker_new(){
++	MSTicker *obj=ms_new(MSTicker,1);
++	ms_ticker_init(obj);
++	return obj;
++}
++
++void ms_ticker_stop(MSTicker *s){
++	ms_mutex_lock(&s->lock);
++	s->run=FALSE;
++	ms_cond_wait(&s->cond,&s->lock);
++	ms_mutex_unlock(&s->lock);
++	ms_thread_join(s->thread,NULL);
++}
++
++
++void ms_ticker_uninit(MSTicker *ticker)
++{
++	ms_ticker_stop(ticker);
++	ms_mutex_destroy(&ticker->lock);
++	ms_cond_destroy(&ticker->cond);
++}
++
++void ms_ticker_destroy(MSTicker *ticker){
++	ms_ticker_uninit(ticker);
++	ms_free(ticker);
++}
++
++static void find_filters(MSList **filters, MSFilter *f ){
++	int i;
++	MSQueue *link;
++	if (f==NULL) ms_fatal("Bad graph.");
++	/*ms_message("seeing %s, seen=%i",f->desc->name,f->seen);*/
++	if (f->seen){
++		return;
++	}
++	f->seen=TRUE;
++	*filters=ms_list_append(*filters,f);
++	/* go upstream */
++	for(i=0;i<f->desc->ninputs;i++){
++		link=f->inputs[i];
++		if (link!=NULL) find_filters(filters,link->prev.filter);
++	}
++	/* go downstream */
++	for(i=0;i<f->desc->noutputs;i++){
++		link=f->outputs[i];
++		if (link!=NULL) find_filters(filters,link->next.filter);
++	}
++}
++
++static MSList *get_sources(MSList *filters){
++	MSList *sources=NULL;
++	MSFilter *f;
++	for(;filters!=NULL;filters=filters->next){
++		f=(MSFilter*)filters->data;
++		if (f->desc->ninputs==0){
++			sources=ms_list_append(sources,f);
++		}
++	}
++	return sources;
++}
++
++int ms_ticker_attach(MSTicker *ticker,MSFilter *f)
++{
++	MSList *sources=NULL;
++	MSList *filters=NULL;
++	MSList *it;
++	
++	if (f->ticker!=NULL) {
++		ms_message("Filter %s is already being scheduled; nothing to do.",f->desc->name);
++		return 0;
++	}
++
++	find_filters(&filters,f);
++	sources=get_sources(filters);
++	if (sources==NULL){
++		ms_fatal("No sources found around filter %s",f->desc->name);
++		ms_list_free(filters);
++		return -1;
++	}
++	/*run preprocess on each filter: */
++	for(it=filters;it!=NULL;it=it->next)
++		ms_filter_preprocess((MSFilter*)it->data,ticker);
++	ms_mutex_lock(&ticker->lock);
++	ticker->execution_list=ms_list_concat(ticker->execution_list,sources);
++	ms_mutex_unlock(&ticker->lock);
++	ms_list_free(filters);
++	return 0;
++}
++
++
++
++int ms_ticker_detach(MSTicker *ticker,MSFilter *f){
++	MSList *sources=NULL;
++	MSList *filters=NULL;
++	MSList *it;
++
++	if (f->ticker==NULL) {
++		ms_message("Filter %s is not scheduled; nothing to do.",f->desc->name);
++		return 0;
++	}
++
++	find_filters(&filters,f);
++	sources=get_sources(filters);
++	if (sources==NULL){
++		ms_mutex_unlock(&ticker->lock);
++		ms_fatal("No sources found around filter %s",f->desc->name);
++		return -1;
++	}
++	ms_mutex_lock(&ticker->lock);
++	for(it=sources;it!=NULL;it=ms_list_next(it)){
++		ticker->execution_list=ms_list_remove(ticker->execution_list,it->data);
++	}
++	ms_mutex_unlock(&ticker->lock);
++	ms_list_for_each(filters,(void (*)(void*))ms_filter_postprocess);
++	ms_list_free(filters);
++	ms_list_free(sources);
++	return 0;
++}
++
++
++static bool_t filter_can_process(MSFilter *f, int tick){
++	/* look if filters before this one have run */
++	int i;
++	MSQueue *l;
++	for(i=0;i<f->desc->ninputs;i++){
++		l=f->inputs[i];
++		if (l!=NULL){
++			if (l->prev.filter->last_tick!=tick) return FALSE;
++		}
++	}
++	return TRUE;
++}
++
++static void call_process(MSFilter *f){
++	bool_t process_done=FALSE;
++	if (f->desc->ninputs==0){
++		ms_filter_process(f);
++	}else{
++		while (ms_filter_inputs_have_data(f)) {
++			if (process_done){
++				ms_warning("Re-scheduling filter %s: all data should be consumed in one process call, so fix it.",f->desc->name);
++			}
++			ms_filter_process(f);
++			process_done=TRUE;
++		}
++	}
++}
++
++static void run_graph(MSFilter *f, MSTicker *s, MSList **unschedulable, bool_t force_schedule){
++	int i;
++	MSQueue *l;
++	if (f->last_tick!=s->ticks ){
++		if (filter_can_process(f,s->ticks) || force_schedule) {
++			/* this is a candidate */
++			f->last_tick=s->ticks;
++			call_process(f);	
++			/* now recurse to next filters */		
++			for(i=0;i<f->desc->noutputs;i++){
++				l=f->outputs[i];
++				if (l!=NULL){
++					run_graph(l->next.filter,s,unschedulable, force_schedule);
++				}
++			}
++		}else{
++			/* this filter has not all inputs that have been filled by filters before it. */
++			*unschedulable=ms_list_prepend(*unschedulable,f);
++		}
++	}
++}
++
++static void run_graphs(MSTicker *s, MSList *execution_list, bool_t force_schedule){
++	MSList *it;
++	MSList *unschedulable=NULL;
++	for(it=execution_list;it!=NULL;it=it->next){
++		run_graph((MSFilter*)it->data,s,&unschedulable,force_schedule);
++	}
++	/* filters that are part of a loop haven't been called in process() because one of their input refers to a filter that could not be scheduled (because they could not be scheduled themselves)... Do you understand ?*/
++	/* we resolve this by simply assuming that they must be called anyway 
++	for the loop to run correctly*/
++	/* we just recall run_graphs on them, as if they were source filters */
++	if (unschedulable!=NULL) {
++		run_graphs(s,unschedulable,TRUE);
++		ms_list_free(unschedulable);
++	}
++}
++
++#ifdef __MACH__
++#include <sys/types.h>
++#include <sys/timeb.h>
++#endif
++
++static uint64_t get_cur_time(void *unused){
++#if defined(_WIN32_WCE)
++	DWORD timemillis = GetTickCount();
++	return timemillis;
++#elif defined(WIN32)
++	return timeGetTime() ;
++#elif defined(__MACH__) && defined(__GNUC__) && (__GNUC__ >= 3)
++	struct timeval tv;
++	gettimeofday(&tv, NULL);
++	return (tv.tv_sec*1000LL) + (tv.tv_usec/1000LL);
++#elif defined(__MACH__)
++	struct timespec ts;
++	struct timeb time_val;
++	
++	ftime (&time_val);
++	ts.tv_sec = time_val.time;
++	ts.tv_nsec = time_val.millitm * 1000000;
++	return (ts.tv_sec*1000LL) + (ts.tv_nsec/1000000LL);
++#else
++	struct timespec ts;
++	if (clock_gettime(CLOCK_REALTIME,&ts)<0){
++		ms_fatal("clock_gettime() doesn't work: %s",strerror(errno));
++	}
++	return (ts.tv_sec*1000LL) + (ts.tv_nsec/1000000LL);
++#endif
++}
++
++static void sleepMs(int ms){
++#ifdef WIN32
++	Sleep(ms);
++#else
++	struct timespec ts;
++	ts.tv_sec=0;
++	ts.tv_nsec=ms*1000000LL;
++	nanosleep(&ts,NULL);
++#endif
++}
++
++static int set_high_prio(void){
+ 	int precision=2;
+-#ifdef WIN32
++#ifdef WIN32
+ 	MMRESULT mm;
+ 	TIMECAPS ptc;
+ 	mm=timeGetDevCaps(&ptc,sizeof(ptc));
+ 	if (mm==0){
+-		if (ptc.wPeriodMin<precision)
+-			ptc.wPeriodMin=precision;
+-		else
+-			precision = ptc.wPeriodMin;
++		if (ptc.wPeriodMin<precision)
++			ptc.wPeriodMin=precision;
++		else
++			precision = ptc.wPeriodMin;
+ 		mm=timeBeginPeriod(ptc.wPeriodMin);
+ 		if (mm!=TIMERR_NOERROR){
+ 			ms_warning("timeBeginPeriod failed.");
+@@ -298,171 +298,172 @@
+ 		ms_warning("timeGetDevCaps failed.");
+ 	}
+ 
+-	if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)){
+-		ms_warning("SetThreadPriority() failed (%d)\n", GetLastError());
+-	}
+-#endif
+-	return precision;
+-}
+-
+-static void unset_high_prio(int precision){
+-#ifdef WIN32
++	if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)){
++		ms_warning("SetThreadPriority() failed (%d)\n", GetLastError());
++	}
++#endif
++	return precision;
++}
++
++static void unset_high_prio(int precision){
++#ifdef WIN32
+ 	MMRESULT mm;
+ 
+-	if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL)){
+-		ms_warning("SetThreadPriority() failed (%d)\n", GetLastError());
+-	}
+-
+-	mm=timeEndPeriod(precision);
+-#endif
+-}
+-
+-#ifndef WIN32_TIMERS
+-
+-void * ms_ticker_run(void *arg)
+-{
+-	MSTicker *s=(MSTicker*)arg;
+-	uint64_t realtime;
+-	int lastlate=0;
+-	int precision=2;
+-
+-	precision = set_high_prio();
+-
+-
+-	s->ticks=1;
+-	ms_mutex_lock(&s->lock);
+-	s->orig=s->get_cur_time_ptr(s->get_cur_time_data);
+-
+-	while(s->run){
+-		s->ticks++;
+-		run_graphs(s,s->execution_list,FALSE);
+-		s->time+=s->interval;
+-		while(1){
+-			int64_t diff;
+-			realtime=s->get_cur_time_ptr(s->get_cur_time_data)-s->orig;
+-			ms_mutex_unlock(&s->lock);
+-			diff=s->time-realtime;
+-			if (diff>0){
+-				/* sleep until next tick */
+-				sleepMs(diff);
+-			}else{
+-				int late=-diff;
+-				if (late>s->interval*5 && late>lastlate){
+-					ms_warning("We are late of %d miliseconds.",late);
+-				}
+-				lastlate=late;
+-				break; /*exit the while loop */
+-			}
+-			ms_mutex_lock(&s->lock);
+-		}
+-		ms_mutex_lock(&s->lock);
+-	}
+-	ms_cond_signal(&s->cond);
+-	ms_mutex_unlock(&s->lock);
+-	unset_high_prio(precision);
+-	ms_message("MSTicker thread exiting");
+-	ms_thread_exit(NULL);
+-	return NULL;
+-}
+-
+-#else
+-
+-void * ms_ticker_run(void *arg)
+-{
+-	MSTicker *s=(MSTicker*)arg;
+-	uint64_t realtime;
+-	int precision=2;
+-	UINT timerId;
+-
+-	precision = set_high_prio();
+-
+-	s->TimeEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
+-
+-	s->ticks=1;
+-	ms_mutex_lock(&s->lock);
+-	s->orig=s->get_cur_time_ptr(s->get_cur_time_data);
+-
+-	timerId = timeSetEvent (s->interval, precision, s->TimeEvent, 0,
+-				  TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
+-	while(s->run){
+-		DWORD err;
+-
+-		s->ticks++;
+-		run_graphs(s,s->execution_list,FALSE);
+-
+-		/* elapsed time since origin */
+-		s->time = s->get_cur_time_ptr(s->get_cur_time_data)- s->orig;
+-
+-		ms_mutex_unlock(&s->lock);
+-		err = WaitForSingleObject (s->TimeEvent, s->interval*1000 ); /* wake up each diff */
+-		if (err==WAIT_FAILED)
++	if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL)){
++		ms_warning("SetThreadPriority() failed (%d)\n", GetLastError());
++	}
++
++	mm=timeEndPeriod(precision);
++#endif
++}
++
++#ifndef WIN32_TIMERS
++
++void * ms_ticker_run(void *arg)
++{
++	uint64_t realtime;
++	int64_t diff;
++	MSTicker *s=(MSTicker*)arg;
++	int lastlate=0;
++	int precision=2;
++	int late;
++	
++	precision = set_high_prio();
++
++
++	s->ticks=1;
++	ms_mutex_lock(&s->lock);
++	s->orig=s->get_cur_time_ptr(s->get_cur_time_data);
++
++	while(s->run){
++		s->ticks++;
++		run_graphs(s,s->execution_list,FALSE);
++		s->time+=s->interval;
++		while(1){
++			realtime=s->get_cur_time_ptr(s->get_cur_time_data)-s->orig;
++			ms_mutex_unlock(&s->lock);
++			diff=s->time-realtime;
++			if (diff>0){
++				/* sleep until next tick */
++				sleepMs(diff);
++			}else{
++				late=-diff;
++				if (late>s->interval*5 && late>lastlate){
++					ms_warning("We are late of %d miliseconds.",late);
++				}
++				lastlate=late;
++				break; /*exit the while loop */
++			}
++			ms_mutex_lock(&s->lock);
++		}
++		ms_mutex_lock(&s->lock);
++	}
++	ms_cond_signal(&s->cond);
++	ms_mutex_unlock(&s->lock);
++	unset_high_prio(precision);
++	ms_message("MSTicker thread exiting");
++	ms_thread_exit(NULL);
++	return NULL;
++}
++
++#else
++
++void * ms_ticker_run(void *arg)
++{
++	MSTicker *s=(MSTicker*)arg;
++	uint64_t realtime;
++	int precision=2;
++	UINT timerId;
++
++	precision = set_high_prio();
++
++	s->TimeEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
++
++	s->ticks=1;
++	ms_mutex_lock(&s->lock);
++	s->orig=s->get_cur_time_ptr(s->get_cur_time_data);
++
++	timerId = timeSetEvent (s->interval, precision, s->TimeEvent, 0,
++				  TIME_PERIODIC | TIME_CALLBACK_EVENT_SET);
++	while(s->run){
++		DWORD err;
++
++		s->ticks++;
++		run_graphs(s,s->execution_list,FALSE);
++
++		/* elapsed time since origin */
++		s->time = s->get_cur_time_ptr(s->get_cur_time_data)- s->orig;
++
++		ms_mutex_unlock(&s->lock);
++		err = WaitForSingleObject (s->TimeEvent, s->interval*1000 ); /* wake up each diff */
++		if (err==WAIT_FAILED)
+ 			ms_message("WaitForSingleObject is failing");
+-
+-		ms_mutex_lock(&s->lock);
+-	}
+-	ms_cond_signal(&s->cond);
+-	ms_mutex_unlock(&s->lock);
+-	timeKillEvent (timerId);
+-	CloseHandle (s->TimeEvent);
+-	s->TimeEvent=NULL;
+-	unset_high_prio(precision);
+-	ms_message("MSTicker thread exiting");
+-	ms_thread_exit(NULL);
+-	return NULL;
+-}
+-
+-#endif
+-
+-void ms_ticker_set_time_func(MSTicker *ticker, MSTickerTimeFunc func, void *user_data){
+-	if (func==NULL) func=get_cur_time;
+-	/*ms_mutex_lock(&ticker->lock);*/
+-	ticker->get_cur_time_ptr=func;
+-	ticker->get_cur_time_data=user_data;
+-	/*re-set the origin to take in account that previous function ptr and the
+-	new one may return different times*/
+-	ticker->orig=func(user_data)-ticker->time;
+-	/*ms_mutex_unlock(&ticker->lock);*/
+-	ms_message("ms_ticker_set_time_func: ticker updated.");
+-}
+-
+-static void print_graph(MSFilter *f, MSTicker *s, MSList **unschedulable, bool_t force_schedule){
+-	int i;
+-	MSQueue *l;
+-	if (f->last_tick!=s->ticks ){
+-		if (filter_can_process(f,s->ticks) || force_schedule) {
+-			/* this is a candidate */
+-			f->last_tick=s->ticks;
+-			ms_message("print_graphs: %s", f->desc->name);
+-			/* now recurse to next filters */		
+-			for(i=0;i<f->desc->noutputs;i++){
+-				l=f->outputs[i];
+-				if (l!=NULL){
+-					print_graph(l->next.filter,s,unschedulable, force_schedule);
+-				}
+-			}
+-		}else{
+-			/* this filter has not all inputs that have been filled by filters before it. */
+-			*unschedulable=ms_list_prepend(*unschedulable,f);
+-		}
+-	}
+-}
+-
+-static void print_graphs(MSTicker *s, MSList *execution_list, bool_t force_schedule){
+-	MSList *it;
+-	MSList *unschedulable=NULL;
+-	for(it=execution_list;it!=NULL;it=it->next){
+-		print_graph((MSFilter*)it->data,s,&unschedulable,force_schedule);
+-	}
+-	/* filters that are part of a loop haven't been called in process() because one of their input refers to a filter that could not be scheduled (because they could not be scheduled themselves)... Do you understand ?*/
+-	/* we resolve this by simply assuming that they must be called anyway 
+-	for the loop to run correctly*/
+-	/* we just recall run_graphs on them, as if they were source filters */
+-	if (unschedulable!=NULL) {
+-		print_graphs(s,unschedulable,TRUE);
+-		ms_list_free(unschedulable);
+-	}
+-}
+-
+-void ms_ticker_print_graphs(MSTicker *ticker){
+-	print_graphs(ticker,ticker->execution_list,FALSE);
+-}
++
++		ms_mutex_lock(&s->lock);
++	}
++	ms_cond_signal(&s->cond);
++	ms_mutex_unlock(&s->lock);
++	timeKillEvent (timerId);
++	CloseHandle (s->TimeEvent);
++	s->TimeEvent=NULL;
++	unset_high_prio(precision);
++	ms_message("MSTicker thread exiting");
++	ms_thread_exit(NULL);
++	return NULL;
++}
++
++#endif
++
++void ms_ticker_set_time_func(MSTicker *ticker, MSTickerTimeFunc func, void *user_data){
++	if (func==NULL) func=get_cur_time;
++	/*ms_mutex_lock(&ticker->lock);*/
++	ticker->get_cur_time_ptr=func;
++	ticker->get_cur_time_data=user_data;
++	/*re-set the origin to take in account that previous function ptr and the
++	new one may return different times*/
++	ticker->orig=func(user_data)-ticker->time;
++	/*ms_mutex_unlock(&ticker->lock);*/
++	ms_message("ms_ticker_set_time_func: ticker updated.");
++}
++
++static void print_graph(MSFilter *f, MSTicker *s, MSList **unschedulable, bool_t force_schedule){
++	int i;
++	MSQueue *l;
++	if (f->last_tick!=s->ticks ){
++		if (filter_can_process(f,s->ticks) || force_schedule) {
++			/* this is a candidate */
++			f->last_tick=s->ticks;
++			ms_message("print_graphs: %s", f->desc->name);
++			/* now recurse to next filters */		
++			for(i=0;i<f->desc->noutputs;i++){
++				l=f->outputs[i];
++				if (l!=NULL){
++					print_graph(l->next.filter,s,unschedulable, force_schedule);
++				}
++			}
++		}else{
++			/* this filter has not all inputs that have been filled by filters before it. */
++			*unschedulable=ms_list_prepend(*unschedulable,f);
++		}
++	}
++}
++
++static void print_graphs(MSTicker *s, MSList *execution_list, bool_t force_schedule){
++	MSList *it;
++	MSList *unschedulable=NULL;
++	for(it=execution_list;it!=NULL;it=it->next){
++		print_graph((MSFilter*)it->data,s,&unschedulable,force_schedule);
++	}
++	/* filters that are part of a loop haven't been called in process() because one of their input refers to a filter that could not be scheduled (because they could not be scheduled themselves)... Do you understand ?*/
++	/* we resolve this by simply assuming that they must be called anyway 
++	for the loop to run correctly*/
++	/* we just recall run_graphs on them, as if they were source filters */
++	if (unschedulable!=NULL) {
++		print_graphs(s,unschedulable,TRUE);
++		ms_list_free(unschedulable);
++	}
++}
++
++void ms_ticker_print_graphs(MSTicker *ticker){
++	print_graphs(ticker,ticker->execution_list,FALSE);
++}
+diff -urNad linphone-1.99.0~/mediastreamer2/src/videoenc.c linphone-1.99.0/mediastreamer2/src/videoenc.c
+--- linphone-1.99.0~/mediastreamer2/src/videoenc.c	2007-08-04 22:13:18.000000000 +0200
++++ linphone-1.99.0/mediastreamer2/src/videoenc.c	2007-10-07 01:42:54.000000000 +0200
+@@ -256,7 +256,7 @@
+ 	c->max_b_frames=0; /*don't use b frames*/
+ 	c->flags|=CODEC_FLAG_AC_PRED;
+ 	c->flags|=CODEC_FLAG_H263P_UMV;
+-	c->flags|=CODEC_FLAG_QPEL;
++	/*c->flags|=CODEC_FLAG_QPEL;*/ /*don't enable this one: this forces profile_level to advanced simple profile */
+ 	c->flags|=CODEC_FLAG_4MV;
+ 	c->flags|=CODEC_FLAG_GMC;
+ 	c->flags|=CODEC_FLAG_LOOP_FILTER;
+@@ -418,9 +418,9 @@
+ 	AVFrame pict;
+ 	AVCodecContext *c=&s->av_context;
+ 	int error;
+-	
+ 	mblk_t *comp_buf=s->comp_buf;
+ 	int comp_buf_sz=comp_buf->b_datap->db_lim-comp_buf->b_datap->db_base;
++	
+ 	/* convert image if necessary */
+ 	avcodec_get_frame_defaults(&pict);
+ 	avpicture_fill((AVPicture*)&pict,(uint8_t*)inm->b_rptr,c->pix_fmt,c->width,c->height);
+diff -urNad linphone-1.99.0~/mediastreamer2/src/winsnd2.c linphone-1.99.0/mediastreamer2/src/winsnd2.c
+--- linphone-1.99.0~/mediastreamer2/src/winsnd2.c	2007-07-19 13:29:08.000000000 +0200
++++ linphone-1.99.0/mediastreamer2/src/winsnd2.c	2007-10-07 01:42:54.000000000 +0200
+@@ -29,6 +29,7 @@
+ 
+ #define WINSND_NBUFS 10
+ #define WINSND_NSAMPLES 160
++#define WINSND_MINIMUMBUFFER 5
+ 
+ static MSFilter *ms_winsnd_read_new(MSSndCard *card);
+ static MSFilter *ms_winsnd_write_new(MSSndCard *card);
+diff -urNad linphone-1.99.0~/oRTP/ChangeLog linphone-1.99.0/oRTP/ChangeLog
+--- linphone-1.99.0~/oRTP/ChangeLog	2007-05-03 16:28:30.000000000 +0200
++++ linphone-1.99.0/oRTP/ChangeLog	2007-10-07 01:42:54.000000000 +0200
+@@ -1,4 +1,9 @@
+-2007-04-19  Francois-Xavier Kowalski  <fix at hp.com>
++2007-07-26  Francois-Xavier Kowalski  <fix at hp.com>
++
++	* pkg.list: 1.3 
++	  Do not run makewhatis when installing EPM-generated package.
++
++2007-04-19 Francois-Xavier Kowalski <fix at hp.com>
+ 
+ 	* ortp.spec.in (Requires): 1.4
+ 	  Adapt  to new  documentation generation  change from  gtk-doc to
+diff -urNad linphone-1.99.0~/oRTP/include/ortp/rtpsession.h linphone-1.99.0/oRTP/include/ortp/rtpsession.h
+--- linphone-1.99.0~/oRTP/include/ortp/rtpsession.h	2007-08-01 16:09:29.000000000 +0200
++++ linphone-1.99.0/oRTP/include/ortp/rtpsession.h	2007-10-07 01:42:54.000000000 +0200
+@@ -154,6 +154,7 @@
+ 	struct sockaddr_in rem_addr;
+ #endif
+ 	int rem_addrlen;
++	bool_t enabled; /*tells whether we can send RTCP packets */
+ } RtcpStream;
+ 
+ typedef struct _RtpSession RtpSession;
+@@ -284,6 +285,8 @@
+ 
+ void rtp_session_set_connected_mode(RtpSession *session, bool_t yesno);
+ 
++void rtp_session_enable_rtcp(RtpSession *session, bool_t yesno);
++
+ /*low level recv and send functions */
+ mblk_t * rtp_session_recvm_with_ts (RtpSession * session, uint32_t user_ts);
+ mblk_t * rtp_session_create_packet(RtpSession *session,int header_size, const uint8_t *payload, int payload_size);
+diff -urNad linphone-1.99.0~/oRTP/include/ortp/stun_udp.h linphone-1.99.0/oRTP/include/ortp/stun_udp.h
+--- linphone-1.99.0~/oRTP/include/ortp/stun_udp.h	2007-03-22 20:59:56.000000000 +0100
++++ linphone-1.99.0/oRTP/include/ortp/stun_udp.h	2007-10-07 01:42:54.000000000 +0200
+@@ -94,8 +94,8 @@
+ #else
+ 
+ typedef int Socket;
+-static const Socket INVALID_SOCKET = -1;
+-static const int SOCKET_ERROR = -1;
++#define INVALID_SOCKET -1
++#define SOCKET_ERROR -1
+ 
+ #define closesocket(fd) close(fd)
+ 
+diff -urNad linphone-1.99.0~/oRTP/pkg.list linphone-1.99.0/oRTP/pkg.list
+--- linphone-1.99.0~/oRTP/pkg.list	2006-08-09 15:01:57.000000000 +0200
++++ linphone-1.99.0/oRTP/pkg.list	2007-10-07 01:42:54.000000000 +0200
+@@ -16,20 +16,15 @@
+ 
+ %system linux
+ 
+-# Compress man pages
+-%define __spec_install_post /usr/lib/rpm/brp-compress || :
+-
+ # Package all-in one: should be split later on...
+ %provides ortp-devel
+ 
+ %postinstall << EOF
+ ldconfig 2>&1 | logger -i -s -t ${PACKAGE}
+-makewhatis -u -w 2>&1 | logger -i -s -t ${PACKAGE}
+ EOF
+ 
+ %postremove << EOF
+ ldconfig 2>&1 | logger -i -s -t ${PACKAGE}
+-makewhatis -u -w 2>&1 | logger -i -s -t ${PACKAGE}
+ EOF
+ 
+ %system hpux
+diff -urNad linphone-1.99.0~/oRTP/src/rtpsession.c linphone-1.99.0/oRTP/src/rtpsession.c
+--- linphone-1.99.0~/oRTP/src/rtpsession.c	2007-08-01 16:14:52.000000000 +0200
++++ linphone-1.99.0/oRTP/src/rtpsession.c	2007-10-07 01:42:54.000000000 +0200
+@@ -265,6 +265,7 @@
+ 	rtp_session_enable_jitter_buffer(session,TRUE);
+ 	rtp_session_set_jitter_buffer_params(session,&jbp);
+ 	rtp_session_set_time_jump_limit(session,5000);
++	rtp_session_enable_rtcp(session,TRUE);
+ 	session->recv_buf_size = UDP_MAX_SIZE;
+ 	session->symmetric_rtp = FALSE;
+ 	session->permissive=FALSE;
+@@ -364,6 +365,17 @@
+ 	rtp_session_telephone_events_supported(session);
+ }
+ 
++/**
++ *	By default oRTP automatically sends RTCP SR or RR packets. If
++ *	yesno is set to FALSE, the RTCP sending of packet is disabled.
++ *	This functionnality might be needed for some equipments that do not
++ *	support RTCP, leading to a traffic of ICMP errors on the network.
++ *	It can also be used to save bandwidth despite the RTCP bandwidth is 
++ *	actually and usually very very low.
++**/
++void rtp_session_enable_rtcp(RtpSession *session, bool_t yesno){
++	session->rtcp.enabled=yesno;
++}
+ 
+ /**
+  *	Set the RTP profile to be used for the sending by this session. By default, all session are created by
+@@ -1478,9 +1490,10 @@
+ 	float time;
+ 	if (bytes==0) return 0;
+ 	gettimeofday(&current,NULL);
+-	time=(current.tv_sec - orig->tv_sec) +
+-		((current.tv_usec - orig->tv_usec)*1e-6);
+-	bw=((float)bytes)*8/time;
++	time=(float)(current.tv_sec - orig->tv_sec) +
++		((float)(current.tv_usec - orig->tv_usec)*1e-6);
++	bw=((float)bytes)*8/(time+0.001); 
++	/*+0.0001 avoids a division by zero without changing the results significatively*/
+ 	return bw;
+ }
+ 
+diff -urNad linphone-1.99.0~/oRTP/src/rtpsession_inet.c linphone-1.99.0/oRTP/src/rtpsession_inet.c
+--- linphone-1.99.0~/oRTP/src/rtpsession_inet.c	2007-08-01 10:24:35.000000000 +0200
++++ linphone-1.99.0/oRTP/src/rtpsession_inet.c	2007-10-07 01:42:54.000000000 +0200
+@@ -786,7 +786,9 @@
+ 		destlen=0;
+ 	}
+ 
+-	if ((sockfd>=0 || rtp_session_using_transport(session, rtcp)) && (session->rtcp.rem_addrlen>0 ||using_connected_socket) ){
++	if (session->rtcp.enabled &&
++		( (sockfd>=0 && (session->rtcp.rem_addrlen>0 ||using_connected_socket))
++			|| rtp_session_using_transport(session, rtcp) ) ){
+ 		if (rtp_session_using_transport(session, rtcp)){
+ 			error = (session->rtcp.tr->t_sendto) (session->rtcp.tr, m, 0,
+ 			destaddr, destlen);
+@@ -809,7 +811,7 @@
+ 				rtp_signal_table_emit3(&session->on_network_error,(long)"Error sending RTCP packet",INT_TO_POINTER(getSocketErrorCode()));
+ 			}else ortp_warning ("Error sending rtcp packet: %s ; socket=%i; addr=%s", getSocketError(), session->rtcp.socket, ortp_inet_ntoa((struct sockaddr*)&session->rtcp.rem_addr,session->rtcp.rem_addrlen,host,sizeof(host)) );
+ 		}
+-	}else ortp_warning("Cannot send rtcp report: sockfd=%i, rem_addrlen=%i, connected=%i",sockfd,session->rtcp.rem_addrlen,using_connected_socket);
++	}else ortp_message("Not sending rtcp report: sockfd=%i, rem_addrlen=%i, connected=%i",sockfd,session->rtcp.rem_addrlen,using_connected_socket);
+ 	freemsg (m);
+ 	return error;
+ }

Propchange: linphone/trunk/debian/patches/fix_segfault.dpatch
------------------------------------------------------------------------------
    svn:executable = *




More information about the Pkg-voip-commits mailing list