static void linphonec_display_warning (LinphoneCore * lc, const char *something);
static void stub () {}
static void linphonec_notify_received(LinphoneCore *lc,const char *from,const char *msg);
+static void linphonec_ack_paused_received(LinphoneCore *lc, LinphoneCall *call);
+static void linphonec_ack_resumed_received(LinphoneCore *lc, LinphoneCall *call);
static void linphonec_notify_presence_received(LinphoneCore *lc,LinphoneFriend *fid);
static void linphonec_new_unknown_subscriber(LinphoneCore *lc,
LinphoneFriend *lf, const char *url);
.paused_recv = linphonec_paused_received,
.resumed_recv = linphonec_resumed_received,
.notify_recv = linphonec_notify_received,
+ .ack_paused_recv = linphonec_ack_paused_received,
+ .ack_resumed_recv = linphonec_ack_resumed_received,
.notify_presence_recv = linphonec_notify_presence_received,
.new_unknown_subscriber = linphonec_new_unknown_subscriber,
.auth_info_requested = linphonec_prompt_for_auth,
}
}
+/*
+ * Linphone core callback
+ */
+static void
+linphonec_ack_paused_received(LinphoneCore *lc, LinphoneCall *call)
+{
+ char *from=linphone_call_get_remote_address_as_string(call);
+ if(from)
+ {
+ linphonec_out("the previous pause sent to %s has been acknowledged\n",from);
+ ms_free(from);
+ }
+}
+
+/*
+ * Linphone core callback
+ */
+static void
+linphonec_ack_resumed_received(LinphoneCore *lc, LinphoneCall *call)
+{
+ char *from=linphone_call_get_remote_address_as_string(call);
+ if(from)
+ {
+ linphonec_out("the previous resume sent to %s has been acknowledged\n",from);
+ ms_free(from);
+ }
+}
+
/*
* Linphone core callback
*/
ring_stop(lc->ringstream);
lc->ringstream=NULL;
}
+ if(!linphone_core_in_call(lc))
+ {
+ linphone_core_set_as_current_call(lc,call);
+ }
if(call == linphone_core_get_current_call(lc))
linphone_core_start_media_streams(lc,call);
}
/* play the ring */
if (lc->sound_conf.ring_sndcard!=NULL && !linphone_core_in_call(lc)){
- ms_message("Starting local ring...");
- lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
+ if(lc->ringstream==NULL)
+ {
+ ms_message("Starting local ring...");
+ lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
+ }
+ else
+ {
+ ms_message("the local ring is already started");
+ }
}
call->state=LinphoneCallRinging;
sal_call_notify_ringing(h);
call->state=LinphoneCallRinging;
}
+/*
+ * could be reach :
+ * - when the call is accepted
+ * - when a request is accepted (pause, resume)
+ */
static void call_accepted(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
return ;
}
if (call->state==LinphoneCallAVRunning){
- return ; /*already accepted*/
+ ms_message("GET ACK of resume\n");
+ if(lc->vtable.ack_resumed_recv)
+ lc->vtable.ack_resumed_recv(lc,call);
+ return ; //already accepted
}
if ((lc->audiostream!=NULL) && (lc->audiostream->ticker!=NULL)){
/*case where we accepted early media */
call->media_pending=FALSE;
}
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
- gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
- linphone_connect_incoming(lc,call);
+ //if we initiate a pause
+ if(call->state == LinphoneCallPaused)
+ {
+ ms_message("GET ACK of pause\n");
+ if(lc->vtable.ack_paused_recv)
+ lc->vtable.ack_paused_recv(lc,call);
+ }//if there is an accepted incoming call
+ else
+ {
+ gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
+ linphone_connect_incoming(lc,call);
+ }
}else{
/*send a bye*/
ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
return;
}
ms_message("Current call terminated...");
- if (lc->ringstream!=NULL) {
+ //we stop the call only if we have this current call or if we are in call
+ if (lc->ringstream!=NULL && ( (ms_list_size(lc->calls) == 1) || linphone_core_in_call(lc) )) {
ring_stop(lc->ringstream);
lc->ringstream=NULL;
}
linphone_core_start_invite(call->core,call,NULL);
}
}
+ else
+ {
+ ms_warning("ping reply without call attached...");
+ }
}
SalCallbacks linphone_sal_callbacks={
(vs!=NULL) ? (rtp_session_compute_send_bandwidth(vs)*1e-3) : 0);
}
-static void linphone_core_disconnected(LinphoneCore *lc){
- lc->vtable.display_warning(lc,_("Remote end seems to have disconnected, the call is going to be closed."));
- linphone_core_terminate_call(lc,NULL);
+static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
+ char temp[256];
+ char *from;
+ if(call)
+ from = linphone_call_get_remote_address_as_string(call);
+ if(from)
+ {
+ snprintf(temp,sizeof(temp),"Remote end %s seems to have disconnected, the call is going to be closed.",from);
+ free(from);
+ }
+ else
+ {
+ snprintf(temp,sizeof(temp),"Remote end seems to have disconnected, the call is going to be closed.");
+ }
+ lc->vtable.display_warning(lc,temp);
+ linphone_core_terminate_call(lc,call);//TODO failure ??
}
static void monitor_network_state(LinphoneCore *lc, time_t curtime){
* serialized with a mutex.
**/
void linphone_core_iterate(LinphoneCore *lc){
+ MSList *the_call;
+ LinphoneCall *call;
int disconnect_timeout = linphone_core_get_nortp_timeout(lc);
time_t curtime=time(NULL);
int elapsed;
if (lc->auto_net_state_mon) monitor_network_state(lc,curtime);
proxy_update(lc);
- LinphoneCall *call = linphone_core_get_current_call(lc);
- if(call){
+
+ //we have to iterate for each call
+ the_call = lc->calls;
+ while(the_call != NULL)
+ {
+ call = (LinphoneCall *)the_call->data;
if (call->state==LinphoneCallPreEstablishing && (curtime-call->start_time>=2)){
- /*start the call even if the OPTIONS reply did not arrive*/
- linphone_core_start_invite(lc,call,NULL);
- }
- if (call->dir==LinphoneCallIncoming && call->state==LinphoneCallRinging){
- elapsed=curtime-call->start_time;
- ms_message("incoming call ringing for %i seconds",elapsed);
- if (elapsed>lc->sip_conf.inc_timeout){
- call->log->status=LinphoneCallMissed;
- linphone_core_terminate_call(lc,NULL);
+ /*start the call even if the OPTIONS reply did not arrive*/
+ linphone_core_start_invite(lc,call,NULL);
}
- }else if (call->state==LinphoneCallAVRunning){
- if (one_second_elapsed){
+ if (call->dir==LinphoneCallIncoming && call->state==LinphoneCallRinging){
+ elapsed=curtime-call->start_time;
+ ms_message("incoming call ringing for %i seconds",elapsed);
+ if (elapsed>lc->sip_conf.inc_timeout){
+ call->log->status=LinphoneCallMissed;
+ linphone_core_terminate_call(lc,call);
+ }
+ }
+
+ the_call = the_call->next;
+ }//end while
+ //and consider the current call
+ call = linphone_core_get_current_call(lc);
+ if(call)
+ {
+ if (call->state==LinphoneCallAVRunning)
+ {
+ if (one_second_elapsed)
+ {
RtpSession *as=NULL,*vs=NULL;
lc->prevtime=curtime;
if (lc->audiostream!=NULL)
toggle_video_preview(lc,FALSE);
}
if (disconnected)
- linphone_core_disconnected(lc);
+ linphone_core_disconnected(lc,call);
linphone_core_do_plugin_tasks(lc);
ms_free(contact);
}
call->state=LinphoneCallInit;
- linphone_core_init_media_streams(lc,call);
+ //TODO : should probably not be done here
+ if(! linphone_core_in_call(lc) )
+ linphone_core_init_media_streams(lc,call);
if (!lc->sip_conf.sdp_200_ack){
call->media_pending=TRUE;
sal_call_set_local_media_description(call->op,call->localdesc);
linphone_call_unref(call);
return NULL;
}
- linphone_core_set_as_current_call(lc,call);
if (dest_proxy!=NULL || lc->sip_conf.ping_with_options==FALSE){
err=linphone_core_start_invite(lc,call,dest_proxy);
}else{
}
void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call){
+#ifdef PRINTF_DEBUG
+ printf("%s(%d)\n",__FUNCTION__,__LINE__);
+#endif
SalMediaDescription *md=call->localdesc;
lc->audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc));
if (linphone_core_echo_limiter_enabled(lc)){
}
void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){
+#ifdef PRINTF_DEBUG
+ printf("%s(%d)\n",__FUNCTION__,__LINE__);
+#endif
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
const char *tool="linphone-" LINPHONE_VERSION;
char *cname;
int used_pt=-1;
+ if(lc->audiostream == NULL)
+ {
+ ms_warning("init media stream is needed before starting");
+ linphone_core_init_media_streams(lc,call);
+ /*
+ * example of problem :
+ * 2 incomings calls, you answer and pause one, afterward if you try to answer the other call you will get SEGFAULT
+ */
+ }
/* adjust rtp jitter compensation. It must be at least the latency of the sound card */
int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp);
}
void linphone_core_stop_media_streams(LinphoneCore *lc, LinphoneCall *call){
+#ifdef PRINTF_DEBUG
+ printf("%s(%d)\n",__FUNCTION__,__LINE__);
+#endif
if (lc->audiostream!=NULL) {
audio_stream_stop(lc->audiostream);
lc->audiostream=NULL;
* @param lc The LinphoneCore
**/
int linphone_core_terminate_all_calls(LinphoneCore *lc){
- MSList *calls;
-
- calls = lc->calls;
- while(calls->next != NULL)
+ while(lc->calls)
{
- linphone_core_terminate_call(lc,(LinphoneCall *)calls->data);
- calls = calls->next;
+ LinphoneCall *the_call = lc->calls->data;
+ linphone_core_terminate_call(lc,the_call);
}
ms_list_free(lc->calls);
return -1;
ms_error("The call asked to be paused was not the current on\n");
return -3;
}
- sal_call_hold(call->op,TRUE);
+ if(sal_call_hold(call->op,TRUE) != 0)
+ {
+ lc->vtable.display_warning(lc,_("Could not pause the call"));
+ }
call->state = LinphoneCallPaused;
linphone_core_unset_the_current_call(lc);
linphone_core_stop_media_streams(lc,call);
+ //have to be done ... because if another call is incoming before this pause, you will get sound on the end point paused
+ linphone_core_init_media_streams(lc,call);
lc->vtable.display_status(lc,_("Pause the current call"));
return 0;
}
return -2;
}
}
+ if(call->state == LinphoneCallInit || call->state == LinphoneCallPreEstablishing || call->state == LinphoneCallRinging )
+ {
+ ms_warning("we cannot resume a call when the communication is not established");
+ return -3;
+ }
if(linphone_core_get_current_call(lc) != NULL)
{
ms_error("There is already a call in process pause or stop it first\n");
- return -3;
+ return -4;
}
linphone_core_init_media_streams(lc,call);
- sal_call_hold(call->op,FALSE);
+ if(sal_call_hold(call->op,FALSE) != 0)
+ {
+ lc->vtable.display_warning(lc,_("Could not resume the call"));
+ }
call->state = LinphoneCallAVRunning;
linphone_core_set_as_current_call(lc,call);
linphone_core_start_media_streams(lc,call);
static void linphone_core_uninit(LinphoneCore *lc)
{
- if(linphone_core_get_calls_nb(lc)){
- int i;
- linphone_core_terminate_all_calls(lc);
- for(i=0;i<10;++i){
-#ifndef WIN32
- usleep(50000);
+ while(lc->calls)
+ {
+ LinphoneCall *the_call = lc->calls->data;
+ linphone_core_terminate_call(lc,the_call);
+ linphone_core_iterate(lc);
+#ifdef WIN32
+ Sleep(50000);
#else
- Sleep(50);
+ usleep(50000);
#endif
- linphone_core_iterate(lc);
- }
}
+
if (lc->friends)
ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions);
gstate_new_state(lc, GSTATE_POWER_SHUTDOWN, NULL);