Increasingly, consumers have more computing intelligence sitting
in their TV rooms. Many have cable or satellite boxes which are
essentially purpose-built PCs. We have game consoles like the
Playstation and Xbox 360 which are powerful computers in their own
right. Not surprisingly, many tech-savvy consumers even have
dedicated PCs attached to their TVs, often including CableCard
units to allow them access to the channels they're paying for.
This is a modified excerpt from the draft version of Silverlight 5 in Action,
current available via the Manning Early Access program.
One of the available accessories for the Xbox 360 is the Media
Remote (or the older Universal Media Remote). This remote control
looks very much like the ones you may use for your television set,
blu-ray player, or other media device. Apple has a similar but more
spartan remote named the Apple Remote.
Finally, many current keyboards include dedicated media keys for
volume control, play/pause and more. I personally use a Microsoft
Natural Ergonomic Keyboard 4000 (yeah, our naming is nuts) which
includes dedicated keys for volume, mute, and play/pause. My lenovo
W520 laptop has media keys which are accessible by hitting the blue
Fn key combined with the arrow keys. Collectively (remote and
keyboard), we consider these functions "media commands".
As one of the single most popular uses for Silverlight on the PC
is watching video, especially through commercial providers like
Netflix, support for the remote control and media commands is a
no-brainer.
The MediaCommand event
Like most input events, the MediaCommand event is exposed by the
base UIElement class. Behind the scenes, Silverlight maps into a
single MediaCommand enumeration the various input information from
the different types of media input devices. The table below shows
the supported media commands.
Supported Media Commands
Command
|
Typical Use
|
Play
|
Begin or continue playing the media.
|
Pause
|
Temporarily pause the media
|
TogglePlayPause
|
Many keyboards and remote controls have a single button for play
and pause and simply toggle between functions each time you press
the button. This is more common than dedicated play and pause
buttons.
|
Stop
|
Stop playing the media, and return to the menu or other
appropriate state
|
Record
|
Begin or end recording
|
FastForward
|
Move forward through the media timeline
|
Rewind
|
Move backward through the media timeline
|
NextTrack
|
Move to the next track or marker point in the media
|
PreviousTrack
|
Move to the previous track or marker point in the media
|
IncreaseVolume
|
Raise the volume on the device or player
|
DecreaseVolume
|
Lower the volume on the device or player
|
ChannelUp
|
Increment the channel number
|
ChannelDown
|
Decrement the channel number
|
MuteVolume
|
Mute all audio
|
There are several other media commands (Menu, Title, Info) etc.
which are not currently raised on the PC or Mac. Those commands are
reserved for potential future support.
In addition to the keys and buttons explicitly handled by the
MediaCommand enumeration, other common functions such as Ok/Enter,
numeric entry, navigation arrows and others are handled by their
equivalent keyboard keys, also covered in chapter 8 in Silverlight
5 in Action.
About Media Key Hooks and Hijacking
On the typical modern computer, there are a lot of apps that try
and steal the media keys. Typically these applications are already
running in the background. On the Mac, that's likely iTunes. On the
PC, you may have iTunes or Zune, Media Player or something
else.
In most cases, the only way to guarantee that you'll get the
media commands you want is to have your application run
full-screen, and preferably out-of-browser.
If you find your app isn't getting the media commands you
expect, try running it in full-screen mode. For the 10' experience,
this approach typically makes sense anyway.
MediaCommand and the MediaElement
You aren't restricted to using the built-in MediaCommand
enumeration and event with a media element. You could, for example,
enable the use of these keys to control playing or pausing a game,
or controlling a slide show. That said, the most common use is with
media playback, so we'll focus our example on that scenario.
The listing below shows the UI a bare-bones media application
with a video player and a button to enable viewing full-screen. I
created this application as an out of browser application, but
in-browser works fine as well. You may use any
silverlight-compatible video source, but the downloadable source
code for the book includes a 720p video I recorded showing the
first robot I ever built using the Netduino (the video is not
downloadable from my site, as it's too big to host here). A great
source of downloadable WMVs is Channel 9. Simply select a
video and choose the download link on the right.
<UserControl x:Class="MediaCommandExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
MediaCommand="OnMediaCommand"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<MediaElement x:Name="VideoPlayer"
Source="Media/NetduinoRobotFirstRun.wmv" />
<Button x:Name="FullScreen" Click="FullScreen_Click"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Content="Full Screen" Margin="5" />
</Grid>
</UserControl>
If you run the application with only that markup (and stub the
generated event handlers referenced in the XAML), you'll see an app
which plays a video as soon as it has been launched.
The next step is to add in the full-screen functionality and the
media command handling. The listing below shows how to implement
those features.
private void OnMediaCommand(object sender, MediaCommandEventArgs e)
{
Debug.WriteLine(e.MediaCommand.ToString());
switch (e.MediaCommand)
{
case System.Windows.Media.MediaCommand.Play:
VideoPlayer.Play();
break;
case System.Windows.Media.MediaCommand.Pause:
if (VideoPlayer.CanPause)
VideoPlayer.Pause();
break;
case System.Windows.Media.MediaCommand.TogglePlayPause:
if (VideoPlayer.CurrentState == MediaElementState.Paused ||
VideoPlayer.CurrentState == MediaElementState.Stopped)
VideoPlayer.Play();
else if (VideoPlayer.CurrentState == MediaElementState.Playing)
if (VideoPlayer.CanPause)
VideoPlayer.Pause();
break;
case System.Windows.Media.MediaCommand.IncreaseVolume:
VideoPlayer.Volume += .1;
break;
case System.Windows.Media.MediaCommand.DecreaseVolume:
VideoPlayer.Volume -= .1;
break;
}
}
private void FullScreen_Click(object sender, RoutedEventArgs e)
{
Application.Current.Host.Content.IsFullScreen = true;
}
This example uses the MediaElement methods and properties we've
learned about earlier in this section combined with a small
selection of the new MediaCommand enumeration. The end result is a
media player that can be controlled entirely via your media
keyboard or remote.
As mentioned in the sidebar, if you run into problems with the
commands being hijacked by something else, be sure to hit the "full
screen" button on the page.