-
Julien Wadel authored
Adapt suites declarations.
cdbc47a0
/*
* Copyright (c) 2010-2022 Belledonne Communications SARL.
*
* This file is part of Liblinphone
* (see https://gitlab.linphone.org/BC/public/liblinphone).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <bctoolbox/defs.h>
#include "belle-sip/sipstack.h"
#include "mediastreamer2/msutils.h"
#include "liblinphone_tester.h"
#include "linphone/core.h"
#include "linphone/lpconfig.h"
#include "mediastreamer2/msutils.h"
#include "tester_utils.h"
static int audio_device_name_match(LinphoneAudioDevice *audio_device, const char *name) {
return strcmp(linphone_audio_device_get_device_name(audio_device), name);
}
static void register_device(LinphoneCoreManager *mgr, MSSndCardDesc *card_desc) {
// Get number of devices before loading
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(mgr->lc);
int native_audio_devices_count = (int)bctbx_list_size(audio_devices);
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
MSFactory *factory = linphone_core_get_ms_factory(mgr->lc);
// Adding 1 devices to sound card manager:
// - dummy_test_snd_card_desc
MSSndCardManager *sndcard_manager = ms_factory_get_snd_card_manager(factory);
// This devices are prepended to the list of so that they can be easily accessed later
ms_snd_card_manager_register_desc(sndcard_manager, card_desc);
linphone_core_reload_sound_devices(mgr->lc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
audio_devices = linphone_core_get_extended_audio_devices(mgr->lc);
int audio_devices_count = (int)bctbx_list_size(audio_devices);
BC_ASSERT_EQUAL(audio_devices_count, (native_audio_devices_count + 1), int, "%d");
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
}
static LinphoneAudioDevice *
unregister_device(bool_t enable, LinphoneCoreManager *mgr, LinphoneAudioDevice *current_dev, MSSndCardDesc *card_desc) {
// Unref current_dev
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
linphone_audio_device_unref(current_dev);
if (enable) {
MSFactory *factory = linphone_core_get_ms_factory(mgr->lc);
MSSndCardManager *sndcard_manager = ms_factory_get_snd_card_manager(factory);
// Check that description is in the card manager
BC_ASSERT_PTR_NOT_NULL(bctbx_list_find(sndcard_manager->descs, card_desc));
const int noListUpdated = mgr->stat.number_of_LinphoneCoreAudioDevicesListUpdated;
// Unregister card
ms_snd_card_manager_unregister_desc(sndcard_manager, card_desc);
linphone_core_reload_sound_devices(mgr->lc);
BC_ASSERT_EQUAL(mgr->stat.number_of_LinphoneCoreAudioDevicesListUpdated, noListUpdated + 1, int, "%d");
// Get next device at the head of the list
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per
// type
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(mgr->lc);
LinphoneAudioDevice *next_dev = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(next_dev);
linphone_audio_device_ref(next_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
return next_dev;
}
return linphone_audio_device_ref(current_dev);
}
static void unregister_all_devices(LinphoneCoreManager *mgr) {
MSFactory *factory = linphone_core_get_ms_factory(mgr->lc);
MSSndCardManager *sndcard_manager = ms_factory_get_snd_card_manager(factory);
while (sndcard_manager->descs)
ms_snd_card_manager_unregister_desc(sndcard_manager, bctbx_list_get_data(sndcard_manager->descs));
linphone_core_reload_sound_devices(mgr->lc);
}
static void check_io_devs(LinphoneCoreManager *mgr, const LinphoneAudioDevice *exp_dev, bool_t force_dev_check) {
LinphoneCall *mgr_call = linphone_core_get_current_call(mgr->lc);
const LinphoneCallParams *call_params = mgr_call != NULL ? linphone_call_get_current_params(mgr_call) : NULL;
LinphoneCallState call_state = mgr_call ? linphone_call_get_state(mgr_call) : LinphoneCallStateIdle;
// If no call, then there is no input or output device. Getter should return NULL
if (!linphone_core_get_use_files(mgr->lc) && ((mgr_call != NULL) || (force_dev_check == TRUE))) {
// Note : on these states : Paused, OutgoingRinging, Pausing, IncomingReceived
// => regular devices are null (capture/playback) BUT output device comes from tonemanager. It's why there is no
// specific case for it.
BC_ASSERT_PTR_NOT_NULL(linphone_core_get_output_audio_device(mgr->lc));
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(mgr->lc), exp_dev);
if (!mgr_call ||
(call_params && linphone_call_params_get_audio_direction(call_params) == LinphoneMediaDirectionRecvOnly) ||
call_state == LinphoneCallStatePaused) { /*
FIXME: the audio inputs and outputs are unspecified when in Paused or PausedByRemote states.
Indeed, the mediastreamer2 AudioStream can accept input or output MSSndCard but does nothing with it.
If the MS2AudioStream goes through render, then the MSSndCard will be reset to NULL.
*/
// BC_ASSERT_PTR_NULL(linphone_core_get_input_audio_device(mgr->lc));
} else {
BC_ASSERT_PTR_NOT_NULL(linphone_core_get_input_audio_device(mgr->lc));
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(mgr->lc), exp_dev);
}
} else {
BC_ASSERT_PTR_NULL(linphone_core_get_output_audio_device(mgr->lc));
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
BC_ASSERT_PTR_NULL(linphone_core_get_input_audio_device(mgr->lc));
}
BC_ASSERT_PTR_NOT_NULL(linphone_core_get_default_output_audio_device(mgr->lc));
BC_ASSERT_PTR_EQUAL(linphone_core_get_default_output_audio_device(mgr->lc), exp_dev);
BC_ASSERT_PTR_NOT_NULL(linphone_core_get_default_input_audio_device(mgr->lc));
BC_ASSERT_PTR_EQUAL(linphone_core_get_default_input_audio_device(mgr->lc), exp_dev);
}
static void emulate_unreliable_device(LinphoneCoreManager *mgr,
MSSndCardDesc *card_desc,
const LinphoneAudioDeviceCapabilities desiredCapability,
bool_t force_dev_check) {
register_device(mgr, card_desc);
// Choose manager audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(mgr->lc);
// As it is assumed that new devices are prepended, they can be easily accessed and we do not run the risk of
// gettting a device whose type is Unknown device at the head of the list
LinphoneAudioDevice *exp_dev = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(exp_dev);
linphone_audio_device_ref(exp_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
// Newly added device (dummy_test_snd_card_desc) is expected to have playback and record capabilities
if (LinphoneAudioDeviceCapabilityPlay & desiredCapability) {
BC_ASSERT_TRUE(linphone_audio_device_has_capability(exp_dev, LinphoneAudioDeviceCapabilityPlay));
}
if (LinphoneAudioDeviceCapabilityRecord & desiredCapability) {
BC_ASSERT_TRUE(linphone_audio_device_has_capability(exp_dev, LinphoneAudioDeviceCapabilityRecord));
}
// Set default audio devices
linphone_core_set_default_input_audio_device(mgr->lc, exp_dev);
linphone_core_set_default_output_audio_device(mgr->lc, exp_dev);
// Force input and output device
linphone_core_set_output_audio_device(mgr->lc, exp_dev);
linphone_core_set_input_audio_device(mgr->lc, exp_dev);
linphone_core_set_ringer_device(mgr->lc,
linphone_audio_device_get_id(exp_dev)); // The ringer ca be used on ringback tone
// stay in pause a little while in order to generate traffic
wait_for_until(mgr->lc, NULL, NULL, 5, 2000);
check_io_devs(mgr, exp_dev, force_dev_check);
BC_ASSERT_PTR_EQUAL(linphone_core_get_default_output_audio_device(mgr->lc), exp_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_default_input_audio_device(mgr->lc), exp_dev);
exp_dev = unregister_device(TRUE, mgr, exp_dev, card_desc);
wait_for_until(mgr->lc, NULL, NULL, 1, 100);
check_io_devs(mgr, exp_dev, force_dev_check);
linphone_audio_device_unref(exp_dev);
}
static void call_with_unreliable_device(void) {
bctbx_list_t *lcs = NULL;
bool_t force_dev_check = FALSE;
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
lcs = bctbx_list_append(lcs, marie->lc);
unregister_all_devices(marie);
// This should be the device the core falls back when the current is unregistered
register_device(marie, &dummy3_test_snd_card_desc);
emulate_unreliable_device(marie, &dummy_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 1 done");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc");
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
lcs = bctbx_list_append(lcs, pauline->lc);
unregister_all_devices(pauline);
// This should be the device the core falls back when the current is unregistered
register_device(pauline, &dummy3_test_snd_card_desc);
// Marie is calling (sound played on the ringstream) and Pauline is receiving the call (sound played on the ringtone
// player)
LinphoneCall *marie_call = linphone_core_invite_address(marie->lc, pauline->identity);
BC_ASSERT_PTR_NOT_NULL(marie_call);
// Marie should hear ringback as well
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1, 5000));
// Ringback
emulate_unreliable_device(marie, &dummy2_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 2 done");
// Ringtone
emulate_unreliable_device(pauline, &dummy_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 3 done");
LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
linphone_call_ref(pauline_call);
// Take call - ringing ends
linphone_call_accept(pauline_call);
// force device check as a call is ongoing, paused or resumed therefore it is possible to change the currently used
// audio device
force_dev_check = TRUE;
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
// Call
emulate_unreliable_device(marie, &dummy_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 4 done");
// Call
emulate_unreliable_device(pauline, &dummy2_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 5 done");
linphone_call_pause(pauline_call);
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallPausing, 1));
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallPausedByRemote, 1));
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallPaused, 1));
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
// Paused call
emulate_unreliable_device(pauline, &dummy_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 6 done");
// PausedByRemote call
emulate_unreliable_device(marie, &dummy2_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 7 done");
linphone_call_resume(pauline_call);
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 2));
BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 2));
// Resumed Call
emulate_unreliable_device(marie, &dummy_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 8 done");
// Resumed Call
emulate_unreliable_device(pauline, &dummy2_test_snd_card_desc,
(LinphoneAudioDeviceCapabilityRecord | LinphoneAudioDeviceCapabilityPlay),
force_dev_check);
ms_message("emulate_unreliable_device 9 done");
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// End call
linphone_call_terminate(pauline_call);
linphone_call_unref(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
bctbx_list_free(lcs);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
static void call_with_audio_device_change_using_public_api(void) {
bctbx_list_t *lcs;
// Marie is the caller
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
register_device(marie, &dummy_test_snd_card_desc);
register_device(marie, &dummy2_test_snd_card_desc);
register_device(marie, &dummy_capture_test_snd_card_desc);
register_device(marie, &dummy_playback_test_snd_card_desc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
bctbx_list_t *dev_found = NULL;
// 1st device
dev_found =
bctbx_list_find_custom(audio_devices, (bctbx_compare_func)audio_device_name_match, DUMMY_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *current_dev = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(current_dev);
linphone_audio_device_ref(current_dev);
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
// device dummy_playback in the list
dev_found = bctbx_list_find_custom(audio_devices, (bctbx_compare_func)audio_device_name_match,
DUMMY_PLAYBACK_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *playback_dev = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(playback_dev);
linphone_audio_device_ref(playback_dev);
// device dummy_capture in the list
dev_found = bctbx_list_find_custom(audio_devices, (bctbx_compare_func)audio_device_name_match,
DUMMY_CAPTURE_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *capture_dev = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(capture_dev);
linphone_audio_device_ref(capture_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(NULL, marie->lc);
// Pauline is offline
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
linphone_core_set_network_reachable(pauline->lc, TRUE);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
lcs = bctbx_list_append(lcs, pauline->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, current_dev);
linphone_core_set_default_output_audio_device(marie->lc, current_dev);
LinphoneCall *marie_call = linphone_core_invite_address(marie->lc, pauline->identity);
BC_ASSERT_PTR_NOT_NULL(marie_call);
// Pauline shall receive the call immediately
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 5000));
LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc);
if (!BC_ASSERT_PTR_NOT_NULL(pauline_call)) goto end;
linphone_call_ref(pauline_call);
// Marie should hear ringback as well
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1, 5000));
// Take call - ringing ends
linphone_call_accept(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), current_dev);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
int noDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
linphone_call_set_output_audio_device(marie_call, playback_dev);
linphone_call_set_input_audio_device(marie_call, capture_dev);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, (noDevChanges + 2), int, "%d");
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), playback_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), capture_dev);
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
// Set invalid audio device
noDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
linphone_call_set_output_audio_device(marie_call, capture_dev);
linphone_call_set_input_audio_device(marie_call, playback_dev);
// wait a little bit to ensure that no change is triggered
wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), playback_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), capture_dev);
// Set again the same audio device
noDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
linphone_call_set_output_audio_device(marie_call, playback_dev);
linphone_call_set_input_audio_device(marie_call, capture_dev);
// wait a little bit to ensure that no change is triggered
wait_for_until(pauline->lc, marie->lc, NULL, 5, 1000);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), playback_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), capture_dev);
// End call
linphone_call_terminate(pauline_call);
linphone_call_unref(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
// After call, unref the sound card
linphone_audio_device_unref(current_dev);
linphone_audio_device_unref(playback_dev);
linphone_audio_device_unref(capture_dev);
end:
bctbx_list_free(lcs);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
static void call_with_disconnecting_device_base(bool_t before_ringback, bool_t during_ringback, bool_t during_call) {
bctbx_list_t *lcs;
// Marie is the caller
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
register_device(marie, &dummy_test_snd_card_desc);
register_device(marie, &dummy2_test_snd_card_desc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown device at the head of the list
LinphoneAudioDevice *current_dev = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(current_dev);
linphone_audio_device_ref(current_dev);
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(NULL, marie->lc);
// Pauline is offline
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
linphone_core_set_network_reachable(pauline->lc, FALSE);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
lcs = bctbx_list_append(lcs, pauline->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, current_dev);
linphone_core_set_default_output_audio_device(marie->lc, current_dev);
LinphoneCall *marie_call = linphone_core_invite_address(marie->lc, pauline->identity);
BC_ASSERT_PTR_NOT_NULL(marie_call);
current_dev = unregister_device(before_ringback, marie, current_dev, &dummy_test_snd_card_desc);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// Pauline is now online - ringback can start
linphone_core_set_network_reachable(pauline->lc, TRUE);
// Pauline shall receive the call immediately
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 5000));
LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc);
if (!BC_ASSERT_PTR_NOT_NULL(pauline_call)) goto end;
linphone_call_ref(pauline_call);
// Marie should hear ringback as well
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1, 5000));
// After the ringback startx, the default device is expected to be used
linphone_audio_device_unref(current_dev);
audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
current_dev = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
linphone_audio_device_ref(current_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
linphone_core_set_output_audio_device(marie->lc, current_dev);
linphone_core_set_input_audio_device(marie->lc, current_dev);
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_dev);
current_dev = unregister_device(during_ringback, marie, current_dev, &dummy_test_snd_card_desc);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// Take call - ringing ends
linphone_call_accept(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_dev);
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
// Unref current device as we are deletig its card
current_dev = unregister_device(during_call, marie, current_dev, &dummy_test_snd_card_desc);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// End call
linphone_call_terminate(pauline_call);
linphone_call_unref(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
// After call, unref the sound card
linphone_audio_device_unref(current_dev);
end:
bctbx_list_free(lcs);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
static void call_with_disconnecting_device_before_ringback(void) {
call_with_disconnecting_device_base(TRUE, FALSE, FALSE);
}
static void call_with_disconnecting_device_during_ringback(void) {
call_with_disconnecting_device_base(FALSE, TRUE, FALSE);
}
static void call_with_disconnecting_device_after_ringback(void) {
call_with_disconnecting_device_base(FALSE, FALSE, TRUE);
}
static LinphoneAudioDevice *
dev_mux(LinphoneAudioDevice *current_dev, LinphoneAudioDevice *dev0, LinphoneAudioDevice *dev1) {
LinphoneAudioDevice *next_dev = NULL;
if (current_dev == dev0) {
next_dev = dev1;
} else {
next_dev = dev0;
}
return next_dev;
}
LinphoneAudioDevice *change_device(bool_t enable,
LinphoneCoreManager *mgr,
LinphoneAudioDevice *current_dev,
LinphoneAudioDevice *dev0,
LinphoneAudioDevice *dev1) {
// Unref current_dev
linphone_audio_device_unref(current_dev);
if (enable) {
LinphoneAudioDevice *next_dev = dev_mux(current_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(next_dev);
next_dev = linphone_audio_device_ref(next_dev);
int noDevChanges = mgr->stat.number_of_LinphoneCoreAudioDeviceChanged;
const bool_t coreIsInConference = linphone_core_is_in_conference(mgr->lc);
int devChanges = 0;
if (linphone_audio_device_has_capability(next_dev, LinphoneAudioDeviceCapabilityPlay)) {
// Change output audio device
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
if (coreIsInConference) {
LinphoneConference *conference = linphone_core_get_conference(mgr->lc);
BC_ASSERT_PTR_NOT_NULL(conference);
if (conference) {
linphone_conference_set_output_audio_device(conference, next_dev);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_output_audio_device(conference), next_dev);
devChanges += 1;
}
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(mgr->lc), next_dev);
} else {
LinphoneCall *call = linphone_core_get_current_call(mgr->lc);
if (call) {
linphone_call_set_output_audio_device(call, next_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(call), next_dev);
devChanges += 1;
} else {
linphone_core_set_output_audio_device(mgr->lc, next_dev);
const bctbx_list_t *calls = linphone_core_get_calls(mgr->lc);
devChanges += (1 + ((int)bctbx_list_size(calls)));
}
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(mgr->lc), next_dev);
}
}
if (linphone_audio_device_has_capability(next_dev, LinphoneAudioDeviceCapabilityRecord)) {
// Change input audio device
if (coreIsInConference) {
LinphoneConference *conference = linphone_core_get_conference(mgr->lc);
BC_ASSERT_PTR_NOT_NULL(conference);
if (conference) {
linphone_conference_set_input_audio_device(conference, next_dev);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_input_audio_device(conference), next_dev);
devChanges += 1;
}
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(mgr->lc), next_dev);
} else {
LinphoneCall *call = linphone_core_get_current_call(mgr->lc);
if (call) {
linphone_call_set_input_audio_device(call, next_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(call), next_dev);
devChanges += 1;
} else {
linphone_core_set_input_audio_device(mgr->lc, next_dev);
const bctbx_list_t *calls = linphone_core_get_calls(mgr->lc);
devChanges += (1 + (int)bctbx_list_size(calls));
}
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(mgr->lc), next_dev);
}
}
BC_ASSERT_EQUAL(mgr->stat.number_of_LinphoneCoreAudioDeviceChanged, (noDevChanges + devChanges), int, "%d");
return next_dev;
}
return linphone_audio_device_ref(current_dev);
}
static void simple_call_with_audio_device_change_same_audio_device_base(bool_t before_ringback,
bool_t during_ringback,
bool_t during_call) {
bctbx_list_t *lcs;
// Marie is the caller
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
// load audio devices and get initial number of cards
linphone_core_reload_sound_devices(marie->lc);
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int native_audio_devices_count = (int)bctbx_list_size(audio_devices);
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
MSFactory *factory = linphone_core_get_ms_factory(marie->lc);
// Adding 2 devices to Marie' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
MSSndCardManager *sndcard_manager = ms_factory_get_snd_card_manager(factory);
// This devices are prepended to the list of so that they can be easily accessed later
ms_snd_card_manager_register_desc(sndcard_manager, &dummy_test_snd_card_desc);
ms_snd_card_manager_register_desc(sndcard_manager, &dummy2_test_snd_card_desc);
linphone_core_reload_sound_devices(marie->lc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int audio_devices_count = (int)bctbx_list_size(audio_devices);
BC_ASSERT_EQUAL(audio_devices_count, (native_audio_devices_count + 2), int, "%d");
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown device at the head of the list
LinphoneAudioDevice *dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(dev0);
linphone_audio_device_ref(dev0);
// 2nd device in the list
LinphoneAudioDevice *dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(dev1);
linphone_audio_device_ref(dev1);
// At the start, choose default device i.e. dev0
LinphoneAudioDevice *current_dev = dev0;
BC_ASSERT_PTR_NOT_NULL(current_dev);
linphone_audio_device_ref(current_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(NULL, marie->lc);
// Pauline is offline
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
linphone_core_set_network_reachable(pauline->lc, FALSE);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
lcs = bctbx_list_append(lcs, pauline->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, current_dev);
linphone_core_set_default_output_audio_device(marie->lc, current_dev);
LinphoneCall *marie_call = linphone_core_invite_address(marie->lc, pauline->identity);
BC_ASSERT_PTR_NOT_NULL(marie_call);
current_dev = change_device(before_ringback, marie, current_dev, dev0, dev1);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// Pauline is now online - ringback can start
linphone_core_set_network_reachable(pauline->lc, TRUE);
// Pauline shall receive the call immediately
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 5000));
LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc);
if (!BC_ASSERT_PTR_NOT_NULL(pauline_call)) goto end;
linphone_call_ref(pauline_call);
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
// Marie should hear ringback as well
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1, 5000));
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_dev);
current_dev = change_device(during_ringback, marie, current_dev, dev0, dev1);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// Take call - ringing ends
linphone_call_accept(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_dev);
current_dev = change_device(during_call, marie, current_dev, dev0, dev1);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// End call
linphone_call_terminate(pauline_call);
linphone_call_unref(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
end:
bctbx_list_free(lcs);
// After call, unref the sound card
linphone_audio_device_unref(dev0);
linphone_audio_device_unref(dev1);
linphone_audio_device_unref(current_dev);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
static void simple_call_with_audio_device_change_same_audio_device_pingpong(void) {
simple_call_with_audio_device_change_same_audio_device_base(TRUE, TRUE, TRUE);
}
static void create_devices(LinphoneCoreManager *manager, bctbx_list_t **audio_devices) {
linphone_core_reload_sound_devices(manager->lc);
*audio_devices = linphone_core_get_extended_audio_devices(manager->lc);
int native_audio_devices_count = (int)bctbx_list_size(*audio_devices);
bctbx_list_free_with_data(*audio_devices, (void (*)(void *))linphone_audio_device_unref);
MSFactory *factory = linphone_core_get_ms_factory(manager->lc);
// Adding 2 devices to manager' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
MSSndCardManager *sndcard_manager = ms_factory_get_snd_card_manager(factory);
// This devices are prepended to the list of so that they can be easily accessed later
ms_snd_card_manager_register_desc(sndcard_manager, &dummy_test_snd_card_desc);
ms_snd_card_manager_register_desc(sndcard_manager, &dummy2_test_snd_card_desc);
linphone_core_reload_sound_devices(manager->lc);
// Choose manager's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
*audio_devices = linphone_core_get_extended_audio_devices(manager->lc);
int audio_devices_count = (int)bctbx_list_size(*audio_devices);
BC_ASSERT_EQUAL(audio_devices_count, (native_audio_devices_count + 2), int, "%d");
}
static void simple_call_with_audio_device_change_base(bool_t during_incoming_early_media,
bool_t during_outgoing_early_media,
bool_t before_ringback,
bool_t during_ringback,
bool_t during_call) {
bctbx_list_t *lcs;
// Marie is the caller
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
linphone_core_set_ring_during_incoming_early_media(marie->lc,
(during_incoming_early_media || during_outgoing_early_media));
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
linphone_config_set_bool(linphone_core_get_config(pauline->lc), "sip", "incoming_calls_early_media",
(during_incoming_early_media || during_outgoing_early_media));
bctbx_list_t *audio_devices = NULL, *pauline_audio_devices = NULL;
create_devices(marie, &audio_devices);
create_devices(pauline, &pauline_audio_devices);
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown device at the head of the list
LinphoneAudioDevice *dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(dev0);
linphone_audio_device_ref(dev0);
// 2nd device in the list
LinphoneAudioDevice *dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(dev1);
linphone_audio_device_ref(dev1);
// At the start, choose default devices
LinphoneAudioDevice *current_output_dev = dev0;
BC_ASSERT_PTR_NOT_NULL(current_output_dev);
linphone_audio_device_ref(current_output_dev);
LinphoneAudioDevice *current_input_dev = dev1;
BC_ASSERT_PTR_NOT_NULL(current_input_dev);
linphone_audio_device_ref(current_input_dev);
LinphoneAudioDevice *pauline_dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(pauline_audio_devices);
BC_ASSERT_PTR_NOT_NULL(pauline_dev0);
linphone_audio_device_ref(pauline_dev0);
// 2nd device in the list
LinphoneAudioDevice *pauline_dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(pauline_audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(pauline_dev1);
linphone_audio_device_ref(pauline_dev1);
// At the start, choose default devices
LinphoneAudioDevice *pauline_current_output_dev = pauline_dev0;
BC_ASSERT_PTR_NOT_NULL(pauline_current_output_dev);
linphone_audio_device_ref(pauline_current_output_dev);
LinphoneAudioDevice *pauline_current_input_dev = pauline_dev1;
BC_ASSERT_PTR_NOT_NULL(pauline_current_input_dev);
linphone_audio_device_ref(pauline_current_input_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
bctbx_list_free_with_data(pauline_audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(NULL, marie->lc);
// Pauline is offline
linphone_core_set_network_reachable(pauline->lc, FALSE);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
lcs = bctbx_list_append(lcs, pauline->lc);
int initialNoDevChanges = 0;
int devChanges = 0;
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, current_input_dev);
linphone_core_set_default_output_audio_device(marie->lc, current_output_dev);
linphone_core_set_default_input_audio_device(pauline->lc, pauline_current_input_dev);
linphone_core_set_default_output_audio_device(pauline->lc, pauline_current_output_dev);
linphone_core_set_ringer_device(
pauline->lc,
linphone_audio_device_get_id(
pauline_current_input_dev)); // Set the ringer device to test if changes are not based on this card
LinphoneCall *marie_call = linphone_core_invite_address(marie->lc, pauline->identity);
if (!BC_ASSERT_PTR_NOT_NULL(marie_call)) goto end;
linphone_call_ref(marie_call);
unsigned int audioStreamStopped = _linphone_call_get_nb_audio_stops(marie_call);
if (before_ringback) {
linphone_audio_device_unref(current_output_dev);
current_output_dev = dev_mux(current_output_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(current_output_dev);
linphone_audio_device_ref(current_output_dev);
linphone_audio_device_unref(current_input_dev);
current_input_dev = dev_mux(current_input_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(current_input_dev);
linphone_audio_device_ref(current_input_dev);
initialNoDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
devChanges = 0;
// Change output audio device
linphone_core_set_output_audio_device(marie->lc, current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
devChanges += 2;
// Change input audio device
linphone_core_set_input_audio_device(marie->lc, current_input_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_input_dev);
devChanges += 2;
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, (initialNoDevChanges + devChanges), int,
"%d");
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
}
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
BC_ASSERT_EQUAL(_linphone_call_get_nb_audio_stops(marie_call), audioStreamStopped, unsigned int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
// Pauline is now online - ringback can start
linphone_core_set_network_reachable(pauline->lc, TRUE);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
// Pauline shall receive the call immediately
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 5000));
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc);
if (!BC_ASSERT_PTR_NOT_NULL(pauline_call)) goto end;
linphone_call_ref(pauline_call);
if (during_incoming_early_media || during_outgoing_early_media) {
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia, 1, 5000));
if (during_incoming_early_media) {
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
linphone_audio_device_unref(pauline_current_output_dev);
pauline_current_output_dev = dev_mux(pauline_current_output_dev, pauline_dev0, pauline_dev1);
BC_ASSERT_PTR_NOT_NULL(pauline_current_output_dev);
linphone_audio_device_ref(pauline_current_output_dev);
linphone_audio_device_unref(pauline_current_input_dev);
pauline_current_input_dev = dev_mux(pauline_current_input_dev, pauline_dev0, pauline_dev1);
BC_ASSERT_PTR_NOT_NULL(pauline_current_input_dev);
linphone_audio_device_ref(pauline_current_input_dev);
initialNoDevChanges = pauline->stat.number_of_LinphoneCoreAudioDeviceChanged;
devChanges = 0;
// Change output audio device
linphone_core_set_output_audio_device(pauline->lc, pauline_current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(pauline->lc), pauline_current_output_dev);
devChanges += 2;
// Change input audio device
linphone_core_set_input_audio_device(pauline->lc, pauline_current_input_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(pauline->lc), pauline_current_input_dev);
devChanges += 2;
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCoreAudioDeviceChanged, (initialNoDevChanges + devChanges),
int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(pauline->lc), pauline_current_output_dev);
}
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia, 1, 5000));
BC_ASSERT_EQUAL(_linphone_call_get_nb_audio_stops(marie_call), audioStreamStopped, unsigned int, "%d");
if (during_outgoing_early_media) {
linphone_audio_device_unref(current_output_dev);
current_output_dev = dev_mux(current_output_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(current_output_dev);
linphone_audio_device_ref(current_output_dev);
linphone_audio_device_unref(current_input_dev);
current_input_dev = dev_mux(current_input_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(current_input_dev);
linphone_audio_device_ref(current_input_dev);
initialNoDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
devChanges = 0;
// Change output audio device
linphone_core_set_output_audio_device(marie->lc, current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
devChanges += 2;
// Change input audio device
linphone_core_set_input_audio_device(marie->lc, current_input_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_input_dev);
devChanges += 2;
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, (initialNoDevChanges + devChanges),
int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
++audioStreamStopped; // Call stream need to restart on accept to take account of new device during ringback
}
} else {
// Marie should hear ringback as well
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1, 5000));
}
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_input_dev);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
BC_ASSERT_EQUAL(_linphone_call_get_nb_audio_stops(marie_call), audioStreamStopped, unsigned int, "%d");
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
if (during_ringback) {
linphone_audio_device_unref(current_output_dev);
current_output_dev = dev_mux(current_output_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(current_output_dev);
linphone_audio_device_ref(current_output_dev);
linphone_audio_device_unref(current_input_dev);
current_input_dev = dev_mux(current_input_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(current_input_dev);
linphone_audio_device_ref(current_input_dev);
initialNoDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
devChanges = 0;
// Change output audio device
linphone_core_set_output_audio_device(marie->lc, current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
devChanges += 2;
// Change input audio device
linphone_core_set_input_audio_device(marie->lc, current_input_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_input_dev);
devChanges += 2;
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, (initialNoDevChanges + devChanges), int,
"%d");
}
BC_ASSERT_EQUAL(_linphone_call_get_nb_audio_stops(marie_call), audioStreamStopped, unsigned int, "%d");
if (during_incoming_early_media && during_outgoing_early_media) // In this case, there is one more stop() for marie.
++audioStreamStopped;
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
BC_ASSERT_EQUAL(_linphone_call_get_nb_audio_stops(marie_call), audioStreamStopped, unsigned int, "%d");
// Take call - ringing ends
linphone_call_accept(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_input_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), current_input_dev);
BC_ASSERT_EQUAL(_linphone_call_get_nb_audio_stops(marie_call), audioStreamStopped, unsigned int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(pauline->lc), pauline_current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(pauline->lc), pauline_current_input_dev);
BC_ASSERT_STRING_EQUAL(linphone_audio_device_get_id(linphone_core_get_output_audio_device(pauline->lc)),
linphone_audio_device_get_id(pauline_current_output_dev)); // To know what IDs are
BC_ASSERT_STRING_EQUAL(linphone_audio_device_get_id(linphone_core_get_input_audio_device(pauline->lc)),
linphone_audio_device_get_id(pauline_current_input_dev));
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(pauline_call), pauline_current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(pauline_call), pauline_current_input_dev);
if (during_call) {
linphone_audio_device_unref(current_output_dev);
current_output_dev = dev_mux(current_output_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(current_output_dev);
linphone_audio_device_ref(current_output_dev);
linphone_audio_device_unref(current_input_dev);
current_input_dev = dev_mux(current_input_dev, dev0, dev1);
BC_ASSERT_PTR_NOT_NULL(current_input_dev);
linphone_audio_device_ref(current_input_dev);
initialNoDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
devChanges = 0;
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
// Change output audio device
linphone_core_set_output_audio_device(marie->lc, current_output_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_output_dev);
devChanges += 2;
// Change input audio device
linphone_core_set_input_audio_device(marie->lc, current_input_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_input_dev);
devChanges += 2;
++audioStreamStopped; // From doing render() after setting devices. TODO : only count if filters doesn't
// implement MS_AUDIO_*_SET_INTERNAL_ID
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, (initialNoDevChanges + devChanges), int,
"%d");
}
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// End call
linphone_call_terminate(pauline_call);
++audioStreamStopped;
linphone_call_unref(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
BC_ASSERT_EQUAL(_linphone_call_get_nb_audio_stops(marie_call), audioStreamStopped, unsigned int, "%d");
linphone_call_unref(marie_call);
end:
// After call, unref the sound card
linphone_audio_device_unref(dev0);
linphone_audio_device_unref(dev1);
linphone_audio_device_unref(current_input_dev);
linphone_audio_device_unref(current_output_dev);
linphone_audio_device_unref(pauline_dev0);
linphone_audio_device_unref(pauline_dev1);
linphone_audio_device_unref(pauline_current_input_dev);
linphone_audio_device_unref(pauline_current_output_dev);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
bctbx_list_free(lcs);
}
static void simple_call_with_audio_device_change_during_incoming_early_media(void) {
simple_call_with_audio_device_change_base(TRUE, FALSE, FALSE, FALSE, FALSE);
}
static void simple_call_with_audio_device_change_during_outgoing_early_media(void) {
simple_call_with_audio_device_change_base(FALSE, TRUE, FALSE, FALSE, FALSE);
}
static void simple_call_with_audio_device_change_before_ringback(void) {
simple_call_with_audio_device_change_base(FALSE, FALSE, TRUE, FALSE, FALSE);
}
static void simple_call_with_audio_device_change_during_ringback(void) {
simple_call_with_audio_device_change_base(FALSE, FALSE, FALSE, TRUE, FALSE);
}
static void simple_call_with_audio_device_change_after_ringback(void) {
simple_call_with_audio_device_change_base(FALSE, FALSE, FALSE, FALSE, TRUE);
}
static void simple_call_with_audio_device_change_pingpong(void) {
1191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
simple_call_with_audio_device_change_base(TRUE, TRUE, TRUE, TRUE, TRUE);
}
LinphoneAudioDevice *pause_call_changing_device(bool_t enable,
bctbx_list_t *lcs,
LinphoneCall *call,
LinphoneCoreManager *mgr_pausing,
LinphoneCoreManager *mgr_paused,
LinphoneCoreManager *mgr_change_device,
LinphoneAudioDevice *current_dev,
LinphoneAudioDevice *dev0,
LinphoneAudioDevice *dev1) {
int noCallPaused = mgr_pausing->stat.number_of_LinphoneCallPaused;
int noCallPausing = mgr_pausing->stat.number_of_LinphoneCallPausing;
int noCallPausedByRemote = mgr_paused->stat.number_of_LinphoneCallPausedByRemote;
int noCallResuming = mgr_pausing->stat.number_of_LinphoneCallResuming;
int noStreamRunningPausing = mgr_pausing->stat.number_of_LinphoneCallStreamsRunning;
int noStreamRunningPaused = mgr_paused->stat.number_of_LinphoneCallStreamsRunning;
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(mgr_change_device->lc), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(mgr_change_device->lc), current_dev);
BC_ASSERT_FALSE(linphone_core_is_in_conference(mgr_pausing->lc));
linphone_call_pause(call);
BC_ASSERT_TRUE(wait_for_list(lcs, &mgr_pausing->stat.number_of_LinphoneCallPausing, (noCallPausing + 1), 5000));
BC_ASSERT_TRUE(
wait_for_list(lcs, &mgr_paused->stat.number_of_LinphoneCallPausedByRemote, (noCallPausedByRemote + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &mgr_pausing->stat.number_of_LinphoneCallPaused, (noCallPaused + 1), 5000));
LinphoneAudioDevice *next_dev = change_device(enable, mgr_change_device, current_dev, dev0, dev1);
// Check output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(mgr_change_device->lc), next_dev);
LinphoneAudioDevice *expected_input_dev = NULL;
if (enable || linphone_core_is_in_conference(mgr_change_device->lc)) {
// If the call is paused, input soundcard is not used but as it is changed, the getter returns the new sound
// card
expected_input_dev = next_dev;
} else {
// If call is paused, input soundcard is not used therefore the current one is NULL
expected_input_dev = NULL;
}
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(mgr_change_device->lc), expected_input_dev);
// stay in pause a little while in order to generate traffic
wait_for_until(mgr_pausing->lc, mgr_paused->lc, NULL, 5, 2000);
linphone_call_resume(call);
BC_ASSERT_TRUE(wait_for_list(lcs, &mgr_pausing->stat.number_of_LinphoneCallStreamsRunning,
(noStreamRunningPausing + 1), 5000));
BC_ASSERT_TRUE(
wait_for_list(lcs, &mgr_paused->stat.number_of_LinphoneCallStreamsRunning, (noStreamRunningPaused + 1), 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &mgr_pausing->stat.number_of_LinphoneCallResuming, (noCallResuming + 1), 5000));
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(mgr_change_device->lc), next_dev);
BC_ASSERT_STRING_EQUAL(linphone_audio_device_get_id(linphone_core_get_output_audio_device(mgr_change_device->lc)),
linphone_audio_device_get_id(next_dev)); // To know what IDs are
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(mgr_change_device->lc), next_dev);
return next_dev;
}
static void simple_call_with_audio_device_change_during_call_pause_base(bool_t callee, bool_t caller) {
bctbx_list_t *lcs;
// Marie is the caller
1261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
// Adding 2 devices to Marie' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
register_device(marie, &dummy_test_snd_card_desc);
register_device(marie, &dummy2_test_snd_card_desc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown device at the head of the list
LinphoneAudioDevice *marie_dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(marie_dev0);
marie_dev0 = linphone_audio_device_ref(marie_dev0);
// 2nd device in the list
LinphoneAudioDevice *marie_dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(marie_dev1);
marie_dev1 = linphone_audio_device_ref(marie_dev1);
// At the start, choose default device for marie i.e. marie_dev0
LinphoneAudioDevice *marie_current_dev = marie_dev0;
BC_ASSERT_PTR_NOT_NULL(marie_current_dev);
marie_current_dev = linphone_audio_device_ref(marie_current_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(NULL, marie->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, marie_dev1);
linphone_core_set_default_output_audio_device(marie->lc, marie_dev1);
// Pauline is online - ringback can start immediately
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
linphone_core_set_network_reachable(pauline->lc, TRUE);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
// Adding 2 devices to Pauline sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
register_device(pauline, &dummy_test_snd_card_desc);
register_device(pauline, &dummy2_test_snd_card_desc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
audio_devices = linphone_core_get_extended_audio_devices(pauline->lc);
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown device at the head of the list
LinphoneAudioDevice *pauline_dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(pauline_dev0);
pauline_dev0 = linphone_audio_device_ref(pauline_dev0);
// 2nd device in the list
LinphoneAudioDevice *pauline_dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(pauline_dev1);
pauline_dev1 = linphone_audio_device_ref(pauline_dev1);
// At the start, choose default device for pauline i.e. pauline_dev0
LinphoneAudioDevice *pauline_current_dev = pauline_dev0;
BC_ASSERT_PTR_NOT_NULL(pauline_current_dev);
1331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
pauline_current_dev = linphone_audio_device_ref(pauline_current_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(lcs, pauline->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(pauline->lc, pauline_dev1);
linphone_core_set_default_output_audio_device(pauline->lc, pauline_dev1);
LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL);
linphone_call_params_set_input_audio_device(marie_params, marie_current_dev);
linphone_call_params_set_output_audio_device(marie_params, marie_current_dev);
LinphoneCall *marie_call = linphone_core_invite_address_with_params(marie->lc, pauline->identity, marie_params);
BC_ASSERT_PTR_NOT_NULL(marie_call);
linphone_call_params_unref(marie_params);
// Pauline shall receive the call immediately
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 5000));
LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc);
if (!BC_ASSERT_PTR_NOT_NULL(pauline_call)) goto end;
// Marie should hear ringback as well
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1, 5000));
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), marie_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), marie_current_dev);
LinphoneCallParams *pauline_params = linphone_core_create_call_params(pauline->lc, NULL);
linphone_call_params_set_input_audio_device(pauline_params, pauline_current_dev);
linphone_call_params_set_output_audio_device(pauline_params, pauline_current_dev);
// Take call - ringing ends
linphone_call_accept_with_params(pauline_call, pauline_params);
linphone_call_params_unref(pauline_params);
// Start call with a device that it is not the default one
linphone_audio_device_unref(pauline_current_dev);
pauline_current_dev = linphone_audio_device_ref(pauline_dev1);
BC_ASSERT_PTR_NOT_NULL(pauline_current_dev);
linphone_audio_device_unref(marie_current_dev);
marie_current_dev = linphone_audio_device_ref(marie_dev1);
BC_ASSERT_PTR_NOT_NULL(marie_current_dev);
// Set audio device to start with a known situation
linphone_core_set_input_audio_device(pauline->lc, pauline_current_dev);
linphone_core_set_output_audio_device(pauline->lc, pauline_current_dev);
linphone_core_set_input_audio_device(marie->lc, marie_current_dev);
linphone_core_set_output_audio_device(marie->lc, marie_current_dev);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1));
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// Callee pauses call and changes device
pauline_current_dev = pause_call_changing_device(callee, lcs, pauline_call, pauline, marie, pauline,
pauline_current_dev, pauline_dev0, pauline_dev1);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), marie_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), marie_current_dev);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// Callee pauses call and caller changes device
marie_current_dev = pause_call_changing_device(callee, lcs, pauline_call, pauline, marie, marie, marie_current_dev,
marie_dev0, marie_dev1);
1401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(pauline->lc), pauline_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(pauline->lc), pauline_current_dev);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// Caller pauses call and callee changes device
pauline_current_dev = pause_call_changing_device(caller, lcs, marie_call, marie, pauline, pauline,
pauline_current_dev, pauline_dev0, pauline_dev1);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), marie_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), marie_current_dev);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// Caller pauses call and changes device
marie_current_dev = pause_call_changing_device(caller, lcs, marie_call, marie, pauline, marie, marie_current_dev,
marie_dev0, marie_dev1);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(pauline->lc), pauline_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(pauline->lc), pauline_current_dev);
// stay in pause a little while in order to generate traffic
wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000);
// End call
linphone_call_terminate(pauline_call);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
end:
// After call, unref the sound card
linphone_audio_device_unref(marie_dev0);
linphone_audio_device_unref(marie_dev1);
linphone_audio_device_unref(marie_current_dev);
linphone_core_manager_destroy(marie);
linphone_audio_device_unref(pauline_dev0);
linphone_audio_device_unref(pauline_dev1);
linphone_audio_device_unref(pauline_current_dev);
linphone_core_manager_destroy(pauline);
bctbx_list_free(lcs);
}
static void simple_call_with_audio_device_change_during_call_pause_callee(void) {
simple_call_with_audio_device_change_during_call_pause_base(TRUE, FALSE);
}
static void simple_call_with_audio_device_change_during_call_pause_caller(void) {
simple_call_with_audio_device_change_during_call_pause_base(FALSE, TRUE);
}
static void simple_call_with_audio_device_change_during_call_pause_caller_callee(void) {
simple_call_with_audio_device_change_during_call_pause_base(TRUE, TRUE);
}
static void simple_call_with_audio_devices_reload(void) {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline =
linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
unregister_all_devices(marie);
BC_ASSERT_PTR_NULL(linphone_core_get_output_audio_device(marie->lc));
BC_ASSERT_PTR_NULL(linphone_core_get_input_audio_device(marie->lc));
BC_ASSERT_PTR_NULL(linphone_core_get_output_audio_device(pauline->lc));
BC_ASSERT_PTR_NULL(linphone_core_get_input_audio_device(pauline->lc));
BC_ASSERT_PTR_NULL(linphone_core_get_default_input_audio_device(
pauline->lc)); // Pauline is using files instead of soundcard, so defaults cards for Pauline are NULL
BC_ASSERT_PTR_NULL(linphone_core_get_default_output_audio_device(pauline->lc));
1471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
BC_ASSERT_TRUE(call(marie, pauline));
for (int i = 0; i < 2; ++i) {
BC_ASSERT_PTR_NULL(linphone_core_get_output_audio_device(marie->lc)); // No devices for audio streaming
BC_ASSERT_PTR_NULL(linphone_core_get_input_audio_device(marie->lc));
BC_ASSERT_PTR_NULL(
linphone_core_get_output_audio_device(pauline->lc)); // Pauline is using files instead of soundcard so all
// cards should stay at NULL after accepting the call
BC_ASSERT_PTR_NULL(linphone_core_get_input_audio_device(pauline->lc));
LinphoneCall *marie_call = linphone_core_get_current_call(marie->lc);
BC_ASSERT_PTR_NULL(linphone_call_get_output_audio_device(marie_call)); // No sound card yet
BC_ASSERT_PTR_NULL(linphone_call_get_input_audio_device(marie_call));
LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NULL(linphone_call_get_output_audio_device(pauline_call));
BC_ASSERT_PTR_NULL(linphone_call_get_input_audio_device(pauline_call));
int noDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
int nbDevListUpdates = marie->stat.number_of_LinphoneCoreAudioDevicesListUpdated;
// Device reconnection
register_device(marie, &dummy_test_snd_card_desc);
noDevChanges += 2; // This is a new device from nothing. There are 2 updates : input/output
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDevicesListUpdated, nbDevListUpdates + 1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
BC_ASSERT_PTR_NOT_NULL(linphone_core_get_output_audio_device(marie->lc));
BC_ASSERT_PTR_NOT_NULL(linphone_core_get_input_audio_device(marie->lc));
BC_ASSERT_PTR_NOT_NULL(linphone_call_get_output_audio_device(marie_call));
BC_ASSERT_PTR_NOT_NULL(linphone_call_get_input_audio_device(marie_call));
bctbx_list_t *audio_devices = linphone_core_get_audio_devices(marie->lc);
BC_ASSERT_EQUAL((int)bctbx_list_size(audio_devices), 1, int, "%d");
LinphoneAudioDevice *audio_device = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(audio_device);
linphone_audio_device_ref(audio_device);
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
// Core should not be notified of audio device changed
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
linphone_core_set_output_audio_device(marie->lc, audio_device);
noDevChanges += 1; // Only output has been changed
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), audio_device);
linphone_core_set_input_audio_device(marie->lc, audio_device);
noDevChanges += 1; // Only input has been changed
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), audio_device);
// Now test when all devices disconnect while being in call
unregister_all_devices(marie);
linphone_audio_device_unref(audio_device);
}
end_call(marie, pauline);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCoreLastCallEnded, 1, int, "%d");
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(marie);
}
static void
simple_conference_with_audio_device_change_base(bool_t during_setup, bool_t before_all_join, bool_t after_all_join) {
bctbx_list_t *lcs = NULL;
// Marie is the caller
1541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
LinphoneCoreManager *marie = create_mgr_for_conference("marie_rc", TRUE, NULL);
unregister_all_devices(marie); // Start with no sound cards
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int native_audio_devices_count = (int)bctbx_list_size(audio_devices);
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
// Adding 2 devices to Marie' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
// This devices are prepended to the list of so that they can be easily accessed later
register_device(marie, &dummy_test_snd_card_desc);
register_device(marie, &dummy2_test_snd_card_desc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int audio_devices_count = (int)bctbx_list_size(audio_devices);
BC_ASSERT_EQUAL(audio_devices_count, (native_audio_devices_count + 2), int, "%d");
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown device at the head of the list
LinphoneAudioDevice *dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(dev0);
linphone_audio_device_ref(dev0);
// 2nd device in the list
LinphoneAudioDevice *dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(dev1);
linphone_audio_device_ref(dev1);
// At the start, choose default device i.e. dev0
LinphoneAudioDevice *current_dev = dev0;
BC_ASSERT_PTR_NOT_NULL(current_dev);
linphone_audio_device_ref(current_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(lcs, marie->lc);
// Pauline is offline
LinphoneCoreManager *pauline = create_mgr_for_conference(
transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", TRUE, NULL);
linphone_core_set_network_reachable(pauline->lc, FALSE);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
lcs = bctbx_list_append(lcs, pauline->lc);
LinphoneCoreManager *laure =
create_mgr_for_conference(liblinphone_tester_ipv6_available() ? "laure_tcp_rc" : "laure_rc_udp", TRUE, NULL);
linphone_core_set_network_reachable(laure->lc, TRUE);
lcs = bctbx_list_append(lcs, laure->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, current_dev);
linphone_core_set_default_output_audio_device(marie->lc, current_dev);
// Laure creates the conference
LinphoneConferenceParams *conf_params = linphone_core_create_conference_params_2(laure->lc, NULL);
linphone_conference_params_set_video_enabled(conf_params, FALSE);
LinphoneConference *conf = linphone_core_create_conference_with_params(laure->lc, conf_params);
linphone_conference_params_unref(conf_params);
bctbx_list_t *participants = NULL;
participants = bctbx_list_append(participants, pauline);
1611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
participants = bctbx_list_append(participants, marie);
int noParticipants = (int)bctbx_list_size(participants);
add_participant_to_local_conference_through_invite(lcs, laure, participants, NULL);
LinphoneCall *marie_call = linphone_core_get_current_call(marie->lc);
BC_ASSERT_PTR_NOT_NULL(marie_call);
linphone_audio_device_unref(current_dev);
current_dev = linphone_audio_device_ref(dev1);
BC_ASSERT_PTR_NOT_NULL(current_dev);
// Set audio device to start with a known situation - do not use default device
linphone_core_set_input_audio_device(marie->lc, current_dev); // This set capture
linphone_core_set_output_audio_device(marie->lc, current_dev); // This set Playback
linphone_core_set_ringer_device(marie->lc, linphone_audio_device_get_id(current_dev)); // This set ringer
// wait a bit before Marie changes device
wait_for_list(lcs, NULL, 0, 2000);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc),
current_dev); // Incoming call : the output is the ring stream
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_dev);
current_dev = change_device(during_setup, marie, current_dev, dev0, dev1);
// wait a bit before Marie accepts the call
wait_for_list(lcs, NULL, 0, 2000);
linphone_call_accept(marie_call);
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneConferenceStateCreationPending, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneConferenceStateCreated, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneConferenceStateCreationPending, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneConferenceStateCreated, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallConnected, 1, 10000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallStreamsRunning, 1, 3000));
// wait a bit before Marie changes device
wait_for_list(lcs, NULL, 0, 2000);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_dev);
BC_ASSERT_STRING_EQUAL(linphone_audio_device_get_id(linphone_core_get_output_audio_device(marie->lc)),
linphone_audio_device_get_id(current_dev)); // To know what IDs are
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_dev);
current_dev = change_device(before_all_join, marie, current_dev, dev0, dev1);
// wait a bit before Pauline is reachable
wait_for_list(lcs, NULL, 0, 2000);
linphone_core_set_network_reachable(pauline->lc, TRUE);
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallOutgoingProgress, noParticipants, 2000));
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 10000));
LinphoneCall *pauline_call = linphone_core_get_current_call(pauline->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
linphone_call_accept(pauline_call);
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneConferenceStateCreationPending, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneConferenceStateCreated, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneConferenceStateCreationPending, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneConferenceStateCreated, 1, 5000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallConnected, noParticipants, 10000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallStreamsRunning, noParticipants, 3000));
// make sure that the two calls from Marie's standpoint are in conference
const bctbx_list_t *laure_calls = linphone_core_get_calls(laure->lc);
BC_ASSERT_EQUAL((int)bctbx_list_size(laure_calls), noParticipants, int, "%i");
const bctbx_list_t *it;
for (it = laure_calls; it != NULL; it = it->next) {
BC_ASSERT_TRUE(linphone_call_params_get_local_conference_mode(
linphone_call_get_current_params((LinphoneCall *)it->data)) == TRUE);
}
1681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
// wait a bit before Marie changes device
wait_for_list(lcs, NULL, 0, 2000);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_dev);
current_dev = change_device(after_all_join, marie, current_dev, dev0, dev1);
// wait a bit before ending the conference
wait_for_list(lcs, NULL, 0, 5000);
terminate_conference(participants, laure, conf, NULL);
linphone_conference_unref(conf);
destroy_mgr_in_conference(marie);
destroy_mgr_in_conference(pauline);
destroy_mgr_in_conference(laure);
linphone_audio_device_unref(dev0);
linphone_audio_device_unref(dev1);
linphone_audio_device_unref(current_dev);
bctbx_list_free(participants);
bctbx_list_free(lcs);
}
static void simple_conference_with_audio_device_change_during_setup(void) {
simple_conference_with_audio_device_change_base(TRUE, FALSE, FALSE);
}
static void simple_conference_with_audio_device_change_before_all_join(void) {
simple_conference_with_audio_device_change_base(FALSE, TRUE, FALSE);
}
static void simple_conference_with_audio_device_change_after_all_join(void) {
simple_conference_with_audio_device_change_base(FALSE, FALSE, TRUE);
}
static void simple_conference_with_audio_device_change_pingpong(void) {
simple_conference_with_audio_device_change_base(TRUE, TRUE, TRUE);
}
static void simple_conference_with_audio_device_change_during_pause_base(bool_t callee, bool_t caller) {
bctbx_list_t *lcs = NULL;
// Marie is the caller
LinphoneCoreManager *marie = create_mgr_for_conference("marie_rc", TRUE, NULL);
// load audio devices and get initial number of cards
linphone_core_reload_sound_devices(marie->lc);
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int native_audio_devices_count = (int)bctbx_list_size(audio_devices);
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
MSFactory *factory = linphone_core_get_ms_factory(marie->lc);
// Adding 2 devices to Marie' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
MSSndCardManager *sndcard_manager = ms_factory_get_snd_card_manager(factory);
// This devices are prepended to the list of so that they can be easily accessed later
ms_snd_card_manager_register_desc(sndcard_manager, &dummy_test_snd_card_desc);
ms_snd_card_manager_register_desc(sndcard_manager, &dummy2_test_snd_card_desc);
linphone_core_reload_sound_devices(marie->lc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int audio_devices_count = (int)bctbx_list_size(audio_devices);
BC_ASSERT_EQUAL(audio_devices_count, (native_audio_devices_count + 2), int, "%d");
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
1751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820
// type is Unknown device at the head of the list
LinphoneAudioDevice *marie_dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(marie_dev0);
linphone_audio_device_ref(marie_dev0);
// 2nd device in the list
LinphoneAudioDevice *marie_dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(marie_dev1);
linphone_audio_device_ref(marie_dev1);
// At the start, choose default device i.e. dev0
LinphoneAudioDevice *marie_current_dev = marie_dev0;
BC_ASSERT_PTR_NOT_NULL(marie_current_dev);
linphone_audio_device_ref(marie_current_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(lcs, marie->lc);
// Pauline is onlineoffline
LinphoneCoreManager *pauline = create_mgr_for_conference(
transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", TRUE, NULL);
linphone_core_set_network_reachable(pauline->lc, TRUE);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
// load audio devices and get initial number of cards
linphone_core_reload_sound_devices(pauline->lc);
audio_devices = linphone_core_get_extended_audio_devices(pauline->lc);
native_audio_devices_count = (int)bctbx_list_size(audio_devices);
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
factory = linphone_core_get_ms_factory(pauline->lc);
// Adding 2 devices to Marie' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
sndcard_manager = ms_factory_get_snd_card_manager(factory);
// This devices are prepended to the list of so that they can be easily accessed later
ms_snd_card_manager_register_desc(sndcard_manager, &dummy_test_snd_card_desc);
ms_snd_card_manager_register_desc(sndcard_manager, &dummy2_test_snd_card_desc);
linphone_core_reload_sound_devices(pauline->lc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
audio_devices = linphone_core_get_extended_audio_devices(pauline->lc);
audio_devices_count = (int)bctbx_list_size(audio_devices);
BC_ASSERT_EQUAL(audio_devices_count, (native_audio_devices_count + 2), int, "%d");
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown device at the head of the list
LinphoneAudioDevice *pauline_dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(pauline_dev0);
linphone_audio_device_ref(pauline_dev0);
// 2nd device in the list
LinphoneAudioDevice *pauline_dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(pauline_dev1);
linphone_audio_device_ref(pauline_dev1);
// At the start, choose default device i.e. dev0
LinphoneAudioDevice *pauline_current_dev = pauline_dev0;
BC_ASSERT_PTR_NOT_NULL(pauline_current_dev);
linphone_audio_device_ref(pauline_current_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
1821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
lcs = bctbx_list_append(lcs, pauline->lc);
LinphoneCoreManager *laure =
create_mgr_for_conference(liblinphone_tester_ipv6_available() ? "laure_tcp_rc" : "laure_rc_udp", TRUE, NULL);
linphone_core_set_network_reachable(laure->lc, TRUE);
lcs = bctbx_list_append(lcs, laure->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, marie_current_dev);
linphone_core_set_default_output_audio_device(marie->lc, marie_current_dev);
linphone_core_set_default_input_audio_device(pauline->lc, pauline_current_dev);
linphone_core_set_default_output_audio_device(pauline->lc, pauline_current_dev);
// Laure creates the conference
LinphoneConferenceParams *conf_params = linphone_core_create_conference_params_2(pauline->lc, NULL);
linphone_conference_params_set_video_enabled(conf_params, FALSE);
LinphoneConference *conf = linphone_core_create_conference_with_params(pauline->lc, conf_params);
linphone_conference_params_unref(conf_params);
bctbx_list_t *participants = NULL;
participants = bctbx_list_append(participants, laure);
participants = bctbx_list_append(participants, marie);
int noParticipants = (int)bctbx_list_size(participants);
add_participant_to_local_conference_through_invite(lcs, pauline, participants, NULL);
linphone_audio_device_unref(marie_current_dev);
marie_current_dev = linphone_audio_device_ref(marie_dev1);
BC_ASSERT_PTR_NOT_NULL(marie_current_dev);
linphone_audio_device_unref(pauline_current_dev);
pauline_current_dev = linphone_audio_device_ref(pauline_dev1);
BC_ASSERT_PTR_NOT_NULL(pauline_current_dev);
LinphoneCall *marie_call = linphone_core_get_current_call(marie->lc);
BC_ASSERT_PTR_NOT_NULL(marie_call);
// Set audio device to start with a known situation - do not use default device
linphone_core_set_input_audio_device(marie->lc, marie_current_dev);
linphone_core_set_output_audio_device(marie->lc, marie_current_dev);
linphone_core_set_input_audio_device(pauline->lc, pauline_current_dev);
linphone_core_set_output_audio_device(pauline->lc, pauline_current_dev);
// wait a bit before Marie accepts the call
wait_for_list(lcs, NULL, 0, 2000);
linphone_call_accept(marie_call);
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallConnected, 1, 10000));
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1, 3000));
// wait a bit before Pauline is reachable
wait_for_list(lcs, NULL, 0, 2000);
linphone_core_set_network_reachable(pauline->lc, TRUE);
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingProgress, noParticipants, 2000));
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallIncomingReceived, 1, 10000));
LinphoneCall *laure_call = linphone_core_get_current_call(laure->lc);
BC_ASSERT_PTR_NOT_NULL(laure_call);
linphone_call_accept(laure_call);
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallConnected, noParticipants, 10000));
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, noParticipants, 3000));
LinphoneCall *pauline_call = NULL;
// make sure that the two calls from Marie's standpoint are in conference
const bctbx_list_t *pauline_calls = linphone_core_get_calls(pauline->lc);
BC_ASSERT_EQUAL((int)bctbx_list_size(pauline_calls), noParticipants, int, "%i");
const bctbx_list_t *it;
for (it = pauline_calls; it != NULL; it = it->next) {
1891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960
pauline_call = (LinphoneCall *)it->data;
BC_ASSERT_TRUE(linphone_call_params_get_local_conference_mode(
linphone_call_get_current_params((LinphoneCall *)it->data)) == TRUE);
}
if (!BC_ASSERT_PTR_NOT_NULL(pauline_call)) goto end;
linphone_call_ref(pauline_call);
// wait a bit before changing device
wait_for_list(lcs, NULL, 0, 2000);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), marie_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), marie_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(pauline->lc), pauline_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(pauline->lc), pauline_current_dev);
// Callee pauses call and callee changes device
pauline_current_dev = pause_call_changing_device(callee, lcs, marie_call, marie, pauline, pauline,
pauline_current_dev, pauline_dev0, pauline_dev1);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), marie_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), marie_current_dev);
// wait a bit before Marie changes device
wait_for_list(lcs, NULL, 0, 2000);
// Caller pauses call and changes device
marie_current_dev = pause_call_changing_device(caller, lcs, marie_call, marie, pauline, marie, marie_current_dev,
marie_dev0, marie_dev1);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(pauline->lc), pauline_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(pauline->lc), pauline_current_dev);
// wait a bit before ending the conference
wait_for_list(lcs, NULL, 0, 5000);
terminate_conference(participants, pauline, conf, NULL);
end:
if (pauline_call) linphone_call_unref(pauline_call);
linphone_conference_unref(conf);
// After call, unref the sound card
linphone_audio_device_unref(marie_dev0);
linphone_audio_device_unref(marie_dev1);
linphone_audio_device_unref(marie_current_dev);
destroy_mgr_in_conference(marie);
linphone_audio_device_unref(pauline_dev0);
linphone_audio_device_unref(pauline_dev1);
linphone_audio_device_unref(pauline_current_dev);
destroy_mgr_in_conference(pauline);
destroy_mgr_in_conference(laure);
bctbx_list_free(participants);
bctbx_list_free(lcs);
}
static void simple_conference_with_audio_device_change_during_pause_callee(void) {
simple_conference_with_audio_device_change_during_pause_base(TRUE, FALSE);
}
static void simple_conference_with_audio_device_change_during_pause_caller(void) {
simple_conference_with_audio_device_change_during_pause_base(FALSE, TRUE);
}
static void simple_conference_with_audio_device_change_during_pause_caller_callee(void) {
simple_conference_with_audio_device_change_during_pause_base(TRUE, TRUE);
}
static void conference_with_simple_audio_device_change(void) {
bctbx_list_t *lcs = NULL;
bctbx_list_t *dev_found = NULL;
1961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030
// Marie is the caller
LinphoneCoreManager *marie = create_mgr_for_conference("marie_rc", TRUE, NULL);
// load audio devices and get initial number of cards
linphone_core_reload_sound_devices(marie->lc);
bctbx_list_t *marie_audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int native_marie_audio_devices_count = (int)bctbx_list_size(marie_audio_devices);
bctbx_list_free_with_data(marie_audio_devices, (void (*)(void *))linphone_audio_device_unref);
MSFactory *marie_factory = linphone_core_get_ms_factory(marie->lc);
// Adding 4 devices to Marie' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
// - dummy_capture_test_snd_card_desc
// - dummy_playback_test_snd_card_desc
MSSndCardManager *marie_sndcard_manager = ms_factory_get_snd_card_manager(marie_factory);
// This devices are prepended to the list of so that they can be easily accessed later
ms_snd_card_manager_register_desc(marie_sndcard_manager, &dummy_test_snd_card_desc);
ms_snd_card_manager_register_desc(marie_sndcard_manager, &dummy2_test_snd_card_desc);
ms_snd_card_manager_register_desc(marie_sndcard_manager, &dummy_capture_test_snd_card_desc);
ms_snd_card_manager_register_desc(marie_sndcard_manager, &dummy_playback_test_snd_card_desc);
linphone_core_reload_sound_devices(marie->lc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
marie_audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int marie_audio_devices_count = (int)bctbx_list_size(marie_audio_devices);
BC_ASSERT_EQUAL(marie_audio_devices_count, (native_marie_audio_devices_count + 4), int, "%d");
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown 1st device
dev_found =
bctbx_list_find_custom(marie_audio_devices, (bctbx_compare_func)audio_device_name_match, DUMMY_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *marie_dev0 = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(marie_dev0);
linphone_audio_device_ref(marie_dev0);
// 2nd device
dev_found =
bctbx_list_find_custom(marie_audio_devices, (bctbx_compare_func)audio_device_name_match, DUMMY2_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *marie_dev1 = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(marie_dev1);
linphone_audio_device_ref(marie_dev1);
// device dummy_playback in the list
dev_found = bctbx_list_find_custom(marie_audio_devices, (bctbx_compare_func)audio_device_name_match,
DUMMY_PLAYBACK_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *marie_playback = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(marie_playback);
linphone_audio_device_ref(marie_playback);
// device dummy_capture in the list
dev_found = bctbx_list_find_custom(marie_audio_devices, (bctbx_compare_func)audio_device_name_match,
DUMMY_CAPTURE_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *marie_capture = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(marie_capture);
linphone_audio_device_ref(marie_capture);
// At the start, choose default device i.e. marie_dev0
LinphoneAudioDevice *marie_current_dev = marie_dev0;
BC_ASSERT_PTR_NOT_NULL(marie_current_dev);
linphone_audio_device_ref(marie_current_dev);
2031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100
// Unref cards
bctbx_list_free_with_data(marie_audio_devices, (void (*)(void *))linphone_audio_device_unref);
// Pauline is offline
LinphoneCoreManager *pauline = create_mgr_for_conference(
transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", TRUE, NULL);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
LinphoneCoreManager *laure =
create_mgr_for_conference(liblinphone_tester_ipv6_available() ? "laure_tcp_rc" : "laure_rc_udp", TRUE, NULL);
// Do not allow Laure to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(laure->lc, FALSE);
// Laure creates the conference
LinphoneConferenceParams *conf_params = linphone_core_create_conference_params_2(laure->lc, NULL);
linphone_conference_params_set_video_enabled(conf_params, FALSE);
LinphoneConference *conf = linphone_core_create_conference_with_params(laure->lc, conf_params);
linphone_conference_params_unref(conf_params);
// load audio devices and get initial number of cards
linphone_core_reload_sound_devices(laure->lc);
bctbx_list_t *laure_audio_devices = linphone_core_get_extended_audio_devices(laure->lc);
int native_laure_audio_devices_count = (int)bctbx_list_size(laure_audio_devices);
bctbx_list_free_with_data(laure_audio_devices, (void (*)(void *))linphone_audio_device_unref);
MSFactory *laure_factory = linphone_core_get_ms_factory(laure->lc);
// Adding 2 devices to Laure' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
MSSndCardManager *laure_sndcard_manager = ms_factory_get_snd_card_manager(laure_factory);
// This devices are prepended to the list of so that they can be easily accessed later
ms_snd_card_manager_register_desc(laure_sndcard_manager, &dummy2_test_snd_card_desc);
ms_snd_card_manager_register_desc(laure_sndcard_manager, &dummy_test_snd_card_desc);
ms_snd_card_manager_register_desc(laure_sndcard_manager, &dummy_capture_test_snd_card_desc);
ms_snd_card_manager_register_desc(laure_sndcard_manager, &dummy_playback_test_snd_card_desc);
linphone_core_reload_sound_devices(laure->lc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
laure_audio_devices = linphone_core_get_extended_audio_devices(laure->lc);
int laure_audio_devices_count = (int)bctbx_list_size(laure_audio_devices);
BC_ASSERT_EQUAL(laure_audio_devices_count, (native_laure_audio_devices_count + 4), int, "%d");
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown 1st device
dev_found =
bctbx_list_find_custom(laure_audio_devices, (bctbx_compare_func)audio_device_name_match, DUMMY2_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *laure_dev0 = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(laure_dev0);
linphone_audio_device_ref(laure_dev0);
// 2nd device
dev_found =
bctbx_list_find_custom(laure_audio_devices, (bctbx_compare_func)audio_device_name_match, DUMMY_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *laure_dev1 = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(laure_dev1);
linphone_audio_device_ref(laure_dev1);
// device dummy_playback in the list
dev_found = bctbx_list_find_custom(laure_audio_devices, (bctbx_compare_func)audio_device_name_match,
DUMMY_PLAYBACK_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *laure_playback = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(laure_playback);
linphone_audio_device_ref(laure_playback);
2101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170
// device dummy_capture in the list
dev_found = bctbx_list_find_custom(laure_audio_devices, (bctbx_compare_func)audio_device_name_match,
DUMMY_CAPTURE_TEST_SOUNDCARD);
BC_ASSERT_PTR_NOT_NULL(dev_found);
LinphoneAudioDevice *laure_capture = (dev_found) ? (LinphoneAudioDevice *)bctbx_list_get_data(dev_found) : NULL;
BC_ASSERT_PTR_NOT_NULL(laure_capture);
linphone_audio_device_ref(laure_capture);
// At the start, choose default device i.e. laure_dev0
LinphoneAudioDevice *laure_current_dev = laure_dev0;
BC_ASSERT_PTR_NOT_NULL(laure_current_dev);
linphone_audio_device_ref(laure_current_dev);
// Unref cards
bctbx_list_free_with_data(laure_audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(lcs, laure->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, marie_current_dev);
linphone_core_set_default_output_audio_device(marie->lc, marie_current_dev);
linphone_core_set_default_input_audio_device(laure->lc, laure_current_dev);
linphone_core_set_default_output_audio_device(laure->lc, laure_current_dev);
bctbx_list_t *participants = NULL;
participants = bctbx_list_append(participants, pauline);
participants = bctbx_list_append(participants, marie);
initiate_calls(participants, laure);
unsigned int idx = 0;
LinphoneCoreManager *prev_mgr = NULL;
for (bctbx_list_t *it = participants; it; it = bctbx_list_next(it)) {
LinphoneCoreManager *m = (LinphoneCoreManager *)bctbx_list_get_data(it);
LinphoneCore *c = m->lc;
lcs = bctbx_list_append(lcs, c);
if (prev_mgr != NULL) {
LinphoneCall *m_called_by_laure = linphone_core_get_current_call(prev_mgr->lc);
LinphoneCall *laure_call_m = linphone_core_get_call_by_remote_address2(laure->lc, prev_mgr->identity);
BC_ASSERT_TRUE(pause_call_1(laure, laure_call_m, prev_mgr, m_called_by_laure));
}
const LinphoneAddress *caller_uri = m->identity;
LinphoneCall *laure_call = linphone_core_get_call_by_remote_address2(laure->lc, caller_uri);
BC_ASSERT_PTR_NOT_NULL(laure_call);
// Take call - ringing ends
linphone_call_accept(laure_call);
idx++;
BC_ASSERT_TRUE(wait_for_until(m->lc, laure->lc, &m->stat.number_of_LinphoneCallConnected, 1, 5000));
BC_ASSERT_TRUE(wait_for_until(m->lc, laure->lc, &m->stat.number_of_LinphoneCallStreamsRunning, 1, 5000));
BC_ASSERT_TRUE(wait_for_until(m->lc, laure->lc, &laure->stat.number_of_LinphoneCallConnected, idx, 5000));
BC_ASSERT_TRUE(wait_for_until(m->lc, laure->lc, &laure->stat.number_of_LinphoneCallStreamsRunning, idx, 5000));
prev_mgr = m;
}
LinphoneCall *marie_call = linphone_core_get_current_call(marie->lc);
BC_ASSERT_PTR_NOT_NULL(marie_call);
int noDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
if (marie_call) {
2171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240
BC_ASSERT_PTR_NOT_NULL(marie_playback);
if (marie_playback) {
linphone_call_set_output_audio_device(marie_call, marie_playback);
}
BC_ASSERT_PTR_NOT_NULL(marie_capture);
if (marie_capture) {
linphone_call_set_input_audio_device(marie_call, marie_capture);
}
}
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, (noDevChanges + 2), int, "%d");
// Check Marie's output device
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), marie_playback);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), marie_capture);
LinphoneCall *laure_call = linphone_core_get_current_call(laure->lc);
BC_ASSERT_PTR_NOT_NULL(laure_call);
noDevChanges = laure->stat.number_of_LinphoneCoreAudioDeviceChanged;
if (laure_call) {
BC_ASSERT_PTR_NOT_NULL(laure_playback);
if (laure_playback) {
linphone_call_set_output_audio_device(laure_call, laure_playback);
}
BC_ASSERT_PTR_NOT_NULL(laure_capture);
if (laure_capture) {
linphone_call_set_input_audio_device(laure_call, laure_capture);
}
}
BC_ASSERT_EQUAL(laure->stat.number_of_LinphoneCoreAudioDeviceChanged, (noDevChanges + 2), int, "%d");
// Check Laure's output device
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(laure_call), laure_playback);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(laure_call), laure_capture);
add_calls_to_local_conference(lcs, laure, conf, participants, FALSE);
// wait a bit before Marie changes device
wait_for_list(lcs, NULL, 0, 2000);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), marie_capture);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), marie_playback);
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), marie_capture);
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), marie_playback);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(laure->lc), laure_capture);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(laure->lc), laure_playback);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_input_audio_device(conf), laure_capture);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_output_audio_device(conf), laure_playback);
// Set invalid audio device to the call
noDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
linphone_call_set_input_audio_device(marie_call, marie_playback);
linphone_call_set_output_audio_device(marie_call, marie_capture);
wait_for_list(lcs, NULL, 0, 1000);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), marie_capture);
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), marie_playback);
// Set invalid audio device to the conference
noDevChanges = laure->stat.number_of_LinphoneCoreAudioDeviceChanged;
linphone_conference_set_input_audio_device(conf, laure_playback);
linphone_conference_set_output_audio_device(conf, laure_capture);
wait_for_list(lcs, NULL, 0, 1000);
BC_ASSERT_EQUAL(laure->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_conference_get_input_audio_device(conf), laure_capture);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_output_audio_device(conf), laure_playback);
2241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310
// Set again the same audio device to the call
noDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
linphone_call_set_input_audio_device(marie_call, marie_capture);
linphone_call_set_output_audio_device(marie_call, marie_playback);
wait_for_list(lcs, NULL, 0, 1000);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_call_get_input_audio_device(marie_call), marie_capture);
BC_ASSERT_PTR_EQUAL(linphone_call_get_output_audio_device(marie_call), marie_playback);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(laure->lc), laure_capture);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(laure->lc), laure_playback);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_input_audio_device(conf), laure_capture);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_output_audio_device(conf), laure_playback);
// Set invalid audio device to the conference
noDevChanges = laure->stat.number_of_LinphoneCoreAudioDeviceChanged;
linphone_conference_set_input_audio_device(conf, laure_capture);
linphone_conference_set_output_audio_device(conf, laure_playback);
wait_for_list(lcs, NULL, 0, 1000);
BC_ASSERT_EQUAL(laure->stat.number_of_LinphoneCoreAudioDeviceChanged, noDevChanges, int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_conference_get_input_audio_device(conf), laure_capture);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_output_audio_device(conf), laure_playback);
marie_current_dev = change_device(TRUE, marie, marie_current_dev, marie_dev0, marie_dev1);
laure_current_dev = change_device(TRUE, laure, laure_current_dev, laure_dev0, laure_dev1);
// wait a bit before Marie and Laure change devices
wait_for_list(lcs, NULL, 0, 2000);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), marie_current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(laure->lc), laure_current_dev);
terminate_conference(participants, laure, conf, NULL);
bctbx_list_free(lcs);
bctbx_list_free(participants);
linphone_audio_device_unref(marie_dev0);
linphone_audio_device_unref(marie_dev1);
linphone_audio_device_unref(marie_playback);
linphone_audio_device_unref(marie_capture);
linphone_audio_device_unref(marie_current_dev);
linphone_audio_device_unref(laure_dev0);
linphone_audio_device_unref(laure_dev1);
linphone_audio_device_unref(laure_playback);
linphone_audio_device_unref(laure_capture);
linphone_audio_device_unref(laure_current_dev);
linphone_conference_unref(conf);
destroy_mgr_in_conference(marie);
destroy_mgr_in_conference(pauline);
destroy_mgr_in_conference(laure);
}
static void regex_card_selection(void) {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
linphone_core_reload_sound_devices(marie->lc);
MSFactory *factory = linphone_core_get_ms_factory(marie->lc);
MSSndCardManager *sndcard_manager = ms_factory_get_snd_card_manager(factory);
ms_snd_card_manager_register_desc(sndcard_manager, &dummy_test_snd_card_desc);
ms_snd_card_manager_register_desc(sndcard_manager, &dummy2_test_snd_card_desc);
linphone_core_reload_sound_devices(marie->lc);
// Get dummy
MSSndCard *card = ms_snd_card_manager_get_card(sndcard_manager, ".*dummy .*");
if (!BC_ASSERT_PTR_NOT_NULL(card)) goto end;
BC_ASSERT_STRING_EQUAL(card->name, DUMMY_TEST_SOUNDCARD);
// Get dummy2
2311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380
card = ms_snd_card_manager_get_card(sndcard_manager, ".*dummy2 .*");
if (!BC_ASSERT_PTR_NOT_NULL(card)) goto end;
BC_ASSERT_STRING_EQUAL(card->name, DUMMY2_TEST_SOUNDCARD);
// Get a card only from filter
card = ms_snd_card_manager_get_card(sndcard_manager, "dummyTest?( .*)?:.*");
if (!BC_ASSERT_PTR_NOT_NULL(card)) goto end;
BC_ASSERT_STRING_EQUAL(card->desc->driver_type, "dummyTest");
// Get a card only from filter
card = ms_snd_card_manager_get_card(sndcard_manager, "dummyTest2?( .*)?:.*");
if (!BC_ASSERT_PTR_NOT_NULL(card)) goto end;
BC_ASSERT_STRING_EQUAL(card->desc->driver_type, "dummyTest2");
// Get a card from bad filter and good id
card = ms_snd_card_manager_get_card(sndcard_manager, "dummyTest?( .*)?:.*dummy2.*");
if (!BC_ASSERT_PTR_NULL(card)) goto end;
// Get a card from good filter and bad id
card = ms_snd_card_manager_get_card(sndcard_manager, "dummyTest2?( .*)?:.*dummy3.*");
if (!BC_ASSERT_PTR_NULL(card)) goto end;
// Get a card from good filter and id
card = ms_snd_card_manager_get_card(sndcard_manager, "dummyTest2?( .*)?:.*dummy2.*");
if (!BC_ASSERT_PTR_NOT_NULL(card)) goto end;
BC_ASSERT_STRING_EQUAL(card->name, DUMMY2_TEST_SOUNDCARD);
// ID doesn't exists
card = ms_snd_card_manager_get_card(sndcard_manager, ".*dummy3.*");
if (!BC_ASSERT_PTR_NULL(card)) goto end;
end:
linphone_core_manager_destroy(marie);
}
static void simple_conference_with_audio_device_change_using_public_api(void) {
bctbx_list_t *lcs = NULL;
// Marie is the caller
LinphoneCoreManager *marie = create_mgr_for_conference("marie_rc", TRUE, NULL);
// load audio devices and get initial number of cards
linphone_core_reload_sound_devices(marie->lc);
bctbx_list_t *audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int native_audio_devices_count = (int)bctbx_list_size(audio_devices);
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
MSFactory *factory = linphone_core_get_ms_factory(marie->lc);
// Adding 2 devices to Marie' sound card manager:
// - dummy_test_snd_card_desc
// - dummy2_test_snd_card_desc
MSSndCardManager *sndcard_manager = ms_factory_get_snd_card_manager(factory);
// This devices are prepended to the list of so that they can be easily accessed later
ms_snd_card_manager_register_desc(sndcard_manager, &dummy_test_snd_card_desc);
ms_snd_card_manager_register_desc(sndcard_manager, &dummy2_test_snd_card_desc);
linphone_core_reload_sound_devices(marie->lc);
// Choose Marie's audio devices
// Use linphone_core_get_extended_audio_devices instead of linphone_core_get_audio_devices because we added 2 BT
// devices, therefore we want the raw list In fact, linphone_core_get_audio_devices returns only 1 device per type
audio_devices = linphone_core_get_extended_audio_devices(marie->lc);
int audio_devices_count = (int)bctbx_list_size(audio_devices);
BC_ASSERT_EQUAL(audio_devices_count, (native_audio_devices_count + 2), int, "%d");
// As new devices are prepended, they can be easily accessed and we do not run the risk of gettting a device whose
// type is Unknown device at the head of the list
LinphoneAudioDevice *dev0 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices);
BC_ASSERT_PTR_NOT_NULL(dev0);
linphone_audio_device_ref(dev0);
// 2nd device in the list
LinphoneAudioDevice *dev1 = (LinphoneAudioDevice *)bctbx_list_get_data(audio_devices->next);
BC_ASSERT_PTR_NOT_NULL(dev1);
linphone_audio_device_ref(dev1);
2381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450
// At the start, choose default device i.e. dev0
LinphoneAudioDevice *current_dev = dev0;
BC_ASSERT_PTR_NOT_NULL(current_dev);
linphone_audio_device_ref(current_dev);
// Unref cards
bctbx_list_free_with_data(audio_devices, (void (*)(void *))linphone_audio_device_unref);
lcs = bctbx_list_append(lcs, marie->lc);
LinphoneCoreManager *pauline = create_mgr_for_conference(
transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", TRUE, NULL);
// Do not allow Pauline to use files as the goal of the test is to test audio routes
linphone_core_set_use_files(pauline->lc, FALSE);
lcs = bctbx_list_append(lcs, pauline->lc);
LinphoneCoreManager *laure =
create_mgr_for_conference(liblinphone_tester_ipv6_available() ? "laure_tcp_rc" : "laure_rc_udp", TRUE, NULL);
lcs = bctbx_list_append(lcs, laure->lc);
// Set audio device to start with a known situation
linphone_core_set_default_input_audio_device(marie->lc, current_dev);
linphone_core_set_default_output_audio_device(marie->lc, current_dev);
// Laure creates the conference
LinphoneConferenceParams *conf_params = linphone_core_create_conference_params_2(marie->lc, NULL);
linphone_conference_params_set_video_enabled(conf_params, FALSE);
LinphoneConference *conf = linphone_core_create_conference_with_params(marie->lc, conf_params);
BC_ASSERT_PTR_NOT_NULL(conf);
linphone_conference_params_unref(conf_params);
bctbx_list_t *participants = NULL;
participants = bctbx_list_append(participants, pauline);
participants = bctbx_list_append(participants, laure);
initiate_calls(participants, marie);
unsigned int idx = 0;
LinphoneCoreManager *prev_mgr = NULL;
for (bctbx_list_t *it = participants; it; it = bctbx_list_next(it)) {
LinphoneCoreManager *m = (LinphoneCoreManager *)bctbx_list_get_data(it);
if (prev_mgr != NULL) {
LinphoneCall *m_called_by_marie = linphone_core_get_current_call(prev_mgr->lc);
LinphoneCall *marie_call_m = linphone_core_get_call_by_remote_address2(marie->lc, prev_mgr->identity);
BC_ASSERT_TRUE(pause_call_1(marie, marie_call_m, prev_mgr, m_called_by_marie));
}
const LinphoneAddress *caller_uri = m->identity;
LinphoneCall *marie_call = linphone_core_get_call_by_remote_address2(marie->lc, caller_uri);
BC_ASSERT_PTR_NOT_NULL(marie_call);
// Take call - ringing ends
linphone_call_accept(marie_call);
idx++;
BC_ASSERT_TRUE(wait_for_until(m->lc, marie->lc, &m->stat.number_of_LinphoneCallConnected, 1, 5000));
BC_ASSERT_TRUE(wait_for_until(m->lc, marie->lc, &m->stat.number_of_LinphoneCallStreamsRunning, 1, 5000));
BC_ASSERT_TRUE(wait_for_until(m->lc, marie->lc, &marie->stat.number_of_LinphoneCallConnected, idx, 5000));
BC_ASSERT_TRUE(wait_for_until(m->lc, marie->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, idx, 5000));
prev_mgr = m;
}
add_calls_to_local_conference(lcs, marie, conf, participants, FALSE);
BC_ASSERT_PTR_EQUAL(conf, linphone_core_get_conference(marie->lc));
2451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520
wait_for_list(lcs, NULL, 0, 2000);
BC_ASSERT_PTR_EQUAL(linphone_core_get_output_audio_device(marie->lc), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_core_get_input_audio_device(marie->lc), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_output_audio_device(conf), current_dev);
BC_ASSERT_PTR_EQUAL(linphone_conference_get_input_audio_device(conf), current_dev);
linphone_audio_device_unref(current_dev);
current_dev = linphone_audio_device_ref(dev1);
BC_ASSERT_PTR_NOT_NULL(current_dev);
int noDevChanges = marie->stat.number_of_LinphoneCoreAudioDeviceChanged;
linphone_conference_set_output_audio_device(conf, current_dev);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, (noDevChanges + 1), int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_conference_get_output_audio_device(conf), current_dev);
linphone_conference_set_input_audio_device(conf, current_dev);
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCoreAudioDeviceChanged, (noDevChanges + 2), int, "%d");
BC_ASSERT_PTR_EQUAL(linphone_conference_get_input_audio_device(conf), current_dev);
terminate_conference(participants, marie, conf, NULL);
bctbx_list_free(lcs);
bctbx_list_free(participants);
linphone_conference_unref(conf);
linphone_audio_device_unref(dev0);
linphone_audio_device_unref(dev1);
linphone_audio_device_unref(current_dev);
destroy_mgr_in_conference(marie);
destroy_mgr_in_conference(pauline);
destroy_mgr_in_conference(laure);
}
test_t audio_routes_tests[] = {
TEST_NO_TAG("Simple call with audio devices reload", simple_call_with_audio_devices_reload),
TEST_NO_TAG("Call with disconnecting device before ringback", call_with_disconnecting_device_before_ringback),
TEST_NO_TAG("Call with disconnecting device during ringback", call_with_disconnecting_device_during_ringback),
TEST_NO_TAG("Call with disconnecting device after ringback", call_with_disconnecting_device_after_ringback),
TEST_NO_TAG("Call with audio device change using public API", call_with_audio_device_change_using_public_api),
TEST_NO_TAG("Call with unreliable device", call_with_unreliable_device),
TEST_NO_TAG("Simple call with audio device change during incoming early media",
simple_call_with_audio_device_change_during_incoming_early_media),
TEST_NO_TAG("Simple call with audio device change during outgoing early media",
simple_call_with_audio_device_change_during_outgoing_early_media),
TEST_NO_TAG("Simple call with audio device change before ringback",
simple_call_with_audio_device_change_before_ringback),
TEST_NO_TAG("Simple call with audio device change during ringback",
simple_call_with_audio_device_change_during_ringback),
TEST_NO_TAG("Simple call with audio device change after ringback",
simple_call_with_audio_device_change_after_ringback),
TEST_NO_TAG("Simple call with audio device change ping-pong", simple_call_with_audio_device_change_pingpong),
TEST_NO_TAG("Simple call with audio device change same audio device pingpong",
simple_call_with_audio_device_change_same_audio_device_pingpong),
TEST_NO_TAG("Simple call with audio device change during call pause callee",
simple_call_with_audio_device_change_during_call_pause_callee),
TEST_NO_TAG("Simple call with audio device change during call pause caller",
simple_call_with_audio_device_change_during_call_pause_caller),
TEST_NO_TAG("Simple call with audio device change during call pause both parties",
simple_call_with_audio_device_change_during_call_pause_caller_callee),
TEST_NO_TAG("Conference with simple audio device change", conference_with_simple_audio_device_change),
TEST_NO_TAG("Simple conference with audio device change using public API",
simple_conference_with_audio_device_change_using_public_api),
TEST_NO_TAG("Simple conference with audio device change during setup",
simple_conference_with_audio_device_change_during_setup),
TEST_NO_TAG("Simple conference with audio device change before all join",
simple_conference_with_audio_device_change_before_all_join),
TEST_NO_TAG("Simple conference with audio device change after all join",
simple_conference_with_audio_device_change_after_all_join),
25212522252325242525252625272528252925302531253225332534253525362537253825392540
TEST_NO_TAG("Simple conference with audio device change ping pong",
simple_conference_with_audio_device_change_pingpong),
TEST_NO_TAG("Simple conference with audio device change during pause callee",
simple_conference_with_audio_device_change_during_pause_callee),
TEST_NO_TAG("Simple conference with audio device change during pause caller",
simple_conference_with_audio_device_change_during_pause_caller),
TEST_NO_TAG("Simple conference with audio device change during pause both parties",
simple_conference_with_audio_device_change_during_pause_caller_callee),
TEST_NO_TAG("Regex audio card selection", regex_card_selection)
};
test_suite_t audio_routes_test_suite = {"Audio Routes",
NULL,
NULL,
liblinphone_tester_before_each,
liblinphone_tester_after_each,
sizeof(audio_routes_tests) / sizeof(audio_routes_tests[0]),
audio_routes_tests,
0};