IT tutorials
 
Technology
 

Windows Phone 8 : AudioPlayerAgent Sample (part 3) - Controlling Background Audio from Your Foreground App - MainPageViewModel

3/1/2014 8:05:06 PM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019

Most apps employing background audio are going to want to provide an enhanced interface within the foreground app for controlling playback and displaying track information. This section looks at the MainPage and associated classes of the WPUnleashed.BackgroundAudio project. The page allows the user to play audio via the BackgroundAudioPlayer class. It provides application bar buttons for play and pause, stop, rewind, and forward, and several fields for displaying the current track information.


Note

It is a Windows Phone Marketplace certification requirement that when the user is already playing background music on the phone when your app is launched, your app must ask the user for consent to stop playing or to adjust the background music. This prompt must occur each time the app launches, unless there is an opt-in setting provided to the user, and the user has used this setting to opt in.


A Testable BackgroundAudioPlayer

The BackgroundAudioPlayer class is inherently difficult to use in unit tests because of the cross-process interaction with the AudioPlayerAgent and its dependence on native phone components. For this reason I have provided a wrapper called BackgroundAudioPlayerProxy, which implements a custom IBackgroundAudioPlayer interface. In addition, a second implementation, MockBackgroundAudioPlayer, allows you to test whether your code called the background audio player as expected; it allows you to test, for example, whether your code attempted to play a track.

MainPageViewModel

The viewmodel is declared as a field of the MainPage, as shown:

readonly MainPageViewModel viewModel = new MainPageViewModel(
                                          new BackgroundAudioPlayerProxy(),
                                          new IsolatedStorageUtility());

The MainPageViewModel class constructor accepts an IBackgroundAudioPlayer as well as an IIsolatedStorageUtility instance (see Listing 1). A subscription to the PlayStateChanged event of the background audio player allows the viewmodel to update various properties whenever the play state changes.

The viewmodel contains five commands for controlling the BackgroundAudioPlayer while the app is in the foreground, which provide for playing, pausing, stopping, and skipping between tracks.

The viewmodel’s Refresh method is called to update the viewmodel, which relies on the state of the BackgroundAudioPlayer. A Timer is used to monitor the progress of the track while it is being played.

LISTING 1. MainPageViewModel Constructor


public MainPageViewModel(
    IBackgroundAudioPlayer backgroundAudioPlayer,
    IIsolatedStorageUtility isolatedStorageUtility)
{
    player = ArgumentValidator.AssertNotNull(
                backgroundAudioPlayer, "backgroundAudioPlayer");
    ArgumentValidator.AssertNotNull(
                isolatedStorageUtility, "isolatedStorageUtility");

    player.PlayStateChanged += HandlePlayStateChanged;
    BackgroundAudioPlayerAgent.CopyAudioToIsolatedStorage(isolatedStorageUtility);

    playCommand = new DelegateCommand(obj => player.Play());
    pauseCommand = new DelegateCommand(obj => player.Pause());
    stopCommand = new DelegateCommand(obj => player.Stop());
    previousTrackCommand = new DelegateCommand(obj => player.SkipPrevious());
    nextTrackCommand = new DelegateCommand(obj => player.SkipNext());

    Refresh(false);

    timer = new Timer(HandleTimerTick, null, 3000, 1000);
}


The viewmodel’s TrackArtist and TrackTitle properties reflect the Artist and Title properties of the current AudioTrack.

The viewmodel’s VisualState property, which is of type string, determines the visual state of the view, and the visibility of various application bar buttons. The VisualState value is set to the PlayerState property of the BackgroundAudioPlayer, as shown:

void Refresh(bool setVisualState = true)
{
    switch (player.PlayerState)
    {
        case PlayState.Playing:
            CanPause = true;
            TrackArtist = player.Track.Artist;
            TrackTitle = player.Track.Title;
            break;
        case PlayState.Paused:
            CanPause = false;
            break;
    }

    BufferingProgress = player.BufferingProgress;

    if (setVisualState)
    {
        VisualState = player.PlayerState.ToString("G");
    }

    if (player.Error != null)
    {
        MessageService.ShowError("A problem occured:" + player.Error);
    }
}

When the viewmodel’s VisualState property changes, the view responds by refreshing the VisualStateManager state. This is performed from the MainPage constructor, as shown:

public MainPage()
{
    InitializeComponent();

    DataContext = viewModel;

    viewModel.PropertyChanged
        += (sender, args) =>
            {
                if (args.PropertyName == "VisualState")
                {
                    SetVisualState();
                }
            };
}

The view’s custom AppBar includes icon buttons bound to the viewmodel’s commands, as shown:

<u:AppBar>
    <u:AppBarIconButton
            Command="{Binding PreviousTrackCommand}"
            Text="Previous"
            IconUri="/Images/ApplicationBarIcons/Previous.png" />

    <!-- A toggle button is used rather than visual state to avoid
         repopulating the app bar when the user taps play or pause. -->
    <u:AppBarToggleButton
            x:Name="Button_Play"
            Command1="{Binding PlayCommand}"
            Text1="Play"
            Icon1Uri="/Images/ApplicationBarIcons/Play.png"
            Command2="{Binding PauseCommand}"
            Text2="Pause"
            Icon2Uri="/Images/ApplicationBarIcons/Pause.png"
            Toggled="{Binding CanPause}"/>

    <u:AppBarIconButton
            x:Name="Button_Stop"
            Command="{Binding StopCommand}"
            Text="Stop"
            IconUri="/Images/ApplicationBarIcons/Stop.png" />

    <u:AppBarIconButton
            Command="{Binding NextTrackCommand}"
            Text="Previous"
            IconUri="/Images/ApplicationBarIcons/Next.png" />
</u:AppBar>

The viewmodel’s ViewState property determines the visibility of each button. The XAML that defines the VisualStateGroups is not shown, but if you are interested, see the downloadable sample code.

Two TextBlock controls are used to display the viewmodel’s TrackArtist and TrackTitle properties, like so:

<TextBlock Text="{Binding TrackArtist}"
            Style="{StaticResource PhoneTextTitle3Style}"
            TextWrapping="Wrap" />
<TextBlock Text="{Binding TrackTitle}"
            Style="{StaticResource PhoneTextTitle2Style}"
            TextWrapping="Wrap" />

Whenever the track changes, these fields are updated according to the new track.

 
Others
 
- Windows Phone 8 : AudioPlayerAgent Sample (part 2) - AudioPlayerAgent Virtual Methods
- Windows Phone 8 : AudioPlayerAgent Sample (part 1)
- Windows Phone 8 : Coordinating Background Audio Playback (part 2) - Representing Audio Files with the AudioTrack Class, Creating a Custom Audio Player Agent
- Windows Phone 8 : Coordinating Background Audio Playback (part 1) - Background Audio Player
- Microsoft Exchange Server 2013 : Site mailboxes (part 3) - The life cycle of site mailboxes, Site mailbox provisioning policy
- Microsoft Exchange Server 2013 : Site mailboxes (part 2) - How site mailboxes work - Synchronization between Exchange and SharePoint
- Microsoft Exchange Server 2013 : Site mailboxes (part 1) - How site mailboxes work
- Microsoft Exchange Server 2013 : Migration to modern public folders
- Microsoft Exchange Server 2013 : Migration to modern public folders
- Windows 8 : Using Secure Boot and SmartScreen Filter
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Technology FAQ
- Is possible to just to use a wireless router to extend wireless access to wireless access points?
- Ruby - Insert Struct to MySql
- how to find my Symantec pcAnywhere serial number
- About direct X / Open GL issue
- How to determine eclipse version?
- What SAN cert Exchange 2010 for UM, OA?
- How do I populate a SQL Express table from Excel file?
- code for express check out with Paypal.
- Problem with Templated User Control
- ShellExecute SW_HIDE
programming4us programming4us