Warning, /system/mycroft-gui/import/qml/AudioPlayer.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 * Copyright 2019 by Aditya Mehra <aix.m@outlook.com>
0003 * Copyright 2019 by Marco Martin <mart@kde.org>
0004 *
0005 * Licensed under the Apache License, Version 2.0 (the "License");
0006 * you may not use this file except in compliance with the License.
0007 * You may obtain a copy of the License at
0008 *
0009 * http://www.apache.org/licenses/LICENSE-2.0
0010 *
0011 * Unless required by applicable law or agreed to in writing, software
0012 * distributed under the License is distributed on an "AS IS" BASIS,
0013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014 * See the License for the specific language governing permissions and
0015 * limitations under the License.
0016 *
0017 */
0018
0019 import QtQuick 2.15
0020 import QtQuick.Controls 2.15 as Controls
0021 import QtQuick.Layouts 1.15
0022 import org.kde.kirigami 2.19 as Kirigami
0023 import Mycroft 1.0 as Mycroft
0024 import QtMultimedia
0025
0026 Item {
0027 id: root
0028
0029 property alias source: player.source
0030 property string status: "stop"
0031 property int switchWidth: Kirigami.Units.gridUnit * 22
0032 property alias thumbnail: albumimg.source
0033 property alias title: songtitle.text
0034 property bool progressBar: true
0035 property bool thumbnailVisible: true
0036 property bool titleVisible: true
0037 property var nextAction
0038 property var previousAction
0039 property alias currentState: player.status
0040 readonly property bool horizontal: width > switchWidth
0041
0042 onEnabledChanged: syncStatusTimer.restart()
0043 onSourceChanged: syncStatusTimer.restart()
0044 Component.onCompleted: syncStatusTimer.restart()
0045
0046 // Sometimes can't be restarted reliably immediately, put it in a timer
0047 onActiveFocusChanged: {
0048 if(activeFocus){
0049 playButton.forceActiveFocus();
0050 }
0051 }
0052
0053 function msToTime(duration) {
0054 var seconds = parseInt((duration/1000)%60);
0055 var minutes = parseInt((duration/(1000*60))%60);
0056
0057 minutes = (minutes < 10) ? "0" + minutes : minutes;
0058 seconds = (seconds < 10) ? "0" + seconds : seconds;
0059
0060 return minutes + ":" + seconds;
0061 }
0062
0063 Timer {
0064 id: syncStatusTimer
0065 interval: 0
0066 onTriggered: {
0067 if (enabled && status == "play") {
0068 player.play();
0069 } else if (status == "stop") {
0070 player.stop();
0071 } else {
0072 player.pause();
0073 }
0074 }
0075 }
0076 MediaPlayer {
0077 id: player
0078 autoPlay: false
0079 readonly property string currentStatus: root.enabled ? root.status : "pause"
0080
0081 onCurrentStatusChanged: {
0082 switch(currentStatus){
0083 case "stop":
0084 player.stop();
0085 break;
0086 case "pause":
0087 player.pause()
0088 break;
0089 case "play":
0090 player.play()
0091 break;
0092 }
0093 }
0094 }
0095
0096
0097 GridLayout {
0098 anchors {
0099 top: root.horizontal ? undefined : parent.top
0100 left: parent.left
0101 right: parent.right
0102 bottom: parent.bottom
0103 }
0104 columns: root.horizontal ? 2 : 1
0105 height: implicitHeight
0106
0107 Image {
0108 id: albumimg
0109 fillMode: Image.PreserveAspectCrop
0110 visible: root.thumbnailVisible ? 1 : 0
0111 enabled: root.thumbnailVisible ? 1 : 0
0112 Layout.preferredWidth: root.horizontal ? Kirigami.Units.gridUnit * 10 : Kirigami.Units.gridUnit * 5
0113 Layout.preferredHeight: root.horizontal ? Kirigami.Units.gridUnit * 10 : Kirigami.Units.gridUnit * 5
0114 Layout.alignment: Qt.AlignHCenter
0115 }
0116
0117 ColumnLayout {
0118 Layout.fillWidth: true
0119 Layout.fillHeight: true
0120 spacing: Kirigami.Units.largeSpacing
0121
0122 Kirigami.Heading {
0123 id: songtitle
0124 text: title
0125 level: root.horizontal ? 1 : 3
0126 Layout.fillWidth: true
0127 elide: Text.ElideRight
0128 font.capitalization: Font.Capitalize
0129 visible: root.titleVisible ? 1 : 0
0130 enabled: root.titleVisible ? 1 : 0
0131 }
0132
0133 RowLayout {
0134 Layout.fillWidth: true
0135 Layout.fillHeight: true
0136 Layout.alignment: root.horizontal ? Qt.AlignLeft : Qt.AlignHCenter
0137 spacing: Kirigami.Units.largeSpacing
0138
0139 Controls.RoundButton {
0140 id: previousButton
0141 Layout.minimumWidth: Kirigami.Units.iconSizes.smallMedium
0142 Layout.minimumHeight: width
0143 Layout.fillWidth: true
0144 Layout.fillHeight: true
0145 Layout.maximumWidth: Kirigami.Units.gridUnit * 3
0146 Layout.maximumHeight: width
0147 focus: false
0148 icon.name: "media-seek-backward"
0149 KeyNavigation.right: playButton
0150 KeyNavigation.down: seekableslider
0151 onClicked: {
0152 triggerGuiEvent(previousAction, {})
0153 }
0154
0155 background: Rectangle {
0156 Kirigami.Theme.colorSet: Kirigami.Theme.Button
0157 radius: width
0158 color: previousButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor
0159 }
0160
0161 Keys.onReturnPressed: {
0162 clicked()
0163 }
0164 }
0165
0166 Controls.RoundButton {
0167 id: playButton
0168 Layout.minimumWidth: Kirigami.Units.iconSizes.medium
0169 Layout.minimumHeight: width
0170 Layout.fillWidth: true
0171 Layout.fillHeight: true
0172 Layout.maximumWidth: Kirigami.Units.gridUnit * 4
0173 Layout.maximumHeight: width
0174 focus: false
0175 icon.name: player.playbackState === MediaPlayer.PlayingState ? "media-playback-pause" : "media-playback-start"
0176 KeyNavigation.left: previousButton
0177 KeyNavigation.right: nextButton
0178 KeyNavigation.down: seekableslider
0179 onClicked: {
0180 player.playbackState === MediaPlayer.PlayingState ? player.pause() : player.play()
0181 }
0182
0183 background: Rectangle {
0184 Kirigami.Theme.colorSet: Kirigami.Theme.Button
0185 radius: width
0186 color: playButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor
0187 }
0188
0189 Keys.onReturnPressed: {
0190 clicked()
0191 }
0192 }
0193
0194 Controls.RoundButton {
0195 id: nextButton
0196 Layout.minimumWidth: Kirigami.Units.iconSizes.smallMedium
0197 Layout.minimumHeight: width
0198 Layout.fillWidth: true
0199 Layout.fillHeight: true
0200 Layout.maximumWidth: Kirigami.Units.gridUnit * 3
0201 Layout.maximumHeight: width
0202 focus: false
0203 icon.name: "media-seek-forward"
0204 KeyNavigation.left: playButton
0205 KeyNavigation.down: seekableslider
0206 onClicked: {
0207 triggerGuiEvent(nextAction, {})
0208 }
0209
0210 background: Rectangle {
0211 Kirigami.Theme.colorSet: Kirigami.Theme.Button
0212 radius: width
0213 color: nextButton.activeFocus ? Kirigami.Theme.highlightColor : Kirigami.Theme.backgroundColor
0214 }
0215
0216 Keys.onReturnPressed: {
0217 clicked()
0218 }
0219 }
0220 }
0221
0222 RowLayout {
0223 spacing: Kirigami.Units.smallSpacing
0224 Layout.fillWidth: true
0225 visible: root.progressBar ? 1 : 0
0226 enabled: root.progressBar ? 1 : 0
0227
0228 Controls.Slider {
0229 id: seekableslider
0230 to: player.duration
0231 Layout.fillWidth: true
0232 property bool sync: false
0233
0234 onValueChanged: {
0235 if (!sync)
0236 player.seek(value)
0237 }
0238
0239 Connections {
0240 target: player
0241 onPositionChanged: {
0242 seekableslider.sync = true
0243 seekableslider.value = player.position
0244 seekableslider.sync = false
0245 }
0246 }
0247
0248 Keys.onLeftPressed: {
0249 var l = 0
0250 l = seekableslider.position - 0.05
0251 seekableslider.value = seekableslider.valueAt(l);
0252 }
0253
0254 Keys.onRightPressed: {
0255 var l = 0
0256 l = seekableslider.position + 0.05
0257 seekableslider.value = seekableslider.valueAt(l);
0258 }
0259 }
0260
0261 Controls.Label {
0262 id: positionLabel
0263 text: msToTime(player.position) + " / " + msToTime(player.duration)
0264 }
0265 }
0266 }
0267 }
0268 }
0269