void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
	SalMediaDescription *oldmd=call->resultdesc;
	
	if (lc->ringstream!=NULL){
		ring_stop(lc->ringstream);
		lc->ringstream=NULL;
	}
	if (new_md!=NULL){
		sal_media_description_ref(new_md);
		call->media_pending=FALSE;
	}else{
		call->media_pending=TRUE;
	}
	call->resultdesc=new_md;
	if (call->audiostream && call->audiostream->ticker){
		/* we already started media: check if we really need to restart it*/
		if (oldmd){
			if (!media_parameters_changed(call,oldmd,new_md) && !call->playing_ringbacktone){
				sal_media_description_unref(oldmd);
				if (call->all_muted){
					ms_message("Early media finished, unmuting inputs...");
					/*we were in early media, now we want to enable real media */
					linphone_call_enable_camera (call,linphone_call_camera_enabled (call));
					if (call->audiostream)
						linphone_core_mute_mic (lc, linphone_core_is_mic_muted(lc));
#ifdef VIDEO_ENABLED
					if (call->videostream && call->camera_active)
						video_stream_change_camera(call->videostream,lc->video_conf.device );
#endif
				}
				ms_message("No need to restart streams, SDP is unchanged.");
				return;
			}else{
				ms_message("Media descriptions are different, need to restart the streams.");
			}
		}
		linphone_call_stop_media_streams (call);
		linphone_call_init_media_streams (call);
	}
	if (oldmd) 
		sal_media_description_unref(oldmd);
	
	if (new_md) {
		bool_t all_muted=FALSE;
		bool_t send_ringbacktone=FALSE;
		
		if (call->audiostream==NULL){
			/*this happens after pausing the call locally. The streams is destroyed and then we wait the 200Ok to recreate it*/
			linphone_call_init_media_streams (call);
		}
		if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
			send_ringbacktone=TRUE;
		}
		if (call->state==LinphoneCallIncomingEarlyMedia ||
		    (call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){
			all_muted=TRUE;
		}
		linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
	}
}
Beispiel #2
0
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
	SalMediaDescription *oldmd=call->resultdesc;
	bool_t all_muted=FALSE;
	bool_t send_ringbacktone=FALSE;

	linphone_core_stop_ringing(lc);
	if (!new_md) {
		ms_error("linphone_core_update_streams() called with null media description");
		return;
	}
	if (call->biggestdesc==NULL || new_md->n_total_streams>call->biggestdesc->n_total_streams){
		/*we have been offered and now are ready to proceed, or we added a new stream*/
		/*store the media description to remember the mapping of calls*/
		if (call->biggestdesc){
			sal_media_description_unref(call->biggestdesc);
			call->biggestdesc=NULL;
		}
		if (sal_call_is_offerer(call->op))
			call->biggestdesc=sal_media_description_ref(call->localdesc);
		else
			call->biggestdesc=sal_media_description_ref(sal_call_get_remote_media_description(call->op));
	}
	sal_media_description_ref(new_md);
	call->expect_media_in_ack=FALSE;
	call->resultdesc=new_md;
	if ((call->audiostream && call->audiostream->ms.ticker) || (call->videostream && call->videostream->ms.ticker)){
		/* we already started media: check if we really need to restart it*/
		if (oldmd){
			int md_changed = media_parameters_changed(call, oldmd, new_md);
			if ((md_changed & SAL_MEDIA_DESCRIPTION_CODEC_CHANGED) || call->playing_ringbacktone) {
				ms_message("Media descriptions are different, need to restart the streams.");
			} else {
				if (md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) {
					if (call->all_muted){
						ms_message("Early media finished, unmuting inputs...");
						/*we were in early media, now we want to enable real media */
						linphone_call_enable_camera (call,linphone_call_camera_enabled (call));
						if (call->audiostream)
							linphone_core_enable_mic(lc, linphone_core_mic_enabled(lc));
#ifdef VIDEO_ENABLED
						if (call->videostream && call->camera_enabled)
							video_stream_change_camera(call->videostream,lc->video_conf.device );
#endif
					}
					ms_message("No need to restart streams, SDP is unchanged.");
					goto end;
				}else {
					if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) {
						ms_message("Network parameters have changed, update them.");
						linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
					}
					if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) {
						ms_message("Crypto parameters have changed, update them.");
						linphone_call_update_crypto_parameters(call, oldmd, new_md);
					}
					goto end;
				}
			}
		}
		linphone_call_stop_media_streams (call);
		linphone_call_init_media_streams (call);
	}
	
	if (call->audiostream==NULL){
		/*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/
		linphone_call_init_media_streams (call);
	}
	if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
		send_ringbacktone=TRUE;
	}
	if (call->state==LinphoneCallIncomingEarlyMedia ||
		(call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){
		all_muted=TRUE;
	}
	linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
	if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){
		linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
	}
	end:
	if (oldmd) 
		sal_media_description_unref(oldmd);
	
}
static void call_received(SalOp *h){
	LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
	char *barmesg;
	LinphoneCall *call;
	const char *from,*to;
	char *tmp;
	LinphoneAddress *from_parsed;
	LinphoneAddress *from_addr, *to_addr;
	SalMediaDescription *md;
	bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
	const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
	
	/* first check if we can answer successfully to this invite */
	if (lc->presence_mode==LinphoneStatusBusy ||
	    lc->presence_mode==LinphoneStatusOffline ||
	    lc->presence_mode==LinphoneStatusDoNotDisturb ||
	    lc->presence_mode==LinphoneStatusMoved){
		if (lc->presence_mode==LinphoneStatusBusy )
			sal_call_decline(h,SalReasonBusy,NULL);
		else if (lc->presence_mode==LinphoneStatusOffline)
			sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
		else if (lc->presence_mode==LinphoneStatusDoNotDisturb)
			sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
		else if (lc->alt_contact!=NULL && lc->presence_mode==LinphoneStatusMoved)
			sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
		sal_op_release(h);
		return;
	}
	if (!linphone_core_can_we_add_call(lc)){/*busy*/
		sal_call_decline(h,SalReasonBusy,NULL);
		sal_op_release(h);
		return;
	}
	from=sal_op_get_from(h);
	to=sal_op_get_to(h);
	from_addr=linphone_address_new(from);
	to_addr=linphone_address_new(to);

	if (is_duplicate_call(lc,from_addr,to_addr)){
		ms_warning("Receiving duplicated call, refusing this one.");
		sal_call_decline(h,SalReasonBusy,NULL);
		linphone_address_destroy(from_addr);
		linphone_address_destroy(to_addr);
		return;
	}
	
	call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
	sal_call_set_local_media_description(h,call->localdesc);
	md=sal_call_get_final_media_description(h);

	if (md && sal_media_description_empty(md)){
		sal_call_decline(h,SalReasonMedia,NULL);
		linphone_call_unref(call);
		return;
	}
	
	/* the call is acceptable so we can now add it to our list */
	linphone_core_add_call(lc,call);
	
	from_parsed=linphone_address_new(sal_op_get_from(h));
	linphone_address_clean(from_parsed);
	tmp=linphone_address_as_string(from_parsed);
	linphone_address_destroy(from_parsed);
	barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
	    (sal_call_autoanswer_asked(h)) ?_(" and asked autoanswer."):_("."));
	if (lc->vtable.show) lc->vtable.show(lc);
	if (lc->vtable.display_status) 
	    lc->vtable.display_status(lc,barmesg);

	/* play the ring if this is the only call*/
	if (lc->sound_conf.ring_sndcard!=NULL && ms_list_size(lc->calls)==1){
		lc->current_call=call;
		if (lc->ringstream && lc->dmfs_playing_start_time!=0){
			ring_stop(lc->ringstream);
			lc->ringstream=NULL;
			lc->dmfs_playing_start_time=0;
		}
		if(lc->ringstream==NULL && lc->sound_conf.local_ring){
			MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
			ms_message("Starting local ring...");
			lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,ringcard);
		}
		else
		{
			ms_message("the local ring is already started");
		}
	}else{
		/*TODO : play a tone within the context of the current call */
	}

	
	linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
	linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
	
	if (call->state==LinphoneCallIncomingReceived){
		sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL);

		if (propose_early_media || ringback_tone!=NULL){
			linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
			linphone_core_update_streams(lc,call,md);
		}
		if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
			linphone_core_accept_call(lc,call);
		}
	}
	linphone_call_unref(call);

	ms_free(barmesg);
	ms_free(tmp);
}