summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--resources/qml/delegates/PlayableMediaMessage.qml18
-rw-r--r--resources/qml/ui/media/MediaControls.qml28
-rw-r--r--src/ui/MxcMediaProxy.cpp18
-rw-r--r--src/ui/MxcMediaProxy.h37
4 files changed, 67 insertions, 34 deletions
diff --git a/resources/qml/delegates/PlayableMediaMessage.qml b/resources/qml/delegates/PlayableMediaMessage.qml
index 7c035922..e948df02 100644
--- a/resources/qml/delegates/PlayableMediaMessage.qml
+++ b/resources/qml/delegates/PlayableMediaMessage.qml
@@ -24,23 +24,24 @@ Item {
     property int tempWidth: originalWidth < 1? 400: originalWidth
     implicitWidth: type == MtxEvent.VideoMessage ? Math.round(tempWidth*Math.min((timelineView.height/divisor)/(tempWidth*proportionalHeight), 1)) : 500
     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
 
     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 {
         id: mxcmedia
 
         // TODO: Show error in overlay or so?
         roomm: room
-        // FIXME: This takes 500ms on my device, why and how can we avoid that?
-        audioOutput: AudioOutput {
-            muted: mediaControls.muted
-            volume: mediaControls.desiredVolume
-        }
+        eventId: content.eventId
         videoOutput: videoOutput
+
+        muted: mediaControls.muted
+        volume: mediaControls.desiredVolume
     }
 
     Rectangle {
@@ -56,6 +57,7 @@ Item {
 
         Image {
             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
             asynchronous: true
             fillMode: Image.PreserveAspectFit
@@ -85,7 +87,7 @@ Item {
             mediaState: mxcmedia.playbackState
             onPositionChanged: mxcmedia.position = position
             onPlayPauseActivated: mxcmedia.playbackState == MediaPlayer.PlayingState ? mxcmedia.pause() : mxcmedia.play()
-            onLoadActivated: mxcmedia.eventId = eventId
+            onLoadActivated: mxcmedia.startDownload()
         }
     }
 
diff --git a/resources/qml/ui/media/MediaControls.qml b/resources/qml/ui/media/MediaControls.qml
index 0519a194..f4373908 100644
--- a/resources/qml/ui/media/MediaControls.qml
+++ b/resources/qml/ui/media/MediaControls.qml
@@ -71,7 +71,7 @@ Rectangle {
         spacing: 0
         anchors.bottom: control.bottom
         anchors.left: control.left
-        anchors.right: control.right
+        width: Math.max(implicitWidth, control.width)
 
         NhekoSlider {
             Layout.fillWidth: true
@@ -134,8 +134,9 @@ Rectangle {
 
                 state: ""
                 Layout.alignment: Qt.AlignLeft
-                Layout.preferredWidth: 0
+                Layout.preferredWidth: 100
                 opacity: 0
+                enabled: false
                 orientation: Qt.Horizontal
                 value: 1
                 onDesiredVolumeChanged: {
@@ -158,12 +159,6 @@ Rectangle {
                             }
 
                         }
-
-                        NumberAnimation {
-                            properties: "Layout.preferredWidth"
-                            duration: 150
-                        }
-
                     },
                     Transition {
                         from: "shown"
@@ -181,10 +176,6 @@ Rectangle {
                                     easing.type: Easing.InQuad
                                 }
 
-                                NumberAnimation {
-                                    properties: "Layout.preferredWidth"
-                                    duration: 150
-                                }
 
                             }
 
@@ -198,27 +189,24 @@ Rectangle {
                     when: Settings.mobileMode || volumeButton.hovered || volumeSlider.hovered || volumeSlider.pressed
 
                     PropertyChanges {
-                        volumeSlider.implicitWidth: 100
-                    }
-
-                    PropertyChanges {
                         volumeSlider.opacity: 1
+                        volumeSlider.enabled: true
                     }
 
                 }
 
             }
 
+            Item {
+                Layout.fillWidth: true
+            }
+
             Label {
                 Layout.alignment: Qt.AlignRight
                 text: (!control.mediaLoaded ? "-- " : durationToString(control.positionValue)) + " / " + durationToString(control.duration)
                 color: palette.text
             }
 
-            Item {
-                Layout.fillWidth: true
-            }
-
         }
 
     }
diff --git a/src/ui/MxcMediaProxy.cpp b/src/ui/MxcMediaProxy.cpp
index 5fae0654..3d486f6a 100644
--- a/src/ui/MxcMediaProxy.cpp
+++ b/src/ui/MxcMediaProxy.cpp
@@ -23,8 +23,6 @@
 MxcMediaProxy::MxcMediaProxy(QObject *parent)
   : QMediaPlayer(parent)
 {
-    connect(this, &MxcMediaProxy::eventIdChanged, &MxcMediaProxy::startDownload);
-    connect(this, &MxcMediaProxy::roomChanged, &MxcMediaProxy::startDownload);
     connect(
       this, &QMediaPlayer::errorOccurred, this, [](QMediaPlayer::Error error, QString errorString) {
           nhlog::ui()->debug("Media player error {} and errorStr {}",
@@ -36,6 +34,17 @@ MxcMediaProxy::MxcMediaProxy(QObject *parent)
                           static_cast<int>(status),
                           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(ChatPage::instance()->timelineManager()->rooms(),
@@ -55,7 +64,7 @@ MxcMediaProxy::orientation() const
 }
 
 void
-MxcMediaProxy::startDownload()
+MxcMediaProxy::startDownload(bool onlyCached)
 {
     if (!room_)
         return;
@@ -126,6 +135,9 @@ MxcMediaProxy::startDownload()
         }
     }
 
+    if (onlyCached)
+        return;
+
     http::client()->download(url,
                              [filename, url, processBuffer](const std::string &data,
                                                             const std::string &,
diff --git a/src/ui/MxcMediaProxy.h b/src/ui/MxcMediaProxy.h
index 64c61c4f..2e8b2fa1 100644
--- a/src/ui/MxcMediaProxy.h
+++ b/src/ui/MxcMediaProxy.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <QAudioOutput>
 #include <QBuffer>
 #include <QMediaPlayer>
 #include <QObject>
@@ -26,9 +27,16 @@ class MxcMediaProxy : public QMediaPlayer
     Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
     Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
     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:
     MxcMediaProxy(QObject *parent = nullptr);
+    ~MxcMediaProxy()
+    {
+        stop();
+        this->setSourceDevice(nullptr);
+    }
 
     bool loaded() const { return buffer.size() > 0; }
     QString eventId() const { return eventId_; }
@@ -45,6 +53,25 @@ public:
     }
     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:
     void roomChanged();
     void eventIdChanged();
@@ -52,10 +79,12 @@ signals:
     void newBuffer(QUrl, QIODevice *buf);
 
     void orientationChanged();
-    void videoSurfaceChanged();
 
-private slots:
-    void startDownload();
+    void volumeChanged();
+    void mutedChanged();
+
+public slots:
+    void startDownload(bool onlyCached = false);
 
 private:
     TimelineModel *room_ = nullptr;
@@ -63,4 +92,6 @@ private:
     QString filename_;
     QBuffer buffer;
     QObject *m_surface = nullptr;
+    float volume_      = 1.f;
+    bool muted_        = false;
 };