First commit
There was history before but now there is no more.
This commit is contained in:
commit
8d57bfb1ae
35 changed files with 2231 additions and 0 deletions
150
Video.qml
Normal file
150
Video.qml
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue