NASA World Wind on Media Center Edition
you might remember that i did the port of NASAs WorldWind to run on a Pocket PC with /cfWorldWind? well, i've spent the last year working with Media Center Edition ... and thought it was finally time to bring it to the big screen. since WorldWind already runs on desktop PCs, this is not a port. running stand alone apps from MediaCenter is actually another development model that i hadn't explored yet ... so that is my real excuse. all this article will do is use the WorldWind plugin model to extend its functionality without having to change any of its existing code. for kicks, this will also create a plugin for controlling WorldWind with a wired XBox 360 controller and use Virtual Earth functionality to find your current location.
first i had to figure out which MCE extensibility model to use to with WorldWind. it came down to WorldWind being a DirectX application. that matters because DirectX will not remote over extender sessions (e.g. this will only work directly on MCE and not through an XBox 360 extender). because of this limitation, i decided to keep WorldWind as a stand alone app with just minimal hooks to and from MCE. and the goal was to make this work without having to change any existing WW code, and just use their plugin model to add additional functionality. these are the steps that i took :
this starts out just following the tips from this article : Introduction to the 10-Foot Experience for Windows Game Developers
to get a WorldWind icon to show up in MCE, you create a .MCL file. a .MCL file is just XML that specifies the path to what application to run, title, thumbnail to display, etc... i created mceWorldWind.mcl and added that to the WW directory (C:\Program Files\NASA\World Wind 1.3\) along with the thumbnail mceWorldWind.png.
to get the .MCL file to show up in MCE under 'More Programs', create a shortcut for the .MCL file (in the WW directory) and place the shortcut in : C:\Documents and Settings\[Current User]\Start Menu\Programs\Accessories\Media Center\Media Center Programs\
now you need to create another shortcut named 'MCELauncher_WorldWind' that the 'run' attribute in the .MCL file points to. this shortcut will point to MCELauncher.exe (also in the WW directory). MCELauncher is a sample program (with code) included in the DirectX SDK. all i did was build it. MCELauncher is necessary to transition from the full screen DirectX experience of MCE to the full screen DirectX experience from WW. i.e. only one app can be full screen DirectX at a time. so the .MCL file specifies that the program it opens requires directX ... so MCE transitions out of DirectX exclusive mode ... but this takes a couple seconds. if WW tries to start before MCE transitions out of this mode then you'll get this exception screen. NOTE an alternate fix to this problem is to change the WW code to make a couple attempts to get a full screen Device and sleep a second or two in-between attempts.
the shortcut to MCELauncher will also need some command line arguments to it. NOTE you cannot pass command line arguments in the .MCL file. my shortcuts target looks like the following : C:\Program Files\NASA\World Wind 1.3\MCELauncher.exe "C:\Program Files\NASA\World Wind 1.3\WorldWind.exe" /f
first it has the path to MCELauncher. then it has the path to WW which MCELauncher will start once MCE has given up exclusive mode to DirectX. finally, the '/f' flag tells WW to run in full screen mode. NOTE even though the shortcut name is 'MCELauncher_WorldWind' you must reference it in the .MCL file as 'MCELauncher_WorldWind.lnk'
with that setup, you should now be able to start WorldWind from MCE
now we need to be able to get back to MCE from WorldWind. so what i did was create an McePlugin.cs class using the WW extensibility model. it started out by just adding a thumbnail to the WW MenuBar. then when you select that MenuButton, it closes WW.
the problem is that it doesn't auto return to MCE. so i added code to check to see if MCE was already running locally, and if it is it makes a ShellExecute call to 'open' MCE again.
to install the plugin just copy McePlugin.cs and McePlugin.png to C:\Program Files\NASA\World Wind 1.3\Plugins\McePlugin\. then you'll need to set it so the plugin will auto launch from the Plug-Ins - Load/Unload menu.
now we can start WW from MCE and exit WW to return to MCE.
but at this point we can only control WW from our television if we have the Media Center Remote Keyboard. now we need to add actual Remote Control capability. so i extended the McePlugin.cs class to use a NativeWindow to listen for the appropriate commands from the remote. if it recognizes a command, then it will send the keyboard command that WW expects.
the MenuBar was the tricky part because i don't think it currently has keyboard commands mapped for it? so i've got a little hack code that keeps track of the current MenuButton you are on, and pressing the 'rewind' and 'forward' buttons will move to the previous or next MenuButton. when you hit the 'Ok' button on the remote, then that MenuButton will either be selected or unselected based on its current state. hopefully a later version of WW will make the MenuBar keyboard enabled which would make this much easier to accomplish
that gives us almost the complete WorldWind experience from MediaCenter using a remote control. NOTE i'm not doing anything to handle the forms that can be popped up by some of the MenuButtons ... so i don't recommend selecting any of those
er, um ... so you saw my gamertag at the top of the article didn't you? ... well that means the XBox 360 is in the mix somehow. again, the solution above for WW on MCE will not work on the XBox 360 because DirectX will not work over remote desktop. but that doesn't keep us from using an XBox 360 Wired Controller on our MCE PC. i've actually already written the code (/mceXInput) to control MCE with a controller. the problem is that the steps above have taken us out of MCE and into WW, which doesn't know anything about the controller. also, the remote isn't exactly a satisfying control experience for MCE ... so lets fix that
created another plugin XBoxPlugin.cs which is entirely separate from the McePlugin above. you can use this plugin with WW regardless if you have MCE or not, you just need to have a wired XBox 360 Controller with the driver installed on the PC. then copy XBoxPlugin.cs to C:\Program Files\NASA\World Wind 1.3\Plugins\XBoxPlugin. all it does is listen for commands from an XBox 360 controller and then it sends the appropriate keyboard commands. NOTE if WW switches to .NET 2.0, they can use the Managed DirectX XInput API, instead of my lower level wrapper
this is just a real simple plugin to get an estimate of your current location. it also can be used stand-alone from the other plugins above. all it does is make a call to VirtualEarth (local.live.com) to find your current location based on IpAddress. if the location can be found (and the service is not busy), then WW will auto focus on the returned latitude and longitude. if the location cannot be found, then nothing will happen. NOTE i tried to use the WiFi location finder, which gives a little more accurate results, but i couldn't get this to work from custom code anymore.
the pic above shows my general location after selecting the button. ViaVirtualEarth.com is where i came up with idea for this plugin from this article : Obtaining the Visitor's Location
the following video shows starting WW from MCE, using the LocationFinder plugin, panning and zooming, and exiting back to MCE
so this article showed how to use WorldWind from MediaCenter, control WW with an XBox 360 Controller, and use a call to VirtualEarth to get your location and move to it in WW. this was accomplished without having to modify any WorldWind code. finished the code and article over a weekend
the code for each plugin is below. they can be used at the same time or separately. to install, unzip the (.cs and .png) files to C:\Program Files\NASA\World Wind 1.3\Plugins\. then use the Plugin-Load/Unload form to enable them
need to take a little break from nonstop coding. some reading sounds good. later