Fix audio playback

Since the preparation for encrypted events landed, audio playback was broken since QtMultimedia (gstreamer)
doesn't use our custom QNAM. Instead of letting QtMultimedia download the media, we thus need to manually download it
and point QML Audio to the local file. On the positive side, this also allows encrypted Audio files to be played and enables us to seek in the audio delegate :)
It does however mean that we do need to do an annoying bit of manual state management.

BUG: 457687
This commit is contained in:
Tobias Fella
2022-08-09 21:40:00 +02:00
parent 3c98a8fac4
commit 7dfac8a9f7
2 changed files with 72 additions and 18 deletions

View File

@@ -1,18 +1,14 @@
// SPDX-FileCopyrightText: 2019-2020 Black Hat <bhat@encom.eu.org> // SPDX-FileCopyrightText: 2022 Tobias Fella <fella@posteo.de>
// SPDX-License-Identifier: GPL-3.0-only // SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import Qt.labs.platform 1.1 as Platform
import QtMultimedia 5.15 import QtMultimedia 5.15
import org.kde.kirigami 2.15 as Kirigami import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0 import org.kde.neochat 1.0
import NeoChat.Component 1.0
import NeoChat.Dialog 1.0
import NeoChat.Menu.Timeline 1.0
TimelineContainer { TimelineContainer {
id: audioDelegate id: audioDelegate
@@ -21,6 +17,9 @@ TimelineContainer {
onOpenContextMenu: openFileContext(model, audioDelegate) onOpenContextMenu: openFileContext(model, audioDelegate)
readonly property bool downloaded: model.progressInfo && model.progressInfo.completed
onDownloadedChanged: audio.play()
hoverComponent: hoverActions hoverComponent: hoverActions
innerObject: Control { innerObject: Control {
Layout.fillWidth: true Layout.fillWidth: true
@@ -28,36 +27,90 @@ TimelineContainer {
Audio { Audio {
id: audio id: audio
source: currentRoom.urlToMxcUrl(content.url) source: model.progressInfo.localPath
autoLoad: false autoLoad: false
} }
states: [
State {
name: "notDownloaded"
when: !model.progressInfo.completed && !model.progressInfo.active
PropertyChanges {
target: playButton
icon.name: "media-playback-start"
onClicked: currentRoom.downloadFile(model.eventId)
}
},
State {
name: "downloading"
when: model.progressInfo.active && !model.progressInfo.completed
PropertyChanges {
target: downloadBar
visible: true
}
PropertyChanges {
target: playButton
icon.name: "media-playback-stop"
onClicked: {
currentRoom.cancelFileTransfer(model.eventId)
}
}
},
State {
name: "paused"
when: model.progressInfo.completed && (audio.playbackState === Audio.StoppedState || audio.playbackState === Audio.PausedState)
PropertyChanges {
target: playButton
icon.name: "media-playback-start"
onClicked: {
audio.play()
}
}
},
State {
name: "playing"
when: model.progressInfo.completed && audio.playbackState === Audio.PlayingState
PropertyChanges {
target: playButton
icon.name: "media-playback-pause"
onClicked: audio.pause()
}
}
]
contentItem: ColumnLayout { contentItem: ColumnLayout {
RowLayout { RowLayout {
ToolButton { ToolButton {
icon.name: audio.playbackState == Audio.PlayingState ? "media-playback-pause" : "media-playback-start" id: playButton
onClicked: {
if (audio.playbackState == Audio.PlayingState) {
audio.pause()
} else {
audio.play()
}
}
} }
Label { Label {
text: model.display text: model.display
wrapMode: Text.Wrap
Layout.fillWidth: true
} }
} }
ProgressBar {
id: downloadBar
visible: false
Layout.fillWidth: true
from: 0
to: model.content.info.size
value: model.progressInfo.progress
}
RowLayout { RowLayout {
visible: audio.hasAudio visible: audio.hasAudio
Layout.leftMargin: Kirigami.Units.largeSpacing Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing Layout.rightMargin: Kirigami.Units.largeSpacing
// Server doesn't support seeking, so use ProgressBar instead of Slider :(
ProgressBar { Slider {
from: 0 from: 0
to: audio.duration to: audio.duration
value: audio.position value: audio.position
onMoved: audio.seek(value)
} }
Label { Label {

View File

@@ -193,6 +193,7 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
} }
refreshEventRoles(eventId, {ReactionRole, Qt::DisplayRole}); refreshEventRoles(eventId, {ReactionRole, Qt::DisplayRole});
}); });
connect(m_currentRoom, &Room::newFileTransfer, this, &MessageEventModel::refreshEvent);
connect(m_currentRoom, &Room::fileTransferProgress, this, &MessageEventModel::refreshEvent); connect(m_currentRoom, &Room::fileTransferProgress, this, &MessageEventModel::refreshEvent);
connect(m_currentRoom, &Room::fileTransferCompleted, this, &MessageEventModel::refreshEvent); connect(m_currentRoom, &Room::fileTransferCompleted, this, &MessageEventModel::refreshEvent);
connect(m_currentRoom, &Room::fileTransferFailed, this, &MessageEventModel::refreshEvent); connect(m_currentRoom, &Room::fileTransferFailed, this, &MessageEventModel::refreshEvent);