From b886fbda41be9a437c741f8e6fba1b4bf3be54fd Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 2 Mar 2015 17:25:52 +0100 Subject: [PATCH] Play a ringback tone when an early-media call is accepted with inactive audio. --- coreapi/callbacks.c | 28 +++++++++++++------- tester/video_tester.c | 61 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 11 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 909e376dd..1c41d70cc 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -393,6 +393,19 @@ static void try_early_media_forking(LinphoneCall *call, SalMediaDescription *md) } } +static void start_remote_ring(LinphoneCore *lc, LinphoneCall *call) { + if (lc->sound_conf.play_sndcard!=NULL){ + MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; + if (call->localdesc->streams[0].max_rate>0) ms_snd_card_set_preferred_sample_rate(ringcard, call->localdesc->streams[0].max_rate); + /*we release sound before playing ringback tone*/ + if (call->audiostream) + audio_stream_unprepare_sound(call->audiostream); + if( lc->sound_conf.remote_ring ){ + lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard); + } + } +} + static void call_ringing(SalOp *h){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(h); @@ -413,16 +426,7 @@ static void call_ringing(SalOp *h){ return; } if (lc->ringstream!=NULL) return;/*already ringing !*/ - if (lc->sound_conf.play_sndcard!=NULL){ - MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; - if (call->localdesc->streams[0].max_rate>0) ms_snd_card_set_preferred_sample_rate(ringcard, call->localdesc->streams[0].max_rate); - /*we release sound before playing ringback tone*/ - if (call->audiostream) - audio_stream_unprepare_sound(call->audiostream); - if( lc->sound_conf.remote_ring ){ - lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard); - } - } + start_remote_ring(lc, call); ms_message("Remote ringing..."); linphone_core_notify_display_status(lc,_("Remote ringing...")); linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing"); @@ -446,6 +450,10 @@ static void call_ringing(SalOp *h){ linphone_core_stop_ringing(lc); ms_message("Doing early media..."); linphone_core_update_streams(lc,call,md); + if ((linphone_call_params_get_audio_direction(linphone_call_get_current_params(call)) == LinphoneMediaDirectionInactive) && call->audiostream) { + if (lc->ringstream != NULL) return; /* Already ringing! */ + start_remote_ring(lc, call); + } } } diff --git a/tester/video_tester.c b/tester/video_tester.c index 7e3809e31..6fc2fedf1 100644 --- a/tester/video_tester.c +++ b/tester/video_tester.c @@ -131,6 +131,24 @@ static void early_media_video_call_state_changed(LinphoneCore *lc, LinphoneCall } } +static void early_media_video_call_state_changed_with_inactive_audio(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg) { + LinphoneCallParams *params; + + video_call_state_changed(lc, call, cstate, msg); + switch (cstate) { + case LinphoneCallIncomingReceived: + params = linphone_core_create_default_call_parameters(lc); + linphone_call_params_enable_video(params, TRUE); + linphone_call_params_set_audio_direction(params, LinphoneMediaDirectionInactive); + linphone_call_params_set_video_direction(params, LinphoneMediaDirectionRecvOnly); + linphone_core_accept_early_media_with_params(lc, call, params); + linphone_call_params_unref(params); + break; + default: + break; + } +} + bool_t wait_for_three_cores(LinphoneCore *lc1, LinphoneCore *lc2, LinphoneCore *lc3, int timeout) { MSList *lcs = NULL; bool_t result; @@ -216,6 +234,10 @@ static LinphoneCallParams * configure_for_early_media_video_receiving(LinphoneCo return _configure_for_video(manager, early_media_video_call_state_changed); } +static LinphoneCallParams * configure_for_early_media_video_receiving_with_inactive_audio(LinphoneCoreManager *manager) { + return _configure_for_video(manager, early_media_video_call_state_changed_with_inactive_audio); +} + static void early_media_video_during_video_call_test(void) { LinphoneCoreManager *marie; @@ -336,9 +358,46 @@ static void two_incoming_early_media_video_calls_test(void) { linphone_core_manager_destroy(laure); } +static void early_media_video_with_inactive_audio(void) { + LinphoneCoreManager *marie; + LinphoneCoreManager *pauline; + LinphoneCallParams *marie_params; + LinphoneCallParams *pauline_params; + + marie = linphone_core_manager_new("marie_rc"); + pauline = linphone_core_manager_new("pauline_rc"); + marie_params = configure_for_early_media_video_receiving_with_inactive_audio(marie); + pauline_params = configure_for_early_media_video_sending(pauline); + + /* Early media video call from pauline to marie. */ + CU_ASSERT_TRUE(video_call_with_params(pauline, marie, pauline_params, NULL, FALSE)); + + /* Wait for 2s. */ + wait_for_three_cores(marie->lc, pauline->lc, NULL, 2000); + + /* Check that we are in LinphoneCallOutgoingEarlyMedia state and that the ringstream is present meaning we are playing the ringback tone. */ + CU_ASSERT_EQUAL(linphone_call_get_state(linphone_core_get_current_call(pauline->lc)), LinphoneCallOutgoingEarlyMedia); + CU_ASSERT_PTR_NOT_NULL(pauline->lc->ringstream); + + linphone_core_terminate_all_calls(marie->lc); + CU_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); + CU_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); + CU_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1)); + CU_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1)); + + CU_ASSERT_EQUAL(marie->stat.number_of_video_windows_created, 1); + CU_ASSERT_EQUAL(pauline->stat.number_of_video_windows_created, 1); + + linphone_call_params_unref(marie_params); + linphone_call_params_unref(pauline_params); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + test_t video_tests[] = { { "Early-media video during video call", early_media_video_during_video_call_test }, - { "Two incoming early-media video calls", two_incoming_early_media_video_calls_test } + { "Two incoming early-media video calls", two_incoming_early_media_video_calls_test }, + { "Early-media video with inactive audio", early_media_video_with_inactive_audio } }; test_suite_t video_test_suite = {