fuzbal/Video.qml

151 lines
4.1 KiB
QML
Raw Normal View History

// 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 // dont 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)
}
}
}
}
}