Add sound manager initial source code
[staging/soundmanager.git] / sample / mediaplayer / 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 'api' as API
25
26 ApplicationWindow {
27     id: root
28
29     property int sourceID: 0
30     property bool registered_media: false
31     property int  connectionID
32     property int  sourceIndex
33
34     API.LightMediaScanner {
35         id: binding
36         url: bindingAddress
37     }
38
39     API.BluetoothManager {
40         id: bluetooth
41         url: bindingAddress
42     }
43
44     MediaPlayer {
45         id: player
46         audioRole: MediaPlayer.MusicRole
47         autoLoad: true
48         playlist: playlist
49
50         function time2str(value) {
51             return Qt.formatTime(new Date(value), 'mm:ss')
52         }
53     }
54     function stopMediaplayer(){
55         console.log("stop mediaplayer from C++")
56         player.pause()
57     }
58
59     function slotReply(msg){
60         var jstr = JSON.stringify(msg)
61         console.log("mediaplayer: Json jstr:" + jstr)
62         var content = JSON.parse(jstr);
63         var verb = content.response.verb
64         var err = content.response.error
65         console.log("mediaplayer: verb: " + verb)
66         console.log("mediaplayer: content.response.error: " + err)
67         switch(verb)
68         {
69             case "connect":
70                 console.log("mediaplayer: replied by connect")
71                 if(err == 0){
72                     connectionID = content.response.mainConnectionID
73                     console.log("mediaplayer: mainConnectionID is " + connectionID)
74                 }
75                 break;
76             case "registerSource":
77                 console.log("mediaplayer: replied by registerSource")
78                 if(err == 0){
79                     sourceID = content.response.sourceID
80                     registered_media = true
81                 }
82         }
83     }
84
85     function slotEvent(event,msg){
86         var jstr = JSON.stringify(msg)
87         var content = JSON.parse(jstr);
88         var eventName = content.event
89         console.log("mediaplayer: event qml: event" + eventName + " msg: " + jstr)
90         switch(eventName)
91         {
92             case "soundmanager\/asyncSetSourceState":
93                 // This event doesn't come for now
94                 console.log("mediaplayer: soundmanager\/asyncSetSourceState")
95                 console.log("mediaplayer: my soundID:" + sourceID + "handle:" + content.data.handle + ",sourceID:" + content.data.sourceID + ",sourceState:" + content.data.sourceState)
96                 if(sourceID == content.data.sourceID){
97                     console.log("mediaplayer: call ackSetSourceState")
98                     var arg = JSON.stringify({handle:content.data.handle, error:0})
99                     smw.call("ackSetSourceState", arg)
100                     switch(content.data.sourceState){
101                         case "on":
102                             player.play()
103                             break;
104                         case "off":
105                             player.pause()
106                             break;
107                         case "paused":
108                             player.pause()
109                             break;
110                         default:
111                             break;
112                     }
113                 }
114                 break;
115             case "soundmanager\/asyncConnect":
116                 // In reality, device should be opened in this timing
117                 if(connectionID == content.data.connectionID){
118                     //player.open_device()
119                 }
120                 break;
121             case "soundmanager\/asyncDisconnect":
122                 // In reality, device should be closed in this timing
123                 if(connectionID == content.data.connectionID){
124                     // player.close_device()
125                 }
126                 break;
127             default:
128                 break;
129         }
130     }
131
132     Timer {
133         id: timer
134         interval: 250
135         running: (bluetooth.av_connected && bluetooth.state == "playing")
136         repeat: true
137         onTriggered: {
138             bluetooth.position = bluetooth.position + 250
139             slider.value = bluetooth.position
140         }
141     }
142
143     Playlist {
144         id: playlist
145         playbackMode: random.checked ? Playlist.Random : loop.checked ? Playlist.Loop : Playlist.Sequential
146     }
147
148
149     ColumnLayout {
150         anchors.fill: parent
151         Item {
152             Layout.fillWidth: true
153             Layout.fillHeight: true
154             Layout.preferredHeight: 1080
155             clip: true
156             Image {
157                 id: albumart
158                 anchors.left: parent.left
159                 anchors.right: parent.right
160                 anchors.bottom: parent.bottom
161                 height: sourceSize.height * width / sourceSize.width
162                 fillMode: Image.PreserveAspectCrop
163                 source: player.metaData.coverArtImage ? player.metaData.coverArtImage : ''
164                 visible: bluetooth.av_connected == false
165             }
166
167             Item {
168                 anchors.left: parent.left
169                 anchors.right: parent.right
170                 anchors.bottom: parent.bottom
171                 height :307
172                 Rectangle {
173                     anchors.fill: parent
174                     color: 'black'
175                     opacity: 0.75
176                 }
177
178                 ColumnLayout {
179                     anchors.fill: parent
180                     anchors.margins: root.width * 0.02
181                     Item {
182                         Layout.fillWidth: true
183                         Layout.fillHeight: true
184                         Row {
185                             spacing: 20
186                             ToggleButton {
187                                 id: random
188                                 visible: bluetooth.connected == false
189                                 offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg'
190                                 onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg'
191                             }
192                             ToggleButton {
193                                 id: loop
194                                 visible: bluetooth.connected == false
195                                 offImage: './images/AGL_MediaPlayer_Loop_Inactive.svg'
196                                 onImage: './images/AGL_MediaPlayer_Loop_Active.svg'
197                             }
198                         }
199                         ColumnLayout {
200                             anchors.fill: parent
201                             Label {
202                                 id: title
203                                 Layout.alignment: Layout.Center
204                                 text: bluetooth.av_connected ? bluetooth.title : (player.metaData.title ? player.metaData.title : '')
205                                 horizontalAlignment: Label.AlignHCenter
206                                 verticalAlignment: Label.AlignVCenter
207                             }
208                             Label {
209                                 Layout.alignment: Layout.Center
210                                 text: bluetooth.av_connected ? bluetooth.artist : (player.metaData.contributingArtist ? player.metaData.contributingArtist : '')
211                                 horizontalAlignment: Label.AlignHCenter
212                                 verticalAlignment: Label.AlignVCenter
213                                 font.pixelSize: title.font.pixelSize * 0.6
214                             }
215                         }
216                     }
217                     Slider {
218                         id: slider
219                         Layout.fillWidth: true
220                         to: bluetooth.av_connected ? bluetooth.duration : player.duration
221                         enabled: bluetooth.av_connected == false
222                         value: bluetooth.av_connected ? bluetooth.position : player.position
223                         function getPosition() {
224                             if (bluetooth.av_connected) {
225                                 return player.time2str(bluetooth.position)
226                             }
227                             return player.time2str(player.position)
228                         }
229                         Label {
230                             id: position
231                             anchors.left: parent.left
232                             anchors.bottom: parent.top
233                             font.pixelSize: 32
234                             text: slider.getPosition()
235                         }
236                         Label {
237                             id: duration
238                             anchors.right: parent.right
239                             anchors.bottom: parent.top
240                             font.pixelSize: 32
241                             text: bluetooth.av_connected ? player.time2str(bluetooth.duration) : player.time2str(player.duration)
242                         }
243                         onPressedChanged: player.seek(value)
244                     }
245                     RowLayout {
246                         Layout.fillHeight: true
247 //                        Image {
248 //                            source: './images/AGL_MediaPlayer_Playlist_Inactive.svg'
249 //                        }
250 //                        Image {
251 //                            source: './images/AGL_MediaPlayer_CD_Inactive.svg'
252 //                        }
253                         Item { Layout.fillWidth: true }
254                         ImageButton {
255                             id: previous
256                             offImage: './images/AGL_MediaPlayer_BackArrow.svg'
257                             onClicked: {
258                                 if (bluetooth.av_connected) {
259                                     bluetooth.sendMediaCommand("Previous")
260                                     bluetooth.position = 0
261                                 } else {
262                                     playlist.previous()
263                                 }
264                             }
265                         }
266                         ImageButton {
267                             id: play
268                             offImage: './images/AGL_MediaPlayer_Player_Play.svg'
269                             onClicked: {
270                                 if (bluetooth.av_connected) {
271                                     bluetooth.sendMediaCommand("Play")
272                                 } else {
273                                     console.log("mediaplayer: registered_media is " + registered_media)
274                                     if(registered_media)
275                                     {
276                                         console.log("mediaplayer: call connect")
277                                         var JsonArg = JSON.stringify({sourceID:sourceID, sinkID: 1})
278                                         smw.call("connect", JsonArg)
279                                     }
280                                 }
281                             }
282                             states: [
283                                 State {
284                                     when: player.playbackState === MediaPlayer.PlayingState
285                                     PropertyChanges {
286                                         target: play
287                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
288                                         onClicked: {
289                                             var JsonArg = JSON.stringify({mainConnectionID: connectionID})
290                                             console.log(JsonArg)
291                                             smw.call("disconnect",JsonArg)  
292                                         }
293                                     }
294                                 },
295                                 State {
296                                     when: bluetooth.av_connected && bluetooth.state == "playing"
297                                     PropertyChanges {
298                                         target: play
299                                         offImage: './images/AGL_MediaPlayer_Player_Pause.svg'
300                                         onClicked: bluetooth.sendMediaCommand("Pause")
301                                     }
302                                 }
303
304                             ]
305                         }
306                         ImageButton {
307                             id: forward
308                             offImage: './images/AGL_MediaPlayer_ForwardArrow.svg'
309                             onClicked: {
310                                 if (bluetooth.av_connected) {
311                                     bluetooth.sendMediaCommand("Next")
312                                 } else {
313                                     playlist.next()
314                                 }
315                             }
316                         }
317
318                         Item { Layout.fillWidth: true }
319  
320                         ToggleButton {
321                               visible: bluetooth.connected
322                               checked: bluetooth.av_connected
323                               offImage: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg'
324                               onImage: './images/AGL_MediaPlayer_Bluetooth_Active.svg'
325
326                               onClicked: {
327                                   if (bluetooth.av_connected) {
328                                       bluetooth.disconnect_profiles()
329                                   } else {
330                                       bluetooth.connect_profiles()
331                                   }
332                               }
333                         }
334                     }
335                 }
336             }
337         }
338         Item {
339             Layout.fillWidth: true
340             Layout.fillHeight: true
341             Layout.preferredHeight: 407
342
343                 PlaylistWithMetadata {
344                     id: playlistmodel
345                 source: playlist
346             }
347
348             ListView {
349                 anchors.fill: parent
350                 id: playlistview
351                 visible: bluetooth.av_connected == false
352                 clip: true
353                 header: Label {
354                     x: 50
355                     text: 'PLAYLIST'
356                     opacity: 0.5
357                 }
358                 model: playlistmodel
359                 currentIndex: playlist.currentIndex
360
361                 delegate: MouseArea {
362                     id: delegate
363                     width: ListView.view.width
364                     height: ListView.view.height / 4
365                     RowLayout {
366                         anchors.fill: parent
367                         anchors.leftMargin: 50
368                         anchors.rightMargin: 50
369                         Image {
370                             source: model.coverArt
371                             fillMode: Image.PreserveAspectFit
372                             Layout.preferredWidth: delegate.height
373                             Layout.preferredHeight: delegate.height
374                         }
375                         ColumnLayout {
376                             Layout.fillWidth: true
377                             Label {
378                                 Layout.fillWidth: true
379                                 text: model.title
380                             }
381                             Label {
382                                 Layout.fillWidth: true
383                                 text: model.artist
384                                 color: '#66FF99'
385                                 font.pixelSize: 32
386                             }
387                         }
388                         Label {
389                             text: player.time2str(model.duration)
390                             color: '#66FF99'
391                             font.pixelSize: 32
392                         }
393                     }
394                     onClicked: {
395                         playlist.currentIndex = model.index
396                         sourceIndex = model.index;
397                         console.log("mediaplayer: call connect")
398                         var JsonArg = JSON.stringify({sourceID:sourceID, sinkID: 1})
399                         smw.call("connect", JsonArg)
400                     }
401                 }
402
403                 highlight: Rectangle {
404                     color: 'white'
405                     opacity: 0.25
406                 }
407             }
408         }
409         Component.onCompleted: {
410             var media = JSON.stringify({appname:"mediaplayer"})
411             var bta   = JSON.stringify({appname:"bluetooth_audio"})
412             smw.call("registerSource",media)
413         }
414     }
415 }