summaryrefslogtreecommitdiff
path: root/Video.qml
diff options
context:
space:
mode:
authorTimotej Lazar <timotej.lazar@araneo.si>2021-06-14 19:09:53 +0200
committerTimotej Lazar <timotej.lazar@araneo.si>2021-06-14 19:13:14 +0200
commit8d57bfb1aef3b71557bc408154ee028751fd688e (patch)
tree22ee6eaa22a3cfc7dfd4f938be16a6e28d7eaf1f /Video.qml
First commit
There was history before but now there is no more.
Diffstat (limited to 'Video.qml')
-rw-r--r--Video.qml150
1 files changed, 150 insertions, 0 deletions
diff --git a/Video.qml b/Video.qml
new file mode 100644
index 0000000..f63a7ce
--- /dev/null
+++ b/Video.qml
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: Unlicense
+
+import QtQuick 2.14
+import QtQuick.Controls 2.13
+import QtQuick.Layouts 1.6
+import QtMultimedia 5.11
+
+Page {
+ property bool loaded:
+ media.status !== MediaPlayer.NoMedia &&
+ media.status !== MediaPlayer.InvalidMedia &&
+ media.status !== MediaPlayer.UnknownStatus
+ property alias source: media.source
+ property alias time: media.position
+
+ function pause(yes) {
+ if (yes === undefined)
+ yes = media.playbackState === MediaPlayer.PlayingState
+ if (yes)
+ media.pause()
+ else
+ media.play()
+ }
+
+ function seek(offset, relative) {
+ if (relative)
+ offset += media.position
+ media.seek(offset)
+ }
+
+ Keys.onPressed: {
+ switch (event.key) {
+ // (Un)pause video.
+ case Qt.Key_Space:
+ pause()
+ break
+ // Seek video.
+ case Qt.Key_Left:
+ seek(-500, true)
+ break
+ case Qt.Key_Right:
+ seek(500, true)
+ break
+ // Change playback rate.
+ case Qt.Key_Equal:
+ rate.reset()
+ break
+ case Qt.Key_Comma:
+ rate.decrease()
+ break
+ case Qt.Key_Period:
+ rate.increase()
+ break
+ default:
+ return // don’t accept the event
+ }
+ event.accepted = true
+ }
+
+ // Video.
+ ColumnLayout {
+ spacing: 0
+ anchors.fill: parent
+
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ color: 'black'
+ clip: true
+
+ VideoOutput {
+ anchors.fill: parent
+ fillMode: VideoOutput.PreserveAspectFit
+ source: media
+
+ transform: Scale {
+ id: zoom
+ property real scale: 1.0
+ xScale: scale
+ yScale: scale
+ origin.x: wheel.point.position.x
+ origin.y: wheel.point.position.y
+ }
+
+ MediaPlayer {
+ id: media
+ notifyInterval: 100
+ playbackRate: Number.fromLocaleString(rate.displayText)
+ volume: QtMultimedia.convertVolume(
+ volume.value,
+ QtMultimedia.LogarithmicVolumeScale,
+ QtMultimedia.LinearVolumeScale)
+ }
+
+ TapHandler {
+ acceptedButtons: Qt.RightButton
+ onTapped: pause()
+ }
+
+ WheelHandler {
+ id: wheel
+ onWheel: zoom.scale = Math.max(1.0, (event.angleDelta.y > 0 ? 1.1 : 0.9) * zoom.scale)
+ }
+ }
+ }
+
+ // Video controls.
+ RowLayout {
+ Layout.margins: 5
+
+ Button {
+ icon.name: 'media-playback-pause'
+ implicitWidth: implicitHeight
+ checkable: true
+ checked: media.playbackState !== MediaPlayer.PlayingState
+ onClicked: checked ? media.pause() : media.play()
+ }
+ Label { text: new Date(media.position).toISOString().substr(12, 9) }
+ Slider {
+ Layout.fillWidth: true
+ from: 0; to: media.duration
+ value: media.position
+ onMoved: media.seek(value)
+ }
+ Label { text: new Date(media.duration).toISOString().substr(12, 7) }
+
+ Volume {
+ id: volume
+ muted: media.muted
+ focusPolicy: Qt.NoFocus
+ }
+
+ // Playback speed control.
+ SpinBox {
+ id: rate
+ implicitWidth: 80
+ focusPolicy: Qt.NoFocus
+
+ from: 25; to: 250; stepSize: 25
+ value: 100
+
+ function reset() { value = 100 }
+
+ textFromValue: function (value, locale) {
+ return (value / 100).toLocaleString(locale, 'f', 2)
+ }
+ }
+ }
+ }
+}