X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=app%2FMediaPlayer.qml;h=6f8d0db20f51f51b9f5e742afbde3fda19684ca3;hb=62307df679bcd1a69874bb66439cb6451e9ce29b;hp=dae74a0050c6e23a1f6e1bdd633696fd22135a40;hpb=4eee2655560fbb2f7724095bb7fa488f3f39ba55;p=apps%2Fmediaplayer.git diff --git a/app/MediaPlayer.qml b/app/MediaPlayer.qml index dae74a0..6f8d0db 100644 --- a/app/MediaPlayer.qml +++ b/app/MediaPlayer.qml @@ -19,57 +19,168 @@ import QtQuick.Layouts 1.1 import QtQuick.Controls 2.0 import QtMultimedia 5.6 import AGL.Demo.Controls 1.0 -import MediaPlayer 1.0 ApplicationWindow { id: root - function clearMetadata() { - title.text = '' - artist.text = '' - duration.text = player.time2str(0) - albumart.visible = false + Item { + id: player + + property string title: "" + property string album: "" + property string artist: "" + + property int duration: 0 + property int position: 0 + + property string cover_art: "" + property string status: "" + + function time2str(value) { + return Qt.formatTime(new Date(value), 'mm:ss') + } } - Connections { - target: dbus - onProcessPlaylistUpdate: { - playlist.clear() - playlist.addItems(mediaFiles) - - playlistmodel.setSource(playlist) - playlistview.visible = true - albumart.visible = true + Item { + id: bluetooth + + property string deviceAddress: "" + property bool connected: false + property bool av_connected: false + + property int position: 0 + property int duration: 0 + + property string artist: "" + property string title: "" + property string state: "stopped" + + // AVRCP Target UUID + property string avrcp_uuid: "0000110e-0000-1000-8000-00805f9b34fb" + + function connect_profiles() { + var address = bluetooth.deviceAddress; + bluetooth_connection.connect(address, "a2dp") + bluetooth_connection.connect(address, "avrcp") } - onProcessPlaylistHide: { - player.stop() - playlistview.visible = false - clearMetadata() + function disconnect_profiles() { + var address = bluetooth.deviceAddress; + bluetooth_connection.disconnect(address, "a2dp") + bluetooth_connection.disconnect(address, "avrcp") } + function set_avrcp_controls(cmd) { + bluetooth_connection.set_avrcp_controls(bluetooth.deviceAddress, cmd) + } } - MediaPlayer { - id: player - audioRole: MediaPlayer.MusicRole - autoLoad: true - playlist: playlist - function time2str(value) { - return Qt.formatTime(new Date(value), 'mm:ss') + Connections { + target: bluetooth_connection + + onDeviceListEvent: { + var address = "" + for (var i = 0; i < data.list.length; i++) { + var item = data.list[i] + if (item.Connected == "True" && item.UUIDs.indexOf(bluetooth.avrcp_uuid) >= 0) { + address = item.Address + + bluetooth.connected = true + mediaplayer.pause() + + //NOTE: This hack is here for when MediaPlayer is started + // with an existing connection. + bluetooth.av_connected = item.AVPConnected == "True" + } + } + if (!address) + bluetooth.connected = false + else + bluetooth.deviceAddress = address + } + + onDeviceUpdatedEvent: { + var metadata = data.Metadata + + if (data.Connected == "False") + return + + bluetooth.connected = data.Connected == "True" + bluetooth.av_connected = data.AVPConnected == "True" + bluetooth.deviceAddress = data.Address + + if ('Position' in metadata) + bluetooth.position = metadata.Position + + if ('Duration' in metadata) + bluetooth.duration = metadata.Duration + + if ('Status' in metadata) + bluetooth.state = metadata.Status + + if ('Artist' in metadata) + bluetooth.artist = metadata.Artist + + if ('Title' in metadata) + bluetooth.title = metadata.Title } - onPositionChanged: slider.value = player.position } - Playlist { - id: playlist - playbackMode: random.checked ? Playlist.Random : loop.checked ? Playlist.Loop : Playlist.Sequential + Connections { + target: mediaplayer + + onPlaylistChanged: { + playlist_model.clear(); + + for (var i = 0; i < playlist.list.length; i++) { + var item = playlist.list[i] + + playlist_model.append({ "index": item.index, "artist": item.artist ? item.artist : '', "title": item.title ? item.title : '' }) + + if (item.selected) { + playlistview.currentIndex = i + } + } + } + + onMetadataChanged: { + player.title = metadata.title + player.album = metadata.album + player.artist = metadata.artist + + if (metadata.duration) { + player.duration = metadata.duration + } + + if (metadata.position) { + player.position = metadata.position + } - Component.onCompleted: { - playlist.addItems(mediaFiles) + if (metadata.status) { + player.status = metadata.status + } + + if (metadata.image) { + player.cover_art = metadata.image + } + + playlistview.currentIndex = metadata.index } } + Timer { + id: timer + interval: 250 + running: (bluetooth.av_connected && bluetooth.state == "playing") + repeat: true + onTriggered: { + bluetooth.position = bluetooth.position + 250 + } + } + + ListModel { + id: playlist_model + } ColumnLayout { anchors.fill: parent @@ -85,7 +196,8 @@ ApplicationWindow { anchors.bottom: parent.bottom height: sourceSize.height * width / sourceSize.width fillMode: Image.PreserveAspectCrop - source: player.metaData.coverArtImage ? player.metaData.coverArtImage : '' + source: player.cover_art ? player.cover_art : '' + visible: bluetooth.av_connected == false } Item { @@ -107,15 +219,19 @@ ApplicationWindow { Layout.fillHeight: true Row { spacing: 20 - ToggleButton { - id: random - offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg' - onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg' - } + //ToggleButton { + // id: random + // visible: bluetooth.connected == false + // offImage: './images/AGL_MediaPlayer_Shuffle_Inactive.svg' + // onImage: './images/AGL_MediaPlayer_Shuffle_Active.svg' + //} ToggleButton { id: loop + visible: bluetooth.connected == false + //checked: player.loop_state offImage: './images/AGL_MediaPlayer_Loop_Inactive.svg' onImage: './images/AGL_MediaPlayer_Loop_Active.svg' + onClicked: { mediaplayer.loop(checked) } } } ColumnLayout { @@ -123,14 +239,13 @@ ApplicationWindow { Label { id: title Layout.alignment: Layout.Center - text: player.metaData.title ? player.metaData.title : '' + text: bluetooth.av_connected ? bluetooth.title : (player.title ? player.title : '') horizontalAlignment: Label.AlignHCenter verticalAlignment: Label.AlignVCenter } Label { - id: artist Layout.alignment: Layout.Center - text: player.metaData.contributingArtist ? player.metaData.contributingArtist : '' + text: bluetooth.av_connected ? bluetooth.artist : (player.artist ? player.artist : '') horizontalAlignment: Label.AlignHCenter verticalAlignment: Label.AlignVCenter font.pixelSize: title.font.pixelSize * 0.6 @@ -140,22 +255,30 @@ ApplicationWindow { Slider { id: slider Layout.fillWidth: true - to: player.duration + to: bluetooth.av_connected ? bluetooth.duration : player.duration + enabled: bluetooth.av_connected == false + value: bluetooth.av_connected ? bluetooth.position : player.position + function getPosition() { + if (bluetooth.av_connected) { + return player.time2str(bluetooth.position) + } + return player.time2str(player.position) + } Label { id: position anchors.left: parent.left anchors.bottom: parent.top font.pixelSize: 32 - text: player.time2str(player.position) + text: slider.getPosition() } Label { id: duration anchors.right: parent.right anchors.bottom: parent.top font.pixelSize: 32 - text: player.time2str(player.duration) + text: bluetooth.av_connected ? player.time2str(bluetooth.duration) : player.time2str(player.duration) } - onPressedChanged: player.seek(value) + onPressedChanged: mediaplayer.seek(value) } RowLayout { Layout.fillHeight: true @@ -167,36 +290,78 @@ ApplicationWindow { // } Item { Layout.fillWidth: true } ImageButton { + id: previous offImage: './images/AGL_MediaPlayer_BackArrow.svg' - onClicked: playlist.previous() + onClicked: { + if (bluetooth.av_connected) { + bluetooth.set_avrcp_controls("Previous") + bluetooth.position = 0 + } else { + mediaplayer.previous() + } + } } ImageButton { id: play offImage: './images/AGL_MediaPlayer_Player_Play.svg' - onClicked: player.play() + onClicked: { + if (bluetooth.av_connected) { + bluetooth.set_avrcp_controls("Play") + } else { + mediaplayer.play() + } + } states: [ State { - when: player.playbackState === MediaPlayer.PlayingState + when: player.status == "playing" PropertyChanges { target: play offImage: './images/AGL_MediaPlayer_Player_Pause.svg' - onClicked: player.pause() + onClicked: { + player.status = "" + mediaplayer.pause() + } + } + }, + State { + when: bluetooth.av_connected && bluetooth.state == "playing" + PropertyChanges { + target: play + offImage: './images/AGL_MediaPlayer_Player_Pause.svg' + onClicked: bluetooth.set_avrcp_controls("Pause") } } + ] } ImageButton { + id: forward offImage: './images/AGL_MediaPlayer_ForwardArrow.svg' - onClicked: playlist.next() + onClicked: { + if (bluetooth.av_connected) { + bluetooth.set_avrcp_controls("Next") + } else { + mediaplayer.next() + } + } } Item { Layout.fillWidth: true } -// Image { -// source: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg' -// } -// Image { -// source: './images/AGL_MediaPlayer_Radio_Inactive.svg' -// } + + ToggleButton { + visible: bluetooth.connected + checked: bluetooth.av_connected + offImage: './images/AGL_MediaPlayer_Bluetooth_Inactive.svg' + onImage: './images/AGL_MediaPlayer_Bluetooth_Active.svg' + + onClicked: { + if (bluetooth.av_connected) { + bluetooth.disconnect_profiles() + } else { + bluetooth.connect_profiles() + } + } + } } } } @@ -206,22 +371,18 @@ ApplicationWindow { Layout.fillHeight: true Layout.preferredHeight: 407 - PlaylistWithMetadata { - id: playlistmodel - source: playlist - } - ListView { anchors.fill: parent id: playlistview + visible: bluetooth.av_connected == false clip: true header: Label { x: 50 text: 'PLAYLIST' opacity: 0.5 } - model: playlistmodel - currentIndex: playlist.currentIndex + model: playlist_model + currentIndex: -1 delegate: MouseArea { id: delegate @@ -231,12 +392,6 @@ ApplicationWindow { anchors.fill: parent anchors.leftMargin: 50 anchors.rightMargin: 50 - Image { - source: model.coverArt - fillMode: Image.PreserveAspectFit - Layout.preferredWidth: delegate.height - Layout.preferredHeight: delegate.height - } ColumnLayout { Layout.fillWidth: true Label { @@ -246,19 +401,18 @@ ApplicationWindow { Label { Layout.fillWidth: true text: model.artist - color: '#66FF99' + color: '#00ADDC' font.pixelSize: 32 } } - Label { - text: player.time2str(model.duration) - color: '#66FF99' - font.pixelSize: 32 - } + //Label { + // text: player.time2str(model.duration) + // color: '#00ADDC' + // font.pixelSize: 32 + //} } onClicked: { - playlist.currentIndex = model.index - player.play() + mediaplayer.picktrack(playlistview.model.get(index).index) } }