dbus: add signal support for removable media
[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
24 ApplicationWindow {
25     id: root
26
27     function clearMetadata() {
28         title.text = ''
29         artist.text = ''
30         duration.text = player.time2str(0)
31         albumart.visible = false
32     }
33
34     Connections {
35         target: dbus
36         onProcessPlaylistUpdate: {
37             playlist.clear()
38             playlist.addItems(mediaFiles)
39
40             playlistmodel.setSource(playlist)
41             playlistview.visible = true
42             albumart.visible = true
43         }
44
45         onProcessPlaylistHide: {
46             player.stop()
47             playlistview.visible = false
48             clearMetadata()
49         }
50
51     }
52
53     MediaPlayer {
54         id: player
55         audioRole: MediaPlayer.MusicRole
56         autoLoad: true
57         playlist: playlist
58         function time2str(value) {
59             return Qt.formatTime(new Date(value), 'mm:ss')
60         }
61         onPositionChanged: slider.value = player.position
62     }
63
64     Playlist {
65         id: playlist
66         playbackMode: random.checked ? Playlist.Random : loop.checked ? Playlist.Loop : Playlist.Sequential
67
68         Component.onCompleted: {
69             playlist.addItems(mediaFiles)
70         }
71     }
72
73
74     ColumnLayout {
75         anchors.fill: parent
76         Item {
77             Layout.fillWidth: true
78             Layout.fillHeight: true
79             Layout.preferredHeight: 1080
80             clip: true
81             Image {
82                 id: albumart
83                 anchors.left: parent.left
84                 anchors.right: parent.right
85                 anchors.bottom: parent.bottom
86                 height: sourceSize.height * width / sourceSize.width
87                 fillMode: Image.PreserveAspectCrop
88                 source: player.metaData.coverArtImage ? player.metaData.coverArtImage : ''
89             }
90
91             Item {
92                 anchors.left: parent.left
93                 anchors.right: parent.right
94                 anchors.bottom: parent.bottom
95                 height :307
96                 Rectangle {
97                     anchors.fill: parent
98                     color: 'black'
99                     opacity: 0.75
100                 }
101
102                 ColumnLayout {
103                     anchors.fill: parent
104                     anchors.margins: root.width * 0.02
105                     Item {
106                         Layout.fillWidth: true
107                         Layout.fillHeight: true
108                         Row {
109                             spacing: 20
110                             ToggleButton {
111                                 id: random
112                                 offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg'
113                                 onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg'
114                             }
115                             ToggleButton {
116                                 id: loop
117                                 offImage: './images/AGL_MediaPlayer_Loop_Inactive.svg'
118                                 onImage: './images/AGL_MediaPlayer_Loop_Active.svg'
119                             }
120                         }
121                         ColumnLayout {
122                             anchors.fill: parent
123                             Label {
124                                 id: title
125                                 Layout.alignment: Layout.Center
126                                 text: player.metaData.title ? player.metaData.title : ''
127                                 horizontalAlignment: Label.AlignHCenter
128                                 verticalAlignment: Label.AlignVCenter
129                             }
130                             Label {
131                                 id: artist
132                                 Layout.alignment: Layout.Center
133                                 text: player.metaData.contributingArtist ? player.metaData.contributingArtist : ''
134                                 horizontalAlignment: Label.AlignHCenter
135                                 verticalAlignment: Label.AlignVCenter
136                                 font.pixelSize: title.font.pixelSize * 0.6
137                             }
138                         }
139                     }
140                     Slider {
141                         id: slider
142                         Layout.fillWidth: true
143                         to: player.duration
144                         Label {
145                             id: position
146                             anchors.left: parent.left
147                             anchors.bottom: parent.top
148                             font.pixelSize: 32
149                             text: player.time2str(player.position)
150                         }
151                         Label {
152                             id: duration
153                             anchors.right: parent.right
154                             anchors.bottom: parent.top
155                             font.pixelSize: 32
156                             text: player.time2str(player.duration)
157                         }
158                         onPressedChanged: player.seek(value)
159                     }
160                     RowLayout {
161                         Layout.fillHeight: true
162 //                        Image {
163 //                            source: './images/AGL_MediaPlayer_Playlist_Inactive.svg'
164 //                        }
165 //                        Image {
166 //                            source: './images/AGL_MediaPlayer_CD_Inactive.svg'
167 //                        }
168                         Item { Layout.fillWidth: true }
169                         ImageButton {
170                             offImage: './images/AGL_MediaPlayer_BackArrow.svg'
171                             onClicked: playlist.previous()
172                         }
173                         ImageButton {
174                             id: play
175                             offImage: './images/AGL_MediaPlayer_Player_Play.svg'
176                             onClicked: player.play()
177                             states: [
178                                 State {
179                                     when: player.playbackState === MediaPlayer.PlayingState
180                                     PropertyChanges {
181                                         target: play
182                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
183                                         onClicked: player.pause()
184                                     }
185                                 }
186                             ]
187                         }
188                         ImageButton {
189                             offImage: './images/AGL_MediaPlayer_ForwardArrow.svg'
190                             onClicked: playlist.next()
191                         }
192
193                         Item { Layout.fillWidth: true }
194 //                        Image {
195 //                            source: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg'
196 //                        }
197 //                        Image {
198 //                            source: './images/AGL_MediaPlayer_Radio_Inactive.svg'
199 //                        }
200                     }
201                 }
202             }
203         }
204         Item {
205             Layout.fillWidth: true
206             Layout.fillHeight: true
207             Layout.preferredHeight: 407
208
209             PlaylistWithMetadata {
210                 id: playlistmodel
211                 source: playlist
212             }
213
214             ListView {
215                 anchors.fill: parent
216                 id: playlistview
217                 clip: true
218                 header: Label {
219                     x: 50
220                     text: 'PLAYLIST'
221                     opacity: 0.5
222                 }
223                 model: playlistmodel
224                 currentIndex: playlist.currentIndex
225
226                 delegate: MouseArea {
227                     id: delegate
228                     width: ListView.view.width
229                     height: ListView.view.height / 4
230                     RowLayout {
231                         anchors.fill: parent
232                         anchors.leftMargin: 50
233                         anchors.rightMargin: 50
234                         Image {
235                             source: model.coverArt
236                             fillMode: Image.PreserveAspectFit
237                             Layout.preferredWidth: delegate.height
238                             Layout.preferredHeight: delegate.height
239                         }
240                         ColumnLayout {
241                             Layout.fillWidth: true
242                             Label {
243                                 Layout.fillWidth: true
244                                 text: model.title
245                             }
246                             Label {
247                                 Layout.fillWidth: true
248                                 text: model.artist
249                                 color: '#66FF99'
250                                 font.pixelSize: 32
251                             }
252                         }
253                         Label {
254                             text: player.time2str(model.duration)
255                             color: '#66FF99'
256                             font.pixelSize: 32
257                         }
258                     }
259                     onClicked: {
260                         playlist.currentIndex = model.index
261                         player.play()
262                     }
263                 }
264
265                 highlight: Rectangle {
266                     color: 'white'
267                     opacity: 0.25
268                 }
269             }
270         }
271     }
272 }