<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Niners/c4f.Matt-Ivers/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/Niners/c4f.Matt-Ivers/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Niners/c4f.Matt-Ivers/Posts</link>
    <language>en</language>
    <pubDate>Sun, 19 May 2013 17:16:43 GMT</pubDate>
    <lastBuildDate>Sun, 19 May 2013 17:16:43 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>1</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Control Windows Media Center using a Windows Mobile 5 Device</title>
      <description><![CDATA[
<p>This article demonstrates how to use a smartphone running Windows Mobile 5 to remotely control a host machine running Windows Media Center. I will describe how to create an add-in application that runs within Windows Media Center, and how to create a Windows
 Mobile 5 application that you can use to communicate with the Media Center over a wireless internet connection. Finally, I will demonstrate how to use this implementation to manipulate Media Center using the Windows Media Center API.
</p>
<p><a href="http://blogs.claritycon.com/blogs/matt_ivers/default.aspx">Matt Ivers</a>
</p>
<p><b>Difficulty: </b>Intermediate </p>
<p><b>Time Required:</b> 6-10 hours</p>
<p><b>Cost: </b>$100-$200 </p>
<p><b>Software: </b><a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=dc6c00cb-738A-4B97-8910-5cd29ab5f8d9&amp;DisplayLang=en">Visual Basic or Visual C# Express Editions</a>,
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=A43EA0B7-B85F-4612-AA08-3BF128C5873E&amp;displaylang=en">
Windows Media Center SDK 5.0</a>, <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=dc6c00cb-738A-4B97-8910-5cd29ab5f8d9&amp;DisplayLang=en">
Windows Mobile 5.0 Smartphone SDK</a> </p>
<p><b>Hardware: </b>Mobile device running Windows Mobile 5.0 </p>
<p><b>Download: </b><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/WMC_Remote_Code.zip">C# and VB.Net</a></p>
<ul>
</ul>
<h3>Introduction</h3>
Starting with Windows Media Center Edition 2005, Media Center added extensibility support through hosted add-in assemblies. By implementing an add-in interface and registering the assembly with Media Center, the add-in assembly is given access to the Microsoft.MediaCenter.Hosting.AddInHost
 object. Using this object model, an add-in assembly can programmatically inspect and manipulate various aspects of Windows Media Center. In addition to the exposed Media Center namespaces, the add-in has complete access to all the capabilities of the .NET
 Framework.
<p>&nbsp;</p>
<p>By combining the power of a Media Center add-in with a mobile device running Windows Mobile 5.0, we can extend the capabilities of a Media Center add-in even further. The add-in service I developed runs as a listener service within Windows Media Center on
 the host machine. It is initialized when Windows Media Center is started, runs invisibly in the background, and allows mobile devices to connect and submit requests to it. The mobile solution leverages an existing WiFi internet connection to communicate with
 the add-in via TCP socket connections. The mobile device runs a .NET Compact Framework 2.0 forms application designed for devices running Windows Mobile 5 or higher.</p>
<p>The included remote control application is capable of the following functionality:
</p>
<ul>
<li>Retrieve metadata about currently loaded media </li><li>Affect playback of currently loaded media – Play, Pause, Stop, Next Track, Previous Track
</li><li>Control Media Center volume </li><li>Retrieve a list of available media – Photos, Audio, Video </li><li>Explicitly load media for playback – Audio, Video </li></ul>
<h3>Creating a Windows Media Center add-in application</h3>
The first step in our implementation is creating an add-in that will run within Windows Media Center. This involves creating a new Windows Media Center Presentation Layer Application project, implementing an interface, signing the assembly, and creating a setup
 project to install the assembly and register it with Media center.
<p>&nbsp;</p>
<h4>Creating a new project – Windows Media Center Presentation Layer Application</h4>
Installing the Windows Media Center SDK makes this step simple. Once installed, you create this project like any other in Visual Studio:
<p><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/1_Create_new_WMC_presentation_layer_.jpg" width="500" height="351">&nbsp;</p>
<p><em>Figure 1 - Creating the project</em></p>
<p>Using the Windows Media Center Presentation Layer Application project template yields the following project skeleton:</p>
<p><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/2_AddIn_demo_project3.jpg" width="209" height="240">
</p>
<p><em>Figure&nbsp;2 - Solution Explorer for our new project</em></p>
<p>There are two files of interest here: AddIn.vb and App.xml. AddIn.vb contains our add-in class. Interface methods implemented in this class will be invoked by Windows Media Center when our add-in is launched. App.xml contains configuration information identifying
 our assemblies and add-in attributes. The setup project will use this XML to register our add-in with Windows Media Center during installation.
</p>
<h4>The AddIn class</h4>
Media Center add-in applications must implement two interfaces in order for Media Center to invoke them: Microsoft.MediaCenter.Hosting.IAddInEntryPoint, and Microsoft.MediaCenter.Hosting.IAddInModule. By using the project template, our add-in class already
 implements both (AddIn.vb):
<h5><span class="kwrd"><strong>Visual Basic</strong></span> .NET</h5>
<pre class="csharpcode"><span class="kwrd">Public</span> <span class="kwrd">Class</span> Class1
    <span class="kwrd">Implements</span> IAddInModule
    <span class="kwrd">Implements</span> IAddInEntryPoint

    <span class="rem">' Initialize (IAddInModule)</span>
    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> Initialize(<span class="kwrd">ByVal</span> appInfo <span class="kwrd">As</span> Dictionary(Of <span class="kwrd">String</span>, <span class="kwrd">Object</span>), <span class="kwrd">ByVal</span> entryPointInfo <span class="kwrd">As</span> Dictionary(Of <span class="kwrd">String</span>, <span class="kwrd">Object</span>)) <span class="kwrd">Implements</span> IAddInModule.Initialize
        <span class="rem">' Initialization logic goes here</span>
    <span class="kwrd">End</span> <span class="kwrd">Sub</span>

    <span class="rem">' Uninitialize (IAddInModule)</span>
    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> Uninitialize() <span class="kwrd">Implements</span> IAddInModule.Uninitialize
        <span class="rem">' Clean-up logic goes here</span>
    <span class="kwrd">End</span> <span class="kwrd">Sub</span>

    <span class="rem">' Launch (IAddInEntryPoint)</span>
    <span class="kwrd">Public</span> <span class="kwrd">Sub</span> Launch(<span class="kwrd">ByVal</span> host <span class="kwrd">As</span> AddInHost) <span class="kwrd">Implements</span> IAddInEntryPoint.Launch
        <span class="rem">' This is where normal execution begins</span>
    <span class="kwrd">End</span> <span class="kwrd">Sub</span>
<span class="kwrd">End</span> Class</pre>
<h5>Visual C#</h5>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> Class1 : IAddInModule, IAddInEntryPoint 
{
    <span class="rem">//  Initialize (IAddInModule)</span>
    <span class="kwrd">public</span> <span class="kwrd">void</span> Initialize(Dictionary&lt;<span class="kwrd">string</span>, <span class="kwrd">object</span>&gt; appInfo, Dictionary&lt;<span class="kwrd">string</span>, <span class="kwrd">object</span>&gt; entryPointInfo)
    {
        <span class="rem">//  Initialization logic goes here</span>
    }    
    <span class="rem">//  Uninitialize (IAddInModule)</span>
    <span class="kwrd">public</span> <span class="kwrd">void</span> Uninitialize() 
    {
        <span class="rem">//  Clean-up logic goes here</span>
    }    
    <span class="rem">//  Launch (IAddInEntryPoint)</span>
    <span class="kwrd">public</span> <span class="kwrd">void</span> Launch(AddInHost host) 
    {
        <span class="rem">//  This is where normal execution begins</span>
    }
}
</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>The IAddInModule.Initialize and IAddInModule.Uninitialize interface methods are used by Media Center to signal the beginning and end of the add-in application's lifetime. Use Initialize to create any internal objects your application may require, and the
 Uninitialize to perform any clean-up. Keep in mind that since the add-in application runs within Media Center, it may decide to close your add-in application before it has a chance to exit on its own. In any case, Media Center will call the Uninitialize method
 and give the add-in a window of execution to exit as gracefully as possible. </p>
<p>The IAddInEntryPoint.Launch method is where normal execution code should begin. Media Center will pass an AddInHost object as an input parameter. Through this object, your add-in application can access all the features of the Media Center API.
</p>
<h4>Signing the assembly</h4>
Windows Media Center requires that all add-in assemblies be strongly-named. This requires that the assembly be signed using a key file. Thanks to Visual Studio 2005, signing an assembly is a straightforward process. From your add-in project's “Properties” menu,
 you can browse to the “Signing” tab to create a new strong name key file for the project:
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/3_Sign_an_assembly4.jpg"><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/3_Sign_an_assembly_thumb2.jpg" width="500" height="327"></a>
</p>
<p><em>Figure 3 -&nbsp;Signing our assembly</em></p>
<p>Explicit instruction is also available here:<br>
<a href="http://msdn2.microsoft.com/en-us/library/ms247123(VS.80).aspx">How to: Sign an Assembly (Visual Studio)</a></p>
<h4>Tweaking the App.xml file</h4>
Media Center requires every add-in application to explicitly define a point of entry by which the application is to be launched. The App.xml file contains this configuration information. The Media Center project template used earlier generates the following
 sample:
<p>&nbsp;</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">application</span> <span class="attr">title</span><span class="kwrd">=&quot;DemoProject&quot;</span> <span class="attr">id</span><span class="kwrd">=&quot;{f6dd1141-f288-46fe-bcdb-2d9c5ffd986e}&quot;</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">entrypoint</span> <span class="attr">id</span><span class="kwrd">=&quot;{31a15ce9-0487-43bc-94de-a43409129641}&quot;</span> 
              <span class="attr">addin</span><span class="kwrd">=&quot;DemoProject.Class1, DemoProject,Culture=Neutral,Version=6.0.6000.0&quot;</span>
              <span class="attr">title</span><span class="kwrd">=&quot;DemoProject&quot;</span>
              <span class="attr">description</span><span class="kwrd">=&quot;DemoProject&quot;</span>
              <span class="attr">ImageUrl</span><span class="kwrd">=&quot;.\AppIcon.png&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">category</span> <span class="attr">category</span><span class="kwrd">=&quot;More Programs&quot;</span><span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">entrypoint</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">application</span><span class="kwrd">&gt;</span>
</pre>
<p>The XML definition specifies the add-in applications and their points of entry within Media Center. Add-in applications can be launched on demand from various locations within Media Center, such as from an icon in the “More Programs” group. A full listing
 of all the available points of entry can be found here. Add-in applications can also be launched in the background when Media Center starts. To indicate this, we specify “Background” in the “category” attribute. The “addin” attribute must also be modified
 to point to our add-in class in the format “Assemblyname.ClassName”. The “title”, “description”, and “ImageUrl” attributes are used primarily for on-demand add-ins.
</p>
<p>After making our changes, the Windows Media Center Remote application XML looks like this:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">application</span> <span class="attr">title</span><span class="kwrd">=&quot;WMCServerAddIn&quot;</span> <span class="attr">id</span><span class="kwrd">=&quot;{7b71a7ca-b459-4023-ab12-d5cc8c56b991}&quot;</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">entrypoint</span> <span class="attr">id</span><span class="kwrd">=&quot;{5fe9982b-ca4a-459e-b62c-40399e875d66}&quot;</span> 
              <span class="attr">addin</span><span class="kwrd">=&quot;WMCServerAddIn.ServerAddIn, WMCServerAddIn,Culture=Neutral,Version=6.0.6000.0&quot;</span>
              <span class="attr">title</span><span class="kwrd">=&quot;WMCServerAddIn&quot;</span>
              <span class="attr">description</span><span class="kwrd">=&quot;WMCServerAddIn&quot;</span>
              <span class="attr">ImageUrl</span><span class="kwrd">=&quot;.\AppIcon.png&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">category</span> <span class="attr">category</span><span class="kwrd">=&quot;Background&quot;</span><span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">entrypoint</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">application</span><span class="kwrd">&gt;</span></pre>
<h4>Creating the setup project</h4>
<p>With a basic interface implementation complete and a configuration XML created, we are ready to create the setup project. The setup project will install our assemblies into the Global Assembly Cache and register our XML-defined entry point with Media Center.
 A full step-by-step walkthrough can be found here:</p>
<p><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/MedctrSDK/htm/creatingawindowsinstallerfileforanaddin.asp">Creating a Windows Installer File for a Windows Media Center Add-in</a></p>
<p>Once the setup project is complete, it's time for a test. By using the Host.MediaCenterEnvironment.Dialog class off of the AddInHost object, we can present a dialog box to the user to ensure the add-in launches successfully. After compiling the solution,
 run the installer by right-clicking the setup project and choosing “Install”. Once installation has completed, run Windows Media Center. A few seconds after startup, the add-in is launched:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/4_Hello_world_demo_addin3.jpg"><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/4_Hello_world_demo_addin_thumb1.jpg" width="500" height="374"></a>
</p>
<p><em>Figure 4 - Running our Hello World Media Center Add-in</em></p>
<h3>Creating a Windows Mobile 5.0 client application</h3>
The second step in our implementation is creating a .NET Compact Framework 2.0 forms application. This is a mobile application that will run on a mobile device running Windows Mobile 5 or higher.
<h4>Creating a new project – Windows Mobile CE 5.0 application</h4>
<p>Installing the Windows Mobile Smartphone SDK 5.0 makes this step simple. Once the SDK is installed, you can create a project in Visual Studio using the Windows CE 5.0 Project template.
</p>
<p>The only other typical setup required for developing mobile apps is to change the deployment settings to point to your WM5 device. This can be configured within the Visual Studio toolbar:
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/6_Deploying_to_mobile3.jpg"><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/6_Deploying_to_mobile_thumb1.jpg" width="345" height="201"></a>
</p>
<p><em>Figure&nbsp;5 - changing the deployment settings to target the mobile device</em></p>
<h3>Implementing the Media Center Add-in service</h3>
With a test harness in place at both ends of the implementation, it was time to get to the real code. To facilitate the control of Media Center through the hosted add-in, the service requires a few key components. These include choosing a server / client conversation
 protocol, creating a multithreaded socket server, implementing object serialization, and implementing the programmatic manipulation of Media Center.
<h4>Implementing the socket server</h4>
<p>The socket server uses the Socket object from the System.Networking.Sockets namespace for all of its communications. The listener service begins by binding to the host machine's local address and listening on a port of your choosing. Once the socket is instantiated
 and bound to a local port, it begins listening for and accepting inbound connections. When a new connection is established, a target method BeginSocketConversation will be invoked on a new thread, where the actual communication between the two parties will
 take place. Once the new thread has been invoked, execution will continue in the AcceptConnections method. At this time the newly launched thread notifies the listener to begin accepting new connections again. A ManualResetEvent from the System.Threading namespace
 can be used to communicate changes in state between two or more threads. Here is the code implementation of the socket listener:
</p>
<h5><span class="kwrd">Visual Basic .NET</span></h5>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> AcceptConnections()
        <span class="kwrd">Dim</span> localMachineInfo <span class="kwrd">As</span> IPHostEntry
        <span class="kwrd">Dim</span> localEndPoint <span class="kwrd">As</span> IPEndPoint
        <span class="kwrd">Dim</span> listener <span class="kwrd">As</span> <span class="kwrd">New</span> Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        <span class="kwrd">Try</span>
            localMachineInfo = Dns.Resolve(<span class="kwrd">String</span>.Empty)
            localEndPoint = <span class="kwrd">New</span> IPEndPoint(localMachineInfo.AddressList(0), _port)
            listener.Bind(localEndPoint)
            listener.Listen(10)
            <span class="kwrd">While</span> <span class="kwrd">True</span>
                threadEvent.Reset()
                listener.BeginAccept(<span class="kwrd">New</span> AsyncCallback(<span class="kwrd">AddressOf</span> BeginSocketConversation), listener)
                threadEvent.WaitOne()
            <span class="kwrd">End</span> <span class="kwrd">While</span>
        <span class="kwrd">Catch</span> ex <span class="kwrd">As</span> Exception
          Log.Write(ex)
    <span class="kwrd">End</span> <span class="kwrd">Try</span>
<span class="kwrd">End</span> <span class="kwrd">Sub</span>
</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<h5>Visual C#</h5>
<pre class="csharpcode">Public Class Class1
    Implements IAddInModule
    Implements IAddInEntryPoint

    <span class="str">' Initialize (IAddInModule)
    Public Sub Initialize(ByVal appInfo As Dictionary(Of String, Object), ByVal entryPointInfo As Dictionary(Of String, Object)) Implements IAddInModule.Initialize
        '</span> Initialization logic goes here
    End Sub

    <span class="str">' Uninitialize (IAddInModule)
    Public Sub Uninitialize() Implements IAddInModule.Uninitialize
        '</span> Clean-up logic goes here
    End Sub

    <span class="str">' Launch (IAddInEntryPoint)
    Public Sub Launch(ByVal host As AddInHost) Implements IAddInEntryPoint.Launch
        '</span> This <span class="kwrd">is</span> <span class="kwrd">where</span> normal execution begins
    End Sub
End Class</pre>
<p>Once a connection has been established, the server begins to listen for inbound messages. When new data is received, it is parsed into a custom Message object for easy inspection by a consuming class. An event is then raised to any consuming classes, passing
 a reference to the newly created Message object. The server then resumes listening for new data on the same socket. Here is the code implementation:</p>
<h5>Visual Basic .NET</h5>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> BeginSocketConversation(<span class="kwrd">ByVal</span> ar <span class="kwrd">As</span> IAsyncResult)
    threadEvent.<span class="kwrd">Set</span>()
    <span class="kwrd">RaiseEvent</span> ClientConnected()
    <span class="kwrd">Dim</span> listener <span class="kwrd">As</span> Socket = <span class="kwrd">CType</span>(ar.AsyncState, Socket)
    _socket = listener.EndAccept(ar)
    <span class="kwrd">Dim</span> buffer(PACKET_SIZE) <span class="kwrd">As</span> <span class="kwrd">Byte</span>
    <span class="kwrd">Dim</span> bytesReadCount <span class="kwrd">As</span> <span class="kwrd">Integer</span> = 0
    <span class="kwrd">While</span> <span class="kwrd">True</span>
        <span class="kwrd">Dim</span> sb <span class="kwrd">As</span> <span class="kwrd">New</span> System.Text.StringBuilder
        <span class="kwrd">Do</span>
            <span class="kwrd">Try</span>
                bytesReadCount = _socket.Receive(buffer, buffer.Length, SocketFlags.None)
            <span class="kwrd">Catch</span> ex <span class="kwrd">As</span> Exception
                _socket.Close()
                <span class="kwrd">Exit</span> <span class="kwrd">While</span>
            <span class="kwrd">End</span> <span class="kwrd">Try</span>
            sb.Append(System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, bytesReadCount))
        <span class="kwrd">Loop</span> <span class="kwrd">While</span> _socket.Available &gt; 0
        <span class="kwrd">Dim</span> requestMessage <span class="kwrd">As</span> <span class="kwrd">New</span> RequestMessage()
        requestMessage.DeSerialize(sb.ToString())
        <span class="kwrd">RaiseEvent</span> MessageReceived(requestMessage)
    <span class="kwrd">End</span> <span class="kwrd">While</span>
    <span class="kwrd">RaiseEvent</span> ClientDisconnected()
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<h5><span class="kwrd">Visual C#</span></h5>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> BeginSocketConversation(IAsyncResult ar)
{
    threadEvent.Set();
    ClientConnected();
    Socket listener = ((Socket)(ar.AsyncState));
    _socket = listener.EndAccept(ar);
    <span class="kwrd">byte</span>[,] buffer;
    <span class="kwrd">int</span> bytesReadCount = 0;
    <span class="kwrd">while</span> (<span class="kwrd">true</span>)
    {
        System.Text.StringBuilder sb = <span class="kwrd">new</span> System.Text.StringBuilder();
        <span class="kwrd">for</span> (
        ; (_socket.Available &gt; 0);
        )
        {
            <span class="kwrd">try</span>
            {
                bytesReadCount = _socket.Receive(buffer, buffer.Length, SocketFlags.None);
            }
            <span class="kwrd">catch</span> (Exception ex)
            {
                _socket.Close();
                <span class="kwrd">break</span>;
            }
            sb.Append(System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, bytesReadCount));
        }
        RequestMessage requestMessage = <span class="kwrd">new</span> RequestMessage();
        requestMessage.DeSerialize(sb.ToString());
        MessageReceived(requestMessage);
    }
    ClientDisconnected();
}</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<h4>Object serialization</h4>
The limited resources of a mobile device require an efficient method of transferring data and commands between the device and the host machine. Due to their large size, the .NET remoting libraries and the binary serialization libraries provided by .NET 2.0
 are not available in the .NET Mobile Framework. I chose custom serialization to facilitate the transfer of objects. While less flexible, this enabled objects to be transferred using very little bandwidth.
<p>&nbsp;</p>
<h4>Implementing the AddIn.Launch method</h4>
<p>The custom server object created in the previous section encapsulates all the grunt work of socket-level protocol, accepting connections, serializing / deserializing message objects, and data transfer. Within the AddIn class implementation, all we have to
 do now is instantiate the Server class, indicating the port to listen on: </p>
<h5>Visual Basic .NET</h5>
<pre class="csharpcode"><span class="kwrd">Public</span> <span class="kwrd">Sub</span> Launch(<span class="kwrd">ByVal</span> host <span class="kwrd">As</span> AddInHost) <span class="kwrd">Implements</span> IAddInEntryPoint.Launch
    _wmcHost = host
    _waitForExit = <span class="kwrd">New</span> System.Threading.ManualResetEvent(<span class="kwrd">False</span>)
    _server.Start(DEFAULT_PORT)
    System.Threading.Thread.CurrentThread.Priority = Threading.ThreadPriority.Lowest
    _waitForExit.WaitOne()
<span class="kwrd">End</span> Sub</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<h5>Visual C#</h5>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">void</span> Launch(AddInHost host) 
{
    _wmcHost = host;
    _waitForExit = <span class="kwrd">new</span> System.Threading.ManualResetEvent(<span class="kwrd">false</span>);
    _server.Start(DEFAULT_PORT);
    System.Threading.Thread.CurrentThread.Priority = Threading.ThreadPriority.Lowest;
    _waitForExit.WaitOne();
}</pre>
<p>We also perform two other critical tasks at this time. First, we assign a reference to the AddInHost to a private member variable for later use. Second, we reduce the priority of the add-in's main thread and use a ManualResetEvent to put it to sleep until
 Media Center is closed. The reason for this relates to the nature of an add-in's lifetime within Media Center. The Media Center add-in hosting process will only allow an add-in to execute for the duration of its Launch method. This means that as soon as the
 Launch method returns, the add-in and any child threads it has spawned will be terminated. For this reason, we must keep the add-in alive by blocking the Launch method from exiting.
</p>
<h4>Media Center manipulation</h4>
<p>Using the communications layer and socket listener developed in the previous sections, we can finally get to the task of performing something useful with the input requests. By subscribing to the custom Server object's MessageReceived event, the AddIn class's
 OnDataReceived method will automatically be invoked when a new request message is received from the listener:
</p>
<h5>Visual Basic .NET</h5>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> OnDataReceived(<span class="kwrd">ByVal</span> message <span class="kwrd">As</span> RequestMessage) <span class="kwrd">Handles</span> _server.MessageReceived
    <span class="kwrd">Select</span> <span class="kwrd">Case</span> message.RequestAction
        <span class="kwrd">Case</span> RequestMessage.Action.PauseMedia
_wmcHost.MediaCenterEnvironment.MediaExperience.Transport.PlayRate = PlayRates.PLAYRATE_PAUSE
        <span class="kwrd">Case</span> RequestMessage.Action.VolumeUp
           _wmcHost.MediaCenterEnvironment.AudioMixer.VolumeUp()
        <span class="kwrd">Case</span> RequestMessage.Action.VolumeDown
           _wmcHost.MediaCenterEnvironment.AudioMixer.VolumeDown()
        <span class="kwrd">Case</span> RequestMessage.Action.NextMedia _wmcHost.MediaCenterEnvironment.MediaExperience.Transport.SkipForward()
        <span class="kwrd">Case</span> <span class="kwrd">Else</span>
    <span class="kwrd">End</span> <span class="kwrd">Select</span>
    SendAcknowledgement(message)
<span class="kwrd">End</span> <span class="kwrd">Sub</span></pre>
<h5>Visual C#</h5>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> OnDataReceived(RequestMessage message) 
{
    <span class="kwrd">switch</span> (message.RequestAction) 
    {
        <span class="kwrd">case</span> RequestMessage.Action.PauseMedia:
            _wmcHost.MediaCenterEnvironment.MediaExperience.Transport.PlayRate = PlayRates.PLAYRATE_PAUSE;
            <span class="kwrd">break</span>;
        <span class="kwrd">case</span> RequestMessage.Action.VolumeUp:
            _wmcHost.MediaCenterEnvironment.AudioMixer.VolumeUp();
            <span class="kwrd">break</span>;
        <span class="kwrd">case</span> RequestMessage.Action.VolumeDown:
            _wmcHost.MediaCenterEnvironment.AudioMixer.VolumeDown();
            <span class="kwrd">break</span>;
        <span class="kwrd">case</span> RequestMessage.Action.NextMedia:
            _wmcHost.MediaCenterEnvironment.MediaExperience.Transport.SkipForward();
            <span class="kwrd">break</span>;
    }
    SendAcknowledgement(message);
}</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>&nbsp;</p>
<p>The RequestMessage class shown above is a custom object, originally created by Windows Mobile 5 application running on a connected mobile device. The transport object was then serialized on the device, transmitted, deserialized in the listener service, and
 raised to the add-in class via the MessageReceived event. The RequestAction property is an enumerable type indicating the type of action to take within Media Center. The Media Center API exposed by the AddInHost object (_wmcHost) can then be used to actually
 perform the desired Media Center operation. Finally, we send an acknowledgement message to the mobile device.<br>
</p>
<h3>Implementing the Windows Mobile 5 remote client application</h3>
After completing the Media Center add-in, the mobile application is relatively simple by comparison. The remote application's role is to present the user with a user interface similar to that of an actual remote control. The remote application directs user
 input to the listener add-in, and displays any response data if necessary.
<p>&nbsp;</p>
<h4>Implementing the socket client</h4>
<p>The design of the socket client is much simpler than that of the socket server. All execution will be performed on the primary thread. The client begins by establishing a connection with an add-in server. Once established, the socket client sends and receives
 data synchronously over the socket. Consumers of the socket client need only call the Send method, which will return with the transactional response:
</p>
<h5>Visual Basic .NET</h5>
<pre class="csharpcode"><span class="kwrd">Public</span> <span class="kwrd">Function</span> Send(<span class="kwrd">ByVal</span> request <span class="kwrd">As</span> Message) <span class="kwrd">As</span> <span class="kwrd">String</span>
    <span class="kwrd">Dim</span> responseString <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="kwrd">Nothing</span>
    <span class="kwrd">Try</span>
        <span class="kwrd">If</span> ((<span class="kwrd">Not</span> (_socket) <span class="kwrd">Is</span> <span class="kwrd">Nothing</span>) _
                    <span class="kwrd">AndAlso</span> _socket.Connected) <span class="kwrd">Then</span>
            <span class="kwrd">Dim</span> requestString <span class="kwrd">As</span> <span class="kwrd">String</span> = request.Serialize
            Send(requestString)
            responseString = RecvSynchronous
            <span class="kwrd">Return</span> responseString
        <span class="kwrd">End</span> <span class="kwrd">If</span>
    <span class="kwrd">Catch</span> ex <span class="kwrd">As</span> Exception
        <span class="kwrd">Return</span> <span class="kwrd">Nothing</span>
    <span class="kwrd">End</span> <span class="kwrd">Try</span>
    <span class="kwrd">Return</span> responseString
<span class="kwrd">End</span> <span class="kwrd">Function</span>
</pre>
<h5>Visual C#</h5>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">string</span> Send(Message request)
{
    <span class="kwrd">string</span> responseString = <span class="kwrd">null</span>;
    <span class="kwrd">try</span>
    {
        <span class="kwrd">if</span> (_socket != <span class="kwrd">null</span> &amp;&amp; _socket.Connected)
        {
            <span class="kwrd">string</span> requestString = request.Serialize();
            Send(requestString);
            responseString = RecvSynchronous();
            <span class="kwrd">return</span> responseString;
        }
    }
    <span class="kwrd">catch</span> (Exception ex)
    {
        <span class="kwrd">return</span> <span class="kwrd">null</span>;
    }
    <span class="kwrd">return</span> responseString;
}
</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<h4>Adding the UI layer</h4>
With the communications layer in place the next step in our remote implementation is the user interface. In this final stage, we hook up UI controls to construct the request messages that will be sent to the host service. However, before we do that we must
 first connect with the Media Center host machine. Here's a look at the connection configuration screen:
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/7_Config2.jpg"><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/7_Config_thumb.jpg" width="239" height="319"></a>
</p>
<p><em>Figure 6 - The configuration screen on the mobile device</em></p>
<p>Once we've specified the host and port of our running Media Center add-in service, we can click the “Connect” button to initialize the TCP/IP socket connection. Using the TCP Client class developed earlier, the code required to handle this event is simple:</p>
<h5>Visual Basic .NET</h5>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> btnConnect_Click(<span class="kwrd">ByVal</span> sender <span class="kwrd">As</span> <span class="kwrd">Object</span>, <span class="kwrd">ByVal</span> e <span class="kwrd">As</span> EventArgs)
    <span class="kwrd">Dim</span> host <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="kwrd">Me</span>.txtHost.Text.Trim
    <span class="kwrd">Dim</span> port <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="kwrd">Me</span>.txtPort.Text.Trim
    _client.Connect(host, Convert.ToInt32(port))
<span class="kwrd">End</span> Sub</pre>
<h5>Visual C#</h5>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> btnConnect_Click(<span class="kwrd">object</span> sender, EventArgs e)
{
     <span class="kwrd">string</span> host = <span class="kwrd">this</span>.txtHost.Text.Trim();
     <span class="kwrd">string</span> port = <span class="kwrd">this</span>.txtPort.Text.Trim();
     _client.Connect(host, Convert.ToInt32(port));
}</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>Once connected, the user can navigate the application using the provided tabs at the bottom of the screen. Since this application is intended to function as a remote control, there is a standard media control screen:</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/8_Controls2.jpg"><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/8_Controls_thumb.jpg" width="241" height="319"></a>
</p>
<p><em>Figure 8: The control screen on the mobile device</em></p>
<p>Nothing exotic here, but the basic media control functionality you'd expect from a remote is available. Here's a sample of the code required to support the “Stop” button's click event:</p>
<h5>Visual Basic .NET</h5>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> btnConnect_Click(<span class="kwrd">ByVal</span> sender <span class="kwrd">As</span> <span class="kwrd">Object</span>, <span class="kwrd">ByVal</span> e <span class="kwrd">As</span> EventArgs)
    <span class="kwrd">Dim</span> host <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="kwrd">Me</span>.txtHost.Text.Trim
    <span class="kwrd">Dim</span> port <span class="kwrd">As</span> <span class="kwrd">String</span> = <span class="kwrd">Me</span>.txtPort.Text.Trim
    _client.Connect(host, Convert.ToInt32(port))
<span class="kwrd">End</span> Sub</pre>
<h5>Visual C#</h5>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> btnStop_Click(<span class="kwrd">object</span> sender, EventArgs e)
{
    RequestMessage message = <span class="kwrd">new</span> RequestMessage();
    message.RequestAction = RequestMessage.Action.StopMedia;
    message.Data = String.Empty;
    <span class="kwrd">string</span> responseString = client.Send(message);
    ResponseMessage response = <span class="kwrd">new</span> ResponseMessage(responseString);
}</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>The UI form uses the connected Client object to execute the Stop command. First, the form constructs a Request message, populating the type of action desired (StopMedia). Next, the Request message is passed to the Client class, where it is serialized for
 transport and sent over the connected TCP socket. From there, the running Media Center service will receive the request, perform the media stop, and send an acknowledgement. The Client then returns a Response message, which will contain a Boolean indicating
 if the request was successful or not. </p>
<p>On a Media Stop request, examining the Response object is not very informative. However, for other commands, the Media Center add-in service can be designed to return any kind of information required of the host. The Detail screen is a good example:
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/9_Detail2.jpg"><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/9_Detail_thumb.jpg" width="240" height="321"></a>
</p>
<p><em>Figure 9 - The detail page&nbsp;</em> </p>
<p>When a song or video is currently playing, the above screen can be used to retrieve any metadata associated with it. The event handler for the screen's “Refresh” button looks similar in form to the Stop button's handler:
</p>
<h5>Visual Basic .NET</h5>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> btnRefreshDetail_Click(<span class="kwrd">ByVal</span> sender <span class="kwrd">As</span> <span class="kwrd">Object</span>, <span class="kwrd">ByVal</span> e <span class="kwrd">As</span> EventArgs)
    <span class="kwrd">Dim</span> request <span class="kwrd">As</span> RequestMessage = <span class="kwrd">New</span> RequestMessage
    request.RequestAction = RequestMessage.Action.GetMediaMetadata
    <span class="kwrd">Dim</span> responseString <span class="kwrd">As</span> <span class="kwrd">String</span> = _client.Send(request)
    <span class="kwrd">Dim</span> response <span class="kwrd">As</span> MediaMetadataMessage = <span class="kwrd">New</span> MediaMetadataMessage(responseString)
    <span class="kwrd">For</span> <span class="kwrd">Each</span> item <span class="kwrd">As</span> MediaMetadataMessage.MediaMetadataItem <span class="kwrd">In</span> message.Data
        <span class="kwrd">If</span> ((<span class="kwrd">Not</span> (item.Value) <span class="kwrd">Is</span> <span class="kwrd">Nothing</span>) <span class="kwrd">AndAlso</span> (item.Value.Length &gt; 0)) <span class="kwrd">Then</span>
            <span class="kwrd">Me</span>.txtDetail.Text = (<span class="kwrd">Me</span>.txtDetail.Text &#43; (item.Key &#43; (<span class="str">&quot;: &quot;</span> &#43; item.Value)))
            <span class="kwrd">Me</span>.txtDetail.Text = (<span class="kwrd">Me</span>.txtDetail.Text &#43; <span class="str">&quot;&quot;</span> &amp; vbCrLf)
        <span class="kwrd">End</span> <span class="kwrd">If</span>
    <span class="kwrd">Next</span>
<span class="kwrd">End</span> Sub</pre>
<h5>Visual C#</h5>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> btnRefreshDetail_Click(<span class="kwrd">object</span> sender, EventArgs e)
{
    RequestMessage request = <span class="kwrd">new</span> RequestMessage();
    request.RequestAction = RequestMessage.Action.GetMediaMetadata;
    <span class="kwrd">string</span> responseString = _client.Send(request);
    MediaMetadataMessage response = <span class="kwrd">new</span> MediaMetadataMessage(responseString);
    <span class="kwrd">foreach</span> (MediaMetadataMessage.MediaMetadataItem item <span class="kwrd">in</span> message.Data) {
        <span class="kwrd">if</span> (item.Value != <span class="kwrd">null</span> &amp;&amp; item.Value.Length &gt; 0){
            <span class="kwrd">this</span>.txtDetail.Text &#43;= item.Key &#43; <span class="str">&quot;: &quot;</span> &#43; item.Value;
            <span class="kwrd">this</span>.txtDetail.Text &#43;= <span class="str">&quot;\r\n&quot;</span>;
        }
    }
}</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>This time, however, the Response object has a list of metadata keys and values, which are then enumerated and displayed in a textbox. This Response object was originally populated by the Media Center add-in service:
</p>
<h5>Visual Basic .NET</h5>
<pre class="csharpcode"><span class="kwrd">Private</span> <span class="kwrd">Sub</span> SendMediaMetadata()
    <span class="kwrd">Dim</span> response <span class="kwrd">As</span> <span class="kwrd">New</span> MediaMetadataMessage()
    <span class="kwrd">Dim</span> val <span class="kwrd">As</span> <span class="kwrd">String</span>
    <span class="kwrd">For</span> <span class="kwrd">Each</span> key <span class="kwrd">As</span> <span class="kwrd">String</span> <span class="kwrd">In</span> _wmcHost.MediaCenterEnvironment.MediaExperience.MediaMetadata.Keys
    val = _wmcHost.MediaCenterEnvironment.MediaExperience.MediaMetadata.Item(key).ToString()
    response.Data.Add(<span class="kwrd">New</span> MediaMetadataMessage.MediaMetadataItem(key, val))
    <span class="kwrd">Next</span>
    response.ResponseIndicator = MediaMetadataMessage.ResponseCode.Success
    _server.Send(response)
<span class="kwrd">End</span> Sub</pre>
<h5>Visual C#</h5>
<pre class="csharpcode"><span class="kwrd">private</span> <span class="kwrd">void</span> SendMediaMetadata() 
{
    MediaMetadataMessage response = <span class="kwrd">new</span> MediaMetadataMessage();
    <span class="kwrd">string</span> val;
    <span class="kwrd">foreach</span> (<span class="kwrd">string</span> key <span class="kwrd">in</span> _wmcHost.MediaCenterEnvironment.MediaExperience.MediaMetadata.Keys) 
    {
        val = _wmcHost.MediaCenterEnvironment.MediaExperience.MediaMetadata.Item[key].ToString();
        response.Data.Add(<span class="kwrd">new</span> MediaMetadataMessage.MediaMetadataItem(key, val));
    }
    response.ResponseIndicator = MediaMetadataMessage.ResponseCode.Success;
    _server.Send(response);
}</pre>
<style type="text/css">
<!--
.csharpcode
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{background-color:#ffffff;
	font-family:consolas,"Courier New",courier,monospace;
	color:black;
	font-size:small}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	margin:0em;
	width:100%}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>After receiving a request from the mobile device for the currently playing media's metadata, the Media Center add-in service constructs a list of custom objects (MediaMetadataItem). It populates this list by enumerating properties of the AddInHost object,
 through the namespace MediaCenterEnvironment.MediaExperience.MediaMetadata. It then sends this list on the Response object, where the mobile device will inspect and display the data, as shown above.
</p>
<p>The last feature that the mobile remote application provides is the ability to select specific media to play based on a list of available media on the host. This functionality is provided for audio, video, and images:
</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/10_Music2.jpg"><img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/10_Music_thumb.jpg" width="240" height="320"></a>
<a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/11_Video2.jpg">
<img border="0" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/2632164/11_Video_thumb.jpg" width="240" height="320"></a>
</p>
<p><em>Figure 10 - Music and Video&nbsp;list management&nbsp;</em> </p>
<p>The mobile application requests the list of available media in a similar fashion to the Details screen implementation. The resulting list of files is then bound and displayed in a DataGrid. The Media Center add-in service can then be instructed to play individual
 songs or videos using the AddInHost's MediaCenterEnvironment.PlayMedia method. </p>
<h4><strong>Mobile Application UI design considerations</strong></h4>
<p>Developing on the mobile platform introduces design challenges not found in Windows Forms applications due to the small amount of screen real estate available. Many typical form layouts found in Windows Forms applications won't work well on a mobile device's
 small screen. When developing for a mobile application, try to keep the user interface as simple as possible. Window containers and managers such as a tabbed control enable the developer to functionally divide an application into logical components. This alleviates
 the clutter created by having too many controls in a single window. Also try to keep your text and controls as simple and large as possible. This makes the application easier to view and manipulate, especially in outdoor or bright conditions.</p>
<h3>Conclusion</h3>
<p>Once complete, the remote application gives you a level of control simply not available on hardware-based remote controls. I really enjoyed working on this application because it gave me a chance to integrate a number of different technologies into a single
 implementation. Be sure to download the code and take the remote for a spin. For those not familiar with all of the components used in this article (Media Center add-in services, socket communication, installer and assembly signing, etc.), don't be intimidated.
 The Microsoft-provided SDK packages for both parts of the solution make creating your own add-in projects a snap. Plus, the technical challenges unique to this project have already been overcome! Feel free to modify my implementation, or reuse the included
 socket classes to create an add-in all your own. Finally, please post feedback or questions here or at my
<a href="http://blogs.claritycon.com/blogs/matt_ivers/default.aspx">blog</a>.</p>
<h3>About the Author</h3>
<p>Matt Ivers is a software engineer at Chicago-based <a href="http://www.claritycon.com/">
Clarity Consulting</a>. He has extensive professional experience developing .NET solutions in both Visual C# .NET and VB.NET. Check him out at his
<a href="http://blogs.claritycon.com/blogs/matt_ivers/default.aspx">blog</a> or through the Clarity blog site,
<a href="http://blogs.claritycon.com/">Clarity Blogs</a>. </p>
<h3>References</h3>
<p><a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=A43EA0B7-B85F-4612-AA08-3BF128C5873E&amp;displaylang=en">Windows Media Center SDK 5.0</a><br>
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=dc6c00cb-738A-4B97-8910-5cd29ab5f8d9&amp;DisplayLang=en">Windows Mobile 5.0 Smartphone SDK</a>
</p>
<p><a href="http://msdn2.microsoft.com/en-us/library/ms247123(VS.80).aspx">How to: Sign an Assembly using Visual Studio 2005</a><br>
<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/MedctrSDK/htm/creatingawindowsinstallerfileforanaddin.asp">How to: Create a Windows Installer File for a Windows Media Center Add-in</a>
</p>
<p><a href="http://msdn2.microsoft.com/en-gb/library/ms816327.aspx">Windows Media Center - SDK Overview</a><br>
<a href="http://msdn2.microsoft.com/en-us/library/bb189667.aspx">Windows Media Center - Understanding the Basics</a><br>
<a href="http://msdn2.microsoft.com/en-us/library/bb189733.aspx">Windows Media Center - Development Tools</a><br>
<a href="http://msdn.microsoft.com/smartclient/default.aspx?pull=/library/en-us/dnxpmce/html/positionchangeraddin.asp">Windows Media Center - AddIn example: &quot;Time Travel&quot;</a>
</p>
<p><a href="http://msdn2.microsoft.com/en-us/library/5w7b7x5f.aspx">Using an Asynchronous Server Socket</a></p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Matt-Ivers/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:5f3aee551c9a4099a3d29e7600d3e5ee">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Control-Windows-Media-Center-using-a-Windows-Mobile-5-Device</comments>
      <itunes:summary>
This article demonstrates how to use a smartphone running Windows Mobile 5 to remotely control a host machine running Windows Media Center. I will describe how to create an add-in application that runs within Windows Media Center, and how to create a Windows
 Mobile 5 application that you can use to communicate with the Media Center over a wireless internet connection. Finally, I will demonstrate how to use this implementation to manipulate Media Center using the Windows Media Center API.
 
Matt Ivers
 
Difficulty: Intermediate  
Time Required: 6-10 hours 
Cost: $100-$200  
Software: Visual Basic or Visual C# Express Editions,

Windows Media Center SDK 5.0, 
Windows Mobile 5.0 Smartphone SDK  
Hardware: Mobile device running Windows Mobile 5.0  
Download: C# and VB.Net 


Introduction
Starting with Windows Media Center Edition 2005, Media Center added extensibility support through hosted add-in assemblies. By implementing an add-in interface and registering the assembly with Media Center, the add-in assembly is given access to the Microsoft.MediaCenter.Hosting.AddInHost
 object. Using this object model, an add-in assembly can programmatically inspect and manipulate various aspects of Windows Media Center. In addition to the exposed Media Center namespaces, the add-in has complete access to all the capabilities of the .NET
 Framework.
&amp;nbsp; 
By combining the power of a Media Center add-in with a mobile device running Windows Mobile 5.0, we can extend the capabilities of a Media Center add-in even further. The add-in service I developed runs as a listener service within Windows Media Center on
 the host machine. It is initialized when Windows Media Center is started, runs invisibly in the background, and allows mobile devices to connect and submit requests to it. The mobile solution leverages an existing WiFi internet connection to communicate with
 the add-in via TCP socket connections. The mobile device runs a .NET Compact Framework 2.0 forms application designed </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Control-Windows-Media-Center-using-a-Windows-Mobile-5-Device</link>
      <pubDate>Mon, 14 May 2007 17:08:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Control-Windows-Media-Center-using-a-Windows-Mobile-5-Device</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/2632164_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/2632164_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Matt Ivers</dc:creator>
      <itunes:author>Matt Ivers</itunes:author>
      <slash:comments>25</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Control-Windows-Media-Center-using-a-Windows-Mobile-5-Device/RSS</wfw:commentRss>
      <category>Media</category>
      <category>Home Automation</category>
      <category>audiovideo</category>
      <category>hardwarehacks</category>
    </item>    
</channel>
</rss>