mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-28 00:29:21 +00:00
Release the reference on the focus call when thatone fails
This commit is contained in:
parent
ca8d64d592
commit
b4452da58d
7 changed files with 288 additions and 93 deletions
|
|
@ -32,31 +32,39 @@
|
|||
|
||||
namespace Linphone {
|
||||
|
||||
class Participant {
|
||||
public:
|
||||
Participant(LinphoneCall *call);
|
||||
Participant(const Participant &src);
|
||||
~Participant();
|
||||
bool operator==(const Participant &src) const;
|
||||
const LinphoneAddress *getUri() const {return m_uri;}
|
||||
LinphoneCall *getCall() const {return m_call;}
|
||||
void setCall(LinphoneCall *call) {m_call = call;}
|
||||
|
||||
private:
|
||||
LinphoneAddress *m_uri;
|
||||
LinphoneCall *m_call;
|
||||
};
|
||||
|
||||
class Conference {
|
||||
public:
|
||||
class Participant {
|
||||
public:
|
||||
Participant(LinphoneCall *call);
|
||||
Participant(const Participant &src);
|
||||
~Participant();
|
||||
bool operator==(const Participant &src) const;
|
||||
const LinphoneAddress *getUri() const {return m_uri;}
|
||||
LinphoneCall *getCall() const {return m_call;}
|
||||
void setCall(LinphoneCall *call) {m_call = call;}
|
||||
|
||||
private:
|
||||
LinphoneAddress *m_uri;
|
||||
LinphoneCall *m_call;
|
||||
};
|
||||
|
||||
class Params {
|
||||
public:
|
||||
Params(const LinphoneCore *core = NULL);
|
||||
void enableVideo(bool enable) {m_enableVideo = enable;}
|
||||
bool videoRequested() const {return m_enableVideo;}
|
||||
void setStateChangedCallback(LinphoneConferenceStateChangedCb cb, void *user_data) {
|
||||
m_state_changed_cb=cb;
|
||||
m_user_data=user_data;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_enableVideo;
|
||||
LinphoneConferenceStateChangedCb m_state_changed_cb;
|
||||
void *m_user_data;
|
||||
|
||||
friend class Conference;
|
||||
};
|
||||
|
||||
Conference(LinphoneCore *core, const Params *params = NULL);
|
||||
|
|
@ -88,14 +96,19 @@ public:
|
|||
virtual void onCallStreamStopping(LinphoneCall *call) {};
|
||||
virtual void onCallTerminating(LinphoneCall *call) {};
|
||||
|
||||
LinphoneConferenceState getState() const {return m_state;}
|
||||
static const char *stateToString(LinphoneConferenceState state);
|
||||
|
||||
protected:
|
||||
const Participant *findParticipant(const LinphoneAddress* uri) const;
|
||||
void setState(LinphoneConferenceState state);
|
||||
|
||||
LinphoneCore *m_core;
|
||||
AudioStream *m_localParticipantStream;
|
||||
bool m_isMuted;
|
||||
std::list<Participant> m_participants;
|
||||
Params m_currentParams;
|
||||
LinphoneConferenceState m_state;
|
||||
};
|
||||
|
||||
class LocalConference: public Conference {
|
||||
|
|
@ -153,12 +166,9 @@ public:
|
|||
virtual int stopRecording() {return 0;}
|
||||
|
||||
private:
|
||||
enum State {
|
||||
NotConnectedToFocus,
|
||||
ConnectingToFocus,
|
||||
ConnectedToFocus,
|
||||
};
|
||||
static const char *stateToString(State state);
|
||||
bool focusIsReady() const;
|
||||
bool transferToFocus(LinphoneCall *call);
|
||||
void reset();
|
||||
|
||||
void onFocusCallSateChanged(LinphoneCallState state);
|
||||
void onPendingCallStateChanged(LinphoneCall *call, LinphoneCallState state);
|
||||
|
|
@ -170,10 +180,10 @@ private:
|
|||
const char *m_focusAddr;
|
||||
char *m_focusContact;
|
||||
LinphoneCall *m_focusCall;
|
||||
State m_state;
|
||||
LinphoneCoreVTable *m_vtable;
|
||||
MSList *m_pendingCalls;
|
||||
MSList *m_transferingCalls;
|
||||
bool m_isTerminating;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -183,22 +193,22 @@ using namespace Linphone;
|
|||
using namespace std;
|
||||
|
||||
|
||||
Participant::Participant(LinphoneCall *call) {
|
||||
Conference::Participant::Participant(LinphoneCall *call) {
|
||||
m_uri = linphone_address_clone(linphone_call_get_remote_address(call));
|
||||
m_call = linphone_call_ref(call);
|
||||
}
|
||||
|
||||
Participant::Participant(const Participant &src) {
|
||||
Conference::Participant::Participant(const Participant &src) {
|
||||
m_uri = linphone_address_clone(src.m_uri);
|
||||
m_call = src.m_call ? linphone_call_ref(src.m_call) : NULL;
|
||||
}
|
||||
|
||||
Participant::~Participant() {
|
||||
Conference::Participant::~Participant() {
|
||||
linphone_address_unref(m_uri);
|
||||
if(m_call) linphone_call_unref(m_call);
|
||||
}
|
||||
|
||||
bool Participant::operator==(const Participant &src) const {
|
||||
bool Conference::Participant::operator==(const Participant &src) const {
|
||||
return linphone_address_equal(m_uri, src.m_uri);
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +226,9 @@ Conference::Params::Params(const LinphoneCore *core): m_enableVideo(false) {
|
|||
Conference::Conference(LinphoneCore *core, const Conference::Params *params):
|
||||
m_core(core),
|
||||
m_localParticipantStream(NULL),
|
||||
m_isMuted(false) {
|
||||
m_isMuted(false),
|
||||
m_currentParams(),
|
||||
m_state(LinphoneConferenceStopped) {
|
||||
if(params) m_currentParams = *params;
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +287,19 @@ float Conference::getInputVolume() const {
|
|||
return LINPHONE_VOLUME_DB_LOWEST;
|
||||
}
|
||||
|
||||
const Participant *Conference::findParticipant(const LinphoneAddress *uri) const {
|
||||
const char *Conference::stateToString(LinphoneConferenceState state) {
|
||||
switch(state) {
|
||||
case LinphoneConferenceStopped: return "Stopped";
|
||||
case LinphoneConferenceStarting: return "Starting";
|
||||
case LinphoneConferenceReady: return "Ready";
|
||||
case LinphoneConferenceStartingFailed: return "Startig failed";
|
||||
default: return "Invalid state";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const Conference::Participant *Conference::findParticipant(const LinphoneAddress *uri) const {
|
||||
list<Participant>::const_iterator it = m_participants.begin();
|
||||
while(it!=m_participants.end()) {
|
||||
if(linphone_address_equal(uri, it->getUri())) break;
|
||||
|
|
@ -285,6 +309,17 @@ const Participant *Conference::findParticipant(const LinphoneAddress *uri) const
|
|||
else return &*it;
|
||||
}
|
||||
|
||||
void Conference::setState(LinphoneConferenceState state) {
|
||||
if(m_state != state) {
|
||||
ms_message("Switching conference [%p] into state '%s'", this, stateToString(state));
|
||||
m_state = state;
|
||||
if(m_currentParams.m_state_changed_cb) {
|
||||
m_currentParams.m_state_changed_cb((LinphoneConference *)this, state, m_currentParams.m_user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LocalConference::LocalConference(LinphoneCore *core, const Conference::Params *params):
|
||||
|
|
@ -298,7 +333,7 @@ LocalConference::LocalConference(LinphoneCore *core, const Conference::Params *p
|
|||
MSAudioConferenceParams ms_conf_params;
|
||||
ms_conf_params.samplerate = lp_config_get_int(m_core->config, "sound","conference_rate",16000);
|
||||
m_conf=ms_audio_conference_new(&ms_conf_params, core->factory);
|
||||
|
||||
m_state=LinphoneConferenceReady;
|
||||
}
|
||||
|
||||
LocalConference::~LocalConference() {
|
||||
|
|
@ -587,10 +622,10 @@ RemoteConference::RemoteConference(LinphoneCore *core, const Conference::Params
|
|||
m_focusAddr(NULL),
|
||||
m_focusContact(NULL),
|
||||
m_focusCall(NULL),
|
||||
m_state(NotConnectedToFocus),
|
||||
m_vtable(NULL),
|
||||
m_pendingCalls(NULL),
|
||||
m_transferingCalls(NULL) {
|
||||
m_transferingCalls(NULL),
|
||||
m_isTerminating(false) {
|
||||
m_focusAddr = lp_config_get_string(m_core->config, "misc", "conference_focus_addr", "");
|
||||
m_vtable = linphone_core_v_table_new();
|
||||
m_vtable->call_state_changed = callStateChangedCb;
|
||||
|
|
@ -600,7 +635,7 @@ RemoteConference::RemoteConference(LinphoneCore *core, const Conference::Params
|
|||
}
|
||||
|
||||
RemoteConference::~RemoteConference() {
|
||||
if(m_state == ConnectedToFocus) terminate();
|
||||
terminate();
|
||||
linphone_core_remove_listener(m_core, m_vtable);
|
||||
linphone_core_v_table_destroy(m_vtable);
|
||||
}
|
||||
|
|
@ -610,34 +645,38 @@ int RemoteConference::addParticipant(LinphoneCall *call) {
|
|||
LinphoneCallParams *params;
|
||||
|
||||
switch(m_state) {
|
||||
case NotConnectedToFocus:
|
||||
case LinphoneConferenceStopped:
|
||||
case LinphoneConferenceStartingFailed:
|
||||
Conference::addParticipant(call);
|
||||
ms_message("Calling the conference focus (%s)", m_focusAddr);
|
||||
addr = linphone_address_new(m_focusAddr);
|
||||
if(addr) {
|
||||
params = linphone_core_create_call_params(m_core, NULL);
|
||||
linphone_call_params_enable_video(params, m_currentParams.videoRequested());
|
||||
m_focusCall = linphone_call_ref(linphone_core_invite_address_with_params(m_core, addr, params));
|
||||
m_focusCall = linphone_core_invite_address_with_params(m_core, addr, params);
|
||||
m_focusCall->conf_ref = (LinphoneConference *)this;
|
||||
m_localParticipantStream = m_focusCall->audiostream;
|
||||
m_pendingCalls = ms_list_append(m_pendingCalls, call);
|
||||
m_state = ConnectingToFocus;
|
||||
LinphoneCallLog *callLog = linphone_call_get_call_log(m_focusCall);
|
||||
callLog->was_conference = TRUE;
|
||||
linphone_address_unref(addr);
|
||||
linphone_call_params_unref(params);
|
||||
setState(LinphoneConferenceStarting);
|
||||
return 0;
|
||||
} else return -1;
|
||||
|
||||
case ConnectingToFocus:
|
||||
case LinphoneConferenceStarting:
|
||||
Conference::addParticipant(call);
|
||||
m_pendingCalls = ms_list_append(m_pendingCalls, call);
|
||||
if(focusIsReady()) {
|
||||
transferToFocus(call);
|
||||
} else {
|
||||
m_pendingCalls = ms_list_append(m_pendingCalls, call);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ConnectedToFocus:
|
||||
case LinphoneConferenceReady:
|
||||
Conference::addParticipant(call);
|
||||
m_transferingCalls = ms_list_append(m_transferingCalls, call);
|
||||
linphone_core_transfer_call(m_core, call, m_focusContact);
|
||||
transferToFocus(call);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
|
@ -651,15 +690,21 @@ int RemoteConference::removeParticipant(const LinphoneAddress *uri) {
|
|||
int res;
|
||||
|
||||
switch(m_state) {
|
||||
case ConnectedToFocus:
|
||||
case LinphoneConferenceReady:
|
||||
tmp = linphone_address_as_string_uri_only(uri);
|
||||
refer_to = ms_strdup_printf("%s;method=BYE", tmp);
|
||||
res = sal_call_refer(m_focusCall->op, refer_to);
|
||||
ms_free(tmp);
|
||||
ms_free(refer_to);
|
||||
|
||||
if(res == 0) return Conference::removeParticipant(uri);
|
||||
else return -1;
|
||||
if(res == 0) {
|
||||
return Conference::removeParticipant(uri);
|
||||
} else {
|
||||
char *tmp = linphone_address_as_string(uri);
|
||||
ms_error("Conference: could not remove participant '%s': REFER with BYE has failed", tmp);
|
||||
ms_free(tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
default:
|
||||
ms_error("Cannot remove %s from conference: Bad conference state (%s)", linphone_address_as_string(uri), stateToString(m_state));
|
||||
|
|
@ -668,20 +713,25 @@ int RemoteConference::removeParticipant(const LinphoneAddress *uri) {
|
|||
}
|
||||
|
||||
int RemoteConference::terminate() {
|
||||
m_isTerminating = true;
|
||||
switch(m_state) {
|
||||
case ConnectingToFocus:
|
||||
case ConnectedToFocus:
|
||||
case LinphoneConferenceReady:
|
||||
case LinphoneConferenceStarting:
|
||||
linphone_core_terminate_call(m_core, m_focusCall);
|
||||
reset();
|
||||
Conference::terminate();
|
||||
setState(LinphoneConferenceStopped);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Conference::terminate();
|
||||
m_isTerminating = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RemoteConference::enter() {
|
||||
if(m_state != ConnectedToFocus) {
|
||||
if(m_state != LinphoneConferenceReady) {
|
||||
ms_error("Could not enter in the conference: bad conference state (%s)", stateToString(m_state));
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -699,7 +749,7 @@ int RemoteConference::enter() {
|
|||
}
|
||||
|
||||
int RemoteConference::leave() {
|
||||
if(m_state != ConnectedToFocus) {
|
||||
if(m_state != LinphoneConferenceReady) {
|
||||
ms_error("Could not leave the conference: bad conference state (%s)", stateToString(m_state));
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -717,26 +767,45 @@ int RemoteConference::leave() {
|
|||
}
|
||||
|
||||
bool RemoteConference::isIn() const {
|
||||
if(m_state != ConnectedToFocus) return false;
|
||||
if(m_state != LinphoneConferenceReady) return false;
|
||||
LinphoneCallState callState = linphone_call_get_state(m_focusCall);
|
||||
return callState == LinphoneCallStreamsRunning;
|
||||
}
|
||||
|
||||
const char *RemoteConference::stateToString(RemoteConference::State state) {
|
||||
switch(state) {
|
||||
case NotConnectedToFocus: return "NotConnectedToFocus";
|
||||
case ConnectingToFocus: return "ConnectingToFocus";
|
||||
case ConnectedToFocus: return "ConnectedToFocus";
|
||||
default: return "Unknown";
|
||||
bool RemoteConference::focusIsReady() const {
|
||||
LinphoneCallState focusState;
|
||||
if(m_focusCall == NULL) return false;
|
||||
focusState = linphone_call_get_state(m_focusCall);
|
||||
return focusState == LinphoneCallStreamsRunning || focusState == LinphoneCallPaused;
|
||||
}
|
||||
|
||||
bool RemoteConference::transferToFocus(LinphoneCall *call) {
|
||||
if(linphone_core_transfer_call(m_core, call, m_focusContact) == 0) {
|
||||
m_transferingCalls = ms_list_append(m_transferingCalls, call);
|
||||
return true;
|
||||
} else {
|
||||
ms_error("Conference: could not transfer call [%p] to %s", call, m_focusContact);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteConference::reset() {
|
||||
m_localParticipantStream = NULL;
|
||||
m_focusAddr = NULL;
|
||||
if(m_focusContact) {
|
||||
ms_free(m_focusContact);
|
||||
m_focusContact = NULL;
|
||||
}
|
||||
m_focusCall = NULL;
|
||||
m_pendingCalls = ms_list_free(m_pendingCalls);
|
||||
m_transferingCalls = ms_list_free(m_transferingCalls);
|
||||
}
|
||||
|
||||
void RemoteConference::onFocusCallSateChanged(LinphoneCallState state) {
|
||||
MSList *it;
|
||||
|
||||
switch (state) {
|
||||
case LinphoneCallConnected:
|
||||
m_state = ConnectedToFocus;
|
||||
m_focusContact = ms_strdup(linphone_call_get_remote_contact(m_focusCall));
|
||||
it = m_pendingCalls;
|
||||
while (it) {
|
||||
|
|
@ -746,27 +815,21 @@ void RemoteConference::onFocusCallSateChanged(LinphoneCallState state) {
|
|||
MSList *current_elem = it;
|
||||
it = it->next;
|
||||
m_pendingCalls = ms_list_remove_link(m_pendingCalls, current_elem);
|
||||
m_transferingCalls = ms_list_append(m_transferingCalls, pendingCall);
|
||||
linphone_core_transfer_call(m_core, pendingCall, m_focusContact);
|
||||
transferToFocus(pendingCall);
|
||||
} else {
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
setState(LinphoneConferenceReady);
|
||||
break;
|
||||
|
||||
case LinphoneCallError:
|
||||
reset();
|
||||
setState(LinphoneConferenceStartingFailed);
|
||||
break;
|
||||
|
||||
case LinphoneCallEnd:
|
||||
m_state = NotConnectedToFocus;
|
||||
linphone_call_unref(m_focusCall);
|
||||
m_focusCall = NULL;
|
||||
m_localParticipantStream = NULL;
|
||||
if(m_focusContact) {
|
||||
ms_free(m_focusContact);
|
||||
m_focusContact = NULL;
|
||||
}
|
||||
m_pendingCalls = ms_list_free(m_pendingCalls);
|
||||
m_transferingCalls = ms_list_free(m_transferingCalls);
|
||||
Conference::terminate();
|
||||
if(!m_isTerminating) terminate();
|
||||
break;
|
||||
|
||||
default: break;
|
||||
|
|
@ -777,7 +840,7 @@ void RemoteConference::onPendingCallStateChanged(LinphoneCall *call, LinphoneCal
|
|||
switch(state) {
|
||||
case LinphoneCallStreamsRunning:
|
||||
case LinphoneCallPaused:
|
||||
if(m_state == ConnectedToFocus) {
|
||||
if(m_state == LinphoneConferenceReady) {
|
||||
m_pendingCalls = ms_list_remove(m_pendingCalls, call);
|
||||
m_transferingCalls = ms_list_append(m_transferingCalls, call);
|
||||
linphone_core_transfer_call(m_core, call, m_focusContact);
|
||||
|
|
@ -827,6 +890,10 @@ void RemoteConference::transferStateChanged(LinphoneCore *lc, LinphoneCall *tran
|
|||
|
||||
|
||||
|
||||
const char *linphone_conference_state_to_string(LinphoneConferenceState state) {
|
||||
return Conference::stateToString(state);
|
||||
}
|
||||
|
||||
LinphoneConferenceParams *linphone_conference_params_new(const LinphoneCore *core) {
|
||||
return (LinphoneConferenceParams *)new Conference::Params(core);
|
||||
}
|
||||
|
|
@ -847,6 +914,10 @@ bool_t linphone_conference_params_video_requested(const LinphoneConferenceParams
|
|||
return ((Conference::Params *)params)->videoRequested();
|
||||
}
|
||||
|
||||
void linphone_conference_params_set_state_changed_callback(LinphoneConferenceParams *params, LinphoneConferenceStateChangedCb cb, void *user_data) {
|
||||
((Conference::Params *)params)->setStateChangedCallback(cb, user_data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LinphoneConference *linphone_local_conference_new(LinphoneCore *core) {
|
||||
|
|
@ -869,6 +940,10 @@ void linphone_conference_free(LinphoneConference *obj) {
|
|||
delete (Conference *)obj;
|
||||
}
|
||||
|
||||
LinphoneConferenceState linphone_conference_get_state(const LinphoneConference *obj) {
|
||||
return ((Conference *)obj)->getState();
|
||||
}
|
||||
|
||||
int linphone_conference_add_participant(LinphoneConference *obj, LinphoneCall *call) {
|
||||
return ((Conference *)obj)->addParticipant(call);
|
||||
}
|
||||
|
|
@ -918,9 +993,9 @@ int linphone_conference_get_size(const LinphoneConference *obj) {
|
|||
}
|
||||
|
||||
MSList *linphone_conference_get_participants(const LinphoneConference *obj) {
|
||||
const list<Participant> &participants = ((Conference *)obj)->getParticipants();
|
||||
const list<Conference::Participant> &participants = ((Conference *)obj)->getParticipants();
|
||||
MSList *participants_list = NULL;
|
||||
for(list<Participant>::const_iterator it=participants.begin();it!=participants.end();it++) {
|
||||
for(list<Conference::Participant>::const_iterator it=participants.begin();it!=participants.end();it++) {
|
||||
LinphoneAddress *uri = linphone_address_clone(it->getUri());
|
||||
participants_list = ms_list_append(participants_list, uri);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,11 +37,18 @@ extern "C" {
|
|||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* LinphoneConference class
|
||||
*/
|
||||
typedef struct _LinphoneConference LinphoneConference;
|
||||
/**
|
||||
* Parameters for initialization of conferences
|
||||
*/
|
||||
typedef struct _LinphoneCorferenceParams LinphoneConferenceParams;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a #LinphoneConferenceParams with default parameters set.
|
||||
* @param core #LinphoneCore to use to find out the default parameters. Can be NULL.
|
||||
|
|
@ -73,10 +80,7 @@ LINPHONE_PUBLIC bool_t linphone_conference_params_video_requested(const Linphone
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* LinphoneConference class
|
||||
*/
|
||||
typedef struct _LinphoneConference LinphoneConference;
|
||||
|
||||
|
||||
/**
|
||||
* Remove a participant from a conference
|
||||
|
|
|
|||
|
|
@ -37,11 +37,48 @@ typedef enum {
|
|||
LinphoneConferenceClassRemote
|
||||
} LinphoneConferenceClass;
|
||||
|
||||
/**
|
||||
* List of states used by #LinphoneConference
|
||||
*/
|
||||
typedef enum {
|
||||
LinphoneConferenceStopped, /*< Initial state */
|
||||
LinphoneConferenceStarting, /*< A participant has been added but the conference is not running yet */
|
||||
LinphoneConferenceReady, /*< The conference is running */
|
||||
LinphoneConferenceStartingFailed /*< A participant has been added but the initialization of the conference has failed */
|
||||
} LinphoneConferenceState;
|
||||
/**
|
||||
* Type of the funtion to pass as callback to linphone_conference_params_set_state_changed_callback()
|
||||
* @param conference The conference instance which the state has changed
|
||||
* @param new_state The new state of the conferenece
|
||||
* @param user_data Pointer pass to user_data while linphone_conference_params_set_state_changed_callback() was being called
|
||||
*/
|
||||
typedef void (*LinphoneConferenceStateChangedCb)(LinphoneConference *conference, LinphoneConferenceState new_state, void *user_data);
|
||||
|
||||
|
||||
/**
|
||||
* A function to converte a #LinphoneConferenceState into a string
|
||||
*/
|
||||
const char *linphone_conference_state_to_string(LinphoneConferenceState state);
|
||||
|
||||
|
||||
/**
|
||||
* Set a callback which will be called when the state of the conferenec is switching
|
||||
* @param params A #LinphoneConferenceParams object
|
||||
* @param cb The callback to call
|
||||
* @param user_data Pointer to pass to the user_data parameter of #LinphoneConferenceStateChangedCb
|
||||
*/
|
||||
void linphone_conference_params_set_state_changed_callback(LinphoneConferenceParams *params, LinphoneConferenceStateChangedCb cb, void *user_data);
|
||||
|
||||
|
||||
LinphoneConference *linphone_local_conference_new(LinphoneCore *core);
|
||||
LinphoneConference *linphone_local_conference_new_with_params(LinphoneCore *core, const LinphoneConferenceParams *params);
|
||||
LinphoneConference *linphone_remote_conference_new(LinphoneCore *core);
|
||||
LinphoneConference *linphone_remote_conference_new_with_params(LinphoneCore *core, const LinphoneConferenceParams *params);
|
||||
void linphone_conference_free(LinphoneConference *obj);
|
||||
/**
|
||||
* Get the state of a conference
|
||||
*/
|
||||
LinphoneConferenceState linphone_conference_get_state(const LinphoneConference *obj);
|
||||
|
||||
int linphone_conference_add_participant(LinphoneConference *obj, LinphoneCall *call);
|
||||
int linphone_conference_remove_participant_with_call(LinphoneConference *obj, LinphoneCall *call);
|
||||
|
|
|
|||
|
|
@ -7461,18 +7461,30 @@ LinphoneRingtonePlayer *linphone_core_get_ringtoneplayer(LinphoneCore *lc) {
|
|||
return lc->ringtoneplayer;
|
||||
}
|
||||
|
||||
static void linphone_core_conference_state_changed(LinphoneConference *conf, LinphoneConferenceState cstate, void *user_data) {
|
||||
LinphoneCore *lc = (LinphoneCore *)user_data;
|
||||
if(cstate == LinphoneConferenceStartingFailed || cstate == LinphoneConferenceStopped) {
|
||||
linphone_conference_free(lc->conf_ctx);
|
||||
lc->conf_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneConference *linphone_core_create_conference_with_params(LinphoneCore *lc, const LinphoneConferenceParams *params) {
|
||||
const char *conf_method_name;
|
||||
if(lc->conf_ctx == NULL) {
|
||||
LinphoneConferenceParams *params2 = linphone_conference_params_clone(params);
|
||||
linphone_conference_params_set_state_changed_callback(params2, linphone_core_conference_state_changed, lc);
|
||||
conf_method_name = lp_config_get_string(lc->config, "misc", "conference_type", "local");
|
||||
if(strcasecmp(conf_method_name, "local") == 0) {
|
||||
lc->conf_ctx = linphone_local_conference_new_with_params(lc, params);
|
||||
lc->conf_ctx = linphone_local_conference_new_with_params(lc, params2);
|
||||
} else if(strcasecmp(conf_method_name, "remote") == 0) {
|
||||
lc->conf_ctx = linphone_remote_conference_new_with_params(lc, params);
|
||||
lc->conf_ctx = linphone_remote_conference_new_with_params(lc, params2);
|
||||
} else {
|
||||
ms_error("'%s' is not a valid conference method", conf_method_name);
|
||||
linphone_conference_params_free(params2);
|
||||
return NULL;
|
||||
}
|
||||
linphone_conference_params_free(params2);
|
||||
} else {
|
||||
ms_error("Could not create a conference: a conference instance already exists");
|
||||
return NULL;
|
||||
|
|
@ -7482,7 +7494,12 @@ LinphoneConference *linphone_core_create_conference_with_params(LinphoneCore *lc
|
|||
|
||||
int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call) {
|
||||
LinphoneConference *conference = linphone_core_get_conference(lc);
|
||||
if(conference == NULL) conference = linphone_core_create_conference_with_params(lc, NULL);
|
||||
if(conference == NULL) {
|
||||
LinphoneConferenceParams *params = linphone_conference_params_new(lc);
|
||||
linphone_conference_params_set_state_changed_callback(params, linphone_core_conference_state_changed, lc);
|
||||
conference = linphone_core_create_conference_with_params(lc, params);
|
||||
linphone_conference_params_free(params);
|
||||
}
|
||||
if(conference) return linphone_conference_add_participant(lc->conf_ctx, call);
|
||||
else return -1;
|
||||
}
|
||||
|
|
@ -7508,7 +7525,10 @@ int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call) {
|
|||
}
|
||||
|
||||
int linphone_core_terminate_conference(LinphoneCore *lc) {
|
||||
if(lc->conf_ctx == NULL) return -1;
|
||||
if(lc->conf_ctx == NULL) {
|
||||
ms_error("Could not terminate conference: no conference context");
|
||||
return -1;
|
||||
}
|
||||
linphone_conference_terminate(lc->conf_ctx);
|
||||
linphone_conference_free(lc->conf_ctx);
|
||||
lc->conf_ctx = NULL;
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ typedef struct _LinphoneConferenceServer {
|
|||
LinphoneCoreManager base;
|
||||
LinphoneCall *first_call;
|
||||
LinphoneCoreVTable *vtable;
|
||||
LinphoneRegistrationState reg_state;
|
||||
} LinphoneConferenceServer;
|
||||
|
||||
typedef struct _LinphoneCallTestParams {
|
||||
|
|
@ -361,7 +362,7 @@ void liblinphone_tester_uninit(void);
|
|||
int liblinphone_tester_set_log_file(const char *filename);
|
||||
bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, LinphoneIceState state);
|
||||
|
||||
LinphoneConferenceServer* linphone_conference_server_new(const char *rc_file);
|
||||
LinphoneConferenceServer* linphone_conference_server_new(const char *rc_file, bool_t do_registration);
|
||||
void linphone_conference_server_destroy(LinphoneConferenceServer *conf_srv);
|
||||
|
||||
extern const char *liblinphone_tester_mire_id;
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag
|
|||
LinphoneConference *conference;
|
||||
const MSList* calls;
|
||||
bool_t is_remote_conf;
|
||||
bool_t focus_is_up = (focus && ((LinphoneConferenceServer *)focus)->reg_state == LinphoneRegistrationOk);
|
||||
MSList* lcs=ms_list_append(NULL,marie->lc);
|
||||
lcs=ms_list_append(lcs,pauline->lc);
|
||||
lcs=ms_list_append(lcs,laure->lc);
|
||||
|
|
@ -213,9 +214,21 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag
|
|||
if(!is_remote_conf) {
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallUpdating,initial_marie_stat.number_of_LinphoneCallUpdating+1,5000));
|
||||
} else {
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,initial_marie_stat.number_of_LinphoneCallStreamsRunning+1,5000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransferCallConnected,initial_marie_stat.number_of_LinphoneTransferCallConnected+1,5000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,initial_marie_stat.number_of_LinphoneCallEnd+1,5000));
|
||||
if(focus_is_up) {
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,initial_marie_stat.number_of_LinphoneCallStreamsRunning+1,5000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransferCallConnected,initial_marie_stat.number_of_LinphoneTransferCallConnected+1,5000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,initial_marie_stat.number_of_LinphoneCallEnd+1,5000));
|
||||
} else {
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallError, initial_marie_stat.number_of_LinphoneCallError+1, 5000));
|
||||
BC_ASSERT_PTR_NULL(linphone_core_get_conference(marie->lc));
|
||||
BC_ASSERT_EQUAL(linphone_core_terminate_conference(marie->lc), -1, int, "%d");
|
||||
linphone_core_terminate_call(marie->lc, marie_call_pauline);
|
||||
linphone_core_terminate_call(marie->lc, marie_call_laure);
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallEnd, initial_marie_stat.number_of_LinphoneCallEnd+2, 10000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallEnd, initial_pauline_stat.number_of_LinphoneCallEnd+1, 5000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallEnd, initial_laure_stat.number_of_LinphoneCallEnd+1, 5000));
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
linphone_core_add_to_conference(marie->lc,marie_call_pauline);
|
||||
|
|
@ -267,11 +280,11 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag
|
|||
}
|
||||
|
||||
linphone_core_terminate_conference(marie->lc);
|
||||
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,is_remote_conf?2:1,10000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,is_remote_conf?3:1,10000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallEnd,is_remote_conf?2:1,10000));
|
||||
|
||||
|
||||
end:
|
||||
ms_list_free(lcs);
|
||||
}
|
||||
|
||||
|
|
@ -766,7 +779,38 @@ void simple_remote_conference(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");
|
||||
LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc");
|
||||
LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc", TRUE);
|
||||
LpConfig *marie_config = linphone_core_get_config(marie->lc);
|
||||
LinphoneProxyConfig *focus_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)focus)->lc);
|
||||
LinphoneProxyConfig *laure_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)laure)->lc);
|
||||
const char *laure_proxy_uri = linphone_proxy_config_get_server_addr(laure_proxy_config);
|
||||
const char *focus_uri = linphone_proxy_config_get_identity(focus_proxy_config);
|
||||
int laure_n_register = laure->stat.number_of_LinphoneRegistrationOk;
|
||||
MSList *lcs = NULL;
|
||||
|
||||
lp_config_set_string(marie_config, "misc", "conference_type", "remote");
|
||||
lp_config_set_string(marie_config, "misc", "conference_focus_addr", focus_uri);
|
||||
|
||||
linphone_proxy_config_edit(laure_proxy_config);
|
||||
linphone_proxy_config_set_route(laure_proxy_config, laure_proxy_uri);
|
||||
linphone_proxy_config_done(laure_proxy_config);
|
||||
lcs = ms_list_append(lcs, laure->lc);
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneRegistrationOk, laure_n_register+1, 5000));
|
||||
ms_list_free(lcs);
|
||||
|
||||
simple_conference_base(marie, pauline, laure, (LinphoneCoreManager *)focus);
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
linphone_core_manager_destroy(laure);
|
||||
linphone_conference_server_destroy(focus);
|
||||
}
|
||||
|
||||
void simple_remote_conference_shut_down_focus(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");
|
||||
LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc", FALSE);
|
||||
LpConfig *marie_config = linphone_core_get_config(marie->lc);
|
||||
LinphoneProxyConfig *focus_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)focus)->lc);
|
||||
LinphoneProxyConfig *laure_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)laure)->lc);
|
||||
|
|
@ -797,7 +841,7 @@ void eject_from_3_participants_remote_conference(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");
|
||||
LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc");
|
||||
LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc", TRUE);
|
||||
LpConfig *marie_config = linphone_core_get_config(marie->lc);
|
||||
LinphoneProxyConfig *focus_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)focus)->lc);
|
||||
LinphoneProxyConfig *laure_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)laure)->lc);
|
||||
|
|
@ -840,7 +884,8 @@ test_t multi_call_tests[] = {
|
|||
TEST_NO_TAG("Unattended call transfer with error", unattended_call_transfer_with_error),
|
||||
TEST_NO_TAG("Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call),
|
||||
TEST_NO_TAG("Simple remote conference", simple_remote_conference),
|
||||
TEST_NO_TAG("Eject from 3 participants in remote conference", eject_from_3_participants_remote_conference)
|
||||
TEST_NO_TAG("Simple remote conference with shut down focus", simple_remote_conference_shut_down_focus),
|
||||
TEST_NO_TAG("Eject from 3 participants in remote conference", eject_from_3_participants_remote_conference),
|
||||
};
|
||||
|
||||
test_suite_t multi_call_test_suite = {"Multi call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph
|
|||
return video_enabled ? (realtime_text_enabled ? text_success && audio_success && video_success : audio_success && video_success) : realtime_text_enabled ? text_success && audio_success : audio_success;
|
||||
}
|
||||
|
||||
void linphone_conference_server_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg) {
|
||||
static void linphone_conference_server_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg) {
|
||||
LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(lc);
|
||||
LinphoneConferenceServer *conf_srv = (LinphoneConferenceServer *)vtable->user_data;
|
||||
|
||||
|
|
@ -696,7 +696,7 @@ void linphone_conference_server_call_state_changed(LinphoneCore *lc, LinphoneCal
|
|||
}
|
||||
}
|
||||
|
||||
void linphone_conference_server_refer_received(LinphoneCore *core, const char *refer_to) {
|
||||
static void linphone_conference_server_refer_received(LinphoneCore *core, const char *refer_to) {
|
||||
char method[20];
|
||||
LinphoneAddress *refer_to_addr = linphone_address_new(refer_to);
|
||||
char *uri;
|
||||
|
|
@ -714,17 +714,30 @@ void linphone_conference_server_refer_received(LinphoneCore *core, const char *r
|
|||
linphone_address_destroy(refer_to_addr);
|
||||
}
|
||||
|
||||
LinphoneConferenceServer* linphone_conference_server_new(const char *rc_file) {
|
||||
static void linphone_conference_server_registration_state_changed(LinphoneCore *core,
|
||||
LinphoneProxyConfig *cfg,
|
||||
LinphoneRegistrationState cstate,
|
||||
const char *message) {
|
||||
LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(core);
|
||||
LinphoneConferenceServer *m = (LinphoneConferenceServer *)linphone_core_v_table_get_user_data(vtable);
|
||||
if(cfg == linphone_core_get_default_proxy_config(core)) {
|
||||
m->reg_state = cstate;
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneConferenceServer* linphone_conference_server_new(const char *rc_file, bool_t do_registration) {
|
||||
LinphoneConferenceServer *conf_srv = (LinphoneConferenceServer *)ms_new0(LinphoneConferenceServer, 1);
|
||||
LinphoneCoreManager *lm = (LinphoneCoreManager *)conf_srv;
|
||||
|
||||
conf_srv->vtable = linphone_core_v_table_new();
|
||||
conf_srv->vtable->call_state_changed = linphone_conference_server_call_state_changed;
|
||||
conf_srv->vtable->refer_received = linphone_conference_server_refer_received;
|
||||
conf_srv->vtable->registration_state_changed = linphone_conference_server_registration_state_changed;
|
||||
conf_srv->vtable->user_data = conf_srv;
|
||||
conf_srv->reg_state = LinphoneRegistrationNone;
|
||||
linphone_core_manager_init(lm, rc_file);
|
||||
linphone_core_add_listener(lm->lc, conf_srv->vtable);
|
||||
linphone_core_manager_start(lm, TRUE);
|
||||
linphone_core_manager_start(lm, do_registration);
|
||||
return conf_srv;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue