FluentUI/src/controls/FluMediaPlayer.qml

218 lines
5.4 KiB
QML
Raw Normal View History

2023-03-25 13:35:21 +08:00
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtMultimedia 5.15
import FluentUI 1.0
2023-03-24 15:21:47 +08:00
2023-03-25 20:45:33 +08:00
Rectangle {
property url source
2023-03-27 18:24:35 +08:00
property bool showControl: false
property real volume: 30
2023-03-24 18:25:13 +08:00
id:control
width: 480
height: 270
2023-03-25 20:45:33 +08:00
color: FluColors.Black
clip: true
2023-03-24 18:25:13 +08:00
2023-03-25 20:45:33 +08:00
MouseArea{
2023-03-24 18:25:13 +08:00
anchors.fill: parent
2023-03-25 20:45:33 +08:00
onClicked: {
showControl = !showControl
}
2023-03-24 18:25:13 +08:00
}
2023-03-24 15:21:47 +08:00
MediaPlayer {
id: mediaplayer
2023-03-24 18:25:13 +08:00
property bool autoSeek:true
2023-03-25 13:35:21 +08:00
autoPlay: true
2023-03-24 18:25:13 +08:00
source: control.source
2023-03-25 13:35:21 +08:00
onError: {
console.debug(error)
2023-03-24 18:25:13 +08:00
}
onPositionChanged: {
if(autoSeek){
slider.seek(mediaplayer.position*slider.maxValue/mediaplayer.duration)
}
}
2023-03-25 13:35:21 +08:00
onStatusChanged: {
if(status===6){
2023-03-24 18:25:13 +08:00
slider.maxValue = mediaplayer.duration
2023-03-27 18:24:35 +08:00
showControl = true
2023-03-24 18:25:13 +08:00
}
}
2023-03-24 15:21:47 +08:00
}
2023-03-24 18:25:13 +08:00
onSourceChanged: {
2023-03-25 20:45:33 +08:00
slider.seek(0)
2023-03-24 18:25:13 +08:00
}
2023-03-24 15:21:47 +08:00
VideoOutput {
anchors.fill: parent
2023-03-25 13:35:21 +08:00
source: mediaplayer
2023-03-24 15:21:47 +08:00
}
2023-03-24 18:25:13 +08:00
Item{
height: 100
2023-03-25 20:45:33 +08:00
y:showControl ? control.height - 110 : control.height
2023-03-24 18:25:13 +08:00
anchors{
left: parent.left
right: parent.right
leftMargin: 10
rightMargin: 10
2023-03-25 20:45:33 +08:00
}
MouseArea{
anchors.fill: parent
}
Behavior on y{
NumberAnimation{
duration: 150
}
2023-03-24 18:25:13 +08:00
}
Rectangle{
anchors.fill: parent
2023-03-28 21:37:10 +08:00
color:FluTheme.dark ? Qt.rgba(45/255,45/255,45/255,0.97) : Qt.rgba(237/255,237/255,237/255,0.97)
2023-03-24 18:25:13 +08:00
radius: 5
}
FluSlider{
id:slider
size:parent.width-20
y:20
anchors.horizontalCenter: parent.horizontalCenter
enableTip:false
onPressed: {
mediaplayer.autoSeek = false
2023-03-25 23:28:48 +08:00
mediaplayer.pause()
2023-03-24 18:25:13 +08:00
}
2023-03-27 18:24:35 +08:00
value:0
2023-03-24 18:25:13 +08:00
onReleased: {
mediaplayer.autoSeek = true
2023-03-25 23:28:48 +08:00
mediaplayer.play()
2023-03-24 18:25:13 +08:00
}
2023-03-25 23:28:48 +08:00
onValueChanged: {
if(mediaplayer.autoSeek == false){
mediaplayer.seek(value*mediaplayer.duration/slider.maxValue)
}
}
2023-03-25 20:45:33 +08:00
onLineClickFunc:function(val){
mediaplayer.seek(val*mediaplayer.duration/slider.maxValue)
}
2023-03-24 15:21:47 +08:00
}
2023-03-24 18:25:13 +08:00
FluText{
id:start_time
anchors{
top: slider.bottom
topMargin: 10
left: slider.left
}
text: formatDuration(slider.value*mediaplayer.duration/slider.maxValue)
}
FluText{
id:end_time
anchors{
top: slider.bottom
right: slider.right
topMargin: 10
}
text: formatDuration(mediaplayer.duration)
}
2023-03-27 18:24:35 +08:00
Row{
spacing: 10
2023-03-24 18:25:13 +08:00
anchors{
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: 10
}
2023-03-27 18:24:35 +08:00
FluIconButton{
iconSize: 17
iconSource: FluentIcons.SkipBack10
onClicked: {
mediaplayer.seek(Math.max(mediaplayer.position-10*1000,0))
}
}
FluIconButton{
iconSize: 15
iconSource: mediaplayer.playbackState === Audio.PlayingState ? FluentIcons.Pause : FluentIcons.Play
onClicked: {
if(mediaplayer.playbackState === Audio.PlayingState){
mediaplayer.pause()
}else{
mediaplayer.play()
}
}
}
FluIconButton{
iconSize: 17
iconSource: FluentIcons.SkipForward30
onClicked: {
mediaplayer.seek(Math.min(mediaplayer.position+30*1000,mediaplayer.duration))
2023-03-24 18:25:13 +08:00
}
}
}
2023-03-27 18:24:35 +08:00
2023-03-25 23:28:48 +08:00
FluIconButton{
2023-03-27 18:24:35 +08:00
id:btn_volume
2023-03-25 23:28:48 +08:00
iconSize: 17
iconSource: mediaplayer.volume ? FluentIcons.Volume : FluentIcons.Mute
anchors{
left: parent.left
leftMargin: 5
bottom: parent.bottom
bottomMargin: 10
}
onClicked: {
mediaplayer.volume = !mediaplayer.volume
}
}
2023-03-27 18:24:35 +08:00
FluSlider{
id:slider_volume
size: 80
dotSize: 20
value:30
anchors{
left:btn_volume.right
verticalCenter: btn_volume.verticalCenter
leftMargin: 10
}
onValueChanged:{
mediaplayer.volume = value/100
}
}
2023-03-25 23:28:48 +08:00
2023-03-24 18:25:13 +08:00
}
function formatDuration(duration) {
const seconds = Math.floor(duration / 1000);
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const remainingSeconds = seconds % 60;
return `${pad(hours)}:${pad(minutes)}:${pad(remainingSeconds)}`;
2023-03-24 15:21:47 +08:00
}
2023-03-24 18:25:13 +08:00
function pad(value) {
return value.toString().padStart(2, '0');
}
2023-03-25 20:45:33 +08:00
function pause(){
mediaplayer.pause()
}
2023-03-24 18:25:13 +08:00
2023-03-25 20:45:33 +08:00
function play(){
mediaplayer.play()
}
2023-03-24 18:25:13 +08:00
2023-03-24 15:21:47 +08:00
}