Control Freak
LANGUAGES:
C# | HTML
ASP.NET
VERSIONS: 1.0 | 1.1
Streaming Media
Stream Audio and Video from Your ASP.NET Web Site
By Steve C. Orr
ASP.NET doesn t provide any specific way to play music or
video in your Web applications, but that doesn t mean there aren t any options.
For example, the following HTML, when embedded anywhere in an HTML page, will
play a background song for visitors:
<bgsound SRC="SomeSong.mp3" loop="0"
balance="0" volume="0">
As you might guess by looking at the definition, there are
a few options for adjusting the volume, balance, and number of times the song
will be played. Static snippets of HTML like this are sure handy sometimes, but
it would be even better if there were a Web control that would encapsulate the
dynamic rendering of such HTML at run time, and perhaps even provide a basic UI
so users can control the playback of the music.
Audio Control
The basic framework for the control is shown in Figure 1.
This standard custom Web control code should look familiar to you if you ve
been reading this column regularly; all custom Web controls start out
similarly.
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Text;
namespace MediaPlayers
{
[ToolboxData("<{0}:Audio runat=server></{0}:Audio>")]
public class Audio :
System.Web.UI.Control
{
//Properties go here
protected override void
Render(HtmlTextWriter output)
{
//Custom rendering
goes here
output.Write("Test");
}
}
}
Figure 1: All
custom Web controls start with a shell similar to this.
The four properties of this custom control will mirror the
attributes available for the <bgsound> tag: Volume, Loop,
Balance, and FileName. Two of the properties are listed in Figure 2; the rest
can be downloaded from the code that accompanies this article (see end of
article for download details).
private string _FileName = "";
private int _Volume = 0;
[Bindable(true), Category("Appearance"),
Description("URL to
a sound file"),
Editor(typeof(System.Web.UI.Design.UrlEditor),
typeof(System.Drawing.Design.UITypeEditor))]
public string FileName
{
get { return _FileName; }
set { _FileName = value; }
}
[Bindable(true),
Category("Appearance"),
Description("-10000=mute, 0=full volume (default)")]
public int Volume
{
get
{
return _Volume;
}
set
{
if (value>=-10000
&& value<=0) _Volume = value;
else throw new
ArgumentException
("Volume must be between -1000 and
0");
}
}
Figure 2: The FileName
property has special attributes for improved design time support in the
properties window, and the Volume property throws an exception if an invalid
value is set.
First, two private variables are declared to hold the
property values. Next, the FileName property is defined along with several
useful attributes to improve design time support in the properties window. (Note
that some of these attributes will cause a compilation error until you add a
project reference to the System.Design.dll.) When a developer uses this control
on their Web form at design time, an ellipsis button will appear for the
property. When clicked, it displays the dialog box shown in Figure 3 to assist
in the selection of a file.
Figure 3: The FileName property
provides a special design time editor to make it easy for developers to select
a file.
The full code also provides a few more properties for
setting the visibility of the three button controls that will allow the user to
play, stop, and display information about the current track. These three
buttons will be the only user interface visible to the end user at run time, or
they can all be set as invisible if the developer prefers to control the
playback entirely through code. Figure 4 shows the control in action on a Web page
that provides a list of songs for the end user to play on demand. The buttons
use client-side JavaScript to interact with the <bgsound> element of the Web
page, so the music can be started and stopped without posting back to the
server.
Figure 4: The audio control can be
dropped onto any Web form to easily spice it up with music and other sounds.
The Render method listed in Figure 5 examines the
properties of the controls and generates the BGSOUND HTML that will be rendered
to the page. The GenerateButtons procedure creates the HTML for the Play, Stop,
and Info buttons. Images could have been used for the symbols, but using the
WebDings font is a more efficient approach.
protected override void Render(HtmlTextWriter output)
{
StringBuilder sb = new
StringBuilder("<BGSOUND ");
sb.Append("id='"+
this.ClientID + "' ");
sb.Append("name='"+
this.ClientID + "' ");
sb.Append("SRC='"+
_FileName + "' ");
sb.Append("VOLUME='"
+ _Volume.ToString() + "' ");
sb.Append("BALANCE='"
+ _Balance.ToString() + "' ");
sb.Append("LOOP='"
+ _Loop.ToString() + "' ");
sb.Append("/>");
GenerateButtons(sb);
output.Write(sb.ToString());
}
private StringBuilder GenerateButtons(StringBuilder sb)
{
string TempID =
"BG"+ this.ClientID;
sb.Append("<script
language=javascript>var " +
TempID +
"=document.getElementById('"+
this.ClientID +
"');</script>");
if (PlayButtonVisible)
{
sb.Append("<INPUT type='button'
");
sb.Append("style='font-family:Webdings;'
value='4' ");
sb.Append("title='Play'
onClick=\""+ TempID +
".src='"+
_fileName + "'\">");
}
if (StopButtonVisible)
{
sb.Append("<INPUT type='button'
");
sb.Append("style='font-family:Webdings;'
value='<' ");
sb.Append("title='Stop' onClick=" +
TempID + ".src=''>");
}
if (InfoButtonVisible)
{
sb.Append("<INPUT type='button'
");
sb.Append("style='font-family:Webdings;'
value='i' ");
sb.Append("title='Info'
onClick='alert(" +
TempID + ".src)'>");
}
return sb;
}
Figure 5: The
final rendering code examines the control properties to dynamically create the
appropriate <bgsound> tag along with some buttons to allow the end user
to control playback.
The Audio control turns out to be fairly robust,
considering it s doing little more than encapsulating a basic HTML tag. Certainly,
it s a useful way to quickly and easily get some tunes playing on a Web page. However,
it does have some significant limitations if you want to get some really fancy
multimedia interactivity going on.
Here are some features reasonable developers (and users)
might want that are simply impossible to implement using the preceding
approach:
- Fancier controls, such as fast forward and rewind.
- Support for video playback.
- Buffering, so large media files can start
playing without having to wait for the entire media file to download.
- A friendly and familiar user interface, such as
that of Windows Media Player.
The following approach solves all of these problems.
Video Control
Windows Media Player certainly is a leader in the field of
media playback; it provides rich support for many media file types and it
provides an experience with which most users are already quite familiar. By
embedding the Windows Media Player ActiveX control in an HTML page, you can
harness this power. The required HTML (listed in Figure 6) is not entirely
unlike the <bgsound> tag used earlier in the article, although there are
quite a few more options at your disposal.
<OBJECT ID="Player"
CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6"
VIEWASTEXT>
<PARAM name="autoStart"
value="True">
<PARAM
name="URL" value="SomeMediaFile.mpg">
<PARAM
name="rate" value="1">
<PARAM
name="balance" value="0">
<PARAM
name="enabled" value="true">
<PARAM
name="enabledContextMenu" value="true">
<PARAM
name="fullScreen" value="false">
<PARAM
name="playCount" value="1">
<PARAM
name="volume" value="100">
</OBJECT>
Figure 6: By
embedding the Windows Media Player ActiveX control in a Web page with HTML such
as this, you can provide robust audio and video playback capabilities as long
as your users have a recent version of Windows Media Player and they accept the
standard ActiveX security warning.
Of course, this code requires end users to have a recent
version of Windows Media Player installed, and they may need to accept the
standard ActiveX security warning displayed by Internet Explorer.
This ActiveX control handles streaming and buffering
intelligently, so the media file will start playing as soon as is practical,
even before the entire media file has been downloaded.
As with the <bgsound> example at the beginning of
the article, the HTML snippet shown in Figure 6 is quite useful but it s not
very reusable. The rest of this article describes a new custom Web control,
similar to the audio control outlined in the first half of this article. The
main difference is that this new control will encapsulate the options available
with the Media Player ActiveX control instead of the more simplistic <bgsound>
tag.
This control (as well as all custom Web controls) starts
with a basic template similar to that shown in Figure 1. The properties for
this new control do little more than hold values for the parameters in Figure 6
and enforce valid values.
The only thing unique about this control is the HTML that
it generates. This HTML is generated from within the overridden Render event,
which is listed in Figure 7.
//output begin object tag
StringBuilder sb = new StringBuilder("<OBJECT ID='"
+
this.ClientID + "'
name='"+ this.ClientID + "' " +
"CLASSID='CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6'"
+
"VIEWASTEXT" +
"height="+_Height
+ " " + "width="+_Width +
">");
//Render properties as object parameters
sb.Append("<PARAM name='URL' value='"+
_fileName + "'>");
sb.Append("<PARAM name='AutoStart' value='"+
_autoStart.ToString() +
"'>");
sb.Append("<PARAM name='balance' value='"+
_Balance + "'>");
sb.Append("<PARAM name='enabled' value='"+
_Enabled.ToString() +
"'>");
sb.Append("<PARAM name='fullScreen' value='"+
_fullScreen.ToString() +
"'>");
sb.Append("<PARAM name='playCount' value='"+
_Loop.ToString() +
"'>");
sb.Append("<PARAM name='volume' value='"+
_Volume + "'>");
sb.Append("<PARAM name='rate' value='"+
_Rate + "'>");
sb.Append("<PARAM name='StretchToFit' value='"+
_stretchToFit.ToString()
+ "'>");
sb.Append("<PARAM name='enabledContextMenu' value='"
+
_enableContextMenu.ToString()
+ "'>");
//Determine visibility
if (_Invisible)
{
sb.Append("<PARAM
name='uiMode'");
sb.Append("
value='invisible'>");
}
else
{
if (_buttonsVisible)
{
sb.Append("<PARAM
name='uiMode'");
sb.Append("
value='full'>");
}
else
{
sb.Append("<PARAM
name='uiMode'");
sb.Append("
value='none'>");
}
}
//output ending object tag
sb.Append("</OBJECT>");
//flush everything to the output stream
output.Write(sb.ToString());
Figure 7: This
code from the Render event of the new video-capable custom Web control
transforms property values into HTML similar to that of Figure 6.
The code starts by using a StringBuilder to concatenate
the opening <OBJECT > tag, then it uses its properties to generate <PARAM>
tags similar to those shown in Figure 6. The determine visibility code block
simplifies some of the options in the ActiveX control to modify the visibility
of various parts of the control. Finally, the ending </OBJECT> tag is
rendered and the final HTML string is flushed to the output stream. Figure 8
shows the control in action.
Figure 8: By harnessing the power of
Windows Media Player in a Web page you can give your users memorable
experiences.
This custom media control, which essentially encapsulates
the Windows MediaPlayer ActiveX control, can have its properties set at design
time or run time. At run time you might have some code in a Web form s
code-behind file that looks like this:
MediaPlayer1.Filename="SomeMediaFile.avi"; //URL
MediaPlayer1.autoStart=true; //start playing upon page load
MediaPlayer1.ButtonsVisible=true; //play control buttons
MediaPlayer1.EnableContextMenu=true; //right-click menu
MediaPlayer1.fullScreen=false;
MediaPlayer1.Invisible=false; //true=no UI but it still plays
MediaPlayer1.Volume=100; //0 = mute, 100 = full blast
The Filename property accepts any publicly accessible URL
to a media file. Alternatively, you could point it to a custom Web page that
outputs a media file from a secured directory. Such a page might use the
Response.WriteFile method to provide authenticated access to media.
One deficiency you may have noticed with both controls in
this article is that they stop playing when the user navigates to another page
in your Web site, which you may or may not want. If your requirements state
that the music should keep playing throughout the user s visit at your Web
site, then the most common solution is to use frames. That is, host the music
control in one frame and have page navigation occur in a different frame. However,
frames can be a bit of a pain in ASP.NET (often requiring copious amounts of
client-side code), so venture into this territory at your own risk.
Full Throttle
This article only scrapes the surface of the multimedia
capabilities at your disposal. Add some authentication and payment processing
and you ve got yourself an online music and video store (just be sure you ve
got legal rights to sell the media; you may have noticed record companies are
getting mighty uptight about this kind of thing lately!).
I suggest you download the Windows Media SDK if you want
to delve deeper into the possibilities. The documentation is thorough, and will
likely answer many of the questions that may be lingering in the back of your
mind. Using the Windows Media SDK, you can create media player skins and new
codecs, and you can even create online stores and other Web sites that appear
embedded within Windows Media Player.
Beware: Streaming media tends to eat large amounts of
bandwidth, so if your goal is to create a streaming media Web site with any
significant amount of scalability, you re going to need fat pipes to go along
with beefy servers. Needless to say, this all adds up to a significant
financial investment. Also keep in mind that some media formats are more
demanding than others. For example, midi files are quick and tiny; video files
tend to be the bulkiest.
You should now have enough information at your disposal to
create dazzling multimedia experiences for your Web site s users. Impress them,
but try not to annoy them with unwanted noise. One of the best things about
having a media control on a Web page is that it allows you to suggest a musical
overture that matches your Web site s ambiance, but at the same time allows the
user to take control of the experience in case they re just not in the mood.
The sample code in
this article is available for download.
Steve C. Orr is an
MCSD and a Microsoft MVP in ASP.NET. He s been developing software solutions
for leading companies in the Seattle
area for more than a decade. When he s not busy designing software systems, or
writing about it, he can often be found loitering at local user groups and
habitually lurking in the ASP.NET newsgroup. Find out more about him at http://Steve.Orr.net
or e-mail him at mailto:Steve@Orr.net.
Hot Links
<bgsound> documentation:
http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/bgsound.asp
Windows Media Player ActiveX Control documentation:
http://www.msdn.microsoft.com/library/en-us/wmplay10/mmp_sdk/paramtags.asp
Windows Media 10 SDK:
http://www.microsoft.com/windows/windowsmedia/mp10/sdk.aspx