| Comments

| Comments
A second encoder post

| Comments

One of my favorite implementations is to leverage the initParams feature for the Silverlight plug-in.  This enables you to send parameters to your application prior to it starting up.  These parameters are in plain text and can be seen in the HTML source of your page, so obviously you wouldn’t want to include any sensitive information there like passwords, connection strings, etc., etc.  But it can be very helpful for re-using application logic while providing an configurable experience.  You can view a video demonstration of this and other methods of using initialization parameters on the Silverlight Community site here: Using Startup Parameters with Silverlight 2.

Media is one obvious example here as you could re-use a media player and simply provide the source of the media as an initParams value and then you’ll only have to deploy one player.  This works extremely well and enables you to leverage a content delivery network for the distribution of your app and just provide a different URI for the media each use.

For Silverlight Streaming (SLS) services, however, there is yet a parameter in the manifest.xml file that exposes a mapping of this initParams element to the loader for your SLS application. 

Microsoft® Silverlight™ Streaming by Windows Live™ is a companion service for Silverlight that makes it easier for developers and designers to deliver and scale rich media as part of their Silverlight applications. The service offers web designers and developers a free (please read terms and conditions upon registering) and convenient solution for hosting and streaming cross-platform, cross-browser media experiences and rich interactive applications that run on Windows™ and Mac. Combined with the ability to create content with Microsoft® Expression and other 3rd party tools, web designers and content publishers wishing to integrate Silverlight applications into their online properties can enjoy complete control of the end user experience.  You can sign up for an account that will give you 10GB of hosting space for your Silverlight applications.

Here’s some ways you can still leverage that method.

Method 1 – Bootstrap it

This method really would be considered when you are using some Silverlight application that is parameter driven and you want to simply use the XAP and provide the parameter.  Let’s use the media player scenario here because we can leverage a real application, the SL2VideoPlayer project on CodePlex.  This player is driven by parameters, namely one to set the media URI called “m.”  We’ll concentrate on that one.

Let’s say we want to use SLS to host our player application and we want to simply grab the XAP and upload the player and our media.  As I mentioned, SLS doesn’t yet provide a way to tell it in the manifest that there are startup parameters.  But here’s what you can do, provide a “bootstrap” method to instantiate the Silverlight application.

Step 1 – Create the bootstrap function

Just create a file of whatever you want, let’s call it launcher.js for this demo.  In launcher.js we need to write two functions: one that creates our Silverlight object, the other to call that function.  Let’s see what it looks like, then explain.

   1: function launcher(parentId) {
   2:     var parentElement = document.getElementById(parentId);
   3:     Silverlight.createObject(
   4:         "VideoPlayerM.xap",
   5:         parentElement,
   6:         "playerObj",
   7:         {
   8:             width:'800',
   9:             height:'600'
  10:         },
  11:         {
  12:             onError:null,
  13:             onLoad:null
  14:         },
  15:         'm=<your-media-uri>',
  16:         null);
  17: }
  18:  
  19: function StartApp(parentId, appId) {
  20:         launcher(parentId);
  21: }

If you look at the first function called “launcher” this is the one that does the heavy lifting.  Because SLS will include the Silverlight.js file for us, we can use that API to create the instance of the plugin.  The Silverlight.createObject function generates the plugin tag for us and emits the platform/browser-specific code for the plugin.  Line 15 above shows us how we are passing the initParams argument to the function, which is a parameter of the createObject call in the API.  The second function “StartApp” is what we will tell SLS to use when loading the hosted application.  StartApp matches the required signature for SLS using the parentId (the element of the plugin) and the appId (the SLS application ID) we will need to use it.

Now in our manifest file for our SLS application we can have this:

   1: <SilverlightApp>
   2:   <version>2.0</version>
   3:   <loadFunction>StartApp</loadFunction>
   4:   <jsOrder>
   5:     <js>launcher.js</js>
   6:   </jsOrder>
   7: </SilverlightApp>

SLS will look at this manifest and do two things.  First it will ensure that the Javscript file “launcher.js” is included.  Second it will tell the system to run StartApp as the function to start first. 

That’s it – we package the manifest.xml file, launcher.js, VideoPlayerM.xap and our media file up as a zip and upload to a new application using the web administration of our SLS account.

I mention this as an option, because it does work.  However the nature of this is still pretty much a one-time use because the bootstrap function is a part of the application and thus your “parameters” are coded as a part of the launcher, coupled to this application instance.  This still does, however, help you if you want to use an app that requires it and the parameters won’t change…you’re just trying to re-use some Silverlight application!

Method 2 – QueryString params

The other option is a little work-around.  Whenever you have an SLS application you will have an endpoint to that application.  The format of that will be something like this:

http://silverlight.services.live.com/invoke/accountId/applicationName/iframe.html

Where the accountId is your SLS account id, and the applicationName is the name you’ve provided for the app you uploaded already.  Let’s assume our app was called HostedMediaPlayer and my accountId is 217, it would be this:

http://silverlight.services.live.com/invoke/217/HostedMediaPlayer/iframe.html

Now since our application requires startup parameters, clicking on the link (or using it) would generate our nice Silverlight application that does nothing.  So we need to send it the media source (the “m” parameter).  To do that we can pass in our initParams as QueryString parameters like this:

http://silverlight.services.live.com/invoke/217/HostedMediaPlayer/iframe.html?m=MoonlightInstall.wmv

This translates to the initParam that we need.  So now we could also do something like this:

http://silverlight.services.live.com/invoke/217/HostedMediaPlayer/iframe.html?m=http://silverlight.services.live.com/217/bearee2filerename/video.wmv

And we have re-used the same application, but for a different source, still using the parameter-driven nature of it.  I’ve tested this only using very minimal parameters and ones that are simply (i.e., string based with no funky characters, etc).

Summary

Initialization parameters are an awesome and easy way to create and re-use Silverlight applications that are parameter driven.  I hope these two methods for Silverlight Streaming services help you understand the initParams relationship better with the SLS hosted model.  Of course if you aren’t using SLS and you are hosting your own application, then you ultimately have complete control on how to send those parameters and as previously noted, there is a video on some options with that regard.

Hope this helps!  If you found this post helpful, please consider subscribing to my RSS feed or also subscribing via email.

| Comments

Now that Windows 7 beta has been released, there are quite a few people using it and I’ve seen pretty positive feedback about it.  I’ve been running it for about a month now and am impressed with the performance over Vista mostly.  All my programs continue to run fine (only exception is MagicDisc ISO mounter, but found another option – why isn’t ISO mounting a part of Windows – vote here?!?!?!) and I was able to set up a perfect Windows Deployment Server image to quickly image my laptops with the latest build, a slipstreamed version of Office, etc.

NOTE ON CONNECT LINK: People have said they’ve received Page Not Found messages from Connect when clicking the link above.  To be honest, I’m not sure why.  I promise it is there :-).  One user (thanks Barry) noted the following: Register using your MSDN bound passport using the register link in your entry. After that the 404 vanished.  I hope this may work for others as well.

There were a couple of things I wanted to send feedback on regarding the product.  I’m trying to be a good beta user myself and provide feedback on the product just like any other customer.  The cool thing is that the beta team has provided 2 ways within Windows 7 for you to provide feedback.

UPDATE (May 2009): Please leave feedback for Windows 7 using the appropriate beta/release candidate program options.  This blog post is simply a pointer to those methods as they existed in the beta.  Leaving feedback in the comments section here is fine, but it is likely that it isn't being monitored by the Windows 7 team...I'm not on that team!

Send Feedback Link EVERYWHERE in Windows 7

The first is that in every window near the minimize/maximize buttons in the title bar (and a shortcut on the desktop until/unless you delete it) there is a Send Feedback link.  This launches the feedback session.  It asks you to log in with your Windows Live ID, which I did.  I was then greeted with this:

Windows 7 Feedback Dialog Window

It turns out that you first have to be a member of the Connect system (Microsoft’s official public feedback mechanism) program for the beta in order to give feedback.  Seemed strange I thought?  Others who are a part of the beta weren’t getting this message.  As it turns out if you got the download of Windows 7 from the Microsoft Windows site, you’re already a part of the Connect program for the beta.  Others like me who got their download from MSDN or TechNet, didn’t have to “register” the beta and thus are likely in this stage where I was at.  It seems that there was some missing instruction on the MSDN/TechNet sites on a step required in order to give feedback only if you got your beta through these channels.  The information is now back on the site:

Give us feedback on the Windows 7 Beta!

As an MSDN subscriber you have the ability to register with Microsoft Connect to track the status of bugs you report. You will also be able to search, view and vote on bugs other MSDN subscribers have filed.

To register on Connect, please click here. This will enroll you into the MSDN Bug Filing Program. Once you are enrolled in the program you may file bugs using any “send feedback” link in the product and access your feedback tracking page directly from this link.  Source: http://msdn.microsoft.com/subscriptions

Basically, you need to sign up for the Connect program for the Windows 7 beta and then your feedback link will work.

Record your Feedback

The second option for giving feedback is that you actually have the option to record the feedback.  Let’s say you ran into a problem and it was reproducable and you wanted to let the team know about it (please let them know about it).  The tool, called the Problem Steps Recorder, is a part of the Windows 7 beta experience.  To launch this tool, simply click the start menu and type “psr.exe” and start the program.  It will bring up a little recorder and walk you through the next steps.  The end result is an HTML report packaged as a zip file that you can send to someone (application vendor) or attach to your Connect report as indicated above.

You can view a walk through of this at Long Zheng’s site along with a sample report output.  It’s a great idea to add to a product.  Should provide better specifics to a problem.

So if you are a Windows 7 beta user, be sure to use these mechanisms to give feedback about the product and provide as much specifics as you can.

Hope this helps!


This work is licensed under a Creative Commons Attribution By license.

| Comments

In an email dialog today I saw someone asking how he could use an existing Encoder 2 template for existing media or streaming URIs when you don’t have something to encode.  After a few explanations, he replied that someone should blog this – and I agree :-).

So what did he mean?  Well, when you use Expression Encoder, you are typically going to be encoding media to a format to consume.  Encoder also gives you an additional option in the output settings to generate a media player for that encoded content.  These are all based on templates that I’ve previously written about that are available in the product as well is the source code for you to extend.

But what if you have a media file that doesn’t need encoding or you have a streaming URI and you don’t need to encode anything, but want the player?  To some it might not be so obvious so let me try to walk you through the steps.

You need the player

First you need the player.  The XAP that is, of the template you want to use.  There are essentially two ways of going about getting this:

    1. Getting the MediaPlayerTemplate.xap file from an existing output you already did (that used the same template you want)
    2. Building the XAP using the source of the templates and building it from scratch (requires .NET compiler or Visual Studio)

Obviously if you have the XAP of your desired template, you are ready to proceed.  If you don’t, then you’ll need to proceed to step 2.  Here’s what you’ll do:

Building the Player

First, find the template you want.  These are located in C:\Program Files\Microsoft Expression\Encoder 2\Templates\en (note: if you are on 64-bit or a different language, this path may differ slightly).  Within here you’ll see a list of templates by name.  Find the one you want and within that folder there is a Source directory.  That’s what you want.  I highly recommend actually moving the source files to a different place rather than edit directly in the templates directory.  There is a Visual Studio 2008 solution/project file in there and you can open it up and compile. 

As long as you are in there…

If you don’t need all the features of the template (i.e., Adaptive Streaming, etc) consider reading James Clarke’s post on removing some of those references and still creating the same template, but with reduced functionality.

Once compiled (remember to choose the right configuration - i.e., Release, Debug - for your needs), you’ll have in the Bin directory of that project the MediaPlayerTemplate.xap file you need. 

Passing parameters

So how can you compile the player template without media?  The Encoder 2 Silvelright 2 templates are completely parameter driven.  If you notice in any existing encoded project output (look at the default.html file generated) you’ll see the object tag used to host the player.  It may look something like this:

   1: <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
   2:     <param name="source" value="MediaPlayerTemplate.xap"/>
   3:     <param name="onerror" value="onSilverlightError" />
   4:     <param name="initparams" value='autoplay=True,autoload=True,enablecaptions=True,muted=False,stretchmode=0,displaytimecode=False,playlist=&lt;playList><playListItems><playListItem title="Moonlight%201.0%20Install%20on%20OpenSuse" description="Screencast%20of%20Moonlight%20install%20on%20OpenSuse.%20%20Virtual%20image%20provided%20by%20http://susestudio.com." mediaSource="MoonlightInstall.wmv" adaptiveStreaming="False" thumbSource="" frameRate="14.9669006991039" width="800" height="600" ><chapters><chapter  position="9.674" thumbnailSource="MoonlightInstall_9.674.jpg" title="Silverlight%201.0%20Chess%20playback%20from%20Vertigo" /><chapter  position="13.967" thumbnailSource="MoonlightInstall_13.967.jpg" title="Standard%20Silverlight%20installer%20integrates%20with%20Moonlight%20install%20links." /><chapter  position="18.058" thumbnailSource="MoonlightInstall_18.058.jpg" title="Firefox%20first%20nag%20message%20to%20protect%20user%20from%20web%20installs." /><chapter  position="20.784" thumbnailSource="MoonlightInstall_20.784.jpg" title="Second%20Firefox%20nag%20message%20(plugin%20message%20from%20trusted%20sources)" /><chapter  position="24.543" thumbnailSource="MoonlightInstall_24.543.jpg" title="Plugin%20installation%20complete%252C%20Firefox%20restart" /><chapter  position="32.055" thumbnailSource="MoonlightInstall_32.055.jpg" title="Silverlight%201.0%20Chess%20now%20working%20with%20Linux/Moonlight" /><chapter  position="43.801" thumbnailSource="MoonlightInstall_43.801.jpg" title="Video.Show%20from%20Vertigo" /><chapter  position="46.675" thumbnailSource="MoonlightInstall_46.675.jpg" title="Launching%20a%20media%20player%20in%20Moonlight%20for%20first%20time" /><chapter  position="48.334" thumbnailSource="MoonlightInstall_48.334.jpg" title="Microsoft%20Media%20Pack%20(codecs)%20prompt%20for%20install" /><chapter  position="51.249" thumbnailSource="MoonlightInstall_51.249.jpg" title="Media%20Pack%20EULA" /><chapter  position="60.051" thumbnailSource="MoonlightInstall_60.051.jpg" title="Re-launch%20media%20player%20with%20Media%20Pack%20installed" /><chapter  position="71.010" thumbnailSource="MoonlightInstall_71.010.jpg" title="HD%20media%20playback%20via%20Moonlight%20on%20Linux" /><chapter  position="72.490" thumbnailSource="MoonlightInstall_72.490.jpg" title="Fullscreen%20mode" /><chapter  position="76.138" thumbnailSource="MoonlightInstall_76.138.jpg" title="Bubblemark%20application%20on%20Moonlight" /></chapters></playListItem></playListItems></playList>' />            
   5:     
   6:     <a href="http://go2.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
   7:          <img src="http://go2.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
   8:     </a>
   9: </object>
  10: <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>

Notice the initParams option?  If you aren’t familiar, you can send Silverlight 2 applications parameters using this method.  There’s a video walk-through on using initParams you can view on the Silverlight community site.  The key area here (among the other options) for media URIs is the playlist parameter.  Singling that one out you’ll see the structure looks like this:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <playList>
   3:   <playListItems>
   4:     <playListItem title="Moonlight%201.0%20Install%20on%20OpenSuse" description="Screencast%20of%20Moonlight%20install%20on%20OpenSuse.%20%20Virtual%20image%20provided%20by%20http://susestudio.com." mediaSource="MoonlightInstall.wmv" adaptiveStreaming="False" thumbSource="" frameRate="14.9669006991039" width="800" height="600" >
   5:       <chapters>
   6:         <chapter  position="9.674" thumbnailSource="MoonlightInstall_9.674.jpg" title="Silverlight%201.0%20Chess%20playback%20from%20Vertigo" />
   7:         <chapter  position="13.967" thumbnailSource="MoonlightInstall_13.967.jpg" title="Standard%20Silverlight%20installer%20integrates%20with%20Moonlight%20install%20links." />
   8:         <chapter  position="18.058" thumbnailSource="MoonlightInstall_18.058.jpg" title="Firefox%20first%20nag%20message%20to%20protect%20user%20from%20web%20installs." />
   9:         <chapter  position="20.784" thumbnailSource="MoonlightInstall_20.784.jpg" title="Second%20Firefox%20nag%20message%20(plugin%20message%20from%20trusted%20sources)" />
  10:         <chapter  position="24.543" thumbnailSource="MoonlightInstall_24.543.jpg" title="Plugin%20installation%20complete%252C%20Firefox%20restart" />
  11:         <chapter  position="32.055" thumbnailSource="MoonlightInstall_32.055.jpg" title="Silverlight%201.0%20Chess%20now%20working%20with%20Linux/Moonlight" />
  12:         <chapter  position="43.801" thumbnailSource="MoonlightInstall_43.801.jpg" title="Video.Show%20from%20Vertigo" />
  13:         <chapter  position="46.675" thumbnailSource="MoonlightInstall_46.675.jpg" title="Launching%20a%20media%20player%20in%20Moonlight%20for%20first%20time" />
  14:         <chapter  position="48.334" thumbnailSource="MoonlightInstall_48.334.jpg" title="Microsoft%20Media%20Pack%20(codecs)%20prompt%20for%20install" />
  15:         <chapter  position="51.249" thumbnailSource="MoonlightInstall_51.249.jpg" title="Media%20Pack%20EULA" />
  16:         <chapter  position="60.051" thumbnailSource="MoonlightInstall_60.051.jpg" title="Re-launch%20media%20player%20with%20Media%20Pack%20installed" />
  17:         <chapter  position="71.010" thumbnailSource="MoonlightInstall_71.010.jpg" title="HD%20media%20playback%20via%20Moonlight%20on%20Linux" />
  18:         <chapter  position="72.490" thumbnailSource="MoonlightInstall_72.490.jpg" title="Fullscreen%20mode" />
  19:         <chapter  position="76.138" thumbnailSource="MoonlightInstall_76.138.jpg" title="Bubblemark%20application%20on%20Moonlight" />
  20:       </chapters>
  21:     </playListItem>
  22:   </playListItems>
  23: </playList>

This sample above represents a single media file with chapter markers.  The bare minimum for a single media URI would be:

   1: <playList>
   2:   <playListItems>
   3:     <playListItem mediaSource="MoonlightInstall.wmv"></playListItem>
   4:   </playListItems>
   5: </playList>

So if you have a streaming URI (i.e., mms://mysite.com/live-baseball-game.asx) you would use this playlist structure:

   1: <playList>
   2:   <playListItems>
   3:     <playListItem mediaSource="mms://mysite.com/live-baseball-game.asx"></playListItem>
   4:   </playListItems>
   5: </playList>

and then in your HTML page you could have something like this for the full implementation (noting to use the appropriate width/height for your needs):

   1: <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
   2:     <param name="source" value="MediaPlayerTemplate.xap"/>
   3:     <param name="onerror" value="onSilverlightError" />
   4:     <param name="initparams" value='autoplay=True,autoload=True,enablecaptions=True,muted=False,stretchmode=0,displaytimecode=False,playlist=&lt;playList><playListItems><playListItem mediaSource="mms://mysite.com/live-baseball-game.asx"></playListItem></playListItems></playList>' />            
   5:     
   6:     <a href="http://go2.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
   7:          <img src="http://go2.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>
   8:     </a>
   9: </object>
  10: <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>

It is important to note that if you know the other parameters like framerate, etc. you should provide as much information you can for the playListItem node, but I’m just noting the bare minimum above.

Can I do this in code?

Yes, if you were using the media player in code you can still use this method in either XAML as noted in a previous post of mine or in code using something like this:

   1: public Page()
   2:         {
   3:             InitializeComponent();
   4:             Loaded += new RoutedEventHandler(Page_Loaded);
   5:         }
   6:  
   7:         void Page_Loaded(object sender, RoutedEventArgs e)
   8:         {
   9:             ExpressionMediaPlayer.MediaPlayer mp = new ExpressionMediaPlayer.MediaPlayer();
  10:             mp.Width = 800;
  11:             mp.Height = 600;
  12:             ExpressionMediaPlayer.PlaylistItem playListItem = new ExpressionMediaPlayer.PlaylistItem();
  13:             playListItem.MediaUrl = new Uri("mms://mysite.com/live-baseball-game.asx");
  14:             mp.Playlist.Add(playListItem);
  15:             LayoutRoot.Children.Add(mp);
  16:         }

I suspect people would not be using the code concept as much but I just wanted to point it out here.

Summary

So having the MediaPlayerTemplate.xap file is really all you need.  Anything else can be sent as parameters either via the object tag, the XAML control or in code.  This enables being able to really re-use the template you desire without having to run an encoder job just to get the template and change the code.

Hope this helps!