binding: media: fix memory leak with json objects
[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     API.LightMediaScanner {
29         id: binding
30         url: bindingAddress
31     }
32
33     API.BluetoothManager {
34         id: bluetooth
35         url: bindingAddress
36     }
37
38     MediaPlayer {
39         id: player
40         audioRole: MediaPlayer.MusicRole
41         autoLoad: true
42         playlist: playlist
43
44         function time2str(value) {
45             return Qt.formatTime(new Date(value), 'mm:ss')
46         }
47     }
48
49     Timer {
50         id: timer
51         interval: 250
52         running: (bluetooth.av_connected && bluetooth.state == "playing")
53         repeat: true
54         onTriggered: {
55             bluetooth.position = bluetooth.position + 250
56             slider.value = bluetooth.position
57         }
58     }
59
60     Playlist {
61         id: playlist
62         playbackMode: random.checked ? Playlist.Random : loop.checked ? Playlist.Loop : Playlist.Sequential
63     }
64
65
66     ColumnLayout {
67         anchors.fill: parent
68         Item {
69             Layout.fillWidth: true
70             Layout.fillHeight: true
71             Layout.preferredHeight: 1080
72             clip: true
73             Image {
74                 id: albumart
75                 anchors.left: parent.left
76                 anchors.right: parent.right
77                 anchors.bottom: parent.bottom
78                 height: sourceSize.height * width / sourceSize.width
79                 fillMode: Image.PreserveAspectCrop
80                 source: player.metaData.coverArtImage ? player.metaData.coverArtImage : ''
81                 visible: bluetooth.av_connected == false
82             }
83
84             Item {
85                 anchors.left: parent.left
86                 anchors.right: parent.right
87                 anchors.bottom: parent.bottom
88                 height :307
89                 Rectangle {
90                     anchors.fill: parent
91                     color: 'black'
92                     opacity: 0.75
93                 }
94
95                 ColumnLayout {
96                     anchors.fill: parent
97                     anchors.margins: root.width * 0.02
98                     Item {
99                         Layout.fillWidth: true
100                         Layout.fillHeight: true
101                         Row {
102                             spacing: 20
103                             ToggleButton {
104                                 id: random
105                                 visible: bluetooth.connected == false
106                                 offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg'
107                                 onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg'
108                             }
109                             ToggleButton {
110                                 id: loop
111                                 visible: bluetooth.connected == false
112                                 offImage: './images/AGL_MediaPlayer_Loop_Inactive.svg'
113                                 onImage: './images/AGL_MediaPlayer_Loop_Active.svg'
114                             }
115                         }
116                         ColumnLayout {
117                             anchors.fill: parent
118                             Label {
119                                 id: title
120                                 Layout.alignment: Layout.Center
121                                 text: bluetooth.av_connected ? bluetooth.title : (player.metaData.title ? player.metaData.title : '')
122                                 horizontalAlignment: Label.AlignHCenter
123                                 verticalAlignment: Label.AlignVCenter
124                             }
125                             Label {
126                                 Layout.alignment: Layout.Center
127                                 text: bluetooth.av_connected ? bluetooth.artist : (player.metaData.contributingArtist ? player.metaData.contributingArtist : '')
128                                 horizontalAlignment: Label.AlignHCenter
129                                 verticalAlignment: Label.AlignVCenter
130                                 font.pixelSize: title.font.pixelSize * 0.6
131                             }
132                         }
133                     }
134                     Slider {
135                         id: slider
136                         Layout.fillWidth: true
137                         to: bluetooth.av_connected ? bluetooth.duration : player.duration
138                         enabled: bluetooth.av_connected == false
139                         value: bluetooth.av_connected ? bluetooth.position : player.position
140                         function getPosition() {
141                             if (bluetooth.av_connected) {
142                                 return player.time2str(bluetooth.position)
143                             }
144                             return player.time2str(player.position)
145                         }
146                         Label {
147                             id: position
148                             anchors.left: parent.left
149                             anchors.bottom: parent.top
150                             font.pixelSize: 32
151                             text: slider.getPosition()
152                         }
153                         Label {
154                             id: duration
155                             anchors.right: parent.right
156                             anchors.bottom: parent.top
157                             font.pixelSize: 32
158                             text: bluetooth.av_connected ? player.time2str(bluetooth.duration) : player.time2str(player.duration)
159                         }
160                         onPressedChanged: player.seek(value)
161                     }
162                     RowLayout {
163                         Layout.fillHeight: true
164 //                        Image {
165 //                            source: './images/AGL_MediaPlayer_Playlist_Inactive.svg'
166 //                        }
167 //                        Image {
168 //                            source: './images/AGL_MediaPlayer_CD_Inactive.svg'
169 //                        }
170                         Item { Layout.fillWidth: true }
171                         ImageButton {
172                             id: previous
173                             offImage: './images/AGL_MediaPlayer_BackArrow.svg'
174                             onClicked: {
175                                 if (bluetooth.av_connected) {
176                                     bluetooth.sendMediaCommand("Previous")
177                                     bluetooth.position = 0
178                                 } else {
179                                     playlist.previous()
180                                 }
181                             }
182                         }
183                         ImageButton {
184                             id: play
185                             offImage: './images/AGL_MediaPlayer_Player_Play.svg'
186                             onClicked: {
187                                 if (bluetooth.av_connected) {
188                                     bluetooth.sendMediaCommand("Play")
189                                 } else {
190                                     player.play()
191                                 }
192                             }
193                             states: [
194                                 State {
195                                     when: player.playbackState === MediaPlayer.PlayingState
196                                     PropertyChanges {
197                                         target: play
198                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
199                                         onClicked: player.pause()
200                                     }
201                                 },
202                                 State {
203                                     when: bluetooth.av_connected && bluetooth.state == "playing"
204                                     PropertyChanges {
205                                         target: play
206                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
207                                         onClicked: bluetooth.sendMediaCommand("Pause")
208                                     }
209                                 }
210
211                             ]
212                         }
213                         ImageButton {
214                             id: forward
215                             offImage: './images/AGL_MediaPlayer_ForwardArrow.svg'
216                             onClicked: {
217                                 if (bluetooth.av_connected) {
218                                     bluetooth.sendMediaCommand("Next")
219                                 } else {
220                                     playlist.next()
221                                 }
222                             }
223                         }
224
225                         Item { Layout.fillWidth: true }
226  
227                         ToggleButton {
228                               visible: bluetooth.connected
229                               checked: bluetooth.av_connected
230                               offImage: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg'
231                               onImage: './images/AGL_MediaPlayer_Bluetooth_Active.svg'
232
233                               onClicked: {
234                                   if (bluetooth.av_connected) {
235                                       bluetooth.disconnect_profiles()
236                                   } else {
237                                       bluetooth.connect_profiles()
238                                   }
239                               }
240                         }
241                     }
242                 }
243             }
244         }
245         Item {
246             Layout.fillWidth: true
247             Layout.fillHeight: true
248             Layout.preferredHeight: 407
249
250             PlaylistWithMetadata {
251                 id: playlistmodel
252                 source: playlist
253             }
254
255             ListView {
256                 anchors.fill: parent
257                 id: playlistview
258                 visible: bluetooth.av_connected == false
259                 clip: true
260                 header: Label {
261                     x: 50
262                     text: 'PLAYLIST'
263                     opacity: 0.5
264                 }
265                 model: playlistmodel
266                 currentIndex: playlist.currentIndex
267
268                 delegate: MouseArea {
269                     id: delegate
270                     width: ListView.view.width
271                     height: ListView.view.height / 4
272                     RowLayout {
273                         anchors.fill: parent
274                         anchors.leftMargin: 50
275                         anchors.rightMargin: 50
276                         Image {
277                             source: model.coverArt
278                             fillMode: Image.PreserveAspectFit
279                             Layout.preferredWidth: delegate.height
280                             Layout.preferredHeight: delegate.height
281                         }
282                         ColumnLayout {
283                             Layout.fillWidth: true
284                             Label {
285                                 Layout.fillWidth: true
286                                 text: model.title
287                             }
288                             Label {
289                                 Layout.fillWidth: true
290                                 text: model.artist
291                                 color: '#66FF99'
292                                 font.pixelSize: 32
293                             }
294                         }
295                         Label {
296                             text: player.time2str(model.duration)
297                             color: '#66FF99'
298                             font.pixelSize: 32
299                         }
300                     }
301                     onClicked: {
302                         playlist.currentIndex = model.index
303                         player.play()
304                     }
305                 }
306
307                 highlight: Rectangle {
308                     color: 'white'
309                     opacity: 0.25
310                 }
311             }
312         }
313     }
314 }