Commit 3b0a9c00 authored by Simon Morlat's avatar Simon Morlat

add new method to create a conference from a list of participants.

parent 8633c5b8
......@@ -33,6 +33,15 @@
namespace Linphone {
template <typename _type>
inline std::list<_type> toStd(const bctbx_list_t *l){
std::list<_type> ret;
for(; l != NULL; l = l->next){
ret.push_back(static_cast<_type>(l->data));
}
return ret;
}
class Conference {
public:
class Participant {
......@@ -82,7 +91,7 @@ public:
void enableVideo(bool enable) {m_enableVideo = enable;}
bool videoRequested() const {return m_enableVideo;}
void setStateChangedCallback(LinphoneConferenceStateChangedCb cb, void *userData) {
m_stateChangedCb =cb;
m_stateChangedCb = cb;
m_userData = userData;
}
......@@ -99,6 +108,7 @@ public:
const Params &getCurrentParams() const {return m_currentParams;}
virtual int inviteAddresses(const std::list<const LinphoneAddress*> &addresses, const LinphoneCallParams *params) = 0;
virtual int addParticipant(LinphoneCall *call) = 0;
virtual int removeParticipant(LinphoneCall *call) = 0;
virtual int removeParticipant(const LinphoneAddress *uri) = 0;
......@@ -124,6 +134,9 @@ public:
virtual void onCallTerminating(LinphoneCall *call) {};
LinphoneConferenceState getState() const {return m_state;}
LinphoneCore *getCore()const{
return m_core;
}
static const char *stateToString(LinphoneConferenceState state);
protected:
......@@ -146,6 +159,7 @@ public:
LocalConference(LinphoneCore *core, LinphoneConference *conf, const Params *params = NULL);
virtual ~LocalConference();
virtual int inviteAddresses(const std::list<const LinphoneAddress*> &addresses, const LinphoneCallParams *params);
virtual int addParticipant(LinphoneCall *call);
virtual int removeParticipant(LinphoneCall *call);
virtual int removeParticipant(const LinphoneAddress *uri);
......@@ -183,6 +197,7 @@ public:
RemoteConference(LinphoneCore *core, LinphoneConference *conf, const Params *params = NULL);
virtual ~RemoteConference();
virtual int inviteAddresses(const std::list<const LinphoneAddress*> &addresses, const LinphoneCallParams *params);
virtual int addParticipant(LinphoneCall *call);
virtual int removeParticipant(LinphoneCall *call) {return -1;}
virtual int removeParticipant(const LinphoneAddress *uri);
......@@ -382,6 +397,31 @@ void LocalConference::addLocalEndpoint() {
ms_audio_conference_add_member(m_conf,m_localEndpoint);
}
int LocalConference::inviteAddresses(const std::list<const LinphoneAddress*> &addresses, const LinphoneCallParams *params){
for (auto it = addresses.begin(); it != addresses.end(); ++it){
const LinphoneAddress *addr = *it;
LinphoneCall * call = linphone_core_get_call_by_remote_address2(m_core, addr);
if (!call){
/*start a new call by indicating that it has to be put into the conference directlly*/
LinphoneCallParams * new_params = params ? linphone_call_params_copy(params) : linphone_core_create_call_params(m_core, NULL);
LinphoneCall *call;
/*toggle this flag so the call is immediately added to the conference upon acceptance*/
new_params->in_conference = TRUE;
call = linphone_core_invite_address_with_params(m_core, addr, new_params);
if (!call){
ms_error("LocalConference::inviteAddresses(): could not invite participant");
}
linphone_call_params_unref(new_params);
}else{
/*there is already a call to this address, so simply join it to the local conference if not already done*/
if (!call->current_params->in_conference)
addParticipant(call);
}
}
return 0;
}
int LocalConference::addParticipant(LinphoneCall *call) {
if (call->current_params->in_conference){
ms_error("Already in conference");
......@@ -590,6 +630,7 @@ int LocalConference::stopRecording() {
void LocalConference::onCallStreamStarting(LinphoneCall *call, bool isPausedByRemote) {
call->params->has_video = FALSE;
call->camera_enabled = FALSE;
ms_message("LocalConference::onCallStreamStarting(): joining AudioStream [%p] of call [%p] into conference.", call->audiostream, call);
MSAudioEndpoint *ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE);
ms_audio_conference_add_member(m_conf,ep);
ms_audio_conference_mute_member(m_conf,ep,isPausedByRemote);
......@@ -643,6 +684,11 @@ RemoteConference::~RemoteConference() {
linphone_core_cbs_unref(m_coreCbs);
}
int RemoteConference::inviteAddresses(const std::list<const LinphoneAddress *> &addresses, const LinphoneCallParams *params){
ms_error("RemoteConference::inviteAddresses() not implemented");
return -1;
}
int RemoteConference::addParticipant(LinphoneCall *call) {
LinphoneAddress *addr;
LinphoneCallParams *params;
......@@ -1116,3 +1162,7 @@ bool_t linphone_conference_check_class(LinphoneConference *obj, LinphoneConferen
default: return FALSE;
}
}
LinphoneStatus linphone_conference_invite_participants(LinphoneConference *obj, const bctbx_list_t *addresses, const LinphoneCallParams *params){
return obj->conf->inviteAddresses(toStd<const LinphoneAddress*>(addresses), params);
}
......@@ -3471,8 +3471,11 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
bool_t defer = FALSE;
LinphoneCallParams *cp;
if (!(!linphone_call_params_audio_enabled(params) || linphone_call_params_get_audio_direction(params) == LinphoneMediaDirectionInactive)
&& linphone_core_preempt_sound_resources(lc) == -1){
if (!(!linphone_call_params_audio_enabled(params) ||
linphone_call_params_get_audio_direction(params) == LinphoneMediaDirectionInactive ||
linphone_call_params_get_local_conference_mode(params) == TRUE
)
&& linphone_core_preempt_sound_resources(lc) == -1) {
ms_error("linphone_core_invite_address_with_params(): sound is required for this call but another call is already locking the sound resource. Call attempt is rejected.");
return NULL;
}
......@@ -3776,7 +3779,7 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad
return !linphone_address_weak_equal (addr,raddr);
}
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){
LinphoneCall *linphone_core_get_call_by_remote_address(const LinphoneCore *lc, const char *remote_address){
LinphoneCall *call=NULL;
LinphoneAddress *raddr=linphone_address_new(remote_address);
if (raddr) {
......@@ -3786,8 +3789,12 @@ LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const c
return call;
}
LinphoneCall *linphone_core_get_call_by_remote_address2(LinphoneCore *lc, const LinphoneAddress *raddr){
bctbx_list_t *elem=bctbx_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr);
LinphoneCall *linphone_core_find_call_from_uri(const LinphoneCore *lc, const char *remote_address){
return linphone_core_get_call_by_remote_address(lc, remote_address);
}
LinphoneCall *linphone_core_get_call_by_remote_address2(const LinphoneCore *lc, const LinphoneAddress *raddr){
const bctbx_list_t *elem=bctbx_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr);
if (elem) return (LinphoneCall*) elem->data;
return NULL;
......@@ -6580,29 +6587,6 @@ const char *linphone_core_get_user_certificates_path(LinphoneCore *lc){
return lc->user_certificates_path;
}
LinphoneCall* linphone_core_find_call_from_uri(const LinphoneCore *lc, const char *uri) {
bctbx_list_t *calls;
LinphoneCall *c;
const LinphoneAddress *address;
char *current_uri;
if (uri == NULL) return NULL;
calls=lc->calls;
while(calls) {
c=(LinphoneCall*)calls->data;
calls=calls->next;
address = linphone_call_get_remote_address(c);
current_uri=linphone_address_as_string_uri_only(address);
if (strcmp(uri,current_uri)==0) {
ms_free(current_uri);
return c;
} else {
ms_free(current_uri);
}
}
return NULL;
}
bool_t linphone_core_sound_resources_locked(LinphoneCore *lc){
bctbx_list_t *elem;
for(elem=lc->calls;elem!=NULL;elem=elem->next) {
......@@ -7068,6 +7052,10 @@ LinphoneConference *linphone_core_create_conference_with_params(LinphoneCore *lc
return lc->conf_ctx;
}
LinphoneConferenceParams * linphone_core_create_conference_params(LinphoneCore *lc){
return linphone_conference_params_new(lc);
}
LinphoneStatus linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call) {
LinphoneConference *conference = linphone_core_get_conference(lc);
if(conference == NULL) {
......
......@@ -117,6 +117,14 @@ LINPHONE_PUBLIC LinphoneStatus linphone_conference_remove_participant(LinphoneCo
*/
LINPHONE_PUBLIC bctbx_list_t *linphone_conference_get_participants(const LinphoneConference *obj);
/**
* Invite participants to the conference, by supplying a list of LinphoneAddress
* @param obj The conference.
* @param addresses bctbx_list_t of #LinphoneAddress object
* @param params #LinphoneCallParams to use for inviting the participants.
**/
LINPHONE_PUBLIC LinphoneStatus linphone_conference_invite_participants(LinphoneConference *conf, const bctbx_list_t *addresses, const LinphoneCallParams *params);
/**
* @}
*/
......
......@@ -1300,7 +1300,7 @@ LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_call_params(LinphoneCor
* @return The call if it has been found, NULL otherwise
* @ingroup call_control
*/
LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address);
LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address(const LinphoneCore *lc, const char *remote_address);
/**
* Get the call with the remote_address specified
......@@ -1310,7 +1310,7 @@ LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneC
*
* @ingroup call_control
*/
LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address2(LinphoneCore *lc, const LinphoneAddress *remote_address);
LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address2(const LinphoneCore *lc, const LinphoneAddress *remote_address);
/**
......@@ -4013,6 +4013,14 @@ LINPHONE_PUBLIC LinphoneCall* linphone_core_find_call_from_uri(const LinphoneCor
* @{
*/
/**
* Create some default conference parameters for instanciating a a conference with linphone_core_create_conference_with_params().
* @param lc the core
* @return conference parameters.
**/
LINPHONE_PUBLIC LinphoneConferenceParams * linphone_core_create_conference_params(LinphoneCore *lc);
/**
* Create a conference
* @param lc The #LinphoneCore instance where the conference will be created inside.
......@@ -4022,6 +4030,7 @@ LINPHONE_PUBLIC LinphoneCall* linphone_core_find_call_from_uri(const LinphoneCor
*/
LINPHONE_PUBLIC LinphoneConference *linphone_core_create_conference_with_params(LinphoneCore *lc, const LinphoneConferenceParams *params);
/**
* Add a participant to the conference. If no conference is going on
* a new internal conference context is created and the participant is
......
......@@ -381,6 +381,77 @@ static void simple_conference(void) {
linphone_core_manager_destroy(laure);
}
static void simple_conference_from_scratch(void){
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
LinphoneCoreManager* laure = linphone_core_manager_new( "laure_rc_udp");
LinphoneConference *conf;
LinphoneConferenceParams *conf_params;
LinphoneCall *pauline_call, *laure_call;
bctbx_list_t *participants = NULL;
bctbx_list_t *lcs = NULL;
lcs = bctbx_list_append(lcs, marie->lc);
lcs = bctbx_list_append(lcs, pauline->lc);
lcs = bctbx_list_append(lcs, laure->lc);
/*marie creates the conference*/
conf_params = linphone_core_create_conference_params(marie->lc);
linphone_conference_params_enable_video(conf_params, FALSE);
conf = linphone_core_create_conference_with_params(marie->lc, conf_params);
linphone_conference_params_unref(conf_params);
participants = bctbx_list_append(participants, pauline->identity);
participants = bctbx_list_append(participants, laure->identity);
linphone_conference_invite_participants(conf, participants, NULL);
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingProgress,2,2000));
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallIncomingReceived,1,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallIncomingReceived,1,10000));
pauline_call = linphone_core_get_current_call(pauline->lc);
laure_call = linphone_core_get_current_call(laure->lc);
BC_ASSERT_PTR_NOT_NULL(pauline_call);
BC_ASSERT_PTR_NOT_NULL(laure_call);
if (pauline_call && laure_call){
const bctbx_list_t *marie_calls, *it;
linphone_call_accept(pauline_call);
linphone_call_accept(laure_call);
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallConnected,2,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,2,3000));
/*make sure that the two calls from Marie's standpoint are in conference*/
marie_calls = linphone_core_get_calls(marie->lc);
BC_ASSERT_EQUAL(bctbx_list_size(marie_calls), 2, int, "%i");
for (it = marie_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);
}
/*wait a bit for the conference audio processing to run, despite we do not test it for the moment*/
wait_for_list(lcs,NULL,0,5000);
linphone_core_terminate_conference(marie->lc);
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,2,5000));
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallEnd,1,10000));
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallReleased,2,1000));
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallReleased,1,1000));
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallReleased,1,1000));
}
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
linphone_core_manager_destroy(laure);
bctbx_list_free(participants);
bctbx_list_free(lcs);
}
static void simple_encrypted_conference_with_ice(LinphoneMediaEncryption mode) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc");
......@@ -1074,6 +1145,7 @@ test_t multi_call_tests[] = {
TEST_NO_TAG("Incoming call accepted when outgoing call in outgoing ringing", incoming_call_accepted_when_outgoing_call_in_outgoing_ringing),
TEST_NO_TAG("Incoming call accepted when outgoing call in outgoing ringing early media", incoming_call_accepted_when_outgoing_call_in_outgoing_ringing_early_media),
TEST_NO_TAG("Simple conference", simple_conference),
TEST_NO_TAG("Simple conference established from scractch", simple_conference_from_scratch),
TEST_ONE_TAG("Simple conference with ICE", simple_conference_with_ice, "ICE"),
TEST_ONE_TAG("Simple ZRTP conference with ICE", simple_zrtp_conference_with_ice, "ICE"),
TEST_NO_TAG("Eject from 3 participants conference", eject_from_3_participants_local_conference),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment