Test for Mediaplayer of HMI Framework at dab version
[apps/mediaplayer.git] / app / MediaPlayer.qml
1 /*
2  * Copyright (C) 2016 The Qt Company Ltd.
3  * Copyright (C) 2017 Toyota Motor Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 import QtQuick 2.6
19 import QtQuick.Layouts 1.1
20 import QtQuick.Controls 2.0
21 import QtMultimedia 5.6
22 import AGL.Demo.Controls 1.0
23 import MediaPlayer 1.0
24 import QtQml.StateMachine 1.0 as MPSM
25 import 'api' as API
26
27 ApplicationWindow {
28     id: root
29     
30     property int sourceID: 0
31     property int  connectionID
32     property int  sourceIndex
33
34     signal playMediaplayer
35     signal stopMediaplayer
36     signal disconnected
37     signal paused
38     signal connected
39
40     API.LightMediaScanner {
41         id: binding
42         url: bindingAddress
43     }
44
45     API.BluetoothManager {
46         id: bluetooth
47         url: bindingAddress
48     }
49
50     MediaPlayer {
51         id: player
52         audioRole: MediaPlayer.MusicRole
53         autoLoad: true
54         playlist: playlist
55
56         function time2str(value) {
57             return Qt.formatTime(new Date(value), 'mm:ss')
58         }
59     }
60
61     MPSM.StateMachine{
62         id: mediaplayerState
63         initialState: stop
64         running: true
65         MPSM.State{
66             id: haveSoundRight
67             MPSM.SignalTransition{
68                 targetState: stop
69                 signal: disconnected
70             }
71             MPSM.SignalTransition{
72                 targetState: pause
73                 signal: paused
74             }
75             MPSM.SignalTransition{
76                 targetState: playing
77                 signal: playMediaplayer
78             }
79             onEntered: {
80                 console.log("enter haveSoundRight")
81             }
82             onExited : {
83                 // Nothing to do
84             }
85         }
86         MPSM.State{
87             id: stop
88             MPSM.SignalTransition{
89                 targetState: haveSoundRight
90                 signal: connected
91             }
92             onEntered: {
93                 console.log("enter stop state")
94             }
95             onExited : {
96                 // Nothing to do
97             }
98         }
99         MPSM.State{
100             id: pause
101             MPSM.SignalTransition{
102                 targetState: haveSoundRight
103                 signal: connected
104             }
105             MPSM.SignalTransition{
106                 targetState: stop
107                 signal: disconnected
108             }
109             onEntered: {
110                 console.log("enter pause state")
111             }
112             onExited : {
113                 // Nothing to do
114             }
115         }
116         MPSM.State{
117             id: playing
118             MPSM.SignalTransition{
119                 targetState: haveSoundRight
120                 signal: stopMediaplayer
121             }
122             MPSM.SignalTransition{
123                 targetState: lostSoundRight
124                 signal: disconnected
125             }
126             onEntered: {
127                 console.log("enter playing state")
128                 player.play()
129             }
130             onExited : {
131                 player.pause()
132             }
133         }
134         MPSM.State{
135             id: lostSoundRight
136             MPSM.SignalTransition{
137                 targetState: playing
138                 signal: connected
139             }
140             onEntered: {
141                 console.log("enter lostSoundRight")
142             }
143             onExited : {
144             }
145         }
146         MPSM.State{
147             id: temporaryLostSoundRight
148             MPSM.SignalTransition{
149                 targetState: playing
150                 signal: connected
151             }
152             MPSM.SignalTransition{
153                 targetState: lostSoundRight
154                 signal: disconnected
155             }
156             onEntered: {
157                 console.log("enter lostSoundRight")
158             }
159             onExited : {
160             }
161         }
162     }
163
164     function slotReply(msg){
165         var jstr = JSON.stringify(msg)
166         var content = JSON.parse(jstr);
167         var verb = content.response.verb
168         var err = content.response.error
169         switch(verb)
170         {
171             case "connect":
172                 if(err == 0){
173                     connectionID = content.response.mainConnectionID
174                 }
175                 break;
176             case "registerSource":
177                 if(err == 0){
178                     sourceID = content.response.sourceID
179                 }
180         }
181     }
182
183     function slotEvent(event,msg){
184         var jstr = JSON.stringify(msg)
185         var content = JSON.parse(jstr);
186         var eventName = content.event
187         switch(eventName)
188         {
189             case "soundmanager\/asyncSetSourceState":
190                 // This event doesn't come for now
191                 if(sourceID == content.data.sourceID){
192                     console.log("mediaplayer: call ackSetSourceState")
193                     smw.ackSetSourceState(content.data.handle, 0)
194                     switch(content.data.sourceState){
195                         case "on":
196                             connected()
197                             break;
198                         case "off":
199                             disconnected()
200                             break;
201                         case "paused":
202                             paused()
203                             break;
204                         default:
205                             break;
206                     }
207                 }
208                 break;
209             default:
210                 break;
211         }
212     }
213
214     Timer {
215         id: timer
216         interval: 250
217         running: (bluetooth.av_connected && bluetooth.state == "playing")
218         repeat: true
219         onTriggered: {
220             bluetooth.position = bluetooth.position + 250
221             slider.value = bluetooth.position
222         }
223     }
224
225     Playlist {
226         id: playlist
227         playbackMode: random.checked ? Playlist.Random : loop.checked ? Playlist.Loop : Playlist.Sequential
228     }
229
230
231     ColumnLayout {
232         anchors.fill: parent
233         Item {
234             Layout.fillWidth: true
235             Layout.fillHeight: true
236             Layout.preferredHeight: 1080
237             clip: true
238             Image {
239                 id: albumart
240                 anchors.left: parent.left
241                 anchors.right: parent.right
242                 anchors.bottom: parent.bottom
243                 height: sourceSize.height * width / sourceSize.width
244                 fillMode: Image.PreserveAspectCrop
245                 source: player.metaData.coverArtImage ? player.metaData.coverArtImage : ''
246                 visible: bluetooth.av_connected == false
247             }
248
249             Item {
250                 anchors.left: parent.left
251                 anchors.right: parent.right
252                 anchors.bottom: parent.bottom
253                 height :307
254                 Rectangle {
255                     anchors.fill: parent
256                     color: 'black'
257                     opacity: 0.75
258                 }
259
260                 ColumnLayout {
261                     anchors.fill: parent
262                     anchors.margins: root.width * 0.02
263                     Item {
264                         Layout.fillWidth: true
265                         Layout.fillHeight: true
266                         Row {
267                             spacing: 20
268                             ToggleButton {
269                                 id: random
270                                 visible: bluetooth.connected == false
271                                 offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg'
272                                 onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg'
273                             }
274                             ToggleButton {
275                                 id: loop
276                                 visible: bluetooth.connected == false
277                                 offImage: './images/AGL_MediaPlayer_Loop_Inactive.svg'
278                                 onImage: './images/AGL_MediaPlayer_Loop_Active.svg'
279                             }
280                         }
281                         ColumnLayout {
282                             anchors.fill: parent
283                             Label {
284                                 id: title
285                                 Layout.alignment: Layout.Center
286                                 text: bluetooth.av_connected ? bluetooth.title : (player.metaData.title ? player.metaData.title : '')
287                                 horizontalAlignment: Label.AlignHCenter
288                                 verticalAlignment: Label.AlignVCenter
289                             }
290                             Label {
291                                 Layout.alignment: Layout.Center
292                                 text: bluetooth.av_connected ? bluetooth.artist : (player.metaData.contributingArtist ? player.metaData.contributingArtist : '')
293                                 horizontalAlignment: Label.AlignHCenter
294                                 verticalAlignment: Label.AlignVCenter
295                                 font.pixelSize: title.font.pixelSize * 0.6
296                             }
297                         }
298                     }
299                     Slider {
300                         id: slider
301                         Layout.fillWidth: true
302                         to: bluetooth.av_connected ? bluetooth.duration : player.duration
303                         enabled: bluetooth.av_connected == false
304                         value: bluetooth.av_connected ? bluetooth.position : player.position
305                         function getPosition() {
306                             if (bluetooth.av_connected) {
307                                 return player.time2str(bluetooth.position)
308                             }
309                             return player.time2str(player.position)
310                         }
311                         Label {
312                             id: position
313                             anchors.left: parent.left
314                             anchors.bottom: parent.top
315                             font.pixelSize: 32
316                             text: slider.getPosition()
317                         }
318                         Label {
319                             id: duration
320                             anchors.right: parent.right
321                             anchors.bottom: parent.top
322                             font.pixelSize: 32
323                             text: bluetooth.av_connected ? player.time2str(bluetooth.duration) : player.time2str(player.duration)
324                         }
325                         onPressedChanged: player.seek(value)
326                     }
327                     RowLayout {
328                         Layout.fillHeight: true
329 //                        Image {
330 //                            source: './images/AGL_MediaPlayer_Playlist_Inactive.svg'
331 //                        }
332 //                        Image {
333 //                            source: './images/AGL_MediaPlayer_CD_Inactive.svg'
334 //                        }
335                         Item { Layout.fillWidth: true }
336                         ImageButton {
337                             id: previous
338                             offImage: './images/AGL_MediaPlayer_BackArrow.svg'
339                             onClicked: {
340                                 if (bluetooth.av_connected) {
341                                     bluetooth.sendMediaCommand("Previous")
342                                     bluetooth.position = 0
343                                 } else {
344                                     playlist.previous()
345                                 }
346                             }
347                         }
348                         ImageButton {
349                             id: play
350                             offImage: './images/AGL_MediaPlayer_Player_Play.svg'
351                             onClicked: {
352                                 if (bluetooth.av_connected) {
353                                     bluetooth.sendMediaCommand("Play")
354                                 } else {
355                                     playMediaplayer()
356                                 }
357                             }
358                             states: [
359                                 State {
360                                     when: player.playbackState === MediaPlayer.PlayingState
361                                     PropertyChanges {
362                                         target: play
363                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
364                                         onClicked: {
365                                             stopMediaplayer()
366                                         }
367                                     }
368                                 },
369                                 State {
370                                     when: bluetooth.av_connected && bluetooth.state == "playing"
371                                     PropertyChanges {
372                                         target: play
373                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
374                                         onClicked: bluetooth.sendMediaCommand("Pause")
375                                     }
376                                 }
377
378                             ]
379                         }
380                         ImageButton {
381                             id: forward
382                             offImage: './images/AGL_MediaPlayer_ForwardArrow.svg'
383                             onClicked: {
384                                 if (bluetooth.av_connected) {
385                                     bluetooth.sendMediaCommand("Next")
386                                 } else {
387                                     playlist.next()
388                                 }
389                             }
390                         }
391
392                         Item { Layout.fillWidth: true }
393  
394                         ToggleButton {
395                               visible: bluetooth.connected
396                               checked: bluetooth.av_connected
397                               offImage: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg'
398                               onImage: './images/AGL_MediaPlayer_Bluetooth_Active.svg'
399
400                               onClicked: {
401                                   if (bluetooth.av_connected) {
402                                       bluetooth.disconnect_profiles()
403                                   } else {
404                                       bluetooth.connect_profiles()
405                                   }
406                               }
407                         }
408                     }
409                 }
410             }
411         }
412         Item {
413             Layout.fillWidth: true
414             Layout.fillHeight: true
415             Layout.preferredHeight: 407
416
417                 PlaylistWithMetadata {
418                     id: playlistmodel
419                 source: playlist
420             }
421
422             ListView {
423                 anchors.fill: parent
424                 id: playlistview
425                 visible: bluetooth.av_connected == false
426                 clip: true
427                 header: Label {
428                     x: 50
429                     text: 'PLAYLIST'
430                     opacity: 0.5
431                 }
432                 model: playlistmodel
433                 currentIndex: playlist.currentIndex
434
435                 delegate: MouseArea {
436                     id: delegate
437                     width: ListView.view.width
438                     height: ListView.view.height / 4
439                     RowLayout {
440                         anchors.fill: parent
441                         anchors.leftMargin: 50
442                         anchors.rightMargin: 50
443                         Image {
444                             source: model.coverArt
445                             fillMode: Image.PreserveAspectFit
446                             Layout.preferredWidth: delegate.height
447                             Layout.preferredHeight: delegate.height
448                         }
449                         ColumnLayout {
450                             Layout.fillWidth: true
451                             Label {
452                                 Layout.fillWidth: true
453                                 text: model.title
454                             }
455                             Label {
456                                 Layout.fillWidth: true
457                                 text: model.artist
458                                 color: '#66FF99'
459                                 font.pixelSize: 32
460                             }
461                         }
462                         Label {
463                             text: player.time2str(model.duration)
464                             color: '#66FF99'
465                             font.pixelSize: 32
466                         }
467                     }
468                     onClicked: {
469                         playlist.currentIndex = model.index
470                         sourceIndex = model.index;
471                         console.log("mediaplayer: call connect")
472                         playMediaplayer()
473                     }
474                 }
475
476                 highlight: Rectangle {
477                     color: 'white'
478                     opacity: 0.25
479                 }
480             }
481         }
482         Component.onCompleted: {
483             smw.registerSource("mediaplayer")
484         }
485     }
486 }