mediaplayer: qml: remove QtMultimedia
[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: ""
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             bluetooth.connected = data.Connected == "True"
108             bluetooth.av_connected = data.AVPConnected == "True"
109             bluetooth.deviceAddress = data.Address
110
111             if ('Position' in metadata)
112                 bluetooth.position = metadata.Position
113
114             if ('Duration' in metadata)
115                 bluetooth.duration = metadata.Duration
116
117             if ('Status' in metadata)
118                 bluetooth.state = metadata.Status
119
120             if ('Artist' in metadata)
121                 bluetooth.artist = metadata.Artist
122
123             if ('Title' in metadata)
124                 bluetooth.title = metadata.Title
125         }
126     }
127
128     Connections {
129         target: mediaplayer
130
131         onPlaylistChanged: {
132             playlist_model.clear();
133
134             for (var i = 0; i < playlist.list.length; i++) {
135                 var item = playlist.list[i]
136
137                 playlist_model.append({ "index": item.index, "artist": item.artist ? item.artist : '', "title": item.title ? item.title : '' })
138
139                 if (item.selected) {
140                     playlistview.currentIndex = i
141                 }
142             }
143         }
144
145         onMetadataChanged: {
146             player.title = metadata.title
147             player.album = metadata.album
148             player.artist = metadata.artist
149
150             if (metadata.duration) {
151                 player.duration = metadata.duration
152             }
153
154             if (metadata.position) {
155                 player.position = metadata.position
156             }
157
158             if (metadata.status) {
159                 player.status = metadata.status
160             }
161
162             if (metadata.image) {
163                 player.cover_art = metadata.image
164             }
165
166             playlistview.currentIndex = metadata.index
167         }
168     }
169
170     Timer {
171         id: timer
172         interval: 250
173         running: (bluetooth.av_connected && bluetooth.state == "playing")
174         repeat: true
175         onTriggered: {
176             bluetooth.position = bluetooth.position + 250
177         }
178     }
179
180     ListModel {
181         id: playlist_model
182     }
183
184     ColumnLayout {
185         anchors.fill: parent
186         Item {
187             Layout.fillWidth: true
188             Layout.fillHeight: true
189             Layout.preferredHeight: 1080
190             clip: true
191             Image {
192                 id: albumart
193                 anchors.left: parent.left
194                 anchors.right: parent.right
195                 anchors.bottom: parent.bottom
196                 height: sourceSize.height * width / sourceSize.width
197                 fillMode: Image.PreserveAspectCrop
198                 source: player.cover_art ? player.cover_art : ''
199                 visible: bluetooth.av_connected == false
200             }
201
202             Item {
203                 anchors.left: parent.left
204                 anchors.right: parent.right
205                 anchors.bottom: parent.bottom
206                 height :307
207                 Rectangle {
208                     anchors.fill: parent
209                     color: 'black'
210                     opacity: 0.75
211                 }
212
213                 ColumnLayout {
214                     anchors.fill: parent
215                     anchors.margins: root.width * 0.02
216                     Item {
217                         Layout.fillWidth: true
218                         Layout.fillHeight: true
219                         Row {
220                             spacing: 20
221                             //ToggleButton {
222                             //    id: random
223                             //    visible: bluetooth.connected == false
224                             //    offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg'
225                             //    onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg'
226                             //}
227                             ToggleButton {
228                                 id: loop
229                                 visible: bluetooth.connected == false
230                                 //checked: player.loop_state
231                                 offImage: './images/AGL_MediaPlayer_Loop_Inactive.svg'
232                                 onImage: './images/AGL_MediaPlayer_Loop_Active.svg'
233                                 onClicked: { mediaplayer.loop(checked) }
234                             }
235                         }
236                         ColumnLayout {
237                             anchors.fill: parent
238                             Label {
239                                 id: title
240                                 Layout.alignment: Layout.Center
241                                 text: bluetooth.av_connected ? bluetooth.title : (player.title ? player.title : '')
242                                 horizontalAlignment: Label.AlignHCenter
243                                 verticalAlignment: Label.AlignVCenter
244                             }
245                             Label {
246                                 Layout.alignment: Layout.Center
247                                 text: bluetooth.av_connected ? bluetooth.artist : (player.artist ? player.artist : '')
248                                 horizontalAlignment: Label.AlignHCenter
249                                 verticalAlignment: Label.AlignVCenter
250                                 font.pixelSize: title.font.pixelSize * 0.6
251                             }
252                         }
253                     }
254                     Slider {
255                         id: slider
256                         Layout.fillWidth: true
257                         to: bluetooth.av_connected ? bluetooth.duration : player.duration
258                         enabled: bluetooth.av_connected == false
259                         value: bluetooth.av_connected ? bluetooth.position : player.position
260                         function getPosition() {
261                             if (bluetooth.av_connected) {
262                                 return player.time2str(bluetooth.position)
263                             }
264                             return player.time2str(player.position)
265                         }
266                         Label {
267                             id: position
268                             anchors.left: parent.left
269                             anchors.bottom: parent.top
270                             font.pixelSize: 32
271                             text: slider.getPosition()
272                         }
273                         Label {
274                             id: duration
275                             anchors.right: parent.right
276                             anchors.bottom: parent.top
277                             font.pixelSize: 32
278                             text: bluetooth.av_connected ? player.time2str(bluetooth.duration) : player.time2str(player.duration)
279                         }
280                         onPressedChanged: mediaplayer.seek(value)
281                     }
282                     RowLayout {
283                         Layout.fillHeight: true
284 //                        Image {
285 //                            source: './images/AGL_MediaPlayer_Playlist_Inactive.svg'
286 //                        }
287 //                        Image {
288 //                            source: './images/AGL_MediaPlayer_CD_Inactive.svg'
289 //                        }
290                         Item { Layout.fillWidth: true }
291                         ImageButton {
292                             id: previous
293                             offImage: './images/AGL_MediaPlayer_BackArrow.svg'
294                             onClicked: {
295                                 if (bluetooth.av_connected) {
296                                     bluetooth.set_avrcp_controls("Previous")
297                                     bluetooth.position = 0
298                                 } else {
299                                     mediaplayer.previous()
300                                 }
301                             }
302                         }
303                         ImageButton {
304                             id: play
305                             offImage: './images/AGL_MediaPlayer_Player_Play.svg'
306                             onClicked: {
307                                 if (bluetooth.av_connected) {
308                                     bluetooth.set_avrcp_controls("Play")
309                                 } else {
310                                     mediaplayer.play()
311                                 }
312                             }
313                             states: [
314                                 State {
315                                     when: player.status == "playing"
316                                     PropertyChanges {
317                                         target: play
318                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
319                                         onClicked: {
320                                             player.status = ""
321                                             mediaplayer.pause()
322                                         }
323                                     }
324                                 },
325                                 State {
326                                     when: bluetooth.av_connected && bluetooth.state == "playing"
327                                     PropertyChanges {
328                                         target: play
329                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
330                                         onClicked: bluetooth.set_avrcp_controls("Pause")
331                                     }
332                                 }
333
334                             ]
335                         }
336                         ImageButton {
337                             id: forward
338                             offImage: './images/AGL_MediaPlayer_ForwardArrow.svg'
339                             onClicked: {
340                                 if (bluetooth.av_connected) {
341                                     bluetooth.set_avrcp_controls("Next")
342                                 } else {
343                                     mediaplayer.next()
344                                 }
345                             }
346                         }
347
348                         Item { Layout.fillWidth: true }
349  
350                         ToggleButton {
351                               visible: bluetooth.connected
352                               checked: bluetooth.av_connected
353                               offImage: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg'
354                               onImage: './images/AGL_MediaPlayer_Bluetooth_Active.svg'
355
356                               onClicked: {
357                                   if (bluetooth.av_connected) {
358                                       bluetooth.disconnect_profiles()
359                                   } else {
360                                       bluetooth.connect_profiles()
361                                   }
362                               }
363                         }
364                     }
365                 }
366             }
367         }
368         Item {
369             Layout.fillWidth: true
370             Layout.fillHeight: true
371             Layout.preferredHeight: 407
372
373             ListView {
374                 anchors.fill: parent
375                 id: playlistview
376                 visible: bluetooth.av_connected == false
377                 clip: true
378                 header: Label {
379                     x: 50
380                     text: 'PLAYLIST'
381                     opacity: 0.5
382                 }
383                 model: playlist_model
384                 currentIndex: -1
385
386                 delegate: MouseArea {
387                     id: delegate
388                     width: ListView.view.width
389                     height: ListView.view.height / 4
390                     RowLayout {
391                         anchors.fill: parent
392                         anchors.leftMargin: 50
393                         anchors.rightMargin: 50
394                         ColumnLayout {
395                             Layout.fillWidth: true
396                             Label {
397                                 Layout.fillWidth: true
398                                 text: model.title
399                             }
400                             Label {
401                                 Layout.fillWidth: true
402                                 text: model.artist
403                                 color: '#00ADDC'
404                                 font.pixelSize: 32
405                             }
406                         }
407                         //Label {
408                         //    text: player.time2str(model.duration)
409                         //    color: '#00ADDC'
410                         //    font.pixelSize: 32
411                         //}
412                     }
413                     onClicked: {
414                         mediaplayer.picktrack(playlistview.model.get(index).index)
415                     }
416                 }
417
418                 highlight: Rectangle {
419                     color: 'white'
420                     opacity: 0.25
421                 }
422             }
423         }
424     }
425 }