Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Control Windows Media Center using a Windows Mobile 5 Device

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

Tags:

Follow the Discussion

  • Clint RutkasClint I'm a "developer"

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

  • JamesJames

    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.

  • TrentTrent

    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

  • Clint RutkasClint I'm a "developer"

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

  • TrentTrent

    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?

  • JayJay

    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?

  • TrentTrent

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

  • Clint RutkasClint I'm a "developer"

    @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

  • TrentTrent

    Yes. I have the Media Center SDK

  • Clint RutkasClint I'm a "developer"

    Pinging Matt on this.

  • Jan DJan D

    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:MJ:M

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

  • jay2008jay2008

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

  • Jay SJay S

    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!!

  • Clint RutkasClint I'm a "developer"

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

  • Clint RutkasClint I'm a "developer"

    @miki, I know, I'm attempting to get in contact with the author.

  • MikiMiki

    The source code link still doesn't work.

  • tomdeltomdel

    What a shame the link is now dead.. yea if anyone has it please email me it!!!

    deloford[at][hot]mail com

    Thanks!

  • Clint RutkasClint I'm a "developer"

    @tomdel working on getting tracking down the author, sadly this is an old article, processes have been put in place so this shouldn't happen to future articles.

  • Clint RutkasClint I'm a "developer"

    Source code located, article updated with new link, emailed the people that requested it when found.

    Sorry about that guys, processes are put in place to prevent this with future articles and I should have some time to go through and catch these issues in older articles as well.  There are just a LOT of posts ...

  • GaYan SilvaGaYan Silva

    hello... 1st of all.. i must mention that this is a great piece of work Wink

    instead of using the remote connection with media Center, , can we use it as a file manager /? ?

    how can i run the basic commands like opening the Start menu and simple tasks using the same connection ?

  • Clint RutkasClint I'm a "developer"

    @GaYan Silva, excellent question, you'd have to build out a server on the other end of the remote control to be able to do this.  WCF would be an easy way to accomplish this task then just script stuff out.

  • Clint RutkasClint I'm a "developer"

    @GaYan The article walks through how to do this.  Creating an up-to-date example here is on my list of things to do but i have zero ETA on it.

  • GaYanGaYan

    @ Coding4Fun ! Thanks ! !

    I tried to implement WCF .. ! wuh,,, too difficult Big Smile Big Smile

    by the way when i try to compile the app ! i get this error

    ///////////////////////////////////////////////////////////////

    Resx://wmcHookServer/wmcHookServer.resoures/_default': Failure acquiring MCML markup from 'resx://wmcHookServer/wmcHookServer.resoures/_default'.

    ////////////////////////////////////////////////////////////////

    Any Ideas ? im suing windows vista and vs 2008 ! ..

    Thanks in advance !

  • GaYan SilvaGaYan Silva

    @ Coding4Fun, .. yeh,, Thanks ~ ! Ill try to do that, , but the problem occurs when we try to register the addin with the media center,, ,,

    anyway .. ill see about it .. thanks ! if i get it working. ill post the code here !

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.