Quickstart: Creating a Play To Receiver (XAML)

[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]

You can create a software Play To receiver that receives media streamed from a client computer and plays or displays the content as part of your app. This topic shows you how to create a Windows Store app that advertises itself on your local network as a Digital Media Renderer, receives video media from another computer, plays that video, and responds to additional commands from the client computer such as volume changes, playback location changes, and so on.

Prerequisites

Microsoft Visual Studio

Create a new project and enable access to Pictures

  1. Open Visual Studio and select New Project from the File menu. In the Visual C# or Visual Basic section, select Blank Application. Name the application PlayToReceiverSample and click OK.
  2. Open the package.appxmanifest file and select the Capabilities tab. Select the Home or Work Networking capability to enable your application to connect to other computers within your local network. Close and save the manifest file.

Add XAML UI

Open the MainPage.xaml file and add the following to the default Grid element.

<Button x:Name="StartReceiverButton" Content="Start Play To Receiver" Margin="283,26,0,703" Click="StartReceiverButton_Click" />
<Button x:Name="StopReceiverButton" Content="Stop Play To Receiver" Margin="907,26,0,703" Click="StopReceiverButton_Click" />
<MediaElement x:Name="VideoPlayer" Height="600" Width="800" Source="" />
<TextBlock x:Name="StatusTextBlock" Height="60" Width="800" Foreground="Green" Margin="283,689,283,19" />

Add button event handlers

The code in this step defines the event handlers for the start and stop buttons. During the event handler for the start button, the code creates an instance of the PlayToReceiver class that is the Play To receiver for the app. After the code creates the Play To receiver instance, it then associates event handlers with the Play To receiver events. These events are raised when an action is requested by the Play To client computer. These actions include receiving the source media, which raises the SourceChangeRequested event, and requests to pause, continue, or stop playing the media, change the volume level, mute, or un-mute the audio, change the media playback rate or change the playback location time. Each action has a respective event.

After the event handlers are added, the app sets the FriendlyName property of the Play To receiver that identifies the name of the Play To receiver as it is seen on the network, and the properties that show that this Play To receiver only supports video.

After the Play To receiver has been initialized, the app associates event handlers for the HTML5 video tag. These events are raised when an action occurs for the video tag that is included in the app. When these events occur, the event handler calls a notify method of the Play To receiver to inform the Play To client of the action. For example, when the media finishes playing, the ended event of the video tag is raised. During the event handler for the ended event, the code calls the NotifyEnded event of the Play To receiver to inform the client computer that the video has finished.

After both the Play To receiver and the video tag have been initialized, the code in the start button handler calls the StartAsync method to advertise the app as a Digital Media Renderer on the local network. The app also gets a reference to the active display window to prevent the screen from locking.

In the event handler for the stop button, the code calls the StopAsync button to stop advertizing the Play To receiver, releases the reference to the active display window, and removes the event handlers for the Play To receiver and video tag.

Open the MainPage.xaml.cs or MainPage.xaml.vb file and add the following code to the MainPage class.

Windows.Media.PlayTo.PlayToReceiver receiver;
Windows.System.Display.DisplayRequest display;
Windows.UI.Core.CoreDispatcher dispatcher;
bool seeking = false;

private async void StartReceiverButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        dispatcher = Window.Current.CoreWindow.Dispatcher;

        if (receiver == null)
        {
            receiver = new Windows.Media.PlayTo.PlayToReceiver();
        }

        // Add Play To Receiver events and properties
        receiver.CurrentTimeChangeRequested += receiver_CurrentTimeChangeRequested;
        receiver.MuteChangeRequested += receiver_MuteChangeRequested;
        receiver.PauseRequested += receiver_PauseRequested;
        receiver.PlaybackRateChangeRequested += receiver_PlaybackRateChangeRequested;
        receiver.PlayRequested += receiver_PlayRequested;
        receiver.SourceChangeRequested += receiver_SourceChangeRequested;
        receiver.StopRequested += receiver_StopRequested;
        receiver.TimeUpdateRequested += receiver_TimeUpdateRequested;
        receiver.VolumeChangeRequested += receiver_VolumeChangeRequested;

        receiver.FriendlyName = "Sample Play To Receiver";
        receiver.SupportsAudio = false;
        receiver.SupportsVideo = true;
        receiver.SupportsImage = false;

        // Add MediaElement events
        VideoPlayer.CurrentStateChanged += VideoPlayer_CurrentStateChanged;
        VideoPlayer.MediaEnded += VideoPlayer_MediaEnded;
        VideoPlayer.MediaFailed += VideoPlayer_MediaFailed;
        VideoPlayer.MediaOpened += VideoPlayer_MediaOpened;
        VideoPlayer.RateChanged += VideoPlayer_RateChanged;
        VideoPlayer.SeekCompleted += VideoPlayer_SeekCompleted;
        VideoPlayer.VolumeChanged += VideoPlayer_VolumeChanged;

        // Advertise the receiver on the local network and start receiving commands
        await receiver.StartAsync();

        // Prevent the screen from locking
        if (display == null)
            display = new Windows.System.Display.DisplayRequest();
        display.RequestActive();

        StatusTextBlock.Text = "'" + receiver.FriendlyName + "' started.";
    }
    catch
    {
        receiver = null;
        StatusTextBlock.Text = "Failed to start receiver.";
    }
}

private async void StopReceiverButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        if (receiver != null)
        {
            await receiver.StopAsync();

            if (display != null)
                display.RequestRelease();

            // Remove Play To Receiver events
            receiver.CurrentTimeChangeRequested -= receiver_CurrentTimeChangeRequested;
            receiver.MuteChangeRequested -= receiver_MuteChangeRequested;
            receiver.PauseRequested -= receiver_PauseRequested;
            receiver.PlaybackRateChangeRequested -= receiver_PlaybackRateChangeRequested;
            receiver.PlayRequested -= receiver_PlayRequested;
            receiver.SourceChangeRequested -= receiver_SourceChangeRequested;
            receiver.StopRequested -= receiver_StopRequested;
            receiver.TimeUpdateRequested -= receiver_TimeUpdateRequested;
            receiver.VolumeChangeRequested -= receiver_VolumeChangeRequested;

            //  Remove MediaElement events
            VideoPlayer.Pause();

            VideoPlayer.CurrentStateChanged -= VideoPlayer_CurrentStateChanged;
            VideoPlayer.MediaEnded -= VideoPlayer_MediaEnded;
            VideoPlayer.MediaFailed -= VideoPlayer_MediaFailed;
            VideoPlayer.MediaOpened -= VideoPlayer_MediaOpened;
            VideoPlayer.RateChanged -= VideoPlayer_RateChanged;
            VideoPlayer.SeekCompleted -= VideoPlayer_SeekCompleted;
            VideoPlayer.VolumeChanged -= VideoPlayer_VolumeChanged;

            StatusTextBlock.Text = "Stopped '" + receiver.FriendlyName + "'.";
        }
    }
    catch
    {
        StatusTextBlock.Text = "Failed to stop '" + receiver.FriendlyName + "'.";
    }
}
Private receiver As Windows.Media.PlayTo.PlayToReceiver
Private display As Windows.System.Display.DisplayRequest
Private seeking As Boolean = False

Private Async Sub StartReceiverButton_Click()
    Try
        If receiver Is Nothing Then
            receiver = New Windows.Media.PlayTo.PlayToReceiver()
        End If

        ' Add Play To Receiver events and properties
        AddHandler receiver.CurrentTimeChangeRequested, AddressOf receiver_CurrentTimeChangeRequested
        AddHandler receiver.MuteChangeRequested, AddressOf receiver_MuteChangeRequested
        AddHandler receiver.PauseRequested, AddressOf receiver_PauseRequested
        AddHandler receiver.PlaybackRateChangeRequested, AddressOf receiver_PlaybackRateChangeRequested
        AddHandler receiver.PlayRequested, AddressOf receiver_PlayRequested
        AddHandler receiver.SourceChangeRequested, AddressOf receiver_SourceChangeRequested
        AddHandler receiver.StopRequested, AddressOf receiver_StopRequested
        AddHandler receiver.TimeUpdateRequested, AddressOf receiver_TimeUpdateRequested
        AddHandler receiver.VolumeChangeRequested, AddressOf receiver_VolumeChangeRequested

        receiver.FriendlyName = "Sample Play To Receiver"
        receiver.SupportsAudio = False
        receiver.SupportsVideo = True
        receiver.SupportsImage = False

        ' Add MediaElement events
        AddHandler VideoPlayer.CurrentStateChanged, AddressOf VideoPlayer_CurrentStateChanged
        AddHandler VideoPlayer.MediaEnded, AddressOf VideoPlayer_MediaEnded
        AddHandler VideoPlayer.MediaFailed, AddressOf VideoPlayer_MediaFailed
        AddHandler VideoPlayer.MediaOpened, AddressOf VideoPlayer_MediaOpened
        AddHandler VideoPlayer.RateChanged, AddressOf VideoPlayer_RateChanged
        AddHandler VideoPlayer.SeekCompleted, AddressOf VideoPlayer_SeekCompleted
        AddHandler VideoPlayer.VolumeChanged, AddressOf VideoPlayer_VolumeChanged

        ' Advertise the receiver on the local network and start receiving commands
        Await receiver.StartAsync()

        ' Prevent the screen from locking
        If display Is Nothing Then
            display = New Windows.System.Display.DisplayRequest()
            display.RequestActive()

            StatusTextBlock.Text = "'" & receiver.FriendlyName & "' started."
        End If
    Catch
        receiver = Nothing
        StatusTextBlock.Text = "Failed to start receiver. "
    End Try
End Sub

Private Async Sub StopReceiverButton_Click()
    Try
        If receiver IsNot Nothing Then
            Await receiver.StopAsync()

            If display IsNot Nothing Then display.RequestRelease()

            ' Remove Play To Receiver events
            RemoveHandler receiver.CurrentTimeChangeRequested, AddressOf receiver_CurrentTimeChangeRequested
            RemoveHandler receiver.MuteChangeRequested, AddressOf receiver_MuteChangeRequested
            RemoveHandler receiver.PauseRequested, AddressOf receiver_PauseRequested
            RemoveHandler receiver.PlaybackRateChangeRequested, AddressOf receiver_PlaybackRateChangeRequested
            RemoveHandler receiver.PlayRequested, AddressOf receiver_PlayRequested
            RemoveHandler receiver.SourceChangeRequested, AddressOf receiver_SourceChangeRequested
            RemoveHandler receiver.StopRequested, AddressOf receiver_StopRequested
            RemoveHandler receiver.TimeUpdateRequested, AddressOf receiver_TimeUpdateRequested
            RemoveHandler receiver.VolumeChangeRequested, AddressOf receiver_VolumeChangeRequested

            '  Remove MediaElement events
            VideoPlayer.Pause()

            RemoveHandler VideoPlayer.CurrentStateChanged, AddressOf VideoPlayer_CurrentStateChanged
            RemoveHandler VideoPlayer.MediaEnded, AddressOf VideoPlayer_MediaEnded
            RemoveHandler VideoPlayer.MediaFailed, AddressOf VideoPlayer_MediaFailed
            RemoveHandler VideoPlayer.MediaOpened, AddressOf VideoPlayer_MediaOpened
            RemoveHandler VideoPlayer.RateChanged, AddressOf VideoPlayer_RateChanged
            RemoveHandler VideoPlayer.SeekCompleted, AddressOf VideoPlayer_SeekCompleted
            RemoveHandler VideoPlayer.VolumeChanged, AddressOf VideoPlayer_VolumeChanged

            StatusTextBlock.Text = "Stopped '" & receiver.FriendlyName & "'."
        End If
    Catch
        StatusTextBlock.Text = "Failed to stop '" & receiver.FriendlyName & "'."
    End Try
End Sub

Add Play To receiver event handlers

The code in this step adds the code for the Play To receiver event handlers. These event handlers are called in response to requests from the Play To client computer. For example, if the Play To client computer mutes or un-mutes the volume, then the MuteChangeRequested event is raised. In the associated event handler, the app mutes or un-mutes the local video tag in response to the request.

Add the following code to the MainPage.xaml.cs or MainPage.xaml.vb file and after the code from the previous step.

async void receiver_CurrentTimeChangeRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    Windows.Media.PlayTo.CurrentTimeChangeRequestedEventArgs args)
{
    await dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            VideoPlayer.Position = args.Time;
            receiver.NotifySeeking();
            seeking = true;
        });
}

async void receiver_MuteChangeRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    Windows.Media.PlayTo.MuteChangeRequestedEventArgs args)
{
    await dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            VideoPlayer.IsMuted = args.Mute;
        });
}

async void receiver_PauseRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    object args)
{
    await dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            VideoPlayer.Pause();
        });
}

async void receiver_PlaybackRateChangeRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    Windows.Media.PlayTo.PlaybackRateChangeRequestedEventArgs args)
{
    await dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            VideoPlayer.PlaybackRate = args.Rate;
        });
}

async void receiver_PlayRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    object args)
{
    await dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            VideoPlayer.Play();
        });
}

async void receiver_SourceChangeRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    Windows.Media.PlayTo.SourceChangeRequestedEventArgs args)
{
    if (args.Stream != null)
        await dispatcher.RunAsync(
            Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                var stream = args.Stream as Windows.Storage.Streams.IRandomAccessStream;
                VideoPlayer.SetSource(stream, args.Stream.ContentType);
            });
}

async void receiver_StopRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    object args)
{
    await dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            VideoPlayer.Stop();
        });
}

async void receiver_TimeUpdateRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    object args)
{
    await dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            if (VideoPlayer.Position != null)
                receiver.NotifyTimeUpdate(VideoPlayer.Position);
        });
}

async void receiver_VolumeChangeRequested(
    Windows.Media.PlayTo.PlayToReceiver sender,
    Windows.Media.PlayTo.VolumeChangeRequestedEventArgs args)
{
    await dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            VideoPlayer.Volume = args.Volume;
        });
}
Async Sub receiver_CurrentTimeChangeRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Windows.Media.PlayTo.CurrentTimeChangeRequestedEventArgs)
    Await Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        Sub()
            VideoPlayer.Position = args.Time
            receiver.NotifySeeking()
            seeking = True
        End Sub)
End Sub

Async Sub receiver_MuteChangeRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Windows.Media.PlayTo.MuteChangeRequestedEventArgs)
    Await Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        Sub()
            VideoPlayer.IsMuted = args.Mute
        End Sub)
End Sub

Async Sub receiver_PauseRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Object)

    Await Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        Sub()
            VideoPlayer.Pause()
        End Sub)
End Sub

Async Sub receiver_PlaybackRateChangeRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Windows.Media.PlayTo.PlaybackRateChangeRequestedEventArgs)

    Await Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        Sub()
            VideoPlayer.PlaybackRate = args.Rate
        End Sub)
End Sub

Async Sub receiver_PlayRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Object)

    Await Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        Sub()
            VideoPlayer.Play()
        End Sub)
End Sub

Async Sub receiver_SourceChangeRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Windows.Media.PlayTo.SourceChangeRequestedEventArgs)

    If args.Stream IsNot Nothing Then
        Await Dispatcher.RunAsync(
            Windows.UI.Core.CoreDispatcherPriority.Normal,
            Sub()
                Dim stream = TryCast(args.Stream, Windows.Storage.Streams.IRandomAccessStream)
                VideoPlayer.SetSource(stream, args.Stream.ContentType)
            End Sub)
    End If
End Sub

Async Sub receiver_StopRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Object)

    Await Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        Sub()

            VideoPlayer.Stop()
        End Sub)
End Sub

Async Sub receiver_TimeUpdateRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Object)

    Await Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        Sub()
            receiver.NotifyTimeUpdate(VideoPlayer.Position)
        End Sub)
End Sub

Async Sub receiver_VolumeChangeRequested(
    sender As Windows.Media.PlayTo.PlayToReceiver,
    args As Windows.Media.PlayTo.VolumeChangeRequestedEventArgs)

    Await Dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        Sub()
            VideoPlayer.Volume = args.Volume
        End Sub)
End Sub

Add video player event handlers

The code in this step adds the code for the video player event handlers. These event handlers are called when events occur for the local video player. The event handlers then notify the client computer using the respective Play To receiver method.

  1. Add the following code to the MainPage.xaml.cs or MainPage.xaml.vb file and after the code from the previous step.

    void VideoPlayer_CurrentStateChanged(object sender, RoutedEventArgs e)
    {
        if (receiver != null)
        {
            switch (VideoPlayer.CurrentState)
            {
                case MediaElementState.Playing:
                    receiver.NotifyPlaying();
                    break;
                case MediaElementState.Paused:
                    receiver.NotifyPaused();
                    break;
                case MediaElementState.Stopped:
                    receiver.NotifyStopped();
                    break;
            }
        }
    }
    
    void VideoPlayer_MediaFailed(object sender, ExceptionRoutedEventArgs e)
    {
        if (receiver != null) { receiver.NotifyError(); }
    }
    
    void VideoPlayer_MediaEnded(object sender, RoutedEventArgs e)
    {
        if (receiver != null)
        {
            receiver.NotifyEnded();
            VideoPlayer.Stop();
        }
    }
    
    void VideoPlayer_MediaOpened(object sender, RoutedEventArgs e)
    {
        if (receiver != null)
        {
            receiver.NotifyDurationChange(VideoPlayer.NaturalDuration.TimeSpan);
            receiver.NotifyLoadedMetadata();
        }
    }
    
    void VideoPlayer_RateChanged(object sender, RateChangedRoutedEventArgs e)
    {
        if (receiver != null)
            receiver.NotifyRateChange(VideoPlayer.PlaybackRate);
    }
    
    void VideoPlayer_SeekCompleted(object sender, RoutedEventArgs e)
    {
        if (receiver != null)
        {
            if (!seeking)
                receiver.NotifySeeking();
            receiver.NotifySeeked();
            seeking = false;
        }
    }
    
    void VideoPlayer_VolumeChanged(object sender, RoutedEventArgs e)
    {
        if (receiver != null)
            receiver.NotifyVolumeChange(VideoPlayer.Volume, VideoPlayer.IsMuted);
    }
    
    Sub VideoPlayer_CurrentStateChanged()
    
        If receiver IsNot Nothing Then
            Select Case VideoPlayer.CurrentState
                Case MediaElementState.Playing
                    receiver.NotifyPlaying()
                Case MediaElementState.Paused
                    receiver.NotifyPaused()
                Case MediaElementState.Stopped
                    receiver.NotifyStopped()
            End Select
        End If
    End Sub
    
    Sub VideoPlayer_MediaFailed()
        If receiver IsNot Nothing Then receiver.NotifyError()
    End Sub
    
    Sub VideoPlayer_MediaEnded()
        If receiver IsNot Nothing Then
            receiver.NotifyEnded()
            VideoPlayer.Stop()
        End If
    End Sub
    
    Sub VideoPlayer_MediaOpened()
        If receiver IsNot Nothing Then
            receiver.NotifyDurationChange(VideoPlayer.NaturalDuration.TimeSpan)
            receiver.NotifyLoadedMetadata()
        End If
    End Sub
    
    Sub VideoPlayer_RateChanged()
        If receiver IsNot Nothing Then
            receiver.NotifyRateChange(VideoPlayer.PlaybackRate)
        End If
    End Sub
    
    Sub VideoPlayer_SeekCompleted()
        If receiver IsNot Nothing Then
            If Not seeking Then
                receiver.NotifySeeking()
                receiver.NotifySeeked()
                seeking = False
            End If
        End If
    End Sub
    
    Sub VideoPlayer_VolumeChanged()
        If receiver IsNot Nothing Then
            receiver.NotifyVolumeChange(VideoPlayer.Volume, VideoPlayer.IsMuted)
        End If
    End Sub
    
  2. Save and close the MainPage.xaml.cs or MainPage.xaml.vb file

Run the app

  1. In Visual Studio, press F5 (debug) to run the app.
  2. Click the Start Play To Receiver button.
  3. If the Play To receiver successfully starts, open the Settings charm on another computer and select More PC Settings. In the More Settings window, select Devices.
  4. In the Devices section, click Add a device. Locate the Sample Play To Receiver Digital Media Renderer. If you changed the value of the FriendlyName property of the Play To receiver, then locate that name. Select the Play To receiver from the list to add it.
  5. On the client computer, play a video that can be streamed using Play To. While the media is playing, open the Devices charm and select your custom Play To receiver as the target for the streamed video.

Summary

In this quickstart, you created an app that advertises itself as a Digital Media Renderer and plays content streamed from a Play To client.

Streaming media to devices using Play To

Samples

Play To sample

PlayToReceiver sample

Media Server sample