binding: remove non-binding lightmediascanner detection
[apps/mediaplayer.git] / app / MediaPlayer.qml
1 /*
2  * Copyright (C) 2016 The Qt Company Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 import QtQuick 2.6
18 import QtQuick.Layouts 1.1
19 import QtQuick.Controls 2.0
20 import QtMultimedia 5.6
21 import AGL.Demo.Controls 1.0
22 import MediaPlayer 1.0
23 import 'api' as API
24
25 ApplicationWindow {
26     id: root
27
28     Item {
29         id: bluetooth
30         property bool connected: false
31         property string state
32
33         property string artist
34         property string title
35         property int duration: 0
36         property int position: 0
37         property int pos_offset: 0
38
39         function disableBluetooth() {
40             bluetooth.artist = ''
41             bluetooth.title = ''
42             bluetooth.duration = 0
43             bluetooth.position = 0
44             bluetooth.pos_offset = 0
45             bluetooth.connected = false
46         }
47     }
48
49     API.LightMediaScanner {
50         id: binding
51         url: bindingAddress
52     }
53
54     Connections {
55         target: dbus
56
57         onProcessPlaylistHide: {
58             playlistview.visible = false
59             player.stop()
60         }
61
62         onProcessPlaylistShow: {
63             playlistview.visible = true
64             bluetooth.disableBluetooth()
65         }
66
67         onDisplayBluetoothMetadata: {
68             if (avrcp_artist)
69                 bluetooth.artist = avrcp_artist
70             if (avrcp_title)
71                 bluetooth.title = avrcp_title
72             bluetooth.duration = avrcp_duration
73             bluetooth.pos_offset = 0
74         }
75
76         onUpdatePlayerStatus: {
77             bluetooth.connected = true
78             bluetooth.state = status
79         }
80
81         onUpdatePosition: {
82             slider.value = current_position
83             bluetooth.position = current_position
84         }
85     }
86
87     MediaPlayer {
88         id: player
89         audioRole: MediaPlayer.MusicRole
90         autoLoad: true
91         playlist: playlist
92
93         property bool is_bluetooth: false
94         function time2str(value) {
95             return Qt.formatTime(new Date(value), 'mm:ss')
96         }
97         onPositionChanged: slider.value = player.position
98     }
99
100     Timer {
101         id: timer
102         interval: 250
103         running: (bluetooth.connected && bluetooth.state == "playing")
104         repeat: true
105         onTriggered: {
106             bluetooth.position = dbus.getCurrentPosition() - bluetooth.pos_offset
107             slider.value = bluetooth.position
108         }
109     }
110
111     Playlist {
112         id: playlist
113         playbackMode: random.checked ? Playlist.Random : loop.checked ? Playlist.Loop : Playlist.Sequential
114     }
115
116
117     ColumnLayout {
118         anchors.fill: parent
119         Item {
120             Layout.fillWidth: true
121             Layout.fillHeight: true
122             Layout.preferredHeight: 1080
123             clip: true
124             Image {
125                 id: albumart
126                 anchors.left: parent.left
127                 anchors.right: parent.right
128                 anchors.bottom: parent.bottom
129                 height: sourceSize.height * width / sourceSize.width
130                 fillMode: Image.PreserveAspectCrop
131                 source: player.metaData.coverArtImage ? player.metaData.coverArtImage : ''
132                 visible: bluetooth.connected == false
133             }
134
135             Item {
136                 anchors.left: parent.left
137                 anchors.right: parent.right
138                 anchors.bottom: parent.bottom
139                 height :307
140                 Rectangle {
141                     anchors.fill: parent
142                     color: 'black'
143                     opacity: 0.75
144                 }
145
146                 ColumnLayout {
147                     anchors.fill: parent
148                     anchors.margins: root.width * 0.02
149                     Item {
150                         Layout.fillWidth: true
151                         Layout.fillHeight: true
152                         Row {
153                             spacing: 20
154                             ToggleButton {
155                                 id: random
156                                 visible: bluetooth.connected == false
157                                 offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg'
158                                 onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg'
159                             }
160                             ToggleButton {
161                                 id: loop
162                                 visible: bluetooth.connected == false
163                                 offImage: './images/AGL_MediaPlayer_Loop_Inactive.svg'
164                                 onImage: './images/AGL_MediaPlayer_Loop_Active.svg'
165                             }
166                         }
167                         ColumnLayout {
168                             anchors.fill: parent
169                             Label {
170                                 id: title
171                                 Layout.alignment: Layout.Center
172                                 text: bluetooth.title ? bluetooth.title : (player.metaData.title ? player.metaData.title : '')
173                                 horizontalAlignment: Label.AlignHCenter
174                                 verticalAlignment: Label.AlignVCenter
175                             }
176                             Label {
177                                 Layout.alignment: Layout.Center
178                                 text: bluetooth.artist ? bluetooth.artist : (player.metaData.contributingArtist ? player.metaData.contributingArtist : '')
179                                 horizontalAlignment: Label.AlignHCenter
180                                 verticalAlignment: Label.AlignVCenter
181                                 font.pixelSize: title.font.pixelSize * 0.6
182                             }
183                         }
184                     }
185                     Slider {
186                         id: slider
187                         Layout.fillWidth: true
188                         to: bluetooth.connected ? bluetooth.duration : player.duration
189                         enabled: bluetooth.connected == false
190                         function getPosition() {
191                             if (bluetooth.connected && bluetooth.position) {
192                                 return player.time2str(bluetooth.position)
193                             }
194                             return player.time2str(player.position)
195                         }
196                         Label {
197                             id: position
198                             anchors.left: parent.left
199                             anchors.bottom: parent.top
200                             font.pixelSize: 32
201                             text: slider.getPosition()
202                         }
203                         Label {
204                             id: duration
205                             anchors.right: parent.right
206                             anchors.bottom: parent.top
207                             font.pixelSize: 32
208                             text: bluetooth.connected ? player.time2str(bluetooth.duration) : player.time2str(player.duration)
209                         }
210                         onPressedChanged: player.seek(value)
211                     }
212                     RowLayout {
213                         Layout.fillHeight: true
214 //                        Image {
215 //                            source: './images/AGL_MediaPlayer_Playlist_Inactive.svg'
216 //                        }
217 //                        Image {
218 //                            source: './images/AGL_MediaPlayer_CD_Inactive.svg'
219 //                        }
220                         Item { Layout.fillWidth: true }
221                         ImageButton {
222                             id: previous
223                             offImage: './images/AGL_MediaPlayer_BackArrow.svg'
224                             onClicked: {
225                                 if (bluetooth.connected) {
226                                     bluetooth.pos_offset = dbus.getCurrentPosition()
227                                     dbus.processQMLEvent("Previous")
228                                 } else {
229                                     playlist.previous()
230                                 }
231                             }
232                         }
233                         ImageButton {
234                             id: play
235                             offImage: './images/AGL_MediaPlayer_Player_Play.svg'
236                             onClicked: {
237                                 if (bluetooth.connected) {
238                                     dbus.processQMLEvent("Play")
239                                 } else {
240                                     player.play()
241                                 }
242                             }
243                             states: [
244                                 State {
245                                     when: player.playbackState === MediaPlayer.PlayingState
246                                     PropertyChanges {
247                                         target: play
248                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
249                                         onClicked: player.pause()
250                                     }
251                                 },
252                                 State {
253                                     when: bluetooth.connected && bluetooth.state == "playing"
254                                     PropertyChanges {
255                                         target: play
256                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
257                                         onClicked: dbus.processQMLEvent("Pause")
258                                     }
259                                 }
260
261                             ]
262                         }
263                         ImageButton {
264                             id: forward
265                             offImage: './images/AGL_MediaPlayer_ForwardArrow.svg'
266                             onClicked: {
267                                 if (bluetooth.connected) {
268                                     dbus.processQMLEvent("Next")
269                                 } else {
270                                     playlist.next()
271                                 }
272                             }
273                         }
274
275                         Item { Layout.fillWidth: true }
276 //                        Image {
277 //                            source: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg'
278 //                        }
279 //                        Image {
280 //                            source: './images/AGL_MediaPlayer_Radio_Inactive.svg'
281 //                        }
282                     }
283                 }
284             }
285         }
286         Item {
287             Layout.fillWidth: true
288             Layout.fillHeight: true
289             Layout.preferredHeight: 407
290
291             PlaylistWithMetadata {
292                 id: playlistmodel
293                 source: playlist
294             }
295
296             ListView {
297                 anchors.fill: parent
298                 id: playlistview
299                 clip: true
300                 header: Label {
301                     x: 50
302                     text: 'PLAYLIST'
303                     opacity: 0.5
304                 }
305                 model: playlistmodel
306                 currentIndex: playlist.currentIndex
307
308                 delegate: MouseArea {
309                     id: delegate
310                     width: ListView.view.width
311                     height: ListView.view.height / 4
312                     RowLayout {
313                         anchors.fill: parent
314                         anchors.leftMargin: 50
315                         anchors.rightMargin: 50
316                         Image {
317                             source: model.coverArt
318                             fillMode: Image.PreserveAspectFit
319                             Layout.preferredWidth: delegate.height
320                             Layout.preferredHeight: delegate.height
321                         }
322                         ColumnLayout {
323                             Layout.fillWidth: true
324                             Label {
325                                 Layout.fillWidth: true
326                                 text: model.title
327                             }
328                             Label {
329                                 Layout.fillWidth: true
330                                 text: model.artist
331                                 color: '#66FF99'
332                                 font.pixelSize: 32
333                             }
334                         }
335                         Label {
336                             text: player.time2str(model.duration)
337                             color: '#66FF99'
338                             font.pixelSize: 32
339                         }
340                     }
341                     onClicked: {
342                         playlist.currentIndex = model.index
343                         player.play()
344                     }
345                 }
346
347                 highlight: Rectangle {
348                     color: 'white'
349                     opacity: 0.25
350                 }
351             }
352         }
353     }
354 }