Fix lag when media messages are shown and fix media controls

This commit is contained in:
Nicolas Werner 2024-01-08 01:23:55 +01:00
parent 87c063b112
commit eed23cdf11
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
4 changed files with 67 additions and 34 deletions

View file

@ -24,24 +24,25 @@ Item {
property int tempWidth: originalWidth < 1? 400: originalWidth property int tempWidth: originalWidth < 1? 400: originalWidth
implicitWidth: type == MtxEvent.VideoMessage ? Math.round(tempWidth*Math.min((timelineView.height/divisor)/(tempWidth*proportionalHeight), 1)) : 500 implicitWidth: type == MtxEvent.VideoMessage ? Math.round(tempWidth*Math.min((timelineView.height/divisor)/(tempWidth*proportionalHeight), 1)) : 500
width: Math.min(parent?.width ?? implicitWidth, implicitWidth) width: Math.min(parent?.width ?? implicitWidth, implicitWidth)
height: (type == MtxEvent.VideoMessage ? width*proportionalHeight : 80) + fileInfoLabel.height height: (type == MtxEvent.VideoMessage ? width*proportionalHeight : mediaControls.height) + fileInfoLabel.height
//implicitHeight: height //implicitHeight: height
property int metadataWidth property int metadataWidth
property bool fitsMetadata: (parent.width - fileInfoLabel.width) > metadataWidth+4 property bool fitsMetadata: parent != null ? ((parent.width - fileInfoLabel.width) > metadataWidth+4) : false
Component.onCompleted: mxcmedia.startDownload(true)
MxcMedia { MxcMedia {
id: mxcmedia id: mxcmedia
// TODO: Show error in overlay or so? // TODO: Show error in overlay or so?
roomm: room roomm: room
// FIXME: This takes 500ms on my device, why and how can we avoid that? eventId: content.eventId
audioOutput: AudioOutput { videoOutput: videoOutput
muted: mediaControls.muted muted: mediaControls.muted
volume: mediaControls.desiredVolume volume: mediaControls.desiredVolume
} }
videoOutput: videoOutput
}
Rectangle { Rectangle {
id: videoContainer id: videoContainer
@ -56,6 +57,7 @@ Item {
Image { Image {
anchors.fill: parent anchors.fill: parent
visible: content.type == MtxEvent.VideoMessage
source: content.thumbnailUrl ? thumbnailUrl.replace("mxc://", "image://MxcImage/") + "?scale" : "image://colorimage/:/icons/icons/ui/video-file.svg?" + palette.windowText source: content.thumbnailUrl ? thumbnailUrl.replace("mxc://", "image://MxcImage/") + "?scale" : "image://colorimage/:/icons/icons/ui/video-file.svg?" + palette.windowText
asynchronous: true asynchronous: true
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
@ -85,7 +87,7 @@ Item {
mediaState: mxcmedia.playbackState mediaState: mxcmedia.playbackState
onPositionChanged: mxcmedia.position = position onPositionChanged: mxcmedia.position = position
onPlayPauseActivated: mxcmedia.playbackState == MediaPlayer.PlayingState ? mxcmedia.pause() : mxcmedia.play() onPlayPauseActivated: mxcmedia.playbackState == MediaPlayer.PlayingState ? mxcmedia.pause() : mxcmedia.play()
onLoadActivated: mxcmedia.eventId = eventId onLoadActivated: mxcmedia.startDownload()
} }
} }

View file

@ -71,7 +71,7 @@ Rectangle {
spacing: 0 spacing: 0
anchors.bottom: control.bottom anchors.bottom: control.bottom
anchors.left: control.left anchors.left: control.left
anchors.right: control.right width: Math.max(implicitWidth, control.width)
NhekoSlider { NhekoSlider {
Layout.fillWidth: true Layout.fillWidth: true
@ -134,8 +134,9 @@ Rectangle {
state: "" state: ""
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft
Layout.preferredWidth: 0 Layout.preferredWidth: 100
opacity: 0 opacity: 0
enabled: false
orientation: Qt.Horizontal orientation: Qt.Horizontal
value: 1 value: 1
onDesiredVolumeChanged: { onDesiredVolumeChanged: {
@ -158,12 +159,6 @@ Rectangle {
} }
} }
NumberAnimation {
properties: "Layout.preferredWidth"
duration: 150
}
}, },
Transition { Transition {
from: "shown" from: "shown"
@ -181,10 +176,6 @@ Rectangle {
easing.type: Easing.InQuad easing.type: Easing.InQuad
} }
NumberAnimation {
properties: "Layout.preferredWidth"
duration: 150
}
} }
@ -197,28 +188,25 @@ Rectangle {
name: "shown" name: "shown"
when: Settings.mobileMode || volumeButton.hovered || volumeSlider.hovered || volumeSlider.pressed when: Settings.mobileMode || volumeButton.hovered || volumeSlider.hovered || volumeSlider.pressed
PropertyChanges {
volumeSlider.implicitWidth: 100
}
PropertyChanges { PropertyChanges {
volumeSlider.opacity: 1 volumeSlider.opacity: 1
volumeSlider.enabled: true
} }
} }
} }
Item {
Layout.fillWidth: true
}
Label { Label {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
text: (!control.mediaLoaded ? "-- " : durationToString(control.positionValue)) + " / " + durationToString(control.duration) text: (!control.mediaLoaded ? "-- " : durationToString(control.positionValue)) + " / " + durationToString(control.duration)
color: palette.text color: palette.text
} }
Item {
Layout.fillWidth: true
}
} }
} }

View file

@ -23,8 +23,6 @@
MxcMediaProxy::MxcMediaProxy(QObject *parent) MxcMediaProxy::MxcMediaProxy(QObject *parent)
: QMediaPlayer(parent) : QMediaPlayer(parent)
{ {
connect(this, &MxcMediaProxy::eventIdChanged, &MxcMediaProxy::startDownload);
connect(this, &MxcMediaProxy::roomChanged, &MxcMediaProxy::startDownload);
connect( connect(
this, &QMediaPlayer::errorOccurred, this, [](QMediaPlayer::Error error, QString errorString) { this, &QMediaPlayer::errorOccurred, this, [](QMediaPlayer::Error error, QString errorString) {
nhlog::ui()->debug("Media player error {} and errorStr {}", nhlog::ui()->debug("Media player error {} and errorStr {}",
@ -36,6 +34,17 @@ MxcMediaProxy::MxcMediaProxy(QObject *parent)
static_cast<int>(status), static_cast<int>(status),
static_cast<int>(this->error())); static_cast<int>(this->error()));
}); });
connect(this, &MxcMediaProxy::playbackStateChanged, [this](QMediaPlayer::PlaybackState status) {
// We only set the output when starting the playback because otherwise the audio device
// lookup takes about 500ms, which causes a lot of stutter...
if (status == QMediaPlayer::PlayingState && !audioOutput()) {
nhlog::ui()->debug("Set audio output");
auto newOut = new QAudioOutput(this);
newOut->setMuted(muted_);
newOut->setVolume(volume_);
setAudioOutput(newOut);
}
});
connect(this, &MxcMediaProxy::metaDataChanged, [this]() { emit orientationChanged(); }); connect(this, &MxcMediaProxy::metaDataChanged, [this]() { emit orientationChanged(); });
connect(ChatPage::instance()->timelineManager()->rooms(), connect(ChatPage::instance()->timelineManager()->rooms(),
@ -55,7 +64,7 @@ MxcMediaProxy::orientation() const
} }
void void
MxcMediaProxy::startDownload() MxcMediaProxy::startDownload(bool onlyCached)
{ {
if (!room_) if (!room_)
return; return;
@ -126,6 +135,9 @@ MxcMediaProxy::startDownload()
} }
} }
if (onlyCached)
return;
http::client()->download(url, http::client()->download(url,
[filename, url, processBuffer](const std::string &data, [filename, url, processBuffer](const std::string &data,
const std::string &, const std::string &,

View file

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <QAudioOutput>
#include <QBuffer> #include <QBuffer>
#include <QMediaPlayer> #include <QMediaPlayer>
#include <QObject> #include <QObject>
@ -26,9 +27,16 @@ class MxcMediaProxy : public QMediaPlayer
Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged) Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged) Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
Q_PROPERTY(int orientation READ orientation NOTIFY orientationChanged) Q_PROPERTY(int orientation READ orientation NOTIFY orientationChanged)
Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(bool muted READ muted WRITE setMuted NOTIFY mutedChanged)
public: public:
MxcMediaProxy(QObject *parent = nullptr); MxcMediaProxy(QObject *parent = nullptr);
~MxcMediaProxy()
{
stop();
this->setSourceDevice(nullptr);
}
bool loaded() const { return buffer.size() > 0; } bool loaded() const { return buffer.size() > 0; }
QString eventId() const { return eventId_; } QString eventId() const { return eventId_; }
@ -45,6 +53,25 @@ public:
} }
int orientation() const; int orientation() const;
float volume() const { return volume_; }
bool muted() const { return muted_; }
void setVolume(float val)
{
volume_ = val;
if (auto output = audioOutput()) {
output->setVolume(val);
}
emit volumeChanged();
}
void setMuted(bool val)
{
muted_ = val;
if (auto output = audioOutput()) {
output->setMuted(val);
}
emit mutedChanged();
}
signals: signals:
void roomChanged(); void roomChanged();
void eventIdChanged(); void eventIdChanged();
@ -52,10 +79,12 @@ signals:
void newBuffer(QUrl, QIODevice *buf); void newBuffer(QUrl, QIODevice *buf);
void orientationChanged(); void orientationChanged();
void videoSurfaceChanged();
private slots: void volumeChanged();
void startDownload(); void mutedChanged();
public slots:
void startDownload(bool onlyCached = false);
private: private:
TimelineModel *room_ = nullptr; TimelineModel *room_ = nullptr;
@ -63,4 +92,6 @@ private:
QString filename_; QString filename_;
QBuffer buffer; QBuffer buffer;
QObject *m_surface = nullptr; QObject *m_surface = nullptr;
float volume_ = 1.f;
bool muted_ = false;
}; };