Control Windows Media Center using a Windows Mobile 5 Device

Published 14 May 07 01:08 PM | Coding4Fun 

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.

    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.

    The included remote control application is capable of the following functionality:

    • Retrieve metadata about currently loaded media
    • Affect playback of currently loaded media – Play, Pause, Stop, Next Track, Previous Track
    • Control Media Center volume
    • Retrieve a list of available media – Photos, Audio, Video
    • Explicitly load media for playback – Audio, Video

    Creating a Windows Media Center add-in application

    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.

    Creating a new project – Windows Media Center Presentation Layer Application

    Installing the Windows Media Center SDK makes this step simple. Once installed, you create this project like any other in Visual Studio:

     

    Figure 1 - Creating the project

    Using the Windows Media Center Presentation Layer Application project template yields the following project skeleton:

    Figure 2 - Solution Explorer for our new project

    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.

    The AddIn class

    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):
    Visual Basic .NET
    Public Class Class1
        Implements IAddInModule
        Implements IAddInEntryPoint
    
        ' Initialize (IAddInModule)
        Public Sub Initialize(ByVal appInfo As Dictionary(Of String, Object), ByVal entryPointInfo As Dictionary(Of String, Object)) Implements IAddInModule.Initialize
            ' Initialization logic goes here
        End Sub
    
        ' Uninitialize (IAddInModule)
        Public Sub Uninitialize() Implements IAddInModule.Uninitialize
            ' Clean-up logic goes here
        End Sub
    
        ' Launch (IAddInEntryPoint)
        Public Sub Launch(ByVal host As AddInHost) Implements IAddInEntryPoint.Launch
            ' This is where normal execution begins
        End Sub
    End Class
    Visual C#
    public class Class1 : IAddInModule, IAddInEntryPoint 
    {
        //  Initialize (IAddInModule)
        public void Initialize(Dictionary<string, object> appInfo, Dictionary<string, object> entryPointInfo)
        {
            //  Initialization logic goes here
        }    
        //  Uninitialize (IAddInModule)
        public void Uninitialize() 
        {
            //  Clean-up logic goes here
        }    
        //  Launch (IAddInEntryPoint)
        public void Launch(AddInHost host) 
        {
            //  This is where normal execution begins
        }
    }
    

    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.

    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.

    Signing the assembly

    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:

    Figure 3 - Signing our assembly

    Explicit instruction is also available here:
    How to: Sign an Assembly (Visual Studio)

    Tweaking the App.xml file

    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:

    <application title="DemoProject" id="{f6dd1141-f288-46fe-bcdb-2d9c5ffd986e}">
      <entrypoint id="{31a15ce9-0487-43bc-94de-a43409129641}" 
                  addin="DemoProject.Class1, DemoProject,Culture=Neutral,Version=6.0.6000.0"
                  title="DemoProject"
                  description="DemoProject"
                  ImageUrl=".\AppIcon.png">
        <category category="More Programs"/>
      </entrypoint>
    </application>
    

    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.

    After making our changes, the Windows Media Center Remote application XML looks like this:

    <application title="WMCServerAddIn" id="{7b71a7ca-b459-4023-ab12-d5cc8c56b991}">
      <entrypoint id="{5fe9982b-ca4a-459e-b62c-40399e875d66}" 
                  addin="WMCServerAddIn.ServerAddIn, WMCServerAddIn,Culture=Neutral,Version=6.0.6000.0"
                  title="WMCServerAddIn"
                  description="WMCServerAddIn"
                  ImageUrl=".\AppIcon.png">
        <category category="Background"/>
      </entrypoint>
    </application>

    Creating the setup project

    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:

    Creating a Windows Installer File for a Windows Media Center Add-in

    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:

    Figure 4 - Running our Hello World Media Center Add-in

    Creating a Windows Mobile 5.0 client application

    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.

    Creating a new project – Windows Mobile CE 5.0 application

    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.

    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:

    Figure 5 - changing the deployment settings to target the mobile device

    Implementing the Media Center Add-in service

    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.

    Implementing the socket server

    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:

    Visual Basic .NET
    Private Sub AcceptConnections()
            Dim localMachineInfo As IPHostEntry
            Dim localEndPoint As IPEndPoint
            Dim listener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            Try
                localMachineInfo = Dns.Resolve(String.Empty)
                localEndPoint = New IPEndPoint(localMachineInfo.AddressList(0), _port)
                listener.Bind(localEndPoint)
                listener.Listen(10)
                While True
                    threadEvent.Reset()
                    listener.BeginAccept(New AsyncCallback(AddressOf BeginSocketConversation), listener)
                    threadEvent.WaitOne()
                End While
            Catch ex As Exception
              Log.Write(ex)
        End Try
    End Sub
    
    Visual C#
    Public Class Class1
        Implements IAddInModule
        Implements IAddInEntryPoint
    
        ' Initialize (IAddInModule)
        Public Sub Initialize(ByVal appInfo As Dictionary(Of String, Object), ByVal entryPointInfo As Dictionary(Of String, Object)) Implements IAddInModule.Initialize
            ' Initialization logic goes here
        End Sub
    
        ' Uninitialize (IAddInModule)
        Public Sub Uninitialize() Implements IAddInModule.Uninitialize
            ' Clean-up logic goes here
        End Sub
    
        ' Launch (IAddInEntryPoint)
        Public Sub Launch(ByVal host As AddInHost) Implements IAddInEntryPoint.Launch
            ' This is where normal execution begins
        End Sub
    End Class

    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:

    Visual Basic .NET
    Private Sub BeginSocketConversation(ByVal ar As IAsyncResult)
        threadEvent.Set()
        RaiseEvent ClientConnected()
        Dim listener As Socket = CType(ar.AsyncState, Socket)
        _socket = listener.EndAccept(ar)
        Dim buffer(PACKET_SIZE) As Byte
        Dim bytesReadCount As Integer = 0
        While True
            Dim sb As New System.Text.StringBuilder
            Do
                Try
                    bytesReadCount = _socket.Receive(buffer, buffer.Length, SocketFlags.None)
                Catch ex As Exception
                    _socket.Close()
                    Exit While
                End Try
                sb.Append(System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, bytesReadCount))
            Loop While _socket.Available > 0
            Dim requestMessage As New RequestMessage()
            requestMessage.DeSerialize(sb.ToString())
            RaiseEvent MessageReceived(requestMessage)
        End While
        RaiseEvent ClientDisconnected()
    End Sub
    Visual C#
    private void BeginSocketConversation(IAsyncResult ar)
    {
        threadEvent.Set();
        ClientConnected();
        Socket listener = ((Socket)(ar.AsyncState));
        _socket = listener.EndAccept(ar);
        byte[,] buffer;
        int bytesReadCount = 0;
        while (true)
        {
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            for (
            ; (_socket.Available > 0);
            )
            {
                try
                {
                    bytesReadCount = _socket.Receive(buffer, buffer.Length, SocketFlags.None);
                }
                catch (Exception ex)
                {
                    _socket.Close();
                    break;
                }
                sb.Append(System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, bytesReadCount));
            }
            RequestMessage requestMessage = new RequestMessage();
            requestMessage.DeSerialize(sb.ToString());
            MessageReceived(requestMessage);
        }
        ClientDisconnected();
    }

    Object serialization

    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.

    Implementing the AddIn.Launch method

    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:

    Visual Basic .NET
    Public Sub Launch(ByVal host As AddInHost) Implements IAddInEntryPoint.Launch
        _wmcHost = host
        _waitForExit = New System.Threading.ManualResetEvent(False)
        _server.Start(DEFAULT_PORT)
        System.Threading.Thread.CurrentThread.Priority = Threading.ThreadPriority.Lowest
        _waitForExit.WaitOne()
    End Sub
    Visual C#
    public void Launch(AddInHost host) 
    {
        _wmcHost = host;
        _waitForExit = new System.Threading.ManualResetEvent(false);
        _server.Start(DEFAULT_PORT);
        System.Threading.Thread.CurrentThread.Priority = Threading.ThreadPriority.Lowest;
        _waitForExit.WaitOne();
    }

    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.

    Media Center manipulation

    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:

    Visual Basic .NET
    Private Sub OnDataReceived(ByVal message As RequestMessage) Handles _server.MessageReceived
        Select Case message.RequestAction
            Case RequestMessage.Action.PauseMedia
    _wmcHost.MediaCenterEnvironment.MediaExperience.Transport.PlayRate = PlayRates.PLAYRATE_PAUSE
            Case RequestMessage.Action.VolumeUp
               _wmcHost.MediaCenterEnvironment.AudioMixer.VolumeUp()
            Case RequestMessage.Action.VolumeDown
               _wmcHost.MediaCenterEnvironment.AudioMixer.VolumeDown()
            Case RequestMessage.Action.NextMedia _wmcHost.MediaCenterEnvironment.MediaExperience.Transport.SkipForward()
            Case Else
        End Select
        SendAcknowledgement(message)
    End Sub
    Visual C#
    private void OnDataReceived(RequestMessage message) 
    {
        switch (message.RequestAction) 
        {
            case RequestMessage.Action.PauseMedia:
                _wmcHost.MediaCenterEnvironment.MediaExperience.Transport.PlayRate = PlayRates.PLAYRATE_PAUSE;
                break;
            case RequestMessage.Action.VolumeUp:
                _wmcHost.MediaCenterEnvironment.AudioMixer.VolumeUp();
                break;
            case RequestMessage.Action.VolumeDown:
                _wmcHost.MediaCenterEnvironment.AudioMixer.VolumeDown();
                break;
            case RequestMessage.Action.NextMedia:
                _wmcHost.MediaCenterEnvironment.MediaExperience.Transport.SkipForward();
                break;
        }
        SendAcknowledgement(message);
    }

    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.

    Implementing the Windows Mobile 5 remote client application

    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.

    Implementing the socket client

    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:

    Visual Basic .NET
    Public Function Send(ByVal request As Message) As String
        Dim responseString As String = Nothing
        Try
            If ((Not (_socket) Is Nothing) _
                        AndAlso _socket.Connected) Then
                Dim requestString As String = request.Serialize
                Send(requestString)
                responseString = RecvSynchronous
                Return responseString
            End If
        Catch ex As Exception
            Return Nothing
        End Try
        Return responseString
    End Function
    
    Visual C#
    public string Send(Message request)
    {
        string responseString = null;
        try
        {
            if (_socket != null && _socket.Connected)
            {
                string requestString = request.Serialize();
                Send(requestString);
                responseString = RecvSynchronous();
                return responseString;
            }
        }
        catch (Exception ex)
        {
            return null;
        }
        return responseString;
    }
    

    Adding the UI layer

    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:

    Figure 6 - The configuration screen on the mobile device

    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:

    Visual Basic .NET
    Private Sub btnConnect_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim host As String = Me.txtHost.Text.Trim
        Dim port As String = Me.txtPort.Text.Trim
        _client.Connect(host, Convert.ToInt32(port))
    End Sub
    Visual C#
    private void btnConnect_Click(object sender, EventArgs e)
    {
         string host = this.txtHost.Text.Trim();
         string port = this.txtPort.Text.Trim();
         _client.Connect(host, Convert.ToInt32(port));
    }

    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:

    Figure 8: The control screen on the mobile device

    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:

    Visual Basic .NET
    Private Sub btnConnect_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim host As String = Me.txtHost.Text.Trim
        Dim port As String = Me.txtPort.Text.Trim
        _client.Connect(host, Convert.ToInt32(port))
    End Sub
    Visual C#
    private void btnStop_Click(object sender, EventArgs e)
    {
        RequestMessage message = new RequestMessage();
        message.RequestAction = RequestMessage.Action.StopMedia;
        message.Data = String.Empty;
        string responseString = client.Send(message);
        ResponseMessage response = new ResponseMessage(responseString);
    }

    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.

    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:

    Figure 9 - The detail page 

    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:

    Visual Basic .NET
    Private Sub btnRefreshDetail_Click(ByVal sender As Object, ByVal e As EventArgs)
        Dim request As RequestMessage = New RequestMessage
        request.RequestAction = RequestMessage.Action.GetMediaMetadata
        Dim responseString As String = _client.Send(request)
        Dim response As MediaMetadataMessage = New MediaMetadataMessage(responseString)
        For Each item As MediaMetadataMessage.MediaMetadataItem In message.Data
            If ((Not (item.Value) Is Nothing) AndAlso (item.Value.Length > 0)) Then
                Me.txtDetail.Text = (Me.txtDetail.Text + (item.Key + (": " + item.Value)))
                Me.txtDetail.Text = (Me.txtDetail.Text + "" & vbCrLf)
            End If
        Next
    End Sub
    Visual C#
    private void btnRefreshDetail_Click(object sender, EventArgs e)
    {
        RequestMessage request = new RequestMessage();
        request.RequestAction = RequestMessage.Action.GetMediaMetadata;
        string responseString = _client.Send(request);
        MediaMetadataMessage response = new MediaMetadataMessage(responseString);
        foreach (MediaMetadataMessage.MediaMetadataItem item in message.Data) {
            if (item.Value != null && item.Value.Length > 0){
                this.txtDetail.Text += item.Key + ": " + item.Value;
                this.txtDetail.Text += "\r\n";
            }
        }
    }

    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:

    Visual Basic .NET
    Private Sub SendMediaMetadata()
        Dim response As New MediaMetadataMessage()
        Dim val As String
        For Each key As String In _wmcHost.MediaCenterEnvironment.MediaExperience.MediaMetadata.Keys
        val = _wmcHost.MediaCenterEnvironment.MediaExperience.MediaMetadata.Item(key).ToString()
        response.Data.Add(New MediaMetadataMessage.MediaMetadataItem(key, val))
        Next
        response.ResponseIndicator = MediaMetadataMessage.ResponseCode.Success
        _server.Send(response)
    End Sub
    Visual C#
    private void SendMediaMetadata() 
    {
        MediaMetadataMessage response = new MediaMetadataMessage();
        string val;
        foreach (string key in _wmcHost.MediaCenterEnvironment.MediaExperience.MediaMetadata.Keys) 
        {
            val = _wmcHost.MediaCenterEnvironment.MediaExperience.MediaMetadata.Item[key].ToString();
            response.Data.Add(new MediaMetadataMessage.MediaMetadataItem(key, val));
        }
        response.ResponseIndicator = MediaMetadataMessage.ResponseCode.Success;
        _server.Send(response);
    }

    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.

    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:

    Figure 10 - Music and Video list management 

    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.

    Mobile Application UI design considerations

    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.

    Conclusion

    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 blog.

    About the Author

    Matt Ivers is a software engineer at Chicago-based Clarity Consulting. He has extensive professional experience developing .NET solutions in both Visual C# .NET and VB.NET. Check him out at his blog or through the Clarity blog site, Clarity Blogs.

    References

    Windows Media Center SDK 5.0
    Windows Mobile 5.0 Smartphone SDK

    How to: Sign an Assembly using Visual Studio 2005
    How to: Create a Windows Installer File for a Windows Media Center Add-in

    Windows Media Center - SDK Overview
    Windows Media Center - Understanding the Basics
    Windows Media Center - Development Tools
    Windows Media Center - AddIn example: "Time Travel"

    Using an Asynchronous Server Socket

    Comment Notification

    If you would like to receive an email when updates are made to this post, please register here

    Subscribe to this post's comments using RSS

    Comments

    # Matt Ivers said on May 14, 2007 5:27 PM:

    An article of mine was recently published in MSDN's online blog Coding4Fun: http://blogs.msdn.com/coding4fun/archive/2007/05/14/2632164.aspx...

    # » Control Windows Media Center using a Windows Mobile 5 Device said on May 15, 2007 1:59 AM:

    PingBack from http://testsubdomain.netmoviehost.com/control-windows-media-center-using-a-windows-mobile-5-device/

    # Neil Stoker said on May 15, 2007 7:51 AM:

    Hi Matt,

    This is an excellent article - having the requisite bits of hardware, I can't wait to try it at home.  One thing though: at the top of the article it indicates the software required is Visual Basic or Visual C# Express Edition, whereas I'm pretty sure that some of the things you do here require a full version of Visual Studio rather than just Express (I don't have Express installed at work, but I seem to remember there being limitations on making WM5 apps).  Is that the case?

    # Ian Dixon's Blog said on May 15, 2007 12:48 PM:

    Via Windows Media Center Sandbox On Coding4Fun there is a article demonstrating how to use a Windows

    # Terry said on May 15, 2007 2:48 PM:

    The Windows Mobile SDK in the link seems to require a full Visual Sutdio Installatino rather than just the Express Edition. I have C# Express installed and when attempting to install the WM5 SDK I get the following error: "Software Development Tools required to use this SDK for application development are not installed on this workststion. Before trying to run the setup wizard again, verify that the correct software is installed..."

    Nice article, but if it requires tools that cannot run with the Express Editions of Visual Studio then the article probably does not belong here.

    # Steve Sharples said on May 15, 2007 4:18 PM:

    I think you should change the requirements for this article as the Windows Mobile SDK is not compatible with the Express Editions, only Standard and up. Also, the code in the download contains .vdproj project files which are also incompatible with the Express Editions. Cool idea, though!

    # MobileViews Blog :: Control Windows Media Center using a Windows Mobile 5 Device said on May 19, 2007 12:02 PM:

    PingBack from http://www.mobileviews.com/blog/2007/05/19/control-windows-media-center-using-a-windows-mobile-5-device/

    # andy vt's blog said on May 21, 2007 11:30 PM:

    WMP Remote is based [loosely] on the sample application written by Matt Ivers . This solution interacts

    # andy vt's blog said on May 23, 2007 11:46 PM:

    Updated the capabilities of WMPRemote , the PPC client is now built for WM5 and is orientation aware

    # Confused said on May 24, 2007 8:59 PM:

    I was trying to compare this to the Coding4Fun article that was posted long ago about using a PDA as a remote control for Windows Media Player but it seems to have been removed from the Coding4Fun archive. Does anyone know what happened to it?

    # Eric said on May 28, 2007 3:12 PM:

    This sounds really great.

    i havent given it a shot yet, however i could see myself running into some unforseen problems.

    i guess there is no way to get this in a prepackaged version is there? thanks

    # Ankit Jain said on May 29, 2007 12:50 PM:

    Hey.. even I've tried building addins and build a tool around Visual Studio 2005. It's a free text search in the history comment from Version control server.

    - Ankit

    # Ryan Tollefson said on May 31, 2007 2:18 AM:

    This won't work with Visual C# Express - it doesn't support the Windows Mobile SDK.  

    The Windows Mobile 5.0 Smartphone SDK requires Visual Studio 2005 Standard, Professional, or Team Suite Edition.

    # Ryan Tollefson said on June 6, 2007 1:24 PM:

    This doesn't work with the Visual Studio Express Editions - they don't support the Windows Mobile SDK.

    # Aurel said on June 10, 2007 10:59 PM:

     I tried the sample from Matt Ivers, but I have a problem when I start the application to test with the MCMLPad. I have an error code:

    resx://WMCHookServer/WMCHookServer.Resources/_Default : Failure acquiring MCML markup from 'resx://WMCHookServer/WMCHookServer.Resources/_Default'

    Can you help me to find the solution? Thank you

    # Aurelien said on June 12, 2007 2:01 AM:

    I downloaded the sample, but when I try it with the MCML Pad, there is an error code:

    resx://WMCHookServer/WMCHookServer.Resources/_Default : Failure acquiring MCML markup from 'resx://WMCHookServer/WMCHookServer.Resources/_Default '

    Can you help me? Thanks

    # Todd said on June 20, 2007 1:20 PM:

    Can anyone confirm that the sample code compiles and installs correctly on Vista Media Center?  I'm still a noob at getting things to work in the Media Center environment, but I think the Installer piece doesn't register the app in Media Center, and even when I do it manually, it throws file-not-found errors around the GAC components.

    Just curious if it works out of the box for anyone else.

    # doudou2554 said on June 21, 2007 11:07 PM:

    Hello , I tried the source code and I have some problems. Do you can help me?

    Thanks

    # Oliver Rogers said on June 29, 2007 7:32 PM:

    It is a bit misleading in your prerequisites to suggest using Visual Studio Express Editions to create this solution as this version does not support the Mobile Device SDK.

    You have to fork out for the full version of Visual Studio!!

    Is there any work around for this?

    # Josh Chandler said on July 15, 2007 7:43 AM:

    Very exciting developments can't wait to see what addins you guys can develop for Windows Mobile 6

    # Tim Anderson’s ITWriting - Tech writing blog » In praise of SlimServer said on August 27, 2007 6:24 AM:

    PingBack from http://www.itwriting.com/blog/?p=305

    # Edward Prislac said on November 6, 2007 11:37 AM:

    Is there any way I could get the C# source code for this project? I am trying to achieve similar results using a tablet pc instead of windows mobile, but am having a hard time getting some of the example code to work (and specifically, there are some segments where C# code was supposed to be in the article, and instead, more VB.Net code was in it's place) Any help would be much appreciated!

    # dave denning said on December 22, 2007 8:34 AM:

    Does this work on MCE2005 or only Vista?

    # Satish K said on December 27, 2007 10:28 PM:

    The Installed app doesn't run on Vista Media Center but i could rebuild the source code with the following modifications to run on Vista.

    Event handler initializations are missing from C# code. So i added the following lines in Launch().

    _server.ClientConnected += new Server.ClientConnectedEventHandler(OnConnected);

    _server.ClientDisconnected += new Server.ClientDisconnectedEventHandler(OnDisconnected);

    _server.MessageReceived += new Server.MessageReceivedEventHandler(OnDataReceived);

    I used following environment to build/run the Application.

    Vista Home Premium.

    Visual Studio 2005 Professional Edition.

    Windows Media Center SDK

    Source code from this article.

    Dell Axim X51v (Windows Mobile 5.0)

    The source code is well written and documented. Excellent Article.

    # Software Information » Coding4Fun : Control Windows Media Center using a Windows Mobile 5 Device said on January 25, 2008 2:29 PM:

    PingBack from http://softwareinformation.247blogging.info/coding4fun-control-windows-media-center-using-a-windows-mobile-5-device/

    # pezi said on January 30, 2008 9:37 AM:

    where can i find de source code? the link doesn't work

    # Coding4Fun said on February 1, 2008 2:01 PM:

    @pezi:  Working on fixing it

    # Leonardi said on June 4, 2008 5:01 PM:

    Still couldn't get this to work with Vista MC. Tried Satish K suggested changes but it doesn't work for me. Any suggestion?

    # Josh said on July 2, 2008 10:29 PM:

    Is there any solution to getting this to work with Vista MCE in Vb.net?

    # Lobato said on July 29, 2008 7:50 AM:

    Where is the link to the source code download? Has it been removed? Will it be back? :)

    # Coding4Fun said on July 31, 2008 6:21 PM:

    @Lobato:  I just tried the link for the source code and it worked.

    # Matt said on August 26, 2008 8:14 AM:

    @Coding4Fun: Just wondered why you have not commented on the use of Express Edition? I have Express Edition but not the real version and wondered if it is worth me trying to get this work.

    I ask as this is AWESOME!! and I would really like to have this functionality.

    If it is just for Standard, could you make the binaries available?

    Thanks,

    Matt

    # Coding4Fun said on August 27, 2008 5:28 PM:

    @Matt:  Currently Express can't do Windows Mobile development.

    Are you a student?  That does open a few doors for you.  hit the contact button at the top if you want to talk more about this.

    # James said on October 2, 2008 10:33 PM:

    I think maybe a few changes are needed to work with VS 2008.  I slogged through to where I can get the C# template "Windows Media Center Application - Background".  I got the Installer project set up, and it "installs" without errors.  But that's about as far as I get.

    From what I can tell, if I install the template project without modification, it should pop up a dialog "The background application did something." when I launch Media Center, but nothing happens.  Is there a place I can view what addins MC thinks are registered?  Can I debug this somehow?  It's a pretty basic hurdle to get over, but MC addin development is not that common of a discussion topic.

    # Trent said on November 2, 2008 2:26 PM:

    Hi...I'm new to programming...

    but I recieve the error "resx://WMCHookServer/WMCHookServer.Resources/_Default : Failure acquiring MCML markup from 'resx://WMCHookServer/WMCHookServer.Resources/_Default "...It seems like the image failed to load(I think) but...can you help me?

    PS: I'm only 13 yrs old

    I have Vista Ultimate and a Pocket PC

    with CE 5

    # Coding4Fun said on November 5, 2008 1:03 PM:

    @Trent are you using the download we provided at the top and you are getting that error?

    # Trent said on November 7, 2008 12:41 PM:

    Yes...and i also have VS 2005 full version..I'm not using the express edition... I'm currently using the VB version too... is there another version of the software that I should download?

    # Jay said on November 24, 2008 11:56 PM:

    I am getting could not load file or assembly 'WMCServer' when I try to load Media Center after install. Using Visual Studio 2005, MS Vista Home Premium.

    WMCServer and WMCCommon are included in the solution as references. Looks like it is failing in the Launch method at the first _server call. I added the code to initialize the event handlers as stated above; however, no dice. I also used WiX to build the install.

    Any suggestions?

    # Trent said on December 29, 2008 11:46 AM:

    is there anther file i should download besides the one on the top of the page?

    # Coding4Fun said on December 29, 2008 5:42 PM:

    @Trent and @Jay did you install the Windows Media Center SDK?

    http://www.microsoft.com/downloads/details.aspx?FamilyId=A43EA0B7-B85F-4612-AA08-3BF128C5873E&displaylang=en

    # Trent said on January 14, 2009 12:17 PM:

    Yes. I have the Media Center SDK

    # Coding4Fun said on January 19, 2009 6:38 PM:

    Pinging Matt on this.

    # Jan D said on March 5, 2009 6:19 AM:

    Interesting article, but after creating the project (for Media Center, not for Mobile) there are warnings about references for this imports:

    Imports Microsoft.MediaCenter.Hosting

    Imports Microsoft.MediaCenter.UI

    I have the SDK installed, what am I doing wrong?

    # J:M said on September 3, 2009 5:38 AM:

    Do you have Media Center on your dev computer? If no, copy the dll:s from the ehome dir on a Media Center computer.

    # Jay S said on November 8, 2009 3:51 AM:

    THIS IS AN AWSOME ARTICLE!! ive been looking for some instructions on how to control media center in this way. This is the first in depth article ive seen thanks!!

    # jay2008 said on November 8, 2009 8:45 AM:

    The source code link does not work, can anyone help me find the c# source code for this?

    # Coding4Fun said on November 9, 2009 9:31 AM:

    @jay2008 looking into getting this resolved, thanks for telling me.

    Leave a Comment

    (required) 
    (optional)
    (required) 

      
    Enter Code Here: Required

    Search

    This Blog

    Syndication

    Page view tracker