Improve output of multiple screen resolution
[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 AGL.Demo.Controls 1.0
21
22 ApplicationWindow {
23     id: root
24
25     width: container.width * container.scale
26     height: container.height * container.scale
27
28     Item {
29         id: player
30
31         property string title: ""
32         property string album: ""
33         property string artist: ""
34
35         property int duration: 0
36         property int position: 0
37
38         property string cover_art: ""
39         property string status: "stopped"
40
41         function time2str(value) {
42             return Qt.formatTime(new Date(value), 'mm:ss')
43         }
44     }
45
46     Item {
47         id: bluetooth
48
49         property string deviceAddress: ""
50         property bool connected: false
51         property bool av_connected: false
52
53         property int position: 0
54         property int duration: 0
55
56         property string artist: ""
57         property string title: ""
58         property string state: "stopped"
59
60         // AVRCP Target UUID
61         property string avrcp_uuid: "0000110e-0000-1000-8000-00805f9b34fb"
62
63         function connect_profiles() {
64             var address = bluetooth.deviceAddress;
65             bluetooth_connection.connect(address, "a2dp")
66             bluetooth_connection.connect(address, "avrcp")
67         }
68
69         function disconnect_profiles() {
70             var address = bluetooth.deviceAddress;
71             bluetooth_connection.disconnect(address, "a2dp")
72             bluetooth_connection.disconnect(address, "avrcp")
73         }
74
75         function set_avrcp_controls(cmd) {
76             bluetooth_connection.set_avrcp_controls(bluetooth.deviceAddress, cmd)
77         }
78     }
79
80     Connections {
81         target: bluetooth_connection
82
83         onDeviceListEvent: {
84             var address = ""
85             for (var i = 0; i < data.list.length; i++) {
86                 var item = data.list[i]
87                 if (item.Connected == "True" && item.UUIDs.indexOf(bluetooth.avrcp_uuid) >= 0) {
88                     address = item.Address
89
90                     bluetooth.connected = true
91                     mediaplayer.pause()
92
93                     //NOTE: This hack is here for when MediaPlayer is started
94                     //      with an existing connection.
95                     bluetooth.av_connected = item.AVPConnected == "True" 
96                 }
97             }
98             if (!address)
99                 bluetooth.connected = false
100             else
101                 bluetooth.deviceAddress = address
102         }
103
104         onDeviceUpdatedEvent: {
105             var metadata = data.Metadata
106
107             if (data.Connected == "False")
108                 return
109
110             if (!bluetooth.av_connected && data.AVPConnected == "True") {
111                 mediaplayer.pause()
112                 player.status = "stopped"
113             }
114
115             bluetooth.connected = data.Connected == "True"
116             bluetooth.av_connected = data.AVPConnected == "True"
117             bluetooth.deviceAddress = data.Address
118
119             if ('Position' in metadata)
120                 bluetooth.position = metadata.Position
121
122             if ('Duration' in metadata)
123                 bluetooth.duration = metadata.Duration
124
125             if ('Status' in metadata)
126                 bluetooth.state = metadata.Status
127
128             if ('Artist' in metadata)
129                 bluetooth.artist = metadata.Artist
130
131             if ('Title' in metadata)
132                 bluetooth.title = metadata.Title
133         }
134     }
135
136     Connections {
137         target: mediaplayer
138
139         onMetadataChanged: {
140             player.title = metadata.title
141             player.album = metadata.album
142             player.artist = metadata.artist
143
144             if (metadata.duration) {
145                 player.duration = metadata.duration
146             }
147
148             if (metadata.position) {
149                 player.position = metadata.position
150             }
151
152             if (metadata.status) {
153                 player.status = metadata.status
154             }
155
156             if (metadata.image) {
157                 player.cover_art = metadata.image
158             }
159
160             playlistview.currentIndex = metadata.index
161         }
162     }
163
164     Timer {
165         id: timer
166         interval: 250
167         running: (bluetooth.av_connected && bluetooth.state == "playing")
168         repeat: true
169         onTriggered: {
170             bluetooth.position = bluetooth.position + 250
171         }
172     }
173
174     Item {
175         id: container
176         anchors.centerIn: parent
177         width: 1080
178         height: 1487
179         scale: screenInfo.scale_factor()
180
181     ColumnLayout {
182         anchors.fill: parent
183         Item {
184             Layout.fillWidth: true
185             Layout.fillHeight: true
186             Layout.preferredHeight: 1080
187             clip: true
188             Image {
189                 id: albumart
190                 anchors.left: parent.left
191                 anchors.right: parent.right
192                 anchors.bottom: parent.bottom
193                 height: sourceSize.height * width / sourceSize.width
194                 fillMode: Image.PreserveAspectCrop
195                 source: player.cover_art ? player.cover_art : ''
196                 visible: bluetooth.av_connected == false
197             }
198
199             Item {
200                 anchors.left: parent.left
201                 anchors.right: parent.right
202                 anchors.bottom: parent.bottom
203                 height :307
204                 Rectangle {
205                     anchors.fill: parent
206                     color: 'black'
207                     opacity: 0.75
208                 }
209
210                 ColumnLayout {
211                     anchors.fill: parent
212                     anchors.margins: root.width * 0.02
213                     Item {
214                         Layout.fillWidth: true
215                         Layout.fillHeight: true
216                         Row {
217                             spacing: 20
218                             //ToggleButton {
219                             //    id: random
220                             //    visible: bluetooth.connected == false
221                             //    offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg'
222                             //    onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg'
223                             //}
224                             ToggleButton {
225                                 id: loop
226                                 visible: bluetooth.connected == false
227                                 //checked: player.loop_state
228                                 offImage: './images/AGL_MediaPlayer_Loop_Inactive.svg'
229                                 onImage: './images/AGL_MediaPlayer_Loop_Active.svg'
230                                 onClicked: { mediaplayer.loop(checked) }
231                             }
232                         }
233                         ColumnLayout {
234                             anchors.fill: parent
235                             Label {
236                                 id: title
237                                 Layout.alignment: Layout.Center
238                                 text: bluetooth.av_connected ? bluetooth.title : (player.title ? player.title : '')
239                                 horizontalAlignment: Label.AlignHCenter
240                                 verticalAlignment: Label.AlignVCenter
241                             }
242                             Label {
243                                 Layout.alignment: Layout.Center
244                                 text: bluetooth.av_connected ? bluetooth.artist : (player.artist ? player.artist : '')
245                                 horizontalAlignment: Label.AlignHCenter
246                                 verticalAlignment: Label.AlignVCenter
247                                 font.pixelSize: title.font.pixelSize * 0.6
248                             }
249                         }
250                     }
251                     Slider {
252                         id: slider
253                         Layout.fillWidth: true
254                         to: bluetooth.av_connected ? bluetooth.duration : player.duration
255                         enabled: bluetooth.av_connected == false
256                         value: bluetooth.av_connected ? bluetooth.position : player.position
257                         function getPosition() {
258                             if (bluetooth.av_connected) {
259                                 return player.time2str(bluetooth.position)
260                             }
261                             return player.time2str(player.position)
262                         }
263                         Label {
264                             id: position
265                             anchors.left: parent.left
266                             anchors.bottom: parent.top
267                             font.pixelSize: 32
268                             text: slider.getPosition()
269                         }
270                         Label {
271                             id: duration
272                             anchors.right: parent.right
273                             anchors.bottom: parent.top
274                             font.pixelSize: 32
275                             text: bluetooth.av_connected ? player.time2str(bluetooth.duration) : player.time2str(player.duration)
276                         }
277                         onPressedChanged: mediaplayer.seek(value)
278                     }
279                     RowLayout {
280                         Layout.fillHeight: true
281 //                        Image {
282 //                            source: './images/AGL_MediaPlayer_Playlist_Inactive.svg'
283 //                        }
284 //                        Image {
285 //                            source: './images/AGL_MediaPlayer_CD_Inactive.svg'
286 //                        }
287                         Item { Layout.fillWidth: true }
288                         ImageButton {
289                             id: previous
290                             offImage: './images/AGL_MediaPlayer_BackArrow.svg'
291                             onClicked: {
292                                 if (bluetooth.av_connected) {
293                                     bluetooth.set_avrcp_controls("Previous")
294                                     bluetooth.position = 0
295                                 } else {
296                                     mediaplayer.previous()
297                                 }
298                             }
299                         }
300                         ImageButton {
301                             id: play
302                             states: [
303                                 State {
304                                     when: !bluetooth.av_connected && player.status == "playing"
305                                     PropertyChanges {
306                                         target: play
307                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
308                                         onClicked: {
309                                             player.status = "stopped"
310                                             mediaplayer.pause()
311                                         }
312                                     }
313                                 },
314                                 State {
315                                     when: bluetooth.av_connected && bluetooth.state == "playing"
316                                     PropertyChanges {
317                                         target: play
318                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
319                                         onClicked: bluetooth.set_avrcp_controls("Pause")
320                                     }
321                                 },
322                                 State {
323                                     when: !bluetooth.av_connected && player.status != "playing"
324                                     PropertyChanges {
325                                         target: play
326                                         offImage: './images/AGL_MediaPlayer_Player_Play.svg'
327                                         onClicked: mediaplayer.play()
328                                     }
329                                 },
330                                 State {
331                                     when: bluetooth.av_connected && bluetooth.state != "playing"
332                                     PropertyChanges {
333                                         target: play
334                                         offImage: './images/AGL_MediaPlayer_Player_Play.svg'
335                                         onClicked: bluetooth.set_avrcp_controls("Play")
336                                     }
337                                 }
338                             ]
339                         }
340                         ImageButton {
341                             id: forward
342                             offImage: './images/AGL_MediaPlayer_ForwardArrow.svg'
343                             onClicked: {
344                                 if (bluetooth.av_connected) {
345                                     bluetooth.set_avrcp_controls("Next")
346                                 } else {
347                                     mediaplayer.next()
348                                 }
349                             }
350                         }
351
352                         Item { Layout.fillWidth: true }
353  
354                         ToggleButton {
355                               visible: bluetooth.connected
356                               checked: bluetooth.av_connected
357                               offImage: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg'
358                               onImage: './images/AGL_MediaPlayer_Bluetooth_Active.svg'
359
360                               onClicked: {
361                                   if (bluetooth.av_connected) {
362                                       bluetooth.disconnect_profiles()
363                                   } else {
364                                       bluetooth.connect_profiles()
365                                   }
366                               }
367                         }
368                     }
369                 }
370             }
371         }
372         Item {
373             Layout.fillWidth: true
374             Layout.fillHeight: true
375             Layout.preferredHeight: 407
376
377             ListView {
378                 anchors.fill: parent
379                 id: playlistview
380                 visible: bluetooth.av_connected == false
381                 clip: true
382                 header: Label {
383                     x: 50
384                     text: 'PLAYLIST'
385                     opacity: 0.5
386                 }
387                 model: MediaplayerModel
388                 currentIndex: -1
389
390                 delegate: MouseArea {
391                     id: delegate
392                     width: ListView.view.width
393                     height: ListView.view.height / 4
394                     RowLayout {
395                         anchors.fill: parent
396                         anchors.leftMargin: 50
397                         anchors.rightMargin: 50
398                         ColumnLayout {
399                             Layout.fillWidth: true
400                             Label {
401                                 Layout.fillWidth: true
402                                 text: model.title
403                             }
404                             Label {
405                                 Layout.fillWidth: true
406                                 text: model.artist
407                                 color: '#00ADDC'
408                                 font.pixelSize: 32
409                             }
410                         }
411                         //Label {
412                         //    text: player.time2str(model.duration)
413                         //    color: '#00ADDC'
414                         //    font.pixelSize: 32
415                         //}
416                     }
417                     onClicked: {
418                         mediaplayer.picktrack(playlistview.model[index].index)
419                     }
420                 }
421
422                 highlight: Rectangle {
423                     color: 'white'
424                     opacity: 0.25
425                 }
426             }
427         }
428     }
429 }
430 }