[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(¤t,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