From fdbf7871417fcdbf874472059b2bee172950ea4a Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Wed, 13 Dec 2017 13:59:33 +0100 Subject: [PATCH] Fix audio conference. --- coreapi/conference.cc | 805 +++++++++--------- coreapi/private_functions.h | 7 +- src/c-wrapper/api/c-call.cpp | 87 +- src/call/call-p.h | 6 + src/call/call.cpp | 56 +- src/call/call.h | 2 + .../session/call-session-listener.h | 3 + src/conference/session/call-session-p.h | 1 + src/conference/session/call-session.cpp | 12 + src/conference/session/call-session.h | 2 + src/conference/session/media-session-p.h | 8 +- src/conference/session/media-session.cpp | 238 ++---- src/core/core-call.cpp | 104 +++ src/core/core-p.h | 4 + src/core/core.h | 1 + tester/call_multi_tester.c | 2 +- 16 files changed, 682 insertions(+), 656 deletions(-) diff --git a/coreapi/conference.cc b/coreapi/conference.cc index ca2196dbd..b9e91d4b3 100644 --- a/coreapi/conference.cc +++ b/coreapi/conference.cc @@ -35,6 +35,9 @@ #include "conference_private.h" #include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "conference/params/media-session-params-p.h" +#include "core/core-p.h" // TODO: From coreapi. Remove me later. #include "private.h" @@ -63,9 +66,8 @@ public: ~Participant() { linphone_address_unref(m_uri); -#if 0 - if(m_call) m_call->conf_ref = NULL; -#endif + if(m_call) + _linphone_call_set_conf_ref(m_call, nullptr); } const LinphoneAddress *getUri() const { @@ -208,7 +210,7 @@ private: MSAudioEndpoint *m_localEndpoint; MSAudioEndpoint *m_recordEndpoint; RtpProfile *m_localDummyProfile; - //bool_t m_terminating; + bool_t m_terminating; }; class RemoteConference: public Conference { @@ -262,124 +264,126 @@ using namespace Linphone; using namespace std; -Conference::Conference(LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params): +Conference::Conference(LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params) : m_core(core), - m_localParticipantStream(NULL), + m_localParticipantStream(nullptr), m_isMuted(false), m_currentParams(), m_state(LinphoneConferenceStopped), m_conference(conf) { - if(params) m_currentParams = *params; + if (params) + m_currentParams = *params; } -int Conference::addParticipant(LinphoneCall *call) { - Participant *p =new Participant(call); +int Conference::addParticipant (LinphoneCall *call) { + Participant *p = new Participant(call); m_participants.push_back(p); -#if 0 - call->conf_ref = m_conference; -#endif + _linphone_call_set_conf_ref(call, m_conference); return 0; } -int Conference::removeParticipant(LinphoneCall *call) { +int Conference::removeParticipant (LinphoneCall *call) { Participant *p = findParticipant(call); - if(p == NULL) return -1; + if (!p) + return -1; delete p; m_participants.remove(p); return 0; } -int Conference::removeParticipant(const LinphoneAddress *uri) { +int Conference::removeParticipant (const LinphoneAddress *uri) { Participant *p = findParticipant(uri); - if(p == NULL) return -1; + if (!p) + return -1; delete p; m_participants.remove(p); return 0; } -int Conference::terminate() { - for(list::iterator it = m_participants.begin(); it!=m_participants.end(); it++) { +int Conference::terminate () { + for (auto it = m_participants.begin(); it != m_participants.end(); it++) delete *it; - } m_participants.clear(); return 0; } -int Conference::muteMicrophone(bool val) { - if (val) { +int Conference::muteMicrophone (bool val) { + if (val) audio_stream_set_mic_gain(m_localParticipantStream, 0); - } else { + else audio_stream_set_mic_gain_db(m_localParticipantStream, m_core->sound_conf.soft_mic_lev); - } - if ( linphone_core_get_rtp_no_xmit_on_audio_mute(m_core) ){ + if (linphone_core_get_rtp_no_xmit_on_audio_mute(m_core)) audio_stream_mute_rtp(m_localParticipantStream, val); - } - m_isMuted=val; + m_isMuted = val; return 0; } -float Conference::getInputVolume() const { - AudioStream *st=m_localParticipantStream; - if (st && st->volsend && !m_isMuted){ - float vol=0; - ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); +float Conference::getInputVolume () const { + AudioStream *st = m_localParticipantStream; + if (st && st->volsend && !m_isMuted) { + float vol = 0; + ms_filter_call_method(st->volsend, MS_VOLUME_GET, &vol); return vol; - } return LINPHONE_VOLUME_DB_LOWEST; } -const char *Conference::stateToString(LinphoneConferenceState state) { +const char *Conference::stateToString (LinphoneConferenceState state) { switch(state) { - case LinphoneConferenceStopped: return "Stopped"; - case LinphoneConferenceStarting: return "Starting"; - case LinphoneConferenceRunning: return "Ready"; - case LinphoneConferenceStartingFailed: return "Startig failed"; - default: return "Invalid state"; + case LinphoneConferenceStopped: + return "Stopped"; + case LinphoneConferenceStarting: + return "Starting"; + case LinphoneConferenceRunning: + return "Ready"; + case LinphoneConferenceStartingFailed: + return "Starting failed"; + default: + return "Invalid state"; } } -void Conference::setState(LinphoneConferenceState state) { - if(m_state != state) { +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_stateChangedCb) { + if (m_currentParams.m_stateChangedCb) m_currentParams.m_stateChangedCb(m_conference, state, m_currentParams.m_userData); - } } } -Conference::Participant *Conference::findParticipant(const LinphoneCall *call) const { - for(list::const_iterator it=m_participants.begin(); it!=m_participants.end(); it++) { - if((*it)->getCall() == call) return *it; +Conference::Participant *Conference::findParticipant (const LinphoneCall *call) const { + for (auto it = m_participants.begin(); it != m_participants.end(); it++) { + if ((*it)->getCall() == call) + return *it; } - return NULL; + return nullptr; } -Conference::Participant *Conference::findParticipant(const LinphoneAddress *uri) const { - for(list::const_iterator it=m_participants.begin(); it!=m_participants.end(); it++) { - if(linphone_address_equal((*it)->getUri(), uri)) return *it; +Conference::Participant *Conference::findParticipant (const LinphoneAddress *uri) const { + for (auto it = m_participants.begin(); it != m_participants.end(); it++) { + if (linphone_address_equal((*it)->getUri(), uri)) + return *it; } - return NULL; + return nullptr; } -LocalConference::LocalConference(LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params): +LocalConference::LocalConference (LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params) : Conference(core, conf, params), - m_conf(NULL), - m_localEndpoint(NULL), - m_recordEndpoint(NULL), - m_localDummyProfile(NULL)/*, - m_terminating(FALSE)*/ { - + m_conf(nullptr), + m_localEndpoint(nullptr), + m_recordEndpoint(nullptr), + m_localDummyProfile(nullptr), + m_terminating(FALSE) { 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= LinphoneConferenceRunning; + 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 = LinphoneConferenceRunning; } LocalConference::~LocalConference() { @@ -387,24 +391,24 @@ LocalConference::~LocalConference() { ms_audio_conference_destroy(m_conf); } -RtpProfile *LocalConference::sMakeDummyProfile(int samplerate){ - RtpProfile *prof=rtp_profile_new("dummy"); - PayloadType *pt=payload_type_clone(&payload_type_l16_mono); - pt->clock_rate=samplerate; - rtp_profile_set_payload(prof,0,pt); +RtpProfile *LocalConference::sMakeDummyProfile (int samplerate) { + RtpProfile *prof = rtp_profile_new("dummy"); + PayloadType *pt = payload_type_clone(&payload_type_l16_mono); + pt->clock_rate = samplerate; + rtp_profile_set_payload(prof, 0, pt); return prof; } -void LocalConference::addLocalEndpoint() { - /*create a dummy audiostream in order to extract the local part of it */ +void LocalConference::addLocalEndpoint () { + /* Create a dummy audiostream in order to extract the local part of it */ /* network address and ports have no meaning and are not used here. */ - AudioStream *st=audio_stream_new(m_core->factory, 65000,65001,FALSE); - MSSndCard *playcard=m_core->sound_conf.lsd_card ? - m_core->sound_conf.lsd_card : m_core->sound_conf.play_sndcard; - MSSndCard *captcard=m_core->sound_conf.capt_sndcard; - const MSAudioConferenceParams *params=ms_audio_conference_get_params(m_conf); - m_localDummyProfile=sMakeDummyProfile(params->samplerate); - + AudioStream *st = audio_stream_new(m_core->factory, 65000, 65001, FALSE); + MSSndCard *playcard = m_core->sound_conf.lsd_card + ? m_core->sound_conf.lsd_card + : m_core->sound_conf.play_sndcard; + MSSndCard *captcard = m_core->sound_conf.capt_sndcard; + const MSAudioConferenceParams *params = ms_audio_conference_get_params(m_conf); + m_localDummyProfile = sMakeDummyProfile(params->samplerate); audio_stream_start_full(st, m_localDummyProfile, "127.0.0.1", 65000, @@ -412,312 +416,294 @@ void LocalConference::addLocalEndpoint() { 65001, 0, 40, - NULL, - NULL, + nullptr, + nullptr, playcard, captcard, linphone_core_echo_cancellation_enabled(m_core) ); - _post_configure_audio_stream(st,m_core,FALSE); - m_localParticipantStream=st; - m_localEndpoint=ms_audio_endpoint_get_from_stream(st,FALSE); - ms_message("conference: adding local endpoint"); - ms_audio_conference_add_member(m_conf,m_localEndpoint); + _post_configure_audio_stream(st, m_core, FALSE); + m_localParticipantStream = st; + m_localEndpoint = ms_audio_endpoint_get_from_stream(st, FALSE); + ms_message("Conference: adding local endpoint"); + ms_audio_conference_add_member(m_conf, m_localEndpoint); } -int LocalConference::inviteAddresses (const list &addresses, const LinphoneCallParams *params) { +int LocalConference::inviteAddresses (const list &addresses, const LinphoneCallParams *params) { for (const auto &address : addresses) { - LinphoneCall * call = linphone_core_get_call_by_remote_address2(m_core, address); + LinphoneCall *call = linphone_core_get_call_by_remote_address2(m_core, address); 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*/ + /* Start a new call by indicating that it has to be put into the conference directly */ + LinphoneCallParams *new_params = params + ? linphone_call_params_copy(params) + : linphone_core_create_call_params(m_core, nullptr); + /* Toggle this flag so the call is immediately added to the conference upon acceptance */ linphone_call_params_set_in_conference(new_params, TRUE); - linphone_call_params_enable_video(new_params, FALSE); /*turn off video as it is not supported for conferencing at this time*/ + /* Turn off video as it is not supported for conferencing at this time */ + linphone_call_params_enable_video(new_params, FALSE); call = linphone_core_invite_address_with_params(m_core, address, new_params); - if (!call) { + 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*/ + } else { + /* There is already a call to this address, so simply join it to the local conference if not already done */ if (!linphone_call_params_get_in_conference(linphone_call_get_current_params(call))) addParticipant(call); } - /*if the local participant is not yet created, created it and it to the conference */ - if (!m_localEndpoint) addLocalEndpoint(); + /* If the local participant is not yet created, created it and it to the conference */ + if (!m_localEndpoint) + addLocalEndpoint(); } return 0; } -int LocalConference::addParticipant(LinphoneCall *call) { -#if 0 - if (linphone_call_params_get_in_conference(call->current_params)){ +int LocalConference::addParticipant (LinphoneCall *call) { + if (linphone_call_params_get_in_conference(linphone_call_get_current_params(call))) { ms_error("Already in conference"); return -1; } - if (call->state==LinphoneCallPaused){ - linphone_call_params_set_in_conference(call->params, TRUE); - linphone_call_params_enable_video(call->params, FALSE); + if (linphone_call_get_state(call) == LinphoneCallPaused) { + const_cast( + L_GET_PRIVATE(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams()))->setInConference(true); + const_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams())->enableVideo(false); linphone_call_resume(call); - }else if (call->state==LinphoneCallStreamsRunning){ + } else if (linphone_call_get_state(call) == LinphoneCallStreamsRunning) { LinphoneCallParams *params = linphone_core_create_call_params(m_core, call); linphone_call_params_set_in_conference(params, TRUE); linphone_call_params_enable_video(params, FALSE); - if (call->audiostream || call->videostream){ - linphone_call_stop_media_streams(call); /*free the audio & video local resources*/ + if (L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio) + || L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeVideo)) { + linphone_call_stop_media_streams(call); /* Free the audio & video local resources */ linphone_call_init_media_streams(call); } - if (call==m_core->current_call){ - m_core->current_call=NULL; - } - /*this will trigger a reINVITE that will later redraw the streams */ - /*FIXME probably a bit too much to just redraw streams !*/ - linphone_call_update(call,params); + if (call == linphone_core_get_current_call(m_core)) + L_GET_PRIVATE_FROM_C_OBJECT(m_core)->setCurrentCall(nullptr); + /* This will trigger a reINVITE that will later redraw the streams */ + /* FIXME: probably a bit too much to just redraw streams! */ + linphone_call_update(call, params); linphone_call_params_unref(params); addLocalEndpoint(); - }else{ - ms_error("Call is in state %s, it cannot be added to the conference.",linphone_call_state_to_string(call->state)); + } else { + ms_error("Call is in state %s, it cannot be added to the conference", + linphone_call_state_to_string(linphone_call_get_state(call))); return -1; } return 0; -#else - return 0; -#endif } -int LocalConference::removeFromConference(LinphoneCall *call, bool_t active){ -#if 0 - int err=0; - char *str; - - if (!linphone_call_params_get_in_conference(call->current_params)){ - if (linphone_call_params_get_in_conference(call->params)){ +int LocalConference::removeFromConference (LinphoneCall *call, bool_t active) { + if (!linphone_call_params_get_in_conference(linphone_call_get_current_params(call))) { + if (linphone_call_params_get_in_conference(linphone_call_get_params(call))) { ms_warning("Not (yet) in conference, be patient"); return -1; - }else{ - ms_error("Not in a conference."); + } else { + ms_error("Not in a conference"); return -1; } } - linphone_call_params_set_in_conference(call->params, FALSE); + const_cast( + L_GET_PRIVATE(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams()))->setInConference(false); - str=linphone_call_get_remote_address_as_string(call); + char *str = linphone_call_get_remote_address_as_string(call); ms_message("%s will be removed from conference", str); ms_free(str); - if (active){ - LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call)); + int err = 0; + if (active) { + LinphoneCallParams *params = linphone_call_params_copy(linphone_call_get_current_params(call)); linphone_call_params_set_in_conference(params, FALSE); - // reconnect local audio with this call + // Reconnect local audio with this call if (isIn()){ - ms_message("Leaving conference for reconnecting with unique call."); + ms_message("Leaving conference for reconnecting with unique call"); leave(); } ms_message("Updating call to actually remove from conference"); - err=linphone_call_update(call,params); + err = linphone_call_update(call, params); linphone_call_params_unref(params); - } else{ + } else { ms_message("Pausing call to actually remove from conference"); - err=_linphone_call_pause(call); + err = _linphone_call_pause(call); } return err; -#else - return 0; -#endif } -int LocalConference::remoteParticipantsCount() { - int count=getSize(); - if (count==0) return 0; - if (!m_localParticipantStream) return count; - return count -1; +int LocalConference::remoteParticipantsCount () { + int count = getSize(); + if (count == 0) + return 0; + if (!m_localParticipantStream) + return count; + return count - 1; } -int LocalConference::convertConferenceToCall(){ - int err=0; -#if 0 - bctbx_list_t *calls=m_core->calls; - - if (remoteParticipantsCount()!=1){ - ms_error("No unique call remaining in conference."); +int LocalConference::convertConferenceToCall () { + if (remoteParticipantsCount() != 1) { + ms_error("No unique call remaining in conference"); return -1; } - while (calls) { - LinphoneCall *rc=(LinphoneCall*)calls->data; - calls=calls->next; - if (linphone_call_params_get_in_conference(linphone_call_get_params(rc))) { // not using current_param - bool_t active_after_removed=isIn(); - err=removeFromConference(rc, active_after_removed); - break; + list> calls = L_GET_CPP_PTR_FROM_C_OBJECT(m_core)->getCalls(); + for (auto it = calls.begin(); it != calls.end(); it++) { + shared_ptr call(*it); + if (L_GET_PRIVATE(call->getParams())->getInConference()) { + bool_t active_after_removed = isIn(); + return removeFromConference(L_GET_C_BACK_PTR(call), active_after_removed); } } -#endif - return err; + return 0; } -int LocalConference::removeParticipant(LinphoneCall *call) { - int err; - char * str=linphone_call_get_remote_address_as_string(call); +int LocalConference::removeParticipant (LinphoneCall *call) { + char *str = linphone_call_get_remote_address_as_string(call); ms_message("Removing call %s from the conference", str); ms_free(str); - err=removeFromConference(call, FALSE); - if (err){ - ms_error("Error removing participant from conference."); + int err = removeFromConference(call, FALSE); + if (err) { + ms_error("Error removing participant from conference"); return err; } - if (remoteParticipantsCount()==1){ - ms_message("conference size is 1: need to be converted to plain call"); - err=convertConferenceToCall(); - } else { - ms_message("the conference need not to be converted as size is %i", remoteParticipantsCount()); - } + if (remoteParticipantsCount() == 1) { + ms_message("Conference size is 1: need to be converted to plain call"); + err = convertConferenceToCall(); + } else + ms_message("The conference need not to be converted as size is %i", remoteParticipantsCount()); return err; } -int LocalConference::removeParticipant(const LinphoneAddress *uri) { +int LocalConference::removeParticipant (const LinphoneAddress *uri) { const Participant *participant = findParticipant(uri); - if(participant == NULL) return -1; + if (!participant) + return -1; LinphoneCall *call = participant->getCall(); - if(call == NULL) return -1; + if (!call) + return -1; return removeParticipant(call); } -int LocalConference::terminate() { -#if 0 - bctbx_list_t *calls=m_core->calls; - m_terminating =TRUE; +int LocalConference::terminate () { + m_terminating = TRUE; - while (calls) { - LinphoneCall *call=(LinphoneCall*)calls->data; - calls=calls->next; - if (linphone_call_params_get_in_conference(linphone_call_get_current_params(call))) { - linphone_call_terminate(call); - } + list> calls = L_GET_CPP_PTR_FROM_C_OBJECT(m_core)->getCalls(); + for (auto it = calls.begin(); it != calls.end(); it++) { + shared_ptr call(*it); + if (L_GET_PRIVATE(call->getCurrentParams())->getInConference()) + call->terminate(); } Conference::terminate(); m_terminating = FALSE; -#endif return 0; } -int LocalConference::enter() { -#if 0 - if (linphone_core_sound_resources_locked(m_core)) { +int LocalConference::enter () { + if (linphone_core_sound_resources_locked(m_core)) return -1; - } - if (m_core->current_call != NULL) { - _linphone_call_pause(m_core->current_call); - } - if (m_localParticipantStream==NULL) addLocalEndpoint(); -#endif + if (linphone_core_get_current_call(m_core)) + _linphone_call_pause(linphone_core_get_current_call(m_core)); + if (!m_localParticipantStream) + addLocalEndpoint(); return 0; } -void LocalConference::removeLocalEndpoint(){ - if (m_localEndpoint){ - ms_audio_conference_remove_member(m_conf,m_localEndpoint); +void LocalConference::removeLocalEndpoint () { + if (m_localEndpoint) { + ms_audio_conference_remove_member(m_conf, m_localEndpoint); ms_audio_endpoint_release_from_stream(m_localEndpoint); - m_localEndpoint=NULL; + m_localEndpoint = nullptr; audio_stream_stop(m_localParticipantStream); - m_localParticipantStream=NULL; + m_localParticipantStream = nullptr; rtp_profile_destroy(m_localDummyProfile); } } -int LocalConference::leave() { +int LocalConference::leave () { if (isIn()) removeLocalEndpoint(); return 0; } -int LocalConference::getSize() const { - if (m_conf == NULL) { +int LocalConference::getSize () const { + if (!m_conf) return 0; - } return ms_audio_conference_get_size(m_conf) - (m_recordEndpoint ? 1 : 0); } -int LocalConference::startRecording(const char *path) { - if (m_conf == NULL) { - ms_warning("linphone_core_start_conference_recording(): no conference now."); +int LocalConference::startRecording (const char *path) { + if (!m_conf) { + ms_warning("linphone_core_start_conference_recording(): no conference now"); return -1; } - if (m_recordEndpoint==NULL){ - m_recordEndpoint=ms_audio_endpoint_new_recorder(m_core->factory); - ms_audio_conference_add_member(m_conf,m_recordEndpoint); + if (!m_recordEndpoint) { + m_recordEndpoint = ms_audio_endpoint_new_recorder(m_core->factory); + ms_audio_conference_add_member(m_conf, m_recordEndpoint); } - ms_audio_recorder_endpoint_start(m_recordEndpoint,path); + ms_audio_recorder_endpoint_start(m_recordEndpoint, path); return 0; } -int LocalConference::stopRecording() { - if (m_conf == NULL) { - ms_warning("linphone_core_stop_conference_recording(): no conference now."); +int LocalConference::stopRecording () { + if (!m_conf) { + ms_warning("linphone_core_stop_conference_recording(): no conference now"); return -1; } - if (m_recordEndpoint==NULL){ - ms_warning("linphone_core_stop_conference_recording(): no record active."); + if (!m_recordEndpoint) { + ms_warning("linphone_core_stop_conference_recording(): no record active"); return -1; } ms_audio_recorder_endpoint_stop(m_recordEndpoint); return 0; } -void LocalConference::onCallStreamStarting(LinphoneCall *call, bool isPausedByRemote) { -#if 0 - linphone_call_params_enable_video(call->params, 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); - call->endpoint=ep; +void LocalConference::onCallStreamStarting (LinphoneCall *call, bool isPausedByRemote) { + const_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams())->enableVideo(false); + L_GET_CPP_PTR_FROM_C_OBJECT(call)->enableCamera(false); + ms_message("LocalConference::onCallStreamStarting(): joining AudioStream [%p] of call [%p] into conference", + L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio), call); + MSAudioEndpoint *ep = ms_audio_endpoint_get_from_stream( + reinterpret_cast(L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio)), + TRUE); + ms_audio_conference_add_member(m_conf, ep); + ms_audio_conference_mute_member(m_conf, ep, isPausedByRemote); + _linphone_call_set_endpoint(call, ep); setState(LinphoneConferenceRunning); Conference::addParticipant(call); -#endif } -void LocalConference::onCallStreamStopping(LinphoneCall *call) { -#if 0 - ms_audio_conference_remove_member(m_conf,call->endpoint); - ms_audio_endpoint_release_from_stream(call->endpoint); - call->endpoint=NULL; +void LocalConference::onCallStreamStopping (LinphoneCall *call) { + ms_audio_conference_remove_member(m_conf, _linphone_call_get_endpoint(call)); + ms_audio_endpoint_release_from_stream(_linphone_call_get_endpoint(call)); + _linphone_call_set_endpoint(call, nullptr); Conference::removeParticipant(call); -#endif } -void LocalConference::onCallTerminating(LinphoneCall *call) { -#if 0 - int remote_count=remoteParticipantsCount(); +void LocalConference::onCallTerminating (LinphoneCall *call) { + int remote_count = remoteParticipantsCount(); ms_message("conference_check_uninit(): size=%i", getSize()); - if (remote_count==1 && !m_terminating){ + if ((remote_count == 1) && !m_terminating) convertConferenceToCall(); - } - if (remote_count==0){ + if (remote_count == 0) { if (m_localParticipantStream) removeLocalEndpoint(); - if (m_recordEndpoint){ + if (m_recordEndpoint) { ms_audio_conference_remove_member(m_conf, m_recordEndpoint); ms_audio_endpoint_destroy(m_recordEndpoint); } setState(LinphoneConferenceStopped); } -#endif } -RemoteConference::RemoteConference(LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params): Conference(core, conf, params) { - m_focusAddr = NULL; - m_focusContact = NULL; - m_focusCall = NULL; - m_coreCbs = NULL; +RemoteConference::RemoteConference (LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params) : + Conference(core, conf, params) { + m_focusAddr = nullptr; + m_focusContact = nullptr; + m_focusCall = nullptr; + m_coreCbs = nullptr; m_focusAddr = lp_config_get_string(m_core->config, "misc", "conference_focus_addr", ""); m_coreCbs = linphone_factory_create_core_cbs(linphone_factory_get()); linphone_core_cbs_set_call_state_changed(m_coreCbs, callStateChangedCb); @@ -726,164 +712,161 @@ RemoteConference::RemoteConference(LinphoneCore *core, LinphoneConference *conf, _linphone_core_add_callbacks(m_core, m_coreCbs, TRUE); } -RemoteConference::~RemoteConference() { +RemoteConference::~RemoteConference () { terminate(); linphone_core_remove_callbacks(m_core, m_coreCbs); linphone_core_cbs_unref(m_coreCbs); } -int RemoteConference::inviteAddresses(const list &addresses, const LinphoneCallParams *params){ +int RemoteConference::inviteAddresses (const list &addresses, const LinphoneCallParams *params) { ms_error("RemoteConference::inviteAddresses() not implemented"); return -1; } -int RemoteConference::addParticipant(LinphoneCall *call) { -#if 0 +int RemoteConference::addParticipant (LinphoneCall *call) { LinphoneAddress *addr; LinphoneCallParams *params; - - switch(m_state) { + LinphoneCallLog *callLog; + switch (m_state) { 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_core_invite_address_with_params(m_core, addr, params); - m_localParticipantStream = m_focusCall->audiostream; - m_pendingCalls.push_back(call); - 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; - + if (!addr) + return -1; + params = linphone_core_create_call_params(m_core, nullptr); + linphone_call_params_enable_video(params, m_currentParams.videoRequested()); + m_focusCall = linphone_core_invite_address_with_params(m_core, addr, params); + m_localParticipantStream = reinterpret_cast( + L_GET_PRIVATE_FROM_C_OBJECT(m_focusCall)->getMediaStream(LinphoneStreamTypeAudio)); + m_pendingCalls.push_back(call); + 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; case LinphoneConferenceStarting: Conference::addParticipant(call); - if(focusIsReady()) { + if(focusIsReady()) transferToFocus(call); - } else { + else m_pendingCalls.push_back(call); - } return 0; - case LinphoneConferenceRunning: Conference::addParticipant(call); transferToFocus(call); return 0; - default: ms_error("Could not add call %p to the conference. Bad conference state (%s)", call, stateToString(m_state)); return -1; } -#else - return -1; -#endif } -int RemoteConference::removeParticipant(const LinphoneAddress *uri) { +int RemoteConference::removeParticipant (const LinphoneAddress *uri) { char *refer_to; LinphoneAddress *refer_to_addr; int res; - switch(m_state) { + switch (m_state) { case LinphoneConferenceRunning: - if(findParticipant(uri) == NULL) { + if(!findParticipant(uri)) { char *tmp = linphone_address_as_string(uri); ms_error("Conference: could not remove participant '%s': not in the participants list", tmp); ms_free(tmp); return -1; } - refer_to_addr = linphone_address_clone(uri); linphone_address_set_method_param(refer_to_addr, "BYE"); refer_to = linphone_address_as_string(refer_to_addr); linphone_address_unref(refer_to_addr); res = linphone_call_get_op(m_focusCall)->refer(refer_to); ms_free(refer_to); - - if(res == 0) { + if (res == 0) return Conference::removeParticipant(uri); - } else { + 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)); + ms_error("Cannot remove %s from conference: Bad conference state (%s)", + linphone_address_as_string(uri), stateToString(m_state)); return -1; } } -int RemoteConference::terminate() { - switch(m_state) { +int RemoteConference::terminate () { + switch (m_state) { case LinphoneConferenceRunning: case LinphoneConferenceStarting: linphone_call_terminate(m_focusCall); break; - - default: break; + default: + break; } return 0; } -int RemoteConference::enter() { - if(m_state != LinphoneConferenceRunning) { +int RemoteConference::enter () { + if (m_state != LinphoneConferenceRunning) { ms_error("Could not enter in the conference: bad conference state (%s)", stateToString(m_state)); return -1; } LinphoneCallState callState = linphone_call_get_state(m_focusCall); - switch(callState) { - case LinphoneCallStreamsRunning: break; + switch (callState) { + case LinphoneCallStreamsRunning: + break; case LinphoneCallPaused: linphone_call_resume(m_focusCall); break; default: - ms_error("Could not join the conference: bad focus call state (%s)", linphone_call_state_to_string(callState)); + ms_error("Could not join the conference: bad focus call state (%s)", + linphone_call_state_to_string(callState)); return -1; } return 0; } -int RemoteConference::leave() { - if(m_state != LinphoneConferenceRunning) { +int RemoteConference::leave () { + if (m_state != LinphoneConferenceRunning) { ms_error("Could not leave the conference: bad conference state (%s)", stateToString(m_state)); return -1; } LinphoneCallState callState = linphone_call_get_state(m_focusCall); - switch(callState) { - case LinphoneCallPaused: break; + switch (callState) { + case LinphoneCallPaused: + break; case LinphoneCallStreamsRunning: linphone_call_pause(m_focusCall); break; default: - ms_error("Could not leave the conference: bad focus call state (%s)", linphone_call_state_to_string(callState)); + ms_error("Could not leave the conference: bad focus call state (%s)", + linphone_call_state_to_string(callState)); return -1; } return 0; } -bool RemoteConference::isIn() const { - if(m_state != LinphoneConferenceRunning) return false; +bool RemoteConference::isIn () const { + if (m_state != LinphoneConferenceRunning) + return false; LinphoneCallState callState = linphone_call_get_state(m_focusCall); return callState == LinphoneCallStreamsRunning; } -bool RemoteConference::focusIsReady() const { +bool RemoteConference::focusIsReady () const { LinphoneCallState focusState; - if(m_focusCall == NULL) return false; + if (!m_focusCall) + return false; focusState = linphone_call_get_state(m_focusCall); - return focusState == LinphoneCallStreamsRunning || focusState == LinphoneCallPaused; + return (focusState == LinphoneCallStreamsRunning) || (focusState == LinphoneCallPaused); } -bool RemoteConference::transferToFocus(LinphoneCall *call) { - if(linphone_call_transfer(call, m_focusContact) == 0) { +bool RemoteConference::transferToFocus (LinphoneCall *call) { + if (linphone_call_transfer(call, m_focusContact) == 0) { m_transferingCalls.push_back(call); return true; } else { @@ -892,21 +875,20 @@ bool RemoteConference::transferToFocus(LinphoneCall *call) { } } -void RemoteConference::reset() { - m_localParticipantStream = NULL; - m_focusAddr = NULL; +void RemoteConference::reset () { + m_localParticipantStream = nullptr; + m_focusAddr = nullptr; if(m_focusContact) { ms_free(m_focusContact); - m_focusContact = NULL; + m_focusContact = nullptr; } - m_focusCall = NULL; + m_focusCall = nullptr; m_pendingCalls.clear(); m_transferingCalls.clear(); } -void RemoteConference::onFocusCallSateChanged(LinphoneCallState state) { +void RemoteConference::onFocusCallSateChanged (LinphoneCallState state) { list::iterator it; - switch (state) { case LinphoneCallConnected: m_focusContact = ms_strdup(linphone_call_get_remote_contact(m_focusCall)); @@ -914,101 +896,91 @@ void RemoteConference::onFocusCallSateChanged(LinphoneCallState state) { while (it != m_pendingCalls.end()) { LinphoneCall *pendingCall = *it; LinphoneCallState pendingCallState = linphone_call_get_state(pendingCall); - if(pendingCallState == LinphoneCallStreamsRunning || pendingCallState == LinphoneCallPaused) { + if ((pendingCallState == LinphoneCallStreamsRunning) || (pendingCallState == LinphoneCallPaused)) { it = m_pendingCalls.erase(it); transferToFocus(pendingCall); - } else { + } else it++; - } } setState(LinphoneConferenceRunning); break; - case LinphoneCallError: reset(); Conference::terminate(); setState(LinphoneConferenceStartingFailed); break; - case LinphoneCallEnd: reset(); Conference::terminate(); setState(LinphoneConferenceStopped); break; - - default: break; - } -} - -void RemoteConference::onPendingCallStateChanged(LinphoneCall *call, LinphoneCallState state) { - switch(state) { - case LinphoneCallStreamsRunning: - case LinphoneCallPaused: - if(m_state == LinphoneConferenceRunning) { - m_pendingCalls.remove(call); - m_transferingCalls.push_back(call); - linphone_call_transfer(call, m_focusContact); - } - break; - - case LinphoneCallError: - case LinphoneCallEnd: - m_pendingCalls.remove(call); - Conference::removeParticipant(call); - if(m_participants.size() + m_pendingCalls.size() + m_transferingCalls.size() == 0) { - terminate(); - } - break; - - default: break; - } -} - -void RemoteConference::onTransferingCallStateChanged(LinphoneCall* transfered, LinphoneCallState newCallState) { - switch (newCallState) { - case LinphoneCallConnected: - m_transferingCalls.push_back(transfered); - findParticipant(transfered)->m_call = NULL; - break; - - case LinphoneCallError: - m_transferingCalls.remove(transfered); - Conference::removeParticipant(transfered); - if(m_participants.size() + m_pendingCalls.size() + m_transferingCalls.size() == 0) { - terminate(); - } - break; - default: break; } } -void RemoteConference::callStateChangedCb(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { - LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(lc); - RemoteConference *conf = (RemoteConference *)linphone_core_v_table_get_user_data(vtable); - if (call == conf->m_focusCall) { - conf->onFocusCallSateChanged(cstate); - } else { - list::iterator it = find(conf->m_pendingCalls.begin(), conf->m_pendingCalls.end(), call); - if(it != conf->m_pendingCalls.end()) { - conf->onPendingCallStateChanged(call, cstate); - } +void RemoteConference::onPendingCallStateChanged (LinphoneCall *call, LinphoneCallState state) { + switch (state) { + case LinphoneCallStreamsRunning: + case LinphoneCallPaused: + if (m_state == LinphoneConferenceRunning) { + m_pendingCalls.remove(call); + m_transferingCalls.push_back(call); + linphone_call_transfer(call, m_focusContact); + } + break; + case LinphoneCallError: + case LinphoneCallEnd: + m_pendingCalls.remove(call); + Conference::removeParticipant(call); + if ((m_participants.size() + m_pendingCalls.size() + m_transferingCalls.size()) == 0) + terminate(); + break; + default: + break; } } -void RemoteConference::transferStateChanged(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { +void RemoteConference::onTransferingCallStateChanged (LinphoneCall* transfered, LinphoneCallState newCallState) { + switch (newCallState) { + case LinphoneCallConnected: + m_transferingCalls.push_back(transfered); + findParticipant(transfered)->m_call = nullptr; + break; + case LinphoneCallError: + m_transferingCalls.remove(transfered); + Conference::removeParticipant(transfered); + if ((m_participants.size() + m_pendingCalls.size() + m_transferingCalls.size()) == 0) + terminate(); + break; + default: + break; + } +} + +void RemoteConference::callStateChangedCb (LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { + LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(lc); + RemoteConference *conf = (RemoteConference *)linphone_core_v_table_get_user_data(vtable); + if (call == conf->m_focusCall) + conf->onFocusCallSateChanged(cstate); + else { + list::iterator it = find(conf->m_pendingCalls.begin(), conf->m_pendingCalls.end(), call); + if (it != conf->m_pendingCalls.end()) + conf->onPendingCallStateChanged(call, cstate); + } +} + +void RemoteConference::transferStateChanged (LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(lc); RemoteConference *conf = (RemoteConference *)linphone_core_v_table_get_user_data(vtable); list::iterator it = find(conf->m_transferingCalls.begin(), conf->m_transferingCalls.end(), transfered); - if (it != conf->m_transferingCalls.end()) { + if (it != conf->m_transferingCalls.end()) conf->onTransferingCallStateChanged(transfered, new_call_state); - } } -const char *linphone_conference_state_to_string(LinphoneConferenceState state) { +const char *linphone_conference_state_to_string (LinphoneConferenceState state) { return Conference::stateToString(state); } @@ -1030,45 +1002,45 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneConferenceParams, belle_sip_object_t, FALSE // unown ); -LinphoneConferenceParams *linphone_conference_params_new(const LinphoneCore *core) { +LinphoneConferenceParams *linphone_conference_params_new (const LinphoneCore *core) { LinphoneConferenceParams *obj = belle_sip_object_new(LinphoneConferenceParams); obj->params = new Conference::Params(core); return obj; } -static void _linphone_conference_params_uninit(LinphoneConferenceParams *params) { +static void _linphone_conference_params_uninit (LinphoneConferenceParams *params) { delete params->params; } -LinphoneConferenceParams *linphone_conference_params_ref(LinphoneConferenceParams *params) { +LinphoneConferenceParams *linphone_conference_params_ref (LinphoneConferenceParams *params) { return (LinphoneConferenceParams *)belle_sip_object_ref(params); } -void linphone_conference_params_unref(LinphoneConferenceParams *params) { +void linphone_conference_params_unref (LinphoneConferenceParams *params) { belle_sip_object_unref(params); } -void linphone_conference_params_free(LinphoneConferenceParams *params) { +void linphone_conference_params_free (LinphoneConferenceParams *params) { linphone_conference_params_unref(params); } -static void _linphone_conference_params_clone(LinphoneConferenceParams *params, const LinphoneConferenceParams *orig) { +static void _linphone_conference_params_clone (LinphoneConferenceParams *params, const LinphoneConferenceParams *orig) { params->params = new Conference::Params(*orig->params); } -LinphoneConferenceParams *linphone_conference_params_clone(const LinphoneConferenceParams *params) { +LinphoneConferenceParams *linphone_conference_params_clone (const LinphoneConferenceParams *params) { return (LinphoneConferenceParams *)belle_sip_object_clone((const belle_sip_object_t *)params); } -void linphone_conference_params_enable_video(LinphoneConferenceParams *params, bool_t enable) { +void linphone_conference_params_enable_video (LinphoneConferenceParams *params, bool_t enable) { params->params->enableVideo(enable ? true : false); } -bool_t linphone_conference_params_video_requested(const LinphoneConferenceParams *params) { +bool_t linphone_conference_params_video_requested (const LinphoneConferenceParams *params) { return params->params->videoRequested() ? TRUE : FALSE; } -void linphone_conference_params_set_state_changed_callback(LinphoneConferenceParams *params, LinphoneConferenceStateChangedCb cb, void *user_data) { +void linphone_conference_params_set_state_changed_callback (LinphoneConferenceParams *params, LinphoneConferenceStateChangedCb cb, void *user_data) { params->params->setStateChangedCallback(cb, user_data); } @@ -1078,7 +1050,7 @@ struct _LinphoneConference { Conference *conf; }; -static void _linphone_conference_uninit(LinphoneConference *conf); +static void _linphone_conference_uninit (LinphoneConference *conf); BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneConference); BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneConference); @@ -1089,140 +1061,143 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneConference, belle_sip_object_t, FALSE // unown ); -LinphoneConference *linphone_local_conference_new(LinphoneCore *core) { +LinphoneConference *linphone_local_conference_new (LinphoneCore *core) { LinphoneConference *conf = belle_sip_object_new(LinphoneConference); conf->conf = new LocalConference(core, conf); return conf; } -LinphoneConference *linphone_local_conference_new_with_params(LinphoneCore *core, const LinphoneConferenceParams *params) { +LinphoneConference *linphone_local_conference_new_with_params (LinphoneCore *core, const LinphoneConferenceParams *params) { LinphoneConference *conf = belle_sip_object_new(LinphoneConference); conf->conf = new LocalConference(core, conf, params->params); return conf; } -LinphoneConference *linphone_remote_conference_new(LinphoneCore *core) { +LinphoneConference *linphone_remote_conference_new (LinphoneCore *core) { LinphoneConference *conf = belle_sip_object_new(LinphoneConference); conf->conf = new RemoteConference(core, conf); return conf; } -LinphoneConference *linphone_remote_conference_new_with_params(LinphoneCore *core, const LinphoneConferenceParams *params) { +LinphoneConference *linphone_remote_conference_new_with_params (LinphoneCore *core, const LinphoneConferenceParams *params) { LinphoneConference *conf = belle_sip_object_new(LinphoneConference); conf->conf = new RemoteConference(core, conf, params->params); return conf; } -static void _linphone_conference_uninit(LinphoneConference *conf) { +static void _linphone_conference_uninit (LinphoneConference *conf) { delete conf->conf; } -LinphoneConference *linphone_conference_ref(LinphoneConference *conf) { +LinphoneConference *linphone_conference_ref (LinphoneConference *conf) { return (LinphoneConference *)belle_sip_object_ref(conf); } -void linphone_conference_unref(LinphoneConference *conf) { +void linphone_conference_unref (LinphoneConference *conf) { belle_sip_object_unref(conf); } -LinphoneConferenceState linphone_conference_get_state(const LinphoneConference *obj) { +LinphoneConferenceState linphone_conference_get_state (const LinphoneConference *obj) { return obj->conf->getState(); } -int linphone_conference_add_participant(LinphoneConference *obj, LinphoneCall *call) { +int linphone_conference_add_participant (LinphoneConference *obj, LinphoneCall *call) { return obj->conf->addParticipant(call); } -LinphoneStatus linphone_conference_remove_participant(LinphoneConference *obj, const LinphoneAddress *uri) { +LinphoneStatus linphone_conference_remove_participant (LinphoneConference *obj, const LinphoneAddress *uri) { return obj->conf->removeParticipant(uri); } -int linphone_conference_remove_participant_with_call(LinphoneConference *obj, LinphoneCall *call) { +int linphone_conference_remove_participant_with_call (LinphoneConference *obj, LinphoneCall *call) { return obj->conf->removeParticipant(call); } -int linphone_conference_terminate(LinphoneConference *obj) { +int linphone_conference_terminate (LinphoneConference *obj) { return obj->conf->terminate(); } -int linphone_conference_enter(LinphoneConference *obj) { +int linphone_conference_enter (LinphoneConference *obj) { return obj->conf->enter(); } -int linphone_conference_leave(LinphoneConference *obj) { +int linphone_conference_leave (LinphoneConference *obj) { return obj->conf->leave(); } -bool_t linphone_conference_is_in(const LinphoneConference *obj) { +bool_t linphone_conference_is_in (const LinphoneConference *obj) { return obj->conf->isIn(); } -AudioStream *linphone_conference_get_audio_stream(const LinphoneConference *obj) { +AudioStream *linphone_conference_get_audio_stream (const LinphoneConference *obj) { return obj->conf->getAudioStream(); } -int linphone_conference_mute_microphone(LinphoneConference *obj, bool_t val) { +int linphone_conference_mute_microphone (LinphoneConference *obj, bool_t val) { return obj->conf->muteMicrophone(val ? true : false); } -bool_t linphone_conference_microphone_is_muted(const LinphoneConference *obj) { +bool_t linphone_conference_microphone_is_muted (const LinphoneConference *obj) { return obj->conf->microphoneIsMuted() ? TRUE : FALSE; } -float linphone_conference_get_input_volume(const LinphoneConference *obj) { +float linphone_conference_get_input_volume (const LinphoneConference *obj) { return obj->conf->getInputVolume(); } -int linphone_conference_get_size(const LinphoneConference *obj) { +int linphone_conference_get_size (const LinphoneConference *obj) { return obj->conf->getSize(); } -bctbx_list_t *linphone_conference_get_participants(const LinphoneConference *obj) { +bctbx_list_t *linphone_conference_get_participants (const LinphoneConference *obj) { const list &participants = obj->conf->getParticipants(); - bctbx_list_t *participants_list = NULL; - for(list::const_iterator it=participants.begin();it!=participants.end();it++) { + bctbx_list_t *participants_list = nullptr; + for (auto it = participants.begin(); it != participants.end(); it++) { LinphoneAddress *uri = linphone_address_clone((*it)->getUri()); participants_list = bctbx_list_append(participants_list, uri); } return participants_list; } -int linphone_conference_start_recording(LinphoneConference *obj, const char *path) { +int linphone_conference_start_recording (LinphoneConference *obj, const char *path) { return obj->conf->startRecording(path); } -int linphone_conference_stop_recording(LinphoneConference *obj) { +int linphone_conference_stop_recording (LinphoneConference *obj) { return obj->conf->stopRecording(); } -void linphone_conference_on_call_stream_starting(LinphoneConference *obj, LinphoneCall *call, bool_t is_paused_by_remote) { +void linphone_conference_on_call_stream_starting (LinphoneConference *obj, LinphoneCall *call, bool_t is_paused_by_remote) { obj->conf->onCallStreamStarting(call, is_paused_by_remote ? true : false); } -void linphone_conference_on_call_stream_stopping(LinphoneConference *obj, LinphoneCall *call) { +void linphone_conference_on_call_stream_stopping (LinphoneConference *obj, LinphoneCall *call) { obj->conf->onCallStreamStopping(call); } -void linphone_conference_on_call_terminating(LinphoneConference *obj, LinphoneCall *call) { +void linphone_conference_on_call_terminating (LinphoneConference *obj, LinphoneCall *call) { obj->conf->onCallTerminating(call); } -bool_t linphone_conference_check_class(LinphoneConference *obj, LinphoneConferenceClass _class) { +bool_t linphone_conference_check_class (LinphoneConference *obj, LinphoneConferenceClass _class) { switch(_class) { - case LinphoneConferenceClassLocal: return typeid(obj->conf) == typeid(LocalConference); - case LinphoneConferenceClassRemote: return typeid(obj->conf) == typeid(RemoteConference); - default: return FALSE; + case LinphoneConferenceClassLocal: + return typeid(obj->conf) == typeid(LocalConference); + case LinphoneConferenceClassRemote: + return typeid(obj->conf) == typeid(RemoteConference); + default: + return FALSE; } } -LinphoneStatus linphone_conference_invite_participants(LinphoneConference *obj, const bctbx_list_t *addresses, const LinphoneCallParams *params){ +LinphoneStatus linphone_conference_invite_participants (LinphoneConference *obj, const bctbx_list_t *addresses, const LinphoneCallParams *params){ return obj->conf->inviteAddresses(toStd(addresses), params); } -const char * linphone_conference_get_ID(const LinphoneConference *obj) { +const char *linphone_conference_get_ID (const LinphoneConference *obj) { return obj->conf->getID(); } -void linphone_conference_set_ID(const LinphoneConference *obj, const char *conferenceID) { +void linphone_conference_set_ID (const LinphoneConference *obj, const char *conferenceID) { obj->conf->setID(conferenceID); } diff --git a/coreapi/private_functions.h b/coreapi/private_functions.h index 0abfff37d..f88c46ee0 100644 --- a/coreapi/private_functions.h +++ b/coreapi/private_functions.h @@ -25,6 +25,8 @@ #include #include +#include + #include "private_types.h" #include "tester_utils.h" #include "sal/op.h" @@ -48,8 +50,6 @@ void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *ms LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, LinphonePrivate::SalCallOp *op); -void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message); -/* private: */ LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress * to); LinphonePlayer *linphone_call_build_player(LinphoneCall*call); @@ -61,6 +61,9 @@ IceSession * linphone_call_get_ice_session(const LinphoneCall *call); bool_t linphone_call_get_audio_muted(const LinphoneCall *call); void linphone_call_set_audio_muted(LinphoneCall *call, bool_t value); bool_t linphone_call_get_all_muted(const LinphoneCall *call); +void _linphone_call_set_conf_ref (LinphoneCall *call, LinphoneConference *ref); +MSAudioEndpoint *_linphone_call_get_endpoint (const LinphoneCall *call); +void _linphone_call_set_endpoint (LinphoneCall *call, MSAudioEndpoint *endpoint); LinphoneCallParams * linphone_call_params_new(LinphoneCore *core); SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params); diff --git a/src/c-wrapper/api/c-call.cpp b/src/c-wrapper/api/c-call.cpp index c70b2ea50..c4de8f0f3 100644 --- a/src/c-wrapper/api/c-call.cpp +++ b/src/c-wrapper/api/c-call.cpp @@ -28,7 +28,7 @@ #include "call/local-conference-call.h" #include "call/remote-conference-call.h" #include "conference/params/media-session-params-p.h" -#include "core/core.h" +#include "core/core-p.h" // ============================================================================= @@ -53,14 +53,9 @@ L_DECLARE_C_OBJECT_IMPL_WITH_XTORS(Call, char *remoteUserAgentCache; mutable char *toHeaderCache; /* TODO: all the fields need to be removed */ - struct _LinphoneCore *core; - LinphonePrivate::SalOp *op; - LinphoneCallState transfer_state; /*idle if no transfer*/ + LinphoneConference *confRef; /**> Point on the associated conference if this call is part of a conference. NULL instead. */ MSAudioEndpoint *endpoint; /*used for conferencing*/ - LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/ - LinphoneCall *transfer_target;/*if this call received a transfer request, then transfer_target points to the new call created to the refer target */ LinphoneChatRoom *chat_room; - LinphoneConference *conf_ref; /**> Point on the associated conference if this call is part of a conference. NULL instead. */ ) static void _linphone_call_constructor (LinphoneCall *call) { @@ -94,18 +89,6 @@ static void _linphone_call_destructor (LinphoneCall *call) { if (call->toHeaderCache) bctbx_free(call->toHeaderCache); bctbx_list_free_with_data(call->callbacks, (bctbx_list_free_func)linphone_call_cbs_unref); - if (call->op) { - call->op->release(); - call->op=nullptr; - } - if (call->referer){ - linphone_call_unref(call->referer); - call->referer=nullptr; - } - if (call->transfer_target){ - linphone_call_unref(call->transfer_target); - call->transfer_target=nullptr; - } } @@ -113,35 +96,22 @@ static void _linphone_call_destructor (LinphoneCall *call) { // TODO: To remove! // ============================================================================= -MSWebCam *get_nowebcam_device (MSFactory* f) { -#ifdef VIDEO_ENABLED - return ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(f),"StaticImage: Static picture"); -#else - return nullptr; -#endif +void linphone_call_init_media_streams (LinphoneCall *call) { + L_GET_PRIVATE_FROM_C_OBJECT(call)->initializeMediaStreams(); } -void linphone_call_set_state (LinphoneCall *call, LinphoneCallState cstate, const char *message) {} - -void linphone_call_init_media_streams (LinphoneCall *call) {} - /*This function is not static because used internally in linphone-daemon project*/ -void _post_configure_audio_stream (AudioStream *st, LinphoneCore *lc, bool_t muted) {} - -#if 0 -static bool_t linphone_call_sound_resources_available (LinphoneCall *call) { - LinphoneCore *lc=call->core; - LinphoneCall *current=linphone_core_get_current_call(lc); - return !linphone_core_is_in_conference(lc) && - (current==nullptr || current==call); +void _post_configure_audio_stream (AudioStream *st, LinphoneCore *lc, bool_t muted) { + L_GET_PRIVATE_FROM_C_OBJECT(lc)->postConfigureAudioStream(st, !!muted); } -#endif -void linphone_call_stop_media_streams (LinphoneCall *call) {} +void linphone_call_stop_media_streams (LinphoneCall *call) { + L_GET_PRIVATE_FROM_C_OBJECT(call)->stopMediaStreams(); +} /* Internal version that does not play tone indication*/ int _linphone_call_pause (LinphoneCall *call) { - return 0; + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->pause(); } @@ -149,6 +119,18 @@ int _linphone_call_pause (LinphoneCall *call) { // Private functions. // ============================================================================= +void _linphone_call_set_conf_ref (LinphoneCall *call, LinphoneConference *ref) { + call->confRef = ref; +} + +MSAudioEndpoint *_linphone_call_get_endpoint (const LinphoneCall *call) { + return call->endpoint; +} + +void _linphone_call_set_endpoint (LinphoneCall *call, MSAudioEndpoint *endpoint) { + call->endpoint = endpoint; +} + MediaStream *linphone_call_get_stream (LinphoneCall *call, LinphoneStreamType type) { return L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(type); } @@ -312,15 +294,10 @@ LinphoneCall *linphone_call_get_transfer_target_call (const LinphoneCall *call) } LinphoneCall *linphone_call_get_replaced_call (LinphoneCall *call) { -#if 0 - SalOp *op=sal_call_get_replaces(call->op); - if (op){ - return (LinphoneCall*)sal_op_get_user_pointer(op); - } - return nullptr; -#else - return nullptr; -#endif + shared_ptr replacedCall = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getReplacedCall(); + if (!replacedCall) + return nullptr; + return L_GET_C_BACK_PTR(replacedCall); } int linphone_call_get_duration (const LinphoneCall *call) { @@ -445,19 +422,11 @@ void linphone_call_cancel_dtmfs (LinphoneCall *call) { } bool_t linphone_call_is_in_conference (const LinphoneCall *call) { -#if 0 - return linphone_call_params_get_in_conference(call->params); -#else - return FALSE; -#endif + return !!L_GET_CPP_PTR_FROM_C_OBJECT(call)->isInConference(); } LinphoneConference *linphone_call_get_conference (const LinphoneCall *call) { -#if 0 - return call->conf_ref; -#else - return nullptr; -#endif + return call->confRef; } void linphone_call_set_audio_route (LinphoneCall *call, LinphoneAudioRoute route) { diff --git a/src/call/call-p.h b/src/call/call-p.h index dc93e6e86..6a53434f9 100644 --- a/src/call/call-p.h +++ b/src/call/call-p.h @@ -62,6 +62,9 @@ public: void createPlayer () const; + void initializeMediaStreams (); + void stopMediaStreams (); + private: void resetFirstVideoFrameDecoded (); void startRemoteRing (); @@ -73,6 +76,8 @@ private: void onBackgroundTaskToBeStarted (const std::shared_ptr &session) override; void onBackgroundTaskToBeStopped (const std::shared_ptr &session) override; bool onCallSessionAccepted (const std::shared_ptr &session) override; + void onCallSessionConferenceStreamStarting (const std::shared_ptr &session, bool mute) override; + void onCallSessionConferenceStreamStopping (const std::shared_ptr &session) override; void onCallSessionSetReleased (const std::shared_ptr &session) override; void onCallSessionSetTerminated (const std::shared_ptr &session) override; void onCallSessionStartReferred (const std::shared_ptr &session) override; @@ -97,6 +102,7 @@ private: void onStopRinging (const std::shared_ptr &session) override; void onStopRingingIfInCall (const std::shared_ptr &session) override; void onStopRingingIfNeeded (const std::shared_ptr &session) override; + bool areSoundResourcesAvailable (const std::shared_ptr &session) override; bool isPlayingRingbackTone (const std::shared_ptr &session) override; mutable LinphonePlayer *player = nullptr; diff --git a/src/call/call.cpp b/src/call/call.cpp index ca11eba11..f6f11c844 100644 --- a/src/call/call.cpp +++ b/src/call/call.cpp @@ -25,6 +25,8 @@ #include "core/core-p.h" #include "logger/logger.h" +#include "conference_private.h" + // ============================================================================= using namespace std; @@ -119,10 +121,20 @@ void CallPrivate::createPlayer () const { // ----------------------------------------------------------------------------- +void CallPrivate::initializeMediaStreams () { + static_pointer_cast(getActiveSession())->getPrivate()->initializeStreams(); +} + +void CallPrivate::stopMediaStreams () { + static_pointer_cast(getActiveSession())->getPrivate()->stopStreams(); +} + +// ----------------------------------------------------------------------------- + void CallPrivate::resetFirstVideoFrameDecoded () { #ifdef VIDEO_ENABLED if (nextVideoFrameDecoded._func) - static_cast(getActiveSession().get())->resetFirstVideoFrameDecoded(); + static_pointer_cast(getActiveSession())->resetFirstVideoFrameDecoded(); #endif // ifdef VIDEO_ENABLED } @@ -197,6 +209,20 @@ bool CallPrivate::onCallSessionAccepted (const shared_ptr &se return wasRinging; } +void CallPrivate::onCallSessionConferenceStreamStarting (const shared_ptr &session, bool mute) { + L_Q(); + if (q->getCore()->getCCore()->conf_ctx) { + linphone_conference_on_call_stream_starting(q->getCore()->getCCore()->conf_ctx, L_GET_C_BACK_PTR(q), mute); + } +} + +void CallPrivate::onCallSessionConferenceStreamStopping (const shared_ptr &session) { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + if (lc->conf_ctx && _linphone_call_get_endpoint(L_GET_C_BACK_PTR(q))) + linphone_conference_on_call_stream_stopping(lc->conf_ctx, L_GET_C_BACK_PTR(q)); +} + void CallPrivate::onCallSessionSetReleased (const shared_ptr &session) { L_Q(); linphone_call_unref(L_GET_C_BACK_PTR(q)); @@ -211,10 +237,8 @@ void CallPrivate::onCallSessionSetTerminated (const shared_ptrgetCore()->getPrivate()->removeCall(q->getSharedFromThis()) != 0) lError() << "Could not remove the call from the list!!!"; -#if 0 if (core->conf_ctx) - linphone_conference_on_call_terminating(core->conf_ctx, lcall); -#endif + linphone_conference_on_call_terminating(core->conf_ctx, L_GET_C_BACK_PTR(q)); if (ringingBeep) { linphone_core_stop_dtmf(core); ringingBeep = false; @@ -393,6 +417,13 @@ void CallPrivate::onStopRingingIfNeeded (const shared_ptr &se linphone_core_stop_ringing(lc); } +bool CallPrivate::areSoundResourcesAvailable (const shared_ptr &session) { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + shared_ptr currentCall = q->getCore()->getCurrentCall(); + return !linphone_core_is_in_conference(lc) && (!currentCall || (currentCall == q->getSharedFromThis())); +} + bool CallPrivate::isPlayingRingbackTone (const shared_ptr &session) { return playingRingbackTone; } @@ -712,6 +743,18 @@ string Call::getRemoteUserAgent () const { return d->getActiveSession()->getRemoteUserAgent(); } +shared_ptr Call::getReplacedCall () const { + L_D(); + shared_ptr replacedCallSession = d->getActiveSession()->getReplacedCallSession(); + if (!replacedCallSession) + return nullptr; + for (const auto &call : getCore()->getCalls()) { + if (call->getPrivate()->getActiveSession() == replacedCallSession) + return call; + } + return nullptr; +} + float Call::getSpeakerVolumeGain () const { L_D(); return static_pointer_cast(d->getActiveSession())->getSpeakerVolumeGain(); @@ -774,6 +817,11 @@ LinphoneCallStats *Call::getVideoStats () const { return static_pointer_cast(d->getActiveSession())->getVideoStats(); } +bool Call::isInConference () const { + L_D(); + return d->getActiveSession()->getPrivate()->isInConference(); +} + bool Call::mediaInProgress () const { L_D(); return static_pointer_cast(d->getActiveSession())->mediaInProgress(); diff --git a/src/call/call.h b/src/call/call.h index d15447805..026fa6b0b 100644 --- a/src/call/call.h +++ b/src/call/call.h @@ -101,6 +101,7 @@ public: std::string getRemoteContact () const; const MediaSessionParams *getRemoteParams () const; std::string getRemoteUserAgent () const; + std::shared_ptr getReplacedCall () const; float getSpeakerVolumeGain () const; LinphoneCallState getState () const; LinphoneCallStats *getStats (LinphoneStreamType type) const; @@ -112,6 +113,7 @@ public: LinphoneCallState getTransferState () const; std::shared_ptr getTransferTarget () const; LinphoneCallStats *getVideoStats () const; + bool isInConference () const; bool mediaInProgress () const; void setAudioRoute (LinphoneAudioRoute route); void setAuthenticationTokenVerified (bool value); diff --git a/src/conference/session/call-session-listener.h b/src/conference/session/call-session-listener.h index 0f6b2d6fe..f97f36b21 100644 --- a/src/conference/session/call-session-listener.h +++ b/src/conference/session/call-session-listener.h @@ -35,6 +35,8 @@ public: virtual void onBackgroundTaskToBeStarted (const std::shared_ptr &session) {} virtual void onBackgroundTaskToBeStopped (const std::shared_ptr &session) {} virtual bool onCallSessionAccepted (const std::shared_ptr &session) { return false; } + virtual void onCallSessionConferenceStreamStarting (const std::shared_ptr &session, bool mute) {} + virtual void onCallSessionConferenceStreamStopping (const std::shared_ptr &session) {} virtual void onCallSessionSetReleased (const std::shared_ptr &session) {} virtual void onCallSessionSetTerminated (const std::shared_ptr &session) {} virtual void onCallSessionStartReferred (const std::shared_ptr &session) {} @@ -65,6 +67,7 @@ public: virtual void onStopRingingIfInCall (const std::shared_ptr &session) {} virtual void onStopRingingIfNeeded (const std::shared_ptr &session) {} + virtual bool areSoundResourcesAvailable (const std::shared_ptr &session) { return true; } virtual bool isPlayingRingbackTone (const std::shared_ptr &session) { return false; } }; diff --git a/src/conference/session/call-session-p.h b/src/conference/session/call-session-p.h index 38e9a696b..f056bb75b 100644 --- a/src/conference/session/call-session-p.h +++ b/src/conference/session/call-session-p.h @@ -46,6 +46,7 @@ public: LinphoneProxyConfig * getDestProxy () const { return destProxy; } SalCallOp * getOp () const { return op; } bool isBroken () const { return broken; } + bool isInConference () const; void setParams (CallSessionParams *csp); void setReferPending (bool value) { referPending = value; } void setTransferTarget (std::shared_ptr session) { transferTarget = session; } diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index 1b89299e7..18e445d84 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -212,6 +212,10 @@ void CallSessionPrivate::setParams (CallSessionParams *csp) { params = csp; } +bool CallSessionPrivate::isInConference () const { + return params->getPrivate()->getInConference(); +} + // ----------------------------------------------------------------------------- void CallSessionPrivate::abort (const string &errorMsg) { @@ -1327,6 +1331,14 @@ string CallSession::getRemoteUserAgent () const { return string(); } +shared_ptr CallSession::getReplacedCallSession () const { + L_D(); + SalOp *replacedOp = d->op->get_replaces(); + if (!replacedOp) + return nullptr; + return reinterpret_cast(replacedOp->get_user_pointer())->getSharedFromThis(); +} + CallSessionParams * CallSession::getCurrentParams () const { L_D(); d->updateCurrentParams(); diff --git a/src/conference/session/call-session.h b/src/conference/session/call-session.h index 20d305f71..d334e63b6 100644 --- a/src/conference/session/call-session.h +++ b/src/conference/session/call-session.h @@ -38,6 +38,7 @@ class Content; class Core; class LINPHONE_PUBLIC CallSession : public Object, public CoreAccessor { + friend class Call; friend class CallPrivate; friend class ClientGroupChatRoom; friend class ClientGroupChatRoomPrivate; @@ -88,6 +89,7 @@ public: const Address *getRemoteContactAddress () const; const CallSessionParams *getRemoteParams (); std::string getRemoteUserAgent () const; + std::shared_ptr getReplacedCallSession () const; LinphoneCallState getState () const; const Address& getToAddress () const; LinphoneCallState getTransferState () const; diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h index 1efd7af61..0ea306ab8 100644 --- a/src/conference/session/media-session-p.h +++ b/src/conference/session/media-session-p.h @@ -95,6 +95,9 @@ public: SalCallOp * getOp () const { return op; } void setAudioMuted (bool value) { audioMuted = value; } + void initializeStreams (); + void stopStreams (); + // CoreListener void onNetworkReachable (bool reachable) override; @@ -186,14 +189,10 @@ private: void handleIceEvents (OrtpEvent *ev); void handleStreamEvents (int streamIndex); void initializeAudioStream (); - void initializeStreams (); void initializeTextStream (); void initializeVideoStream (); - void parameterizeEqualizer (AudioStream *stream); void prepareEarlyMediaForking (); - void postConfigureAudioStream (AudioStream *stream, bool muted); void postConfigureAudioStreams (bool muted); - void setPlaybackGainDb (AudioStream *stream, float gain); void setSymmetricRtp (bool value); void setupRingbackPlayer (); void startAudioStream (LinphoneCallState targetState, bool videoWillBeUsed); @@ -201,7 +200,6 @@ private: void startTextStream (); void startVideoStream (LinphoneCallState targetState); void stopAudioStream (); - void stopStreams (); void stopTextStream (); void stopVideoStream (); void tryEarlyMediaForking (SalMediaDescription *md); diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index aac0f68ac..8b6666582 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -27,7 +27,7 @@ #include "conference/participant-p.h" #include "conference/params/media-session-params-p.h" #include "conference/session/media-session.h" -#include "core/core.h" +#include "core/core-p.h" #include "sal/sal.h" #include "utils/payload-type-handler.h" @@ -568,6 +568,53 @@ int MediaSessionPrivate::getStreamIndex (MediaStream *ms) const { // ----------------------------------------------------------------------------- +void MediaSessionPrivate::initializeStreams () { + initializeAudioStream(); + initializeVideoStream(); + initializeTextStream(); +} + +void MediaSessionPrivate::stopStreams () { + L_Q(); + if (audioStream || videoStream || textStream) { + if (audioStream && videoStream) + audio_stream_unlink_video(audioStream, videoStream); + stopAudioStream(); + stopVideoStream(); + stopTextStream(); + if (q->getCore()->getCCore()->msevq) + ms_event_queue_skip(q->getCore()->getCCore()->msevq); + } + + if (audioProfile) { + rtp_profile_destroy(audioProfile); + audioProfile = nullptr; + unsetRtpProfile(mainAudioStreamIndex); + } + if (videoProfile) { + rtp_profile_destroy(videoProfile); + videoProfile = nullptr; + unsetRtpProfile(mainVideoStreamIndex); + } + if (textProfile) { + rtp_profile_destroy(textProfile); + textProfile = nullptr; + unsetRtpProfile(mainTextStreamIndex); + } + if (rtpIoAudioProfile) { + rtp_profile_destroy(rtpIoAudioProfile); + rtpIoAudioProfile = nullptr; + } + if (rtpIoVideoProfile) { + rtp_profile_destroy(rtpIoVideoProfile); + rtpIoVideoProfile = nullptr; + } + + linphone_core_soundcard_hint_check(q->getCore()->getCCore()); +} + +// ----------------------------------------------------------------------------- + void MediaSessionPrivate::onNetworkReachable (bool reachable) { L_Q(); if (reachable) { @@ -929,7 +976,12 @@ MSWebCam * MediaSessionPrivate::getVideoDevice () const { L_Q(); bool paused = (state == LinphoneCallPausing) || (state == LinphoneCallPaused); if (paused || allMuted || !cameraEnabled) - return get_nowebcam_device(q->getCore()->getCCore()->factory); +#ifdef VIDEO_ENABLED + return ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(q->getCore()->getCCore()->factory), + "StaticImage: Static picture"); +#else + return nullptr; +#endif else return q->getCore()->getCCore()->video_conf.device; } @@ -2348,12 +2400,6 @@ void MediaSessionPrivate::initializeAudioStream () { iceAgent->prepareIceForStream(&audioStream->ms, false); } -void MediaSessionPrivate::initializeStreams () { - initializeAudioStream(); - initializeVideoStream(); - initializeTextStream(); -} - void MediaSessionPrivate::initializeTextStream () { L_Q(); if (textStream) @@ -2470,49 +2516,6 @@ void MediaSessionPrivate::initializeVideoStream () { #endif } -void MediaSessionPrivate::parameterizeEqualizer (AudioStream *stream) { - L_Q(); - LinphoneConfig *config = linphone_core_get_config(q->getCore()->getCCore()); - const char *eqActive = lp_config_get_string(config, "sound", "eq_active", nullptr); - if (eqActive) - lWarning() << "'eq_active' linphonerc parameter has no effect anymore. Please use 'mic_eq_active' or 'spk_eq_active' instead"; - const char *eqGains = lp_config_get_string(config, "sound", "eq_gains", nullptr); - if(eqGains) - lWarning() << "'eq_gains' linphonerc parameter has no effect anymore. Please use 'mic_eq_gains' or 'spk_eq_gains' instead"; - if (stream->mic_equalizer) { - MSFilter *f = stream->mic_equalizer; - bool enabled = !!lp_config_get_int(config, "sound", "mic_eq_active", 0); - ms_filter_call_method(f, MS_EQUALIZER_SET_ACTIVE, &enabled); - const char *gains = lp_config_get_string(config, "sound", "mic_eq_gains", nullptr); - if (enabled && gains) { - bctbx_list_t *gainsList = ms_parse_equalizer_string(gains); - for (bctbx_list_t *it = gainsList; it; it = bctbx_list_next(it)) { - MSEqualizerGain *g = reinterpret_cast(bctbx_list_get_data(it)); - lInfo() << "Read microphone equalizer gains: " << g->frequency << "(~" << g->width << ") --> " << g->gain; - ms_filter_call_method(f, MS_EQUALIZER_SET_GAIN, g); - } - if (gainsList) - bctbx_list_free_with_data(gainsList, ms_free); - } - } - if (stream->spk_equalizer) { - MSFilter *f = stream->spk_equalizer; - bool enabled = !!lp_config_get_int(config, "sound", "spk_eq_active", 0); - ms_filter_call_method(f, MS_EQUALIZER_SET_ACTIVE, &enabled); - const char *gains = lp_config_get_string(config, "sound", "spk_eq_gains", nullptr); - if (enabled && gains) { - bctbx_list_t *gainsList = ms_parse_equalizer_string(gains); - for (bctbx_list_t *it = gainsList; it; it = bctbx_list_next(it)) { - MSEqualizerGain *g = reinterpret_cast(bctbx_list_get_data(it)); - lInfo() << "Read speaker equalizer gains: " << g->frequency << "(~" << g->width << ") --> " << g->gain; - ms_filter_call_method(f, MS_EQUALIZER_SET_GAIN, g); - } - if (gainsList) - bctbx_list_free_with_data(gainsList, ms_free); - } - } -} - void MediaSessionPrivate::prepareEarlyMediaForking () { /* We need to disable symmetric rtp otherwise our outgoing streams will be switching permanently between the multiple destinations */ if (audioStream) @@ -2521,71 +2524,15 @@ void MediaSessionPrivate::prepareEarlyMediaForking () { rtp_session_set_symmetric_rtp(videoStream->ms.sessions.rtp_session, false); } -void MediaSessionPrivate::postConfigureAudioStream (AudioStream *stream, bool muted) { - L_Q(); - float micGain = q->getCore()->getCCore()->sound_conf.soft_mic_lev; - if (muted) - audio_stream_set_mic_gain(stream, 0); - else - audio_stream_set_mic_gain_db(stream, micGain); - float recvGain = q->getCore()->getCCore()->sound_conf.soft_play_lev; - if (static_cast(recvGain)) - setPlaybackGainDb(stream, recvGain); - LinphoneConfig *config = linphone_core_get_config(q->getCore()->getCCore()); - float ngThres = lp_config_get_float(config, "sound", "ng_thres", 0.05f); - float ngFloorGain = lp_config_get_float(config, "sound", "ng_floorgain", 0); - if (stream->volsend) { - int dcRemoval = lp_config_get_int(config, "sound", "dc_removal", 0); - ms_filter_call_method(stream->volsend, MS_VOLUME_REMOVE_DC, &dcRemoval); - float speed = lp_config_get_float(config, "sound", "el_speed", -1); - float thres = lp_config_get_float(config, "sound", "el_thres", -1); - float force = lp_config_get_float(config, "sound", "el_force", -1); - int sustain = lp_config_get_int(config, "sound", "el_sustain", -1); - float transmitThres = lp_config_get_float(config, "sound", "el_transmit_thres", -1); - if (static_cast(speed) == -1) - speed = 0.03f; - if (static_cast(force) == -1) - force = 25; - MSFilter *f = stream->volsend; - ms_filter_call_method(f, MS_VOLUME_SET_EA_SPEED, &speed); - ms_filter_call_method(f, MS_VOLUME_SET_EA_FORCE, &force); - if (static_cast(thres) != -1) - ms_filter_call_method(f, MS_VOLUME_SET_EA_THRESHOLD, &thres); - if (static_cast(sustain) != -1) - ms_filter_call_method(f, MS_VOLUME_SET_EA_SUSTAIN, &sustain); - if (static_cast(transmitThres) != -1) - ms_filter_call_method(f, MS_VOLUME_SET_EA_TRANSMIT_THRESHOLD, &transmitThres); - ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_THRESHOLD, &ngThres); - ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_FLOORGAIN, &ngFloorGain); - } - if (stream->volrecv) { - /* Parameters for a limited noise-gate effect, using echo limiter threshold */ - float floorGain = (float)(1 / pow(10, micGain / 10)); - int spkAgc = lp_config_get_int(config, "sound", "speaker_agc_enabled", 0); - MSFilter *f = stream->volrecv; - ms_filter_call_method(f, MS_VOLUME_ENABLE_AGC, &spkAgc); - ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_THRESHOLD, &ngThres); - ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_FLOORGAIN, &floorGain); - } - parameterizeEqualizer(stream); -} - void MediaSessionPrivate::postConfigureAudioStreams (bool muted) { L_Q(); - postConfigureAudioStream(audioStream, muted); + q->getCore()->getPrivate()->postConfigureAudioStream(audioStream, muted); if (linphone_core_dtmf_received_has_listener(q->getCore()->getCCore())) audio_stream_play_received_dtmfs(audioStream, false); if (recordActive) q->startRecording(); } -void MediaSessionPrivate::setPlaybackGainDb (AudioStream *stream, float gain) { - if (stream->volrecv) - ms_filter_call_method(stream->volrecv, MS_VOLUME_SET_DB_GAIN, &gain); - else - lWarning() << "Could not apply playback gain: gain control wasn't activated"; -} - void MediaSessionPrivate::setSymmetricRtp (bool value) { for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { MSMediaStreamSessions *mss = &sessions[i]; @@ -2630,10 +2577,10 @@ void MediaSessionPrivate::startAudioStream (LinphoneCallState targetState, bool playfile = ""; } if (targetState == LinphoneCallPaused) { - /* In paused state, we never use soundcard */ + // In paused state, we never use soundcard playcard = captcard = nullptr; recfile = ""; - /* And we will eventually play "playfile" if set by the user */ + // And we will eventually play "playfile" if set by the user } if (listener && listener->isPlayingRingbackTone(q->getSharedFromThis())) { captcard = nullptr; @@ -2643,22 +2590,20 @@ void MediaSessionPrivate::startAudioStream (LinphoneCallState targetState, bool recfile = ""; } } - /* If playfile are supplied don't use soundcards */ + // If playfile are supplied don't use soundcards bool useRtpIo = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "rtp_io", false); bool useRtpIoEnableLocalOutput = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "rtp_io_enable_local_output", false); if (q->getCore()->getCCore()->use_files || (useRtpIo && !useRtpIoEnableLocalOutput)) { captcard = playcard = nullptr; } if (getParams()->getPrivate()->getInConference()) { - /* First create the graph without soundcard resources */ + // First create the graph without soundcard resources captcard = playcard = nullptr; } -#if 0 - if (!linphone_call_sound_resources_available(call)){ - ms_message("Sound resources are used by another call, not using soundcard."); + if (listener && !listener->areSoundResourcesAvailable(q->getSharedFromThis())) { + lInfo() << "Sound resources are used by another CallSession, not using soundcard"; captcard = playcard = nullptr; } -#endif if (playcard) { ms_snd_card_set_stream_type(playcard, MS_SND_CARD_STREAM_VOICE); @@ -2675,7 +2620,7 @@ void MediaSessionPrivate::startAudioStream (LinphoneCallState targetState, bool audio_stream_mixed_record_open(audioStream, getParams()->getRecordFilePath().c_str()); getCurrentParams()->setRecordFilePath(getParams()->getRecordFilePath()); } - /* Valid local tags are > 0 */ + // Valid local tags are > 0 if (sal_stream_description_has_srtp(stream)) { const SalStreamDescription *localStreamDesc = sal_media_description_find_stream(localDesc, stream->proto, SalAudio); int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast(stream->crypto_local_tag)); @@ -2740,16 +2685,14 @@ void MediaSessionPrivate::startAudioStream (LinphoneCallState targetState, bool } if (listener && listener->isPlayingRingbackTone(q->getSharedFromThis())) setupRingbackPlayer(); - if (getParams()->getPrivate()->getInConference() && q->getCore()->getCCore()->conf_ctx) { - /* Transform the graph to connect it to the conference filter */ -#if 0 + if (getParams()->getPrivate()->getInConference() && listener) { + // Transform the graph to connect it to the conference filter bool mute = (stream->dir == SalStreamRecvOnly); - linphone_conference_on_call_stream_starting(q->getCore()->getCCore()->conf_ctx, call, mute); -#endif + listener->onCallSessionConferenceStreamStarting(q->getSharedFromThis(), mute); } getCurrentParams()->getPrivate()->setInConference(getParams()->getPrivate()->getInConference()); getCurrentParams()->enableLowBandwidth(getParams()->lowBandwidthEnabled()); - /* Start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */ + // Start ZRTP engine if needed : set here or remote have a zrtp-hash attribute SalMediaDescription *remote = op->get_remote_media_description(); const SalStreamDescription *remoteStream = sal_media_description_find_best_stream(remote, SalAudio); if (linphone_core_media_encryption_supported(q->getCore()->getCCore(), LinphoneMediaEncryptionZRTP) @@ -3041,11 +2984,8 @@ void MediaSessionPrivate::stopAudioStream () { } audio_stream_get_local_rtp_stats(audioStream, &log->local_stats); fillLogStats(&audioStream->ms); -#if 0 - if (call->endpoint) { - linphone_conference_on_call_stream_stopping(lc->conf_ctx, call); - } -#endif + if (listener) + listener->onCallSessionConferenceStreamStopping(q->getSharedFromThis()); ms_bandwidth_controller_remove_stream(q->getCore()->getCCore()->bw_controller, &audioStream->ms); audio_stream_stop(audioStream); updateRtpStats(audioStats, mainAudioStreamIndex); @@ -3060,45 +3000,6 @@ void MediaSessionPrivate::stopAudioStream () { } } -void MediaSessionPrivate::stopStreams () { - L_Q(); - if (audioStream || videoStream || textStream) { - if (audioStream && videoStream) - audio_stream_unlink_video(audioStream, videoStream); - stopAudioStream(); - stopVideoStream(); - stopTextStream(); - if (q->getCore()->getCCore()->msevq) - ms_event_queue_skip(q->getCore()->getCCore()->msevq); - } - - if (audioProfile) { - rtp_profile_destroy(audioProfile); - audioProfile = nullptr; - unsetRtpProfile(mainAudioStreamIndex); - } - if (videoProfile) { - rtp_profile_destroy(videoProfile); - videoProfile = nullptr; - unsetRtpProfile(mainVideoStreamIndex); - } - if (textProfile) { - rtp_profile_destroy(textProfile); - textProfile = nullptr; - unsetRtpProfile(mainTextStreamIndex); - } - if (rtpIoAudioProfile) { - rtp_profile_destroy(rtpIoAudioProfile); - rtpIoAudioProfile = nullptr; - } - if (rtpIoVideoProfile) { - rtp_profile_destroy(rtpIoVideoProfile); - rtpIoVideoProfile = nullptr; - } - - linphone_core_soundcard_hint_check(q->getCore()->getCCore()); -} - void MediaSessionPrivate::stopTextStream () { if (textStream) { updateReportingMediaInfo(LINPHONE_CALL_STATS_TEXT); @@ -4432,9 +4333,6 @@ void MediaSession::startIncomingNotification () { linphone_core_report_early_failed_call(d->core, LinphoneCallIncoming, linphone_address_ref(from_addr), linphone_address_ref(to_addr), ei); #endif d->op->decline(SalReasonNotAcceptable, nullptr); -#if 0 - linphone_call_unref(call); -#endif return; } } diff --git a/src/core/core-call.cpp b/src/core/core-call.cpp index 745577cd1..a05b4f75b 100644 --- a/src/core/core-call.cpp +++ b/src/core/core-call.cpp @@ -18,6 +18,7 @@ */ #include +#include #include "core-p.h" #include "call/call-p.h" @@ -27,6 +28,8 @@ // TODO: Remove me later. #include "c-wrapper/c-wrapper.h" +#include + // ============================================================================= using namespace std; @@ -120,6 +123,107 @@ void CorePrivate::unsetVideoWindowId (bool preview, void *id) { #endif } +// ----------------------------------------------------------------------------- + +void CorePrivate::parameterizeEqualizer (AudioStream *stream) { + L_Q(); + LinphoneConfig *config = linphone_core_get_config(q->getCCore()); + const char *eqActive = lp_config_get_string(config, "sound", "eq_active", nullptr); + if (eqActive) + lWarning() << "'eq_active' linphonerc parameter has no effect anymore. Please use 'mic_eq_active' or 'spk_eq_active' instead"; + const char *eqGains = lp_config_get_string(config, "sound", "eq_gains", nullptr); + if(eqGains) + lWarning() << "'eq_gains' linphonerc parameter has no effect anymore. Please use 'mic_eq_gains' or 'spk_eq_gains' instead"; + if (stream->mic_equalizer) { + MSFilter *f = stream->mic_equalizer; + bool enabled = !!lp_config_get_int(config, "sound", "mic_eq_active", 0); + ms_filter_call_method(f, MS_EQUALIZER_SET_ACTIVE, &enabled); + const char *gains = lp_config_get_string(config, "sound", "mic_eq_gains", nullptr); + if (enabled && gains) { + bctbx_list_t *gainsList = ms_parse_equalizer_string(gains); + for (bctbx_list_t *it = gainsList; it; it = bctbx_list_next(it)) { + MSEqualizerGain *g = reinterpret_cast(bctbx_list_get_data(it)); + lInfo() << "Read microphone equalizer gains: " << g->frequency << "(~" << g->width << ") --> " << g->gain; + ms_filter_call_method(f, MS_EQUALIZER_SET_GAIN, g); + } + if (gainsList) + bctbx_list_free_with_data(gainsList, ms_free); + } + } + if (stream->spk_equalizer) { + MSFilter *f = stream->spk_equalizer; + bool enabled = !!lp_config_get_int(config, "sound", "spk_eq_active", 0); + ms_filter_call_method(f, MS_EQUALIZER_SET_ACTIVE, &enabled); + const char *gains = lp_config_get_string(config, "sound", "spk_eq_gains", nullptr); + if (enabled && gains) { + bctbx_list_t *gainsList = ms_parse_equalizer_string(gains); + for (bctbx_list_t *it = gainsList; it; it = bctbx_list_next(it)) { + MSEqualizerGain *g = reinterpret_cast(bctbx_list_get_data(it)); + lInfo() << "Read speaker equalizer gains: " << g->frequency << "(~" << g->width << ") --> " << g->gain; + ms_filter_call_method(f, MS_EQUALIZER_SET_GAIN, g); + } + if (gainsList) + bctbx_list_free_with_data(gainsList, ms_free); + } + } +} + +void CorePrivate::postConfigureAudioStream (AudioStream *stream, bool muted) { + L_Q(); + float micGain = q->getCCore()->sound_conf.soft_mic_lev; + if (muted) + audio_stream_set_mic_gain(stream, 0); + else + audio_stream_set_mic_gain_db(stream, micGain); + float recvGain = q->getCCore()->sound_conf.soft_play_lev; + if (static_cast(recvGain)) + setPlaybackGainDb(stream, recvGain); + LinphoneConfig *config = linphone_core_get_config(q->getCCore()); + float ngThres = lp_config_get_float(config, "sound", "ng_thres", 0.05f); + float ngFloorGain = lp_config_get_float(config, "sound", "ng_floorgain", 0); + if (stream->volsend) { + int dcRemoval = lp_config_get_int(config, "sound", "dc_removal", 0); + ms_filter_call_method(stream->volsend, MS_VOLUME_REMOVE_DC, &dcRemoval); + float speed = lp_config_get_float(config, "sound", "el_speed", -1); + float thres = lp_config_get_float(config, "sound", "el_thres", -1); + float force = lp_config_get_float(config, "sound", "el_force", -1); + int sustain = lp_config_get_int(config, "sound", "el_sustain", -1); + float transmitThres = lp_config_get_float(config, "sound", "el_transmit_thres", -1); + if (static_cast(speed) == -1) + speed = 0.03f; + if (static_cast(force) == -1) + force = 25; + MSFilter *f = stream->volsend; + ms_filter_call_method(f, MS_VOLUME_SET_EA_SPEED, &speed); + ms_filter_call_method(f, MS_VOLUME_SET_EA_FORCE, &force); + if (static_cast(thres) != -1) + ms_filter_call_method(f, MS_VOLUME_SET_EA_THRESHOLD, &thres); + if (static_cast(sustain) != -1) + ms_filter_call_method(f, MS_VOLUME_SET_EA_SUSTAIN, &sustain); + if (static_cast(transmitThres) != -1) + ms_filter_call_method(f, MS_VOLUME_SET_EA_TRANSMIT_THRESHOLD, &transmitThres); + ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_THRESHOLD, &ngThres); + ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_FLOORGAIN, &ngFloorGain); + } + if (stream->volrecv) { + /* Parameters for a limited noise-gate effect, using echo limiter threshold */ + float floorGain = (float)(1 / pow(10, micGain / 10)); + int spkAgc = lp_config_get_int(config, "sound", "speaker_agc_enabled", 0); + MSFilter *f = stream->volrecv; + ms_filter_call_method(f, MS_VOLUME_ENABLE_AGC, &spkAgc); + ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_THRESHOLD, &ngThres); + ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_FLOORGAIN, &floorGain); + } + parameterizeEqualizer(stream); +} + +void CorePrivate::setPlaybackGainDb (AudioStream *stream, float gain) { + if (stream->volrecv) + ms_filter_call_method(stream->volrecv, MS_VOLUME_SET_DB_GAIN, &gain); + else + lWarning() << "Could not apply playback gain: gain control wasn't activated"; +} + // ============================================================================= bool Core::areSoundResourcesLocked () const { diff --git a/src/core/core-p.h b/src/core/core-p.h index d3aa6ad0a..abec29ab1 100644 --- a/src/core/core-p.h +++ b/src/core/core-p.h @@ -52,6 +52,10 @@ public: void setCurrentCall (const std::shared_ptr &call) { currentCall = call; } void unsetVideoWindowId (bool preview, void *id); + void parameterizeEqualizer (AudioStream *stream); + void postConfigureAudioStream (AudioStream *stream, bool muted); + void setPlaybackGainDb (AudioStream *stream, float gain); + void insertChatRoom (const std::shared_ptr &chatRoom); void insertChatRoomWithDb (const std::shared_ptr &chatRoom); std::shared_ptr createBasicChatRoom (const ChatRoomId &chatRoomId, bool isRtt); diff --git a/src/core/core.h b/src/core/core.h index a0e485295..c3ceb823f 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -50,6 +50,7 @@ class LINPHONE_PUBLIC Core : public Object { friend class MainDb; friend class MainDbChatMessageKey; friend class MainDbEventKey; + friend class MediaSessionPrivate; friend class RemoteConferenceEventHandler; friend class ServerGroupChatRoom; friend class ServerGroupChatRoomPrivate; diff --git a/tester/call_multi_tester.c b/tester/call_multi_tester.c index bf874805e..d53a359c0 100644 --- a/tester/call_multi_tester.c +++ b/tester/call_multi_tester.c @@ -1148,7 +1148,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_NO_TAG("Simple conference established from scratch", 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),