Commit fdbf7871 authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Fix audio conference.

parent 8aca567a
This diff is collapsed.
......@@ -25,6 +25,8 @@
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <mediastreamer2/msconference.h>
#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);
......
......@@ -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<LinphonePrivate::Call> 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) {
......
......@@ -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<const CallSession> &session) override;
void onBackgroundTaskToBeStopped (const std::shared_ptr<const CallSession> &session) override;
bool onCallSessionAccepted (const std::shared_ptr<const CallSession> &session) override;
void onCallSessionConferenceStreamStarting (const std::shared_ptr<const CallSession> &session, bool mute) override;
void onCallSessionConferenceStreamStopping (const std::shared_ptr<const CallSession> &session) override;
void onCallSessionSetReleased (const std::shared_ptr<const CallSession> &session) override;
void onCallSessionSetTerminated (const std::shared_ptr<const CallSession> &session) override;
void onCallSessionStartReferred (const std::shared_ptr<const CallSession> &session) override;
......@@ -97,6 +102,7 @@ private:
void onStopRinging (const std::shared_ptr<const CallSession> &session) override;
void onStopRingingIfInCall (const std::shared_ptr<const CallSession> &session) override;
void onStopRingingIfNeeded (const std::shared_ptr<const CallSession> &session) override;
bool areSoundResourcesAvailable (const std::shared_ptr<const CallSession> &session) override;
bool isPlayingRingbackTone (const std::shared_ptr<const CallSession> &session) override;
mutable LinphonePlayer *player = nullptr;
......
......@@ -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<MediaSession>(getActiveSession())->getPrivate()->initializeStreams();
}
void CallPrivate::stopMediaStreams () {
static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->stopStreams();
}
// -----------------------------------------------------------------------------
void CallPrivate::resetFirstVideoFrameDecoded () {
#ifdef VIDEO_ENABLED
if (nextVideoFrameDecoded._func)
static_cast<MediaSession *>(getActiveSession().get())->resetFirstVideoFrameDecoded();
static_pointer_cast<MediaSession>(getActiveSession())->resetFirstVideoFrameDecoded();
#endif // ifdef VIDEO_ENABLED
}
......@@ -197,6 +209,20 @@ bool CallPrivate::onCallSessionAccepted (const shared_ptr<const CallSession> &se
return wasRinging;
}
void CallPrivate::onCallSessionConferenceStreamStarting (const shared_ptr<const CallSession> &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<const CallSession> &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<const CallSession> &session) {
L_Q();
linphone_call_unref(L_GET_C_BACK_PTR(q));
......@@ -211,10 +237,8 @@ void CallPrivate::onCallSessionSetTerminated (const shared_ptr<const CallSession
}
if (q->getCore()->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<const CallSession> &se
linphone_core_stop_ringing(lc);
}
bool CallPrivate::areSoundResourcesAvailable (const shared_ptr<const CallSession> &session) {
L_Q();
LinphoneCore *lc = q->getCore()->getCCore();
shared_ptr<Call> currentCall = q->getCore()->getCurrentCall();
return !linphone_core_is_in_conference(lc) && (!currentCall || (currentCall == q->getSharedFromThis()));
}
bool CallPrivate::isPlayingRingbackTone (const shared_ptr<const CallSession> &session) {
return playingRingbackTone;
}
......@@ -712,6 +743,18 @@ string Call::getRemoteUserAgent () const {
return d->getActiveSession()->getRemoteUserAgent();
}
shared_ptr<Call> Call::getReplacedCall () const {
L_D();
shared_ptr<CallSession> 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<const MediaSession>(d->getActiveSession())->getSpeakerVolumeGain();
......@@ -774,6 +817,11 @@ LinphoneCallStats *Call::getVideoStats () const {
return static_pointer_cast<const MediaSession>(d->getActiveSession())->getVideoStats();
}
bool Call::isInConference () const {
L_D();
return d->getActiveSession()->getPrivate()->isInConference();
}
bool Call::mediaInProgress () const {
L_D();
return static_pointer_cast<const MediaSession>(d->getActiveSession())->mediaInProgress();
......
......@@ -101,6 +101,7 @@ public:
std::string getRemoteContact () const;
const MediaSessionParams *getRemoteParams () const;
std::string getRemoteUserAgent () const;
std::shared_ptr<Call> getReplacedCall () const;
float getSpeakerVolumeGain () const;
LinphoneCallState getState () const;
LinphoneCallStats *getStats (LinphoneStreamType type) const;
......@@ -112,6 +113,7 @@ public:
LinphoneCallState getTransferState () const;
std::shared_ptr<Call> getTransferTarget () const;
LinphoneCallStats *getVideoStats () const;
bool isInConference () const;
bool mediaInProgress () const;
void setAudioRoute (LinphoneAudioRoute route);
void setAuthenticationTokenVerified (bool value);
......
......@@ -35,6 +35,8 @@ public:
virtual void onBackgroundTaskToBeStarted (const std::shared_ptr<const CallSession> &session) {}
virtual void onBackgroundTaskToBeStopped (const std::shared_ptr<const CallSession> &session) {}
virtual bool onCallSessionAccepted (const std::shared_ptr<const CallSession> &session) { return false; }
virtual void onCallSessionConferenceStreamStarting (const std::shared_ptr<const CallSession> &session, bool mute) {}
virtual void onCallSessionConferenceStreamStopping (const std::shared_ptr<const CallSession> &session) {}
virtual void onCallSessionSetReleased (const std::shared_ptr<const CallSession> &session) {}
virtual void onCallSessionSetTerminated (const std::shared_ptr<const CallSession> &session) {}
virtual void onCallSessionStartReferred (const std::shared_ptr<const CallSession> &session) {}
......@@ -65,6 +67,7 @@ public:
virtual void onStopRingingIfInCall (const std::shared_ptr<const CallSession> &session) {}
virtual void onStopRingingIfNeeded (const std::shared_ptr<const CallSession> &session) {}
virtual bool areSoundResourcesAvailable (const std::shared_ptr<const CallSession> &session) { return true; }
virtual bool isPlayingRingbackTone (const std::shared_ptr<const CallSession> &session) { return false; }
};
......
......@@ -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<CallSession> session) { transferTarget = session; }
......
......@@ -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> CallSession::getReplacedCallSession () const {
L_D();
SalOp *replacedOp = d->op->get_replaces();
if (!replacedOp)
return nullptr;
return reinterpret_cast<CallSession *>(replacedOp->get_user_pointer())->getSharedFromThis();
}
CallSessionParams * CallSession::getCurrentParams () const {
L_D();
d->updateCurrentParams();
......
......@@ -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<CallSession> getReplacedCallSession () const;
LinphoneCallState getState () const;
const Address& getToAddress () const;
LinphoneCallState getTransferState () const;
......
......@@ -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);
......
......@@ -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<MSEqualizerGain *>(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<MSEqualizerGain *>(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<int>(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<int>(speed) == -1)
speed = 0.03f;
if (static_cast<int>(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<int>(thres) != -1)
ms_filter_call_method(f, MS_VOLUME_SET_EA_THRESHOLD, &thres);
if (static_cast<int>(sustain) != -1)
ms_filter_call_method(f, MS_VOLUME_SET_EA_SUSTAIN, &sustain);
if (static_cast<int>(transmitThres) != -1)