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