Qt-based BB10 API Examples Documentation

Contents

NowPlaying Example

Files:

Description

The NowPlaying example demonstrates how to use the multimedia framework of BB10 to provide extended information in the UI about the media currently played and to control the media player with hardware keys.

Overview

In this example we'll learn how to use the MediaPlayer and NowPlayingConnection classes, to show extended information about the currently played media in the menu bar of the home screen (see play icon in the screenshot below) and react to the hardware buttons to pause/resume the playback of the media.

The NowPlayingConnection class acts as an mediator between the MediaPlayer and the BB10 system. It provides signals that are emitted whenever the user triggers some actions (e.g. pauses or resumes the playback via hardware button) and it provides properties that can be modified to show data about the media in the media area in the menu bar of the home screen. However the NowPlayingConnection can also be used to control a MediaPlayer programatically.

UI

The UI of this sample application consists of an ImageButton that reflects the current state of the MediaPlayer and is also used to start and stop the playback. At the bottom of the screen a progress bar is located to visualize the current progress of the playback.

    ImageButton {
        horizontalAlignment: HorizontalAlignment.Center
        verticalAlignment: VerticalAlignment.Center

        defaultImageSource: player.mediaState == MediaState.Started ? "asset:///images/stop_button.png" :
                            player.mediaState == MediaState.Paused  ? "asset:///images/pause_button.png" :
                                                                      "asset:///images/play_button.png"

        onClicked: {
            if (player.mediaState == MediaState.Started)
                nowPlaying.revoke()
            else
                nowPlaying.acquire()
        }
    }

The 'defaultImageSource' property of the ImageButton depends on the 'mediaState' property of the MediaPlayer. So whenever the player changes its state, the ImageButton will show the corresponding image. If the user clicks on the button, we invoke the acquire() (play) or revoke() (stop) methods on the NowPlayingConnection depending on the current state of the MediaPlayer.

The MediaPlayer object is created as an attached object to the page. It plays a sound file that is specified at its 'sourceUrl' property.

    MediaPlayer {
        id: player

        sourceUrl: "music/song.mp3"
    },

The NowPlayingConnection object is created as an attached object as well. Its 'duration' and 'position' properties are bound against the 'duration' and 'position' properties of the MediaPlayer, so that whenever the progress of the media player changes, the data in the NowPlayingConnection object are updated automatically. For each signal of the NowPlayingConnection object, a signal handler has been defined to start, stop, pause or resume the playback.

As you can see, we never control the playback of the MediaPlayer directly, we always go through the NowPlayingConnection.

    NowPlayingConnection {
        id: nowPlaying

        duration: player.duration
        position: player.position
        iconUrl: "asset:///images/music.png"
        mediaState: player.mediaState

        onAcquired: {
            player.play()

            nowPlaying.mediaState = MediaState.Started
            nowPlaying.metaData = player.metaData
        }

        onPause: {
            player.pause()
        }

        onPlay: {
            player.play()
        }

        onRevoked: {
            player.stop()
        }
    }

The progress bar is a custom component that is implemented in ProgressBar.qml

    ProgressBar {
        horizontalAlignment: HorizontalAlignment.Center
        verticalAlignment: VerticalAlignment.Bottom

        duration: nowPlaying.duration
        position: nowPlaying.position
    }

We bind the 'duration' and 'position' properties of the NowPlayingConnection object against its custom properties, so that the progress bar can visualize these data.

    Container {
        id: root

        property int duration: 1
        property int position: 1

        bottomPadding: 20

        layout: StackLayout {
            orientation: LayoutOrientation.LeftToRight
        }

        ProgressIndicator {
            verticalAlignment: VerticalAlignment.Center
            preferredWidth: 600

            fromValue: 0
            toValue: root.duration
            value: root.position
        }

        Label {
            verticalAlignment: VerticalAlignment.Center

            property int minutes: Math.floor(root.position/1000/60)
            property int seconds: Math.floor(root.position/1000%60)

            text: qsTr("%1:%2").arg(minutes < 10 ? "0" + minutes : "" + minutes)
                                .arg(seconds < 10 ? "0" + seconds : "" + seconds)
            textStyle {
                base: SystemDefaults.TextStyles.SmallText
                color: Color.Gray
            }
        }
    }

The progress bar consist of a ProgressIndicator and a Label. We define the range of the ProgressIndicator to be between '0' and the duration of the media. The current value is indirectly bound against the 'position' property of the NowPlayingConnection object.

The Label displays the current position by formatting the milliseconds into "mm:ss" format.