#include "linphonecore.h"
#include "private.h"
#include "mediastreamer2/mediastream.h"
+#include "lpconfig.h"
static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details);
const char *from,*to;
char *tmp;
LinphoneAddress *from_parsed;
+ bool_t early_media=lp_config_get_int(lc->config,"sip","send_early_media",0);
/* first check if we can answer successfully to this invite */
if (lc->presence_mode==LinphoneStatusBusy ||
}else{
/*TODO : play a tone within the context of the current call */
}
- sal_call_notify_ringing(h);
+ sal_call_notify_ringing(h,early_media);
#if !(__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)
linphone_call_init_media_streams(call);
+ if (early_media){
+ linphone_call_start_early_media (call);
+ }
#endif
ms_free(barmesg);
ms_free(tmp);
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/msvolume.h"
#include "mediastreamer2/msequalizer.h"
+#include "mediastreamer2/msfileplayer.h"
static MSWebCam *get_nowebcam_device(){
return ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),"StaticImage: Static picture");
LinphoneCall *call, bool_t with_video, bool_t only_one_codec){
MSList *l;
PayloadType *pt;
- const char *username=(call->dir==LinphoneCallOutgoing) ?
- linphone_address_get_username(call->log->from): linphone_address_get_username(call->log->to);
+ const char *me=linphone_core_get_identity(lc);
+ LinphoneAddress *addr=linphone_address_new(me);
+ const char *username=linphone_address_get_username (addr);
SalMediaDescription *md=sal_media_description_new();
+
md->nstreams=1;
strncpy(md->addr,call->localip,sizeof(md->addr));
strncpy(md->username,username,sizeof(md->username));
if (lc->dw_video_bw)
md->streams[1].bandwidth=lc->dw_video_bw;
}
+ linphone_address_destroy(addr);
return md;
}
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
LinphoneCall *call=ms_new0(LinphoneCall,1);
- LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
char *to_str;
char *from_str;
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
linphone_core_run_stun_tests(call->core,call);
discover_mtu(lc,linphone_address_get_domain(from));
- linphone_address_destroy(me);
return call;
}
return prof;
}
-void linphone_call_start_media_streams(LinphoneCall *call){
+static void setup_ring_player(LinphoneCore *lc, LinphoneCall *call){
+ const char *ringfile=lc->sound_conf.remote_ring;
+ int pause_time=3000;
+ audio_stream_play(call->audiostream,ringfile);
+ ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
+}
+
+static void _linphone_call_start_media_streams(LinphoneCall *call, bool_t send_early_media){
LinphoneCore *lc=call->core;
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
const char *tool="linphone-" LINPHONE_VERSION;
if (stream->port==0 || stream->dir==SalStreamRecvOnly){
captcard=NULL;
playfile=NULL;
- }else if (stream->dir==SalStreamSendOnly){
+ }else if (stream->dir==SalStreamSendOnly || send_early_media){
playcard=NULL;
captcard=NULL;
recfile=NULL;
captcard,
linphone_core_echo_cancellation_enabled(lc));
post_configure_audio_streams(call);
+ if (send_early_media) setup_ring_player(lc,call);
audio_stream_set_rtcp_information(call->audiostream, cname, tool);
}else ms_warning("No audio stream accepted ?");
}
}
#ifdef VIDEO_ENABLED
- {
+ if (!send_early_media){
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpAvp,SalVideo);
used_pt=-1;
}
+void linphone_call_start_media_streams(LinphoneCall *call){
+ _linphone_call_start_media_streams(call,FALSE);
+}
+
+void linphone_call_start_early_media(LinphoneCall *call){
+ _linphone_call_start_media_streams(call,TRUE);
+}
static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
audio_stream_get_local_rtp_stats (st,&log->local_stats);
/**
* Returns the default identity SIP address.
*
- * @ingroup proxiesb
+ * @ingroup proxies
* This is an helper function:
*
* If no default proxy is set, this will return the primary contact (
sal_op_set_contact(call->op,contact);
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000
linphone_call_init_media_streams(call);
+#else
+ if (call->audiostream!=NULL && call->audiostream->ticker!=NULL){
+ /*case where we sent early media*/
+ linphone_call_stop_media_streams (call);
+ linphone_call_init_media_streams (call);
+ }
#endif
sal_call_accept(call->op);
if (lc->vtable.display_status!=NULL)
const char *linphone_core_get_primary_contact(LinphoneCore *lc);
+const char * linphone_core_get_identity(LinphoneCore *lc);
+
void linphone_core_set_guess_hostname(LinphoneCore *lc, bool_t val);
bool_t linphone_core_get_guess_hostname(LinphoneCore *lc);
for(i=0,j=0;i<local_offer->nstreams;++i){
ms_message("Processing for stream %i",i);
ls=&local_offer->streams[i];
- rs=sal_media_description_find_stream(remote_answer,ls->proto,ls->type);
+ rs=sal_media_description_find_stream((SalMediaDescription*)remote_answer,ls->proto,ls->type);
if (rs) {
initiate_outgoing(ls,rs,&result->streams[j]);
++j;
for(i=0,j=0;i<remote_offer->nstreams;++i){
rs=&remote_offer->streams[i];
ms_message("Processing for stream %i",i);
- ls=sal_media_description_find_stream(local_capabilities,rs->proto,rs->type);
+ ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,rs->proto,rs->type);
if (ls){
initiate_incoming(ls,rs,&result->streams[j]);
++j;
void linphone_call_init_media_streams(LinphoneCall *call);
void linphone_call_start_media_streams(LinphoneCall *call);
-void linphone_call_set_media_streams_dir(LinphoneCall *call, SalStreamDir dir);
+void linphone_call_start_early_media(LinphoneCall *call);
void linphone_call_stop_media_streams(LinphoneCall *call);
const char * linphone_core_get_identity(LinphoneCore *lc);
}
}
-const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
+SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
SalMediaProto proto, SalStreamType type){
int i;
for(i=0;i<md->nstreams;++i){
- const SalStreamDescription *ss=&md->streams[i];
+ SalStreamDescription *ss=&md->streams[i];
if (ss->proto==proto && ss->type==type) return ss;
}
return NULL;
void sal_media_description_unref(SalMediaDescription *md);
bool_t sal_media_description_empty(const SalMediaDescription *md);
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir dir);
-const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
+SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
SalMediaProto proto, SalStreamType type);
void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir);
/*Call API*/
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
int sal_call(SalOp *h, const char *from, const char *to);
-int sal_call_notify_ringing(SalOp *h);
+int sal_call_notify_ringing(SalOp *h, bool_t early_media);
/*accept an incoming call or, during a call accept a reINVITE*/
int sal_call_accept(SalOp*h);
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
return 0;
}
-int sal_call_notify_ringing(SalOp *h){
- eXosip_lock();
- eXosip_call_send_answer(h->tid,180,NULL);
- eXosip_unlock();
+int sal_call_notify_ringing(SalOp *h, bool_t early_media){
+ osip_message_t *msg;
+ int err;
+
+ /*if early media send also 180 and 183 */
+ if (early_media && h->sdp_answer){
+ msg=NULL;
+ eXosip_lock();
+ err=eXosip_call_build_answer(h->tid,180,&msg);
+ if (msg){
+ set_sdp(msg,h->sdp_answer);
+ eXosip_call_send_answer(h->tid,180,msg);
+ }
+ msg=NULL;
+ err=eXosip_call_build_answer(h->tid,183,&msg);
+ if (msg){
+ set_sdp(msg,h->sdp_answer);
+ eXosip_call_send_answer(h->tid,183,msg);
+ }
+ eXosip_unlock();
+ }else{
+ eXosip_lock();
+ eXosip_call_send_answer(h->tid,180,NULL);
+ eXosip_unlock();
+ }
return 0;
}
-Subproject commit f2ddc59ed02f26ff828243fa400abae925b6f730
+Subproject commit 0d788c476c01c0894959fa2a85b43bbcac5dcb3a