- Workaround to avoid having no sound on inputs when audio enhancements is activated.

- Wasapi : Use options to get human hearing quality, fix variables that weren't updated in case of different audio format, do not use MixFormat without having set fix parameters (16bits/PCM), fix channel mask, reset Audio Client in case of error.
- Remove video button on incoming call that is audio only.
- Come back to first tab when openning Settings.
- Fix stream errors in audio settings when input and output have different definition by using a resampler.
- Change design of secure icon on avatars (position).
This commit is contained in:
Julien Wadel 2022-03-30 09:32:46 +02:00
parent dc0885923a
commit c3747a12cd
22 changed files with 68 additions and 51 deletions

View file

@ -625,6 +625,10 @@ void CallModel::setPausedByUser (bool status) {
}
// -----------------------------------------------------------------------------
bool CallModel::getRemoteVideoEnabled () const {
shared_ptr<const linphone::CallParams> params = mCall->getRemoteParams();
return params && params->videoEnabled();
}
bool CallModel::getVideoEnabled () const {
shared_ptr<const linphone::CallParams> params = mCall->getCurrentParams();

View file

@ -132,6 +132,7 @@ public:
Q_INVOKABLE bool transferTo (const QString &sipAddress);
Q_INVOKABLE bool transferToAnother (const QString &peerAddress);
Q_INVOKABLE bool getRemoteVideoEnabled () const;
Q_INVOKABLE void acceptVideoRequest ();
Q_INVOKABLE void rejectVideoRequest ();

View file

@ -39,8 +39,8 @@ public:
ParticipantModel (std::shared_ptr<linphone::Participant> linphoneParticipant, QObject *parent = nullptr);
Q_PROPERTY(ContactModel *contactModel READ getContactModel CONSTANT)
Q_PROPERTY(QString sipAddress MEMBER mSipAddress READ getSipAddress WRITE setSipAddress NOTIFY sipAddressChanged)
Q_PROPERTY(bool adminStatus MEMBER mAdminStatus READ getAdminStatus WRITE setAdminStatus NOTIFY adminStatusChanged)
Q_PROPERTY(QString sipAddress READ getSipAddress WRITE setSipAddress NOTIFY sipAddressChanged)
Q_PROPERTY(bool adminStatus READ getAdminStatus WRITE setAdminStatus NOTIFY adminStatusChanged)
Q_PROPERTY(QDateTime creationTime READ getCreationTime CONSTANT)
Q_PROPERTY(bool focus READ isFocus CONSTANT)
Q_PROPERTY(int securityLevel READ getSecurityLevel NOTIFY securityLevelChanged)

View file

@ -350,9 +350,7 @@ void SettingsModel::setCaptureDevice (const QString &device) {
CoreManager::getInstance()->getCore()->setCaptureDevice(devId);
CoreManager::getInstance()->getCore()->setInputAudioDevice(*audioDevice);
emit captureDeviceChanged(device);
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
createCaptureGraph();
}
createCaptureGraph();
}else
qWarning() << "Cannot set Capture device. The ID cannot be matched with an existant device : " << device;
}
@ -376,9 +374,7 @@ void SettingsModel::setPlaybackDevice (const QString &device) {
CoreManager::getInstance()->getCore()->setPlaybackDevice(devId);
CoreManager::getInstance()->getCore()->setOutputAudioDevice(*audioDevice);
emit playbackDeviceChanged(device);
if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) {
createCaptureGraph();
}
createCaptureGraph();
}else
qWarning() << "Cannot set Playback device. The ID cannot be matched with an existant device : " << device;
}
@ -1533,4 +1529,4 @@ bool SettingsModel::isReadOnly(const std::string& section, const std::string& na
std::string SettingsModel::getEntryFullName(const std::string& section, const std::string& name) const {
return isReadOnly(section, name)?name+"/readonly" : name;
}
}

View file

@ -138,7 +138,7 @@ void SoundPlayer::buildInternalPlayer () {
SettingsModel *settingsModel = coreManager->getSettingsModel();
mInternalPlayer = coreManager->getCore()->createLocalPlayer(
Utils::appStringToCoreString(settingsModel->getPlaybackDevice()), "", nullptr
Utils::appStringToCoreString(mIsRinger ? settingsModel->getRingerDevice() : settingsModel->getPlaybackDevice()), "", nullptr
);
if(mInternalPlayer)
mInternalPlayer->addListener(mHandlers);

View file

@ -42,6 +42,7 @@ class SoundPlayer : public QObject {
Q_PROPERTY(QString source READ getSource WRITE setSource NOTIFY sourceChanged)
Q_PROPERTY(PlaybackState playbackState READ getPlaybackState WRITE setPlaybackState NOTIFY playbackStateChanged)
Q_PROPERTY(int duration READ getDuration NOTIFY sourceChanged)
Q_PROPERTY(bool isRinger MEMBER mIsRinger)
public:
enum PlaybackState {
@ -92,6 +93,7 @@ private:
QString mSource;
PlaybackState mPlaybackState = StoppedState;
bool mIsRinger = false;
bool mForceClose = false;
QMutex mForceCloseMutex;

View file

@ -64,9 +64,22 @@ void SimpleCaptureGraph::init() {
if (!playbackVolumeFilter) {
playbackVolumeFilter = ms_factory_create_filter(msFactory, MS_VOLUME_ID);
}
if(!resamplerFilter)
resamplerFilter = ms_factory_create_filter(msFactory, MS_RESAMPLE_ID);
int captureRate, playbackRate, captureChannels, playbackChannels;
ms_filter_call_method(audioCapture,MS_FILTER_GET_SAMPLE_RATE,&captureRate);
ms_filter_call_method(audioSink,MS_FILTER_GET_SAMPLE_RATE,&playbackRate);
ms_filter_call_method(audioCapture,MS_FILTER_GET_NCHANNELS,&captureChannels);
ms_filter_call_method(audioSink,MS_FILTER_GET_NCHANNELS,&playbackChannels);
ms_filter_call_method(resamplerFilter,MS_FILTER_SET_SAMPLE_RATE,&captureRate);
ms_filter_call_method(resamplerFilter,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&playbackRate);
ms_filter_call_method(resamplerFilter,MS_FILTER_SET_NCHANNELS,&captureChannels);
ms_filter_call_method(resamplerFilter,MS_FILTER_SET_OUTPUT_NCHANNELS,&playbackChannels);
ms_filter_link(audioCapture, 0, captureVolumeFilter, 0);
ms_filter_link(captureVolumeFilter, 0, playbackVolumeFilter, 0);
ms_filter_link(captureVolumeFilter, 0, resamplerFilter, 0);
ms_filter_link(resamplerFilter, 0, playbackVolumeFilter, 0);
ms_filter_link(playbackVolumeFilter, 0, audioSink, 0);
//Mute playback
@ -99,14 +112,18 @@ void SimpleCaptureGraph::destroy() {
if (audioSink)
ms_filter_unlink(playbackVolumeFilter, 0, audioSink, 0);
if (captureVolumeFilter && playbackVolumeFilter)
ms_filter_unlink(captureVolumeFilter, 0, playbackVolumeFilter, 0);
if (captureVolumeFilter && resamplerFilter)
ms_filter_unlink(captureVolumeFilter, 0, resamplerFilter, 0);
if (resamplerFilter && playbackVolumeFilter)
ms_filter_unlink(resamplerFilter, 0, playbackVolumeFilter, 0);
if (audioCapture)
ms_filter_unlink(audioCapture, 0, captureVolumeFilter, 0);
if (playbackVolumeFilter)
ms_filter_destroy(playbackVolumeFilter);
if (captureVolumeFilter)
ms_filter_destroy(captureVolumeFilter);
if (resamplerFilter)
ms_filter_destroy(resamplerFilter);
if (audioSink)
ms_filter_destroy(audioSink);
if (audioCapture)
@ -117,6 +134,7 @@ void SimpleCaptureGraph::destroy() {
ticker = nullptr;
playbackVolumeFilter = nullptr;
captureVolumeFilter = nullptr;
resamplerFilter = nullptr;
audioSink = nullptr;
audioCapture = nullptr;
}

View file

@ -91,6 +91,7 @@ namespace MediastreamerUtils {
MSFilter *audioCapture = nullptr;
MSFilter *captureVolumeFilter = nullptr;
MSFilter *playbackVolumeFilter = nullptr;
MSFilter *resamplerFilter = nullptr;
MSTicker *ticker = nullptr;
MSSndCard *playbackCard = nullptr;
MSSndCard *captureCard = nullptr;

View file

@ -79,12 +79,11 @@ Rectangle {
}
Icon{
anchors.right: parent.right
anchors.top:parent.top
anchors.topMargin: -5
anchors.horizontalCenter: parent.right
visible: entry!=undefined && entry.haveEncryption != undefined && entry.haveEncryption
icon: entry?(entry.securityLevel === 2?'secure_level_1': entry.securityLevel===3? 'secure_level_2' : 'secure_level_unsafe'):'secure_level_unsafe'
iconSize:15
iconSize: parent.height/2
}
MouseArea{
anchors.fill: parent

View file

@ -58,7 +58,7 @@ Notification {
isCustom: true
backgroundRadius: 90
colorSet: NotificationReceivedCallStyle.acceptVideoCall
visible: SettingsModel.videoSupported
visible: SettingsModel.videoSupported && notification.call.getRemoteVideoEnabled()
onClicked: notification._close(notification.call.acceptWithVideo)
}

View file

@ -129,10 +129,9 @@ ScrollableListView {
visible: modelData.secure>0 &&
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$sipAddress}) : true)
icon:modelData.secure === 2?'secure_level_2':'secure_level_1'
iconSize:15
anchors.right:parent.right
iconSize:parent.height/2
anchors.top:parent.top
anchors.topMargin: -3
anchors.horizontalCenter: parent.right
}
}
}
@ -296,10 +295,9 @@ ScrollableListView {
visible: modelData.secure>0 &&
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({sipAddres:$sipAddress}) : true)
icon:modelData.secure === 2?'secure_level_2':'secure_level_1'
iconSize:15
anchors.right:parent.right
iconSize: parent.height/2
anchors.top:parent.top
anchors.topMargin: -3
anchors.horizontalCenter: parent.right
}
}
}

View file

@ -133,10 +133,9 @@ ScrollableListView {
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler({ sipAddress : sipAddressesView.interpretableSipAddress}) : true)
icon: 'secure_on'
iconSize:15
anchors.right:parent.right
iconSize: parent.height/2
anchors.top:parent.top
anchors.topMargin: -3
anchors.horizontalCenter: parent.right
}
}
}
@ -304,10 +303,9 @@ ScrollableListView {
(sipAddressesView.actions[index].secureIconVisibleHandler ? sipAddressesView.actions[index].secureIconVisibleHandler(sipAddressEntry.entry) : true)
icon: 'secure_on'
iconSize:15
anchors.right:parent.right
iconSize: parent.height/2
anchors.top:parent.top
anchors.topMargin: -3
anchors.horizontalCenter: parent.right
}
}
}

View file

@ -190,10 +190,9 @@ ColumnLayout {
enabled: AccountSettingsModel.conferenceURI != ''
Icon{
icon:'secure_level_1'
iconSize:15
anchors.right:parent.right
iconSize:parent.height/2
anchors.top:parent.top
anchors.topMargin: -3
anchors.horizontalCenter: parent.right
}
onClicked: {sipAddressesMenu.open(sipAddressesMenu.createSecureChatRoom)}

View file

@ -168,10 +168,9 @@ ColumnLayout {
enabled: AccountSettingsModel.conferenceURI != ''
Icon{
icon:'secure_level_1'
iconSize:15
anchors.right:parent.right
iconSize:parent.height/2
anchors.top:parent.top
anchors.topMargin: -3
anchors.horizontalCenter: parent.right
}
onClicked: {actions.itemAt(3).open()}
tooltipMaxWidth: actionBar.width

View file

@ -282,10 +282,9 @@ ColumnLayout {
onClicked: CallsListModel.launchChat(chatRoomModel.participants.addressesToString, 1)
Icon{
icon:'secure_level_1'
iconSize:15
anchors.right:parent.right
iconSize: parent.height/2
anchors.top:parent.top
anchors.topMargin: -3
anchors.horizontalCenter: parent.right
}
}

View file

@ -220,12 +220,11 @@ DialogPlus {
image:modelData.avatar
Icon{
property int securityLevel : 2
anchors.right: parent.right
anchors.top:parent.top
anchors.topMargin: -5
anchors.horizontalCenter: parent.right
visible: UtilsCpp.hasCapability(modelData.sipAddress, LinphoneEnums.FriendCapabilityLimeX3Dh)
icon: 'secure_on'
iconSize:20
iconSize: parent.height/2
}
}
Text{
@ -411,4 +410,4 @@ DialogPlus {
}
}
}
}
}

View file

@ -72,12 +72,11 @@ DialogPlus {
):''
Icon{
property int securityLevel : modelData.securityLevel
anchors.right: parent.right
anchors.top:parent.top
anchors.topMargin: -5
anchors.horizontalCenter: parent.right
visible: modelData && securityLevel !== 1
icon: modelData?(securityLevel === 2?'secure_level_1': securityLevel===3? 'secure_level_2' : 'secure_level_unsafe'):'secure_level_unsafe'
iconSize:15
iconSize: parent.height/2
Timer{// Workaround : no security events are send when device's security change.
onTriggered: parent.securityLevel = modelData.securityLevel
repeat:true

View file

@ -118,10 +118,9 @@ ColumnLayout {
onClicked: CallsListModel.launchChat(historyView.peerAddress, 1)
Icon{
icon:'secure_level_1'
iconSize:15
anchors.right:parent.right
iconSize: parent.height/2
anchors.top:parent.top
anchors.topMargin: -3
anchors.horizontalCenter: parent.right
}
}
}

View file

@ -230,6 +230,7 @@ TabContainer {
active: window.visible
sourceComponent: SoundPlayer {
source: SettingsModel.ringPath
isRinger: true
}
}
}

View file

@ -144,7 +144,7 @@ TabContainer {
title: qsTr('assistantTitle')
width: parent.width
visible: SettingsModel.useWebview() || SettingsModel.developerSettingsEnabled
FormLine {
FormGroup {
label: 'Registration URL'
@ -155,6 +155,7 @@ TabContainer {
onEditingFinished: SettingsModel.assistantRegistrationUrl = text
}
}
visible: SettingsModel.useWebview()
}
FormLine {
@ -167,6 +168,7 @@ TabContainer {
onEditingFinished: SettingsModel.assistantLoginUrl = text
}
}
visible: SettingsModel.useWebview()
}
FormLine {

View file

@ -19,7 +19,10 @@ ApplicationWindow {
title: qsTr('settingsTitle')
onClosing: SettingsModel.settingsWindowClosing()
onClosing: {
SettingsModel.settingsWindowClosing()
tabBar.setCurrentIndex(0)
}
// ---------------------------------------------------------------------------

@ -1 +1 @@
Subproject commit 00fd2d08b3cc24365aba7407c3885e11cc120024
Subproject commit f3daa534e402049c95b300d2bbdab485fdab2f3e