In my previous article I showed how your application can stream a media file to another device on their network using the Play To feature in Windows Store Applications.
You can see my previous article from here.
We can also embed the feature of the Play To Receiver in the application, so that the application can receive the media streaming from a client computer and display the content in your application. We can create a software for the app that receives streaming of media file from another computer on the network and plays video content as part of your app and also can respond to various events from the client side computer.
So, this article will describe how to create an application that enables you to play the video from the client computer using Play To Receiver software in Windows Store Apps.
Now, let's begin to create.
Step 1
Create a Windows Store Blank Application using XAML.
Step 2
You need to add some capabilities to the project. Do that using the following:
- Open the package.appxmanifest file
- Select the Capabilities tab.
- Select the Home or Work Networking capability.
- Close and save the manifest file.
Step 3
Add the code of MainPage.XAML page:
<common:LayoutAwarePage
x:Class="PlayToreceiver.Scenario1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PlayToreceiver"
xmlns:common="using:SDKTemplate.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="Input" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0" Grid.Row="1">
<Button x:Name="StartReceiverButton"" Content="Start Receiver" Margin="0,0,10,0" Click="startPlayToReceiver"/>
<Button x:Name="StopReceiverButton" Content="Stop Receiver" Margin="0,0,10,0" Click="stopPlayToReceiver" IsEnabled="False"/>
</StackPanel>
</Grid>
<Grid x:Name="Output" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1">
<MediaElement x:Name="VideoPlayer" AutomationProperties.Name="dmrVideo" Height="480" Width="640" HorizontalAlignment="Left" VerticalAlignment="Top"
VolumeChanged="dmrVideo_VolumeChanged"
RateChanged="dmrVideo_RateChanged"
MediaOpened="dmrVideo_MediaOpened"
CurrentStateChanged="dmrVideo_CurrentStateChanged"
MediaEnded="dmrVideo_MediaEnded"
MediaFailed="dmrVideo_MediaFailed"
SeekCompleted="dmrVideo_SeekCompleted"
DownloadProgressChanged="dmrVideo_DownloadProgressChanged_1"
AutoPlay="False"/>
<Image HorizontalAlignment="Left" VerticalAlignment="Top" Height="480" Width="640" x:Name="dmrImage"
ImageFailed="dmrImage_ImageFailed_1"
/>
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<VisualState x:Name="FullScreenPortrait"/>
<VisualState x:Name="Snapped"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</common:LayoutAwarePage>
Step 4
In this step add code to start the Play To Receiver and Stop it.
Here is code for the Start Button.
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;
// Advertise the receiver on the local network and start receiving commands
await receiver.StartAsync();
}
}
The above code initializes the instance of the PlayToReceiver class. Then it creates event handlers that respond to the client computer. These actions include receiving the source media and many other actions. Here I also set the friendly name of the device that is identified on the network.
Step 5
Here is the code of the Stop Button.
In this steps dissociate the events with the Play To Receiver. See:
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;
}
}
}
Step 6
Add code for the Play To receiver event handlers. See:
async void receiver_CurrentTimeChangeRequested(PlayToReceiver sender,CurrentTimeChangeRequestedEventArgs args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
VideoPlayer.Position = args.Time;
receiver.NotifySeeking();
seeking = true;
});
}
async void receiver_MuteChangeRequested(PlayToReceiver sender,MuteChangeRequestedEventArgs args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
VideoPlayer.IsMuted = args.Mute;
});
}
async void receiver_PauseRequested(PlayToReceiver sender, object args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
VideoPlayer.Pause();
});
}
async void receiver_PlaybackRateChangeRequested(PlayToReceiver sender,PlaybackRateChangeRequestedEventArgs args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
VideoPlayer.PlaybackRate = args.Rate;
});
}
async void receiver_PlayRequested(PlayToReceiver sender,object args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
VideoPlayer.Play();
});
}
async void receiver_SourceChangeRequested(PlayToReceiver sender,SourceChangeRequestedEventArgs args)
{
if (args.Stream != null)
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
var stream = args.Stream as Windows.Storage.Streams.IRandomAccessStream;
VideoPlayer.SetSource(stream, args.Stream.ContentType);
});
}
async void receiver_StopRequested(PlayToReceiver sender, object args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
VideoPlayer.Stop();
});
}
async void receiver_TimeUpdateRequested(PlayToReceiver sender,object args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (VideoPlayer.Position != null)
receiver.NotifyTimeUpdate(VideoPlayer.Position);
});
}
async void receiver_VolumeChangeRequested(PlayToReceiver sender, VolumeChangeRequestedEventArgs args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
VideoPlayer.Volume = args.Volume;
});
}
Note: The above handlers are fired in response to requests from the Play To client computer.
Step 7
In this step we need to add event handlers of the media player in our application such as Media_Opened, Media_Closed etc.
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);
}
Step 8
Now, our app is ready to receive the media stream from the other computer on the network. Press F5 to run the application.
Click the Start Play To Receiver button.
Step 9
Now, you need to go to another computer and select Settings from the charm bar.
Step 10
Select More PC Settings. In the More Settings window, select Devices->click Add a device.
Step 11
Locate that name and add it. Now, open the Devices charm and select your custom Play To receiver as the target for the streamed video.