Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

Windows Mobile 6.5 in the Australian Media

I was scrolling through the SMH site this morning and noticed the article “Windows Mobile takes a bite at Apple”.  Whilst this article talks about a lot of positive aspects of the Windows Mobile 6.5 platform it really annoys me when there are glaring mistakes:

“WM6 and 6.1 users can download the 6.5 beta version now”

Now unless I’m wrong it’s not possible to download a beta version, nor will it be likely that owners of even recent 6.1 devices can even upgrade to 6.5 when it ships. 

<rant>

I don’t know how long the community have been asking both Microsoft and OEMs to provide a better upgrade story.  If you download the Developer Tool Kit you can have a play with the emulators for Windows Mobile 6.5 – you’ll notice that other than some UI improvements, gestures and of course widgets there isn’t much else that’s different from 6.0/6.1.  So this begs the question, why do OEMs insist on not providing updates to their existing customers – do they want them to switch to another fruitier platform that provides FREE upgrades to new versions of the OS?

Microsoft, stop contributing to this problem and start working with the OEMs to encourage them to ship upgrades rather than always insisting customers buy new devices.

</rant>

More Windows Mobile Controls for .NET Compact Framework with Mirabyte

I noticed Frank’s post on the new Touch Controls Suite 1.0 from Mirabyte.  It’s hard to do the UI justice, particularly because the YouTube video they have on the page uses such horrible colours.  I do like how it appears in Visual Studio and I think the nice touch responsiveness (in WM5 and WM6 apparently) looks great.

image image

It’s great to see more and more controls being built to help Windows Mobile developers build rich user interfaces.

What works/What doesn’t in Windows Mobile 6.5 Widgets

This is going to be the question that is often raised when developers start building widgets for the Windows Mobile 6.5.  Whilst this MSDN article covers some of the basics, it doesn’t cover which common frameworks are supported.  For example is jquery supported? The answer is kindof.  If you go to the jquery test page in IE Mobile on a Windows Mobile 6.5 device (which is the same engine widgets use) you won’t even see the test items appear.  However a lot of the functionality seems to work when you use it in a widget.

Now one thing you can do is to look at which version of javascript (take a look at the wikipedia article on support for ECMAScript in various layout engines) is supported but I suspect that is going to be fairly meaningless unless you know what you’re looking for.  An alternative is to just to try stuff and work out what will/won’t work.  Again this is not a great approach as it means a lot of wasted cycles. 

Luckily the guys at Microsoft have already spent cycles building showcase widgets. There is one included in the emulators as part of the Windows Mobile 6.5 Developer Tool Kit, which is the Search Widget.

image

If you connect the emulator though either ActiveSync or the Windows Mobile Device Center you can take a look at the contents of this widget by going to “\Program Files\Widgets\User\1” using File Explorer. In fact if you want to get your head around how it all works, simply copy this entire folder across to your desktop and open that folder using File –> Open –> Web Site… in Visual Studio 2008.  If you are going to step through the code you may want to run the various javascript files (in the js folder) through a beautifier (http://jsbeautifier.org/) to that it’s easier to follow.

There are a number of javascript files, namely widget.js, utils.js and menu.js, that show you can wrap the built in widget functionality to make it more accessible and easier to use. It’s also worth taking a look at the way this widget is structured as it is setup using language specific folders so that it can handle different languages on the device.

Note: The Search Widget found on the emulator is not sample or redistributable code. I’m recommending that you only use it to understand how widgets work and what will/will not work.

Sync Framework Sample and the Consumer Solution Accelerator for Windows Mobile

Two really interesting downloads to help you build real world Windows Mobile applications:

1) SyncComm (http://synccomm.codeplex.com) is designed to provide you with a starting point for building WCF sync framework applications.

2) Microsoft® Windows Mobile® 6 Consumer Solution Accelerator is designed to help developers see how they can harness the power of Windows Mobile to craft compelling consumer solutions. The Consumer Solution Accelerator consists of a documented sample Visual Studio project as well as documents which detail the creation of the project and how it functions.

The second item isn’t that intuitive to get up and running, especially if you get build errors in Visual Studio.  Don’t forget you may need to import the developer certificates that come with the Windows Mobile SDK into your local certificate store on your computer in order for the cab build to work.

Make My Windows Mobile 6.5 Widget Into a Windows Vista/Windows 7 Gadget

Having shown how easily you can build a widget that wires up some data using Entity Framework, ADO.NET Data Services and the new Ajax4 javascript classes, DataView and DataContext, I thought that I would take a shot at getting my widget to work as a gadget on Windows Vista/Windows 7.  Essentially a gadget is very similar to a widget in that it’s a zip file containing HTML, css, javascript and supporting files (eg images). The two notable differences are that the file extension is .gadget and that the configuration file is gadget.xml instead of config.xml.

The steps for converting the previously created widget into a gadget are:

Step 1: Create a gadget.xml file

Add a new xml file to the ProductWidget web site and call it gadget.xml.  The contents should look similar to the following:

<?xml version="1.0" encoding="utf-8" ?>
<gadget>
  <name>AdventureWorks Product Gadget</name>
  <namespace>
http://www.builttoroam.com/ProductGadget</namespace>
  <version>2.0.0.0</version>
  <author name="Built To Roam">
    <info url="
https://blogimages.builttoroam.com/nick" text="Nick's .NET Travels" />
    <logo src="BTRLogo.png" />
  </author>

  <copyright>Copyright (c) 2009 Built To Roam.  All rights reserved.</copyright>
  <description>Basic product gadget based on ajax 4</description>
  <icons>
    <icon width="64" height="64" src="BTRLogo.png" />
  </icons>
  <hosts>
    <host name="sidebar">
      <base type="HTML" apiVersion="1.0.0" src="Products.htm" />
      <permissions>full</permissions>
      <platform minPlatformVersion="0.3" />
    </host>
  </hosts>
</gadget>

Step 2: Make minor layout changes to ensure content is visible

Unlike a widget, where it will be rendered in full screen on the Windows Mobile device, a gadget needs to know what size to render itself.  A simple way to do this is to define the width and height on the body tag in the Product.htm file.

<body xmlns:sys="javascript:Sys"
      xmlns:dataview="javascript:Sys.UI.DataView"
      xmlns:datacontext="javascript:Sys.Data.AdoNetDataContext"
      sys:activate="*" style=" width:300px; height:500px" >

Step 3: Zip files and name as .gadget

You are essentially done with making changes.  All you need to do now is zip up the files, as you did when creating the widget, and name the file with .gadget extension.  Note that you can include the config.xml and gadget.xml file in the same zip file without them conflicting.  This is useful if you want to build a single widget/gadget that will work across Windows Vista/7 and Windows Mobile 6.5.

Step 4: Double-click your gadget to install

When you double-click the newly created gadget it will install and run your gadget.

image

Again, apologies for the awful design work.  You’ll also not that for some reason when you click on a category it doesn’t highlight the category or load the products associated with it.  Something in the Ajax4 library must be malfunctioning for it not to work properly as a gadget (any suggestions are welcome!!).

Accessing Data with Windows Mobile 6.5 Widgets, Ajax 4, Entity Framework and ADO.NET Data Services.

Step 1: Creating Your Projects

Create a new ASP.NET Web Application (new solution) called DataWidgetDemo.  You can delete the Default.aspx page as this is not required.

Add new web site to your solution.  Select the Empty Website template, change the location to be nested within your solution folder (by default it goes under documents and settings) and call the website ProductWidget.  The location should look like c:\<solution root>\DataWidgetDemo\ProductWidget. You can delete the web.config file as this is not required.

Your solution should look similar to the following:

image 

Step 2: Adding Data

There are two components to exposing data (done in the DataWidgetDemo project):

a) Create an Entity Data Model which will interact with the AdventureWorksLT database– To do this, select Add New Item and then select the ADO.NET Entity Data Model from the Add New Item dialog. In our example we have named the new item AdventureWorksModel.edmx.

Work through the Entity Data Model Wizard, specifying the connection string for your database instance.  When prompted, select the Product and ProductCategory tables. You don’t need to change any of the other default values in this wizard. Once complete this should yield the entity designer with the two tables displayed.

image 

b) In order to consume this from our widget we need to expose the AdventureWorks data via an ADO.NET Data Service. To do this select Add New Item and pick the ADO.NET Data Service template.  Give the new item a name: AdventureWorksData.svc and select Add.

Once this item has been added you just need to specify which data set you want to expose. The text marked in red are the components that have been updated in order to expose all the tables (ie *) in the AdventureWorksLTEntities data model

public class AdventureWorksData : DataService<AdventureWorksLTEntities>
   {
       // This method is called only once to initialize service-wide policies.
       public static void InitializeService(IDataServiceConfiguration config)
       {
           // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
           // Examples:
          config.SetEntitySetAccessRule("*", EntitySetRights.All);
           // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
       }
   }

 

Step 4: Add Ajax 4 JS Libraries

This step requires referencing the ASP.NET Ajax 4 javascript libraries.  As these are still pre-release the location of these files is not well defined but you should be able to locate them on your machine in order to copy them into the ProductWidget web site.

image

Step 5: Building the Products page

The products page is just going to be a simple html page.  Windows Mobile 6.5 can’t render ASP.NET pages (ie aspx) pages as part of widgets as this would require having the equivalent of the ASP.NET server engine on the device.  As such widgets are constrained to html, css and javascript.  To generate the products page select Add New Item on the ProductWidget web site. Select the HTML Page template and give the new page a name, Products.htm, and click Add.

Here we are only going to use HTML! There is not a single of javascript in the following code snippet.  There is javascript, but it’s all included in the ASP.NET Ajax 4 library.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml" >
<head>
    <title>AdventureWorks - Products</title>
    <style type="text/css">
        .sys-template {display: none;}
        .rowSelected  {background-color: yellow;}
    </style>

    <script src="MicrosoftAjax/MicrosoftAjax.debug.js" type="text/javascript"></script>
    <script src="MicrosoftAjax/MicrosoftAjaxTemplates.debug.js" type="text/javascript"></script>
    <script src="MicrosoftAjax/MicrosoftAjaxAdoNet.debug.js" type="text/javascript"></script>

</head>
<body xmlns:sys="javascript:Sys"
      xmlns:dataview="javascript:Sys.UI.DataView"
      xmlns:datacontext="javascript:Sys.Data.AdoNetDataContext"
      sys:activate="*">

    <br /><br />

    <table
        sys:attach="datacontext"
        datacontext:sys-key="dataContext"
        datacontext:serviceuri ="
http://192.168.0.102:18886/AdventureWorksData.svc"
        >
    <thead>
        <tr>
            <th>Select Category</th>
        </tr>
    </thead>
    <tbody
        id="dvCategories"
        class="sys-template"
        sys:attach="dataview"
        dataview:sys-key="categoriesKey"
        dataview:dataprovider="{{ dataContext }}"
        dataview:autofetch="true"
        dataview:selecteditemclass="rowSelected"
        dataview:fetchoperation="ProductCategories"
        dataview:fetchparameters="{{ {$expand: 'Products'} }}"
        >
        <tr sys:command="select">
            <td>{{ Name }}</td>
        </tr>
    </tbody>
    </table>

    <br /><br />

    <table>
    <thead>
        <tr>
            <th>Name</th>
        </tr>
    </thead>
    <tbody
        class="sys-template"
        sys:attach="dataview"
        dataview:sys-key="moviesKey"       
        dataview:data="{binding selectedData.Products, source={{categoriesKey}} }">   
        <tr>
            <td>{binding Name}</td>
        </tr>
    </tbody>
    </table>

    </body>
    </html>

One point to note about this html: The url marked in dark blue needs to be updated to point to the fully qualified url of your ADO.NET Data Service.  As this code will be running on the mobile device or emulator you can’t use localhost as it won’t resolve.  Instead use the IP address of your computer.  This example will work whether you are using Cassini or IIS to host your web application but if you are using Cassini you will need to specify the port number.

Step 6: Add a config.xml file

In order for Windows Mobile 6.5 to install your widget it needs to be able to locate a config.xml file within your widget.  This specifies properties such as the name and author of the widget – sort of a manifest for your widget. Again to add this we select Add New Item on the ProductWidget web site.  Select the XML File template and name the file config.xml.

<?xml version="1.0" encoding="utf-8" ?>
<widget xmlns="
http://www.w3.org/ns/widgets"
        id="http://www.builttoroam.com/ProductWidget"
        version="1.0">

  <name>AdventureWorks Product Widget</name>

  <description>
    Basic product widget based on ajax 4
  </description>

  <author href="https://blogimages.builttoroam.com/nick"
            email="[email protected]">
    Nick Randolph @ Built To Roam
  </author>

  <content src="Products.htm" type="text/html"/>

  <access network="true"/>

  <icon src="BTRLogo.png" />

  <license>
    Copyright (c) 2009 Built To Roam.  All rights reserved.
  </license>
</widget>

You will notice that this config file specifies BTRLogo.png for its icon.  In this case this is a 90x90 png file that I have added to root of the the ProductWidget web site.

Step 7: Zip and Deploy Your Widget

The last step in building your widget is to zip up the contents of the ProductWidget web site.  Don’t zip up the ProductWidget folder itself, just the contents.  Rename the zip file to have the .widget extension:

image

Deployment is as simple as copying the widget file to the emulator and clicking on the widget file on the device.  Note that this deployment mechanism is not going to be supported out of the box by real Windows Mobile 6.5 devices.  Instead there is a registry key that needs to be set to enable this functionality (which is set by default on the emulator images).

image

With this registry key set the widget file will be identified within File Explorer on the device

image

Clicking the Products widget will give you the option to install and run the widget on the device.

image

If you click Yes the widget will be installed onto the device.  After installation your application will immediately be run.  In this case because we are accessing data from across the network you will see the following prompt.

image 

Selecting continue will launch your widget.  Don’t be alarmed if it takes a while to download the data! For a production application you would of course want some animation to indicate that it’s downloading data in the background.

Disclaimer: The UI is not fantastic but this post is around exposing data rather than building the UI around it. As it’s just html and css you can customise the UI as much as you want.

image

Once you have closed your widget you can run it again by selecting its icon from the Start menu.

image

Widgets can be removed in the same way as normal programs.  From the Start menu select Settings –> System –> Remove Programs.

image

Note: You will need to remove your widget if you want to install an updated version.  During development to save you from doing this you can simply copy over updated files.  Your widget will be installed to \Program Files\Widgets\User\<id> where id is a numeric value assigned to your widget.

And there you have it – a simple widget that exposes data from your sql database!

Extending the Widget model on Windows Mobile 6.5

Over the past week we have seen a number of posts from Jorge and the team at Microsoft covering what’s new for developers in Windows Mobile 6.5.  This was kicked off with the release of the Windows Mobile 6.5 Developer Tool Kit which includes both emulators and documentation/samples for working with gestures. 

What isn’t included in the DTK is any documentation on building Widgets. Jorge made a great initial post covering getting started building your first widget but went short of providing any real documentation on the extent of the widget object model. One of the first question that comes to mind is extensibility.  This has in part been answered in a forum question and answer.

The upshot is that in order to extend the widget model you need to build and deploy an activex control that can do the hardwork for you.  If you want to try it out, all you really need are WM6.5 emulator images and the Windows Mobile 5 SDK (that’s right the WM5 SDK!).  In the WM5 SDK you will find a sample called AXSample which surprise, surprise is an ActiveX control sample (On my machine this is in the folder C:\Program Files\Windows Mobile 5.0 SDK R2\Samples\PocketPC\CPP\ATL\AXSample). You can load and run this sample and it will display the simple activex control in the IE Mobile browser (step 1…. done).

The next thing to do is to add the registry value to enable the activex control for use within a widget.  Note that the other registry values mentioned by Jorge are added automatically by Visual Studio when you depoy and run the activeX control sample.  The registry value you need to set includes the CLSID for your activeX control.  You can get this a couple of ways but the easiest is using the Remote Registry Editor:

image

Once you have the CLSID you can go and create the appropriate keys and values:

image

You will note here that I have replaced the <ObjectName> value in Jorge’s answer with “SampleControl”.  This is how we then reference this object from within your widget javascript code:

                var myObj = widget.createObject("SampleControl");
                alert("The current fill color is " + myObj.FillColor);

This is in essence all you need to do in order to extend the widget framework.  This example just shows how you can retrieve a value from the activex control but you could execute any native code you want as part of executing that property.

If you look at the other samples that ship with the Windows Mobile 5 SDK you will notice that there are a host of native code examples on everything from retrieving the current phone number through to accessing POOM.  You can use any of these to build out your widget code to do whatever you want on the device.

Now the downside…. you can’t deploy a widget with an activex control embedded in the widget file via marketplace.  So the question is how you can deploy your widget and still leverage activex controls.  I would suggest the easiest approach is to build the widget so that when it first loads it detects if the activex control is present.  If it’s not, it can direct the user to a download site where you have placed a .cab file with the relevant activex control in it.  Of course, as marketplace has not available yet we don’t know if even this strategy will be possible. 

Get Started with Windows Mobile 6.5 Today

That’s right, whilst there is no official release data for Windows Mobile 6.5 yet, you can go and download the Windows Mobile 6.5 Developer Tool Kit today.  Probably the largest component of which are the emulators.  If you haven’t had the opportunity to look at/play with a 6.5 device yet the emulators are a great way to become familiar with the new UI and how the gestures work.

Update: Jorge has a great post on building a simple widget on the Windows Mobile blog.

Windows Mobile Booklets

I was wandering around some of the shopping malls here in Singapore last night and noticed that a couple of the stores were actually stocking a range of Windows Mobile devices (a bit of a surprise coming from Australia where trying to find a WM device in stores is almost impossible).  Further more in one store I noticed these cute little booklets that are clearly aimed at attracting consumers to purchasing Windows Mobile devices.

IMAG0028

This is interesting from two points:

-Firstly, if the Microsoft team here in Singapore has these booklets (and they are clearly not specific to just Singapore) what about Australia.  Why do we not see these in stores?

-Secondly, and perhaps more of a concern, is why does Windows Mobile need these booklets?  Surely if the devices were “sexy” enough then we wouldn’t need supporting booklets that tout the benefits of the platform?

Day 3 of the Windows Mobile Metro Training in Singapore

Today was the third and final day of the Windows Mobile Metro training here in Singapore and I got a bit of a chance to look out of the window of the Microsoft office.  It appears there is a significant amount of development going on around the port.

IMAG0010IMAG0014 

IMAG0012 IMAG0013

Now, back to the class room and to complete the day we did a bit of a brainstorm on the pros and cons of Windows Mobile in comparison to other mobile platforms. 

 IMAG0016IMAG0017

The good news was that everyone decided that the Pros of the platform generally outweigh the cons.  However, the biggest issue the platform faces is that of market perception – currently Windows Mobile has the perception of being an outdated platform with little or no road map.  In actual fact with the news surrounding marketplace and Windows Mobile 6.5 there are at least a couple of things that users can look forward to. IMHO what Windows Mobile needs is a range of aesthetically pleasing (read “sex appeal”) devices that consumers will line up to buy!

Windows Mobile Metro Training and Mobile Monday at Geek Terminal

Today was the first day of the Windows Mobile Metro training in Singapore.  After flying up last night it was great to see a room full of people in building applications for the Windows Mobile platform.  With the news around Windows Mobile 6.5 hot off the press there is an increasing about of interest around Widgets and what other features there may be in the pipeline.  There is also interest gathering around Windows Marketplace for Mobile and the opportunities to commercialise investments made in building mobile applications.

As we were wrapping up for the day one of the attendees pointed out that Mobile Monday was on and that the topic was on Location Based Services.  This was particularly topical for the class as there are a number of participants who have an interest in using location services in one form or another. 

The following sign says it all – yes, this is where Mobile Monday happens here in Singapore.

image

Entry was policed by this scanner – apparently I should have registered in order to be sent a 2D tag (similar in ways to Microsoft Tag) that I could get scanned at the door.  Honestly, what’s wrong with me dropping my business card into a bowl to gain entry? 

image

The evening’s sessions were quite interesting with the main session being delivered by Y J Baik from Skyhook Wireless.

image image

This was followed by a panel discussion between a couple of local Location Based Service companies. 

image

All in all a great way to finish day one.

Working with the Wave API for Windows and Windows Mobile via the .NET Framework

There are a number of samples out there that show how to work with the Wave API (ie sound recording and playback) on both Windows and Windows Mobile via either the .NET Framework or the .NET Compact Framework.  Unfortunately because of subtle differences between the platforms it is difficult to build a single library that works across both platforms. Over a series of posts I’m going to show you how to work with the api to build a library that will work across both platforms.

The starting point is to look at the api calls themselves.  There is plenty of documentation out there that discusses what each of the calls are supposed to do but essentially the api calls are the same between the platforms with the exception that they reside in different assemblies.  As they are native calls they need to be imported using a DllImport.  Here are most of the Windows (Desktop suffix) and Windows Mobile (CF suffix) imports – there are some additional api calls that you can include if you require them following a similar pattern.

[DllImport("coredll.dll", EntryPoint = "waveInGetNumDevs")]
internal static extern int waveInGetNumDevs_CF();

[DllImport("winmm.dll", EntryPoint = "waveInGetNumDevs")]
internal static extern int waveInGetNumDevs_Desktop();

[DllImport("coredll.dll", EntryPoint = "waveInOpen")]
internal static extern MMSYSERR waveInOpen_CF(out IntPtr phwi, uint uDeviceID, ref WAVEFORMATEX pwfx, IntPtr callback, uint dwInstance, uint fdwOpen);
[DllImport("winmm.dll", EntryPoint = "waveInOpen")]
internal static extern MMSYSERR waveInOpen_Desktop(out IntPtr phwi, uint uDeviceID, ref WAVEFORMATEX pwfx, IntPtr callback, uint dwInstance, uint fdwOpen);

[DllImport("coredll.dll", EntryPoint = "waveInPrepareHeader")]
internal static extern MMSYSERR waveInPrepareHeader_CF(IntPtr hwi, IntPtr pwh, uint cbwh);

[DllImport("winmm.dll", EntryPoint = "waveInPrepareHeader")]
internal static extern MMSYSERR waveInPrepareHeader_Desktop(IntPtr hwi, IntPtr pwh, uint cbwh);

[DllImport("coredll.dll", EntryPoint = "waveInUnprepareHeader")]
internal static extern MMSYSERR waveInUnprepareHeader_CF(IntPtr hwi, IntPtr pwh, uint cbwh);

[DllImport("winmm.dll", EntryPoint = "waveInUnprepareHeader")]
internal static extern MMSYSERR waveInUnprepareHeader_Desktop(IntPtr hwi, IntPtr pwh, uint cbwh);

[DllImport("coredll.dll", EntryPoint = "waveInClose")]
internal static extern MMSYSERR waveInClose_CF(IntPtr hwi);

[DllImport("winmm.dll", EntryPoint = "waveInClose")]
internal static extern MMSYSERR waveInClose_Desktop(IntPtr hwi);

[DllImport("coredll.dll", EntryPoint = "waveInReset")]
internal static extern MMSYSERR waveInReset_CF(IntPtr hwi);

[DllImport("winmm.dll", EntryPoint = "waveInReset")]
internal static extern MMSYSERR waveInReset_Desktop(IntPtr hwi);

[DllImport("coredll.dll", EntryPoint = "waveInStart")]
internal static extern MMSYSERR waveInStart_CF(IntPtr hwi);

[DllImport("winmm.dll", EntryPoint = "waveInStart")]
internal static extern MMSYSERR waveInStart_Desktop(IntPtr hwi);

[DllImport("coredll.dll", EntryPoint = "waveInStop")]
internal static extern MMSYSERR waveInStop_CF(IntPtr hwi);

[DllImport("winmm.dll", EntryPoint = "waveInStop")]
internal static extern MMSYSERR waveInStop_Desktop(IntPtr hwi);

[DllImport("coredll.dll", EntryPoint = "waveInAddBuffer")]
internal static extern MMSYSERR waveInAddBuffer_CF(IntPtr hwi, IntPtr pwh, uint cbwh);

[DllImport("winmm.dll", EntryPoint = "waveInAddBuffer")]
internal static extern MMSYSERR waveInAddBuffer_Desktop(IntPtr hwi, IntPtr pwh, uint cbwh);

[DllImport("coredll.dll", EntryPoint = "waveInGetDevCaps")]
internal static extern MMSYSERR waveInGetDevCaps_CF(uint uDeviceId, byte[] pwic, uint cbwic);

[DllImport("winmm.dll", EntryPoint = "waveInGetDevCaps")]
internal static extern MMSYSERR waveInGetDevCaps_Desktop(uint uDeviceId, byte[] pwic, uint cbwic);

[DllImport("coredll.dll", EntryPoint = "waveOutGetNumDevs")]
internal static extern int waveOutGetNumDevs_CF();

[DllImport("winmm.dll", EntryPoint = "waveOutGetNumDevs")]
internal static extern int waveOutGetNumDevs_Desktop();

[DllImport("coredll.dll", EntryPoint = "waveOutOpen")]
internal static extern MMSYSERR waveOutOpen_CF(out IntPtr phwo, uint uDeviceID, ref WAVEFORMATEX pwfx, IntPtr dwCallback, uint dwInstance, uint fdwOpen);
[DllImport("winmm.dll", EntryPoint = "waveOutOpen")]        internal static extern MMSYSERR waveOutOpen_Desktop(out IntPtr phwo, uint uDeviceID, ref WAVEFORMATEX pwfx, IntPtr dwCallback, uint dwInstance, uint fdwOpen);        /// <summary>

[DllImport("coredll.dll", EntryPoint = "waveOutPrepareHeader")]
internal static extern MMSYSERR waveOutPrepareHeader_CF(IntPtr hwo, IntPtr pwh, uint cbwh);

[DllImport("winmm.dll", EntryPoint = "waveOutPrepareHeader")]
internal static extern MMSYSERR waveOutPrepareHeader_Desktop(IntPtr hwo, IntPtr pwh, uint cbwh);

[DllImport("coredll.dll", EntryPoint = "waveOutWrite")]
internal static extern MMSYSERR waveOutWrite_CF(IntPtr hwo, IntPtr pwh, uint cbwh);

[DllImport("winmm.dll", EntryPoint = "waveOutWrite")]
internal static extern MMSYSERR waveOutWrite_Desktop(IntPtr hwo, IntPtr pwh, uint cbwh);

[DllImport("coredll.dll", EntryPoint = "waveOutUnprepareHeader")]
internal static extern MMSYSERR waveOutUnprepareHeader_CF(IntPtr hwo, IntPtr pwh, uint cbwh);

[DllImport("winmm.dll", EntryPoint = "waveOutUnprepareHeader")]
internal static extern MMSYSERR waveOutUnprepareHeader_Desktop(IntPtr hwo, IntPtr pwh, uint cbwh);

[DllImport("coredll.dll", EntryPoint = "waveOutClose")]
internal static extern MMSYSERR waveOutClose_CF(IntPtr hwo);

[DllImport("winmm.dll", EntryPoint = "waveOutClose")]
internal static extern MMSYSERR waveOutClose_Desktop(IntPtr hwo);

[DllImport("coredll.dll", EntryPoint = "waveOutReset")]
internal static extern MMSYSERR waveOutReset_CF(IntPtr hwo);

[DllImport("winmm.dll", EntryPoint = "waveOutReset")]
internal static extern MMSYSERR waveOutReset_Desktop(IntPtr hwo);

[DllImport("coredll.dll", EntryPoint = "waveOutGetDevCaps")]
internal static extern MMSYSERR waveOutGetDevCaps_CF(uint uDeviceID, byte[] pwoc, uint cbwoc);

[DllImport("winmm.dll", EntryPoint = "waveOutGetDevCaps")]
internal static extern MMSYSERR waveOutGetDevCaps_Desktop(uint uDeviceID, byte[] pwoc, uint cbwoc);

You will notice that the Windows Mobile calls all reference coredll.dll, whilst the Windows calls reference winmm.dll.  In order to build a common library we need a way to abstract these calls so that after initialising the library we never have to worry about whether it’s running on a device or a desktop machine. To do this we just need to define a series of delegates that map to each of these functions, and then create instances of them that point to the relevant functions.

public delegate int HardwareDeviceCount();
public delegate MMSYSERR HardwareOpen(out IntPtr hardwareInterface, uint deviceId, ref WAVEFORMATEX waveFormatSettings, IntPtr callbackFunction, uint callbackData, uint callbackType);
public delegate MMSYSERR HardwareGetDeviceCaps(uint deviceId, byte[] data, uint dataSize);
public delegate MMSYSERR HardwarePrepareHeader(IntPtr hardwareInterface, IntPtr headerReference, uint headerSize);
public delegate MMSYSERR HardwareAddBuffer(IntPtr hardwareInterface, IntPtr bufferReference, uint bufferSize);
public delegate MMSYSERR HardwareStart(IntPtr hardwareInterface);
public delegate MMSYSERR HardwareStop(IntPtr hardwareInterface);
public delegate MMSYSERR HardwareUnprepareHeader(IntPtr hardwareInterface, IntPtr headerReference, uint headerSize);
public delegate MMSYSERR HardwareClose(IntPtr hardwareInterface);
public delegate MMSYSERR HardwareReset(IntPtr hardwareInterface);
public delegate MMSYSERR HardwareGetPosition(IntPtr hardwareInterface, ref MMTIME timeReference, uint timeSize);
public delegate MMSYSERR HardwareGetId(IntPtr hardwareInterface, ref uint deviceOutput);

private static HardwareDeviceCount waveInGetNumDevs;
private static HardwareOpen waveInOpen;
private static HardwareGetDeviceCaps waveInGetDevCaps;
private static HardwarePrepareHeader waveInPrepareHeader;
private static HardwareUnprepareHeader waveInUnprepareHeader;
private static HardwareAddBuffer waveInAddBuffer;
private static HardwareStart waveInStart;
private static HardwareClose waveInClose;
private static HardwareStop waveInStop;
private static HardwareReset waveInReset;

private static HardwareDeviceCount waveOutGetNumDevs;
private static HardwareOpen waveOutOpen;
private static HardwareReset waveOutReset;

private static HardwareGetDeviceCaps waveOutGetDevCaps;
private static HardwarePrepareHeader waveOutPrepareHeader;
private static HardwareUnprepareHeader waveOutUnprepareHeader;
private static HardwareClose waveOutClose;
private static HardwareWrite waveOutWrite;

private static void SetupDesktopDelegates()
{
    waveOutGetNumDevs = NativeMethods.waveOutGetNumDevs_Desktop;
    waveOutOpen = NativeMethods.waveOutOpen_Desktop;
    waveOutReset = NativeMethods.waveOutReset_Desktop;

    waveOutGetDevCaps = NativeMethods.waveOutGetDevCaps_Desktop;
    waveOutPrepareHeader = NativeMethods.waveOutPrepareHeader_Desktop;
    waveOutUnprepareHeader = NativeMethods.waveOutUnprepareHeader_Desktop;
    waveOutClose = NativeMethods.waveOutClose_Desktop;
    waveOutWrite = NativeMethods.waveOutWrite_Desktop;

    waveDataCallback = QueryOutgoingData;
    waveDataCallbackPointer = Marshal.GetFunctionPointerForDelegate(waveDataCallback);
    CALLBACK_TYPE = Wave.CALLBACK_FUNCTION;
}

private static void SetupCompactDelegates()
{
    waveOutGetNumDevs = NativeMethods.waveOutGetNumDevs_CF;
    waveOutOpen = NativeMethods.waveOutOpen_CF;
    waveOutReset = NativeMethods.waveOutReset_CF;

    waveOutGetDevCaps = NativeMethods.waveOutGetDevCaps_CF;
    waveOutPrepareHeader = NativeMethods.waveOutPrepareHeader_CF;
    waveOutUnprepareHeader = NativeMethods.waveOutUnprepareHeader_CF;
    waveOutClose = NativeMethods.waveOutClose_CF;
    waveOutWrite = NativeMethods.waveOutWrite_CF;

    WaveLibrary.Native.CF.SoundMessageWindow window = Wave.SetupMessageWindow();
    window.WaveOutDoneMessage += new WaveDoneEventHandler(MessageWindow_WaveDoneMessage);
    waveDataCallbackPointer = window.Hwnd;
    CALLBACK_TYPE = Wave.CALLBACK_WINDOW;
}

In this code we have declared the set of delegates, a set of static instances and then have a two methods that create instances pointing to either the Windows or Windows Mobile imported functions.  Note that it’s important to have these abstracted into separate methods as the library will throw an exception when it attempts to reference a dll that can’t be located.  Having these calls in a separate function means that only the called function will be JIT’d meaning the exception won’t be thrown.

if (useDesktop)
            {
                SetupDesktopDelegates();
            }
            else
            {
                SetupCompactDelegates();
            }

You can simply call the relevant setup function based on whether you are running on the desktop or a device.

So you want Silverlight on your Windows Mobile device?

At the last couple of Mix events Microsoft has been talking about having a version of Silverlight for mobile devices.  There were big announcements about it being available on not just Windows Mobile, and thus continuing the any device, any browser story they are trying to sell.  The reality is that there are more issues with doing this than you’d imagine, for example: a real device application should be able to access device features but running in the browser sandbox would prevent this….. and so the list of “exceptions” begins.

But why wait until Microsoft finally ships a version of Silverlight for Windows Mobile? If you go and try out the SkyFire mobile browser you will find that you can actually see and interact with Silverlight applications from your browser.

image image

On the left is the Silverlight widget that we have on the nsquared solutions website viewed through IE.  On the right is the same widget viewed via the SkyFire browser – note that an animation is in progress and visible on the device.

So how are they doing this? Well the idea is similar to the DeepFish concept in that it’s essentially a proxy browser.  The browsing is done on the server and just the UI is rendered out to the device – not too dissimilar to remote desktop.  Whilst this of course requires a little more bandwidth it does mean that you get the full capabilities of a desktop browser.  What would be interesting to look at is what the header information is that gets sent to the server – does it see a desktop or mobile browser?

It’s no iPhone UI but it’s a step up for Windows Mobile

Over the weekend, after a long flight back from the US, I got particularly frustrated by my HTC Touch Pro device – the Today screen basically crashed and required me to take the battery out in order to restart the device.

<Rant>

Before I go much further can I state publically that I think that the current HTC devices (namely the Diamond (from other’s feedback) and the Touch Pro) are some of the worst devices I’ve seen. Whilst the HTC customised UI is “nice” something doesn’t play nice on the device causing all sorts of issues.  This coupled with a complete lack of any support from either HTC or eXpansys Australia has left me very disfranchised about the device that I paid >$1000 for. I have purchased a number of devices from eXpansys UK but this was the first and only device I will ever by from the Australian subsidiary – the lack of any real support on the issues with this device means that I would discourage anyone from every purchasing from eXpansys Australia.

</Rant>

Ok, enough of me ranting.  What I did want to cover was the Point UI Home 2 interface. Like so many other interfaces this uses a series of icons and gestures to try to optimise the layout of the home screen.  I’ve included a number of the screens:

image image

image image

Unfortunately it seems that Pocket Controller-Pro doesn’t seem to be able to capture the higher resolution on this device so the images are a little grainy. In the second image you can see the transition between Date/Time/Weather view and the Task list view.  This is done by sweeping your finger across the top part of the display.

At the bottom you have a series of buttons that can be used to bring up Call history, Favourite applications (you can specify 9), Favourite contacts and Messaging.

All in all, I think this UI is much easier to use that the default Touch Pro interface and a significant improvement over the default Windows Mobile 6 UI.  In fact I’d almost say, based on the screenshot presented from WMC that it is more intuitive than what’s coming in Windows Mobile 6.5 with the Honeycomb start interface.

Customer perception of Windows Mobile

Since the announcement of Windows Mobile 6.5 at Mobile World Congress it has received some active criticism from the community.  Whilst the post from Engadget is quite disparaging, other posts, such as Long’s post on the honeycomb menu is slightly more encouraging.

Based on what was announced it would seem that Microsoft has invested into the home/today screen.  This is similar to what HTC, Samsung, Sony and other OEMs have been doing for sometime now.  Whilst it would be a welcome relief to see a different default home screen I’m not sure this is going to fix the market perception of the Windows Mobile platform. 

Taking a step back, lets look at why the OEMs are focusing on the home screen.  Well, in fact the question is a little broader; why are OEMs looking at reskinning or changing the look at feel of Wiindows Mobile?  The home screen is just the starting point for this change as it’s one of the most visible/used parts of Windows Mobile.  There are a couple of points to the answer that I can see:

  • If you look at the user interface of the Windows Mobile today screen over the last couple of years you will notice there hasn’t been much change.  This was in part to ensure the today plugin model continues to function but it was also because the team were focussed on building out other functionality.  Unfortunately this meant that the OEMs feel that they need to innovate and provide a better user experience, rather than wait for a new version of Windows Mobile.
  • OEMs need a way to differentiate.  In the past OEMs and Telcos have relied on pricing and plans to differentiate themselves.  Margins are being eroded and both parties are looking elsewhere to provide value to their customers. Building a better user experience, potentially tailored to specific market segments, it one way to do that.

Now let’s go back to the work Microsoft is doing on the today screen. Currently the honeycomb interface looks nice and modern but will it in 6 months+ time (don’t read anything into that date as I’m just guessing based on the announcements from MWC) when the devices hit the market? If not, OEMs will again have to come up with their own home screens in order to continue to compete.  Further, the new home screen, if adopted by the OEMs just means they have one fewer points to differentiate on.  Upshot is that OEMs will ignore this new home screen and continue to invest in their own home screen in order to differentiate and compete.

If we extrapolate this behaviour out to the rest of the Windows Mobile platform then it indicates that OEMs are going to continue to try to change the UI of anything that ships within Windows Mobile in order to deliver a better, richer user interface for their customers.  This leads to the question as to why is Microsoft bothering revamping their user interface?  Why not focus on extensibility, customizability and core platform functionality?  This is what Windows (in general, and not just Windows Mobile) is best at – the ability to be tailored, tweaked and extended to specific markets.

Google Maps Street View on Windows Mobile

So this post is a bit slow off the mark as this functionality has been around for a while. Following my previous post on Google Maps for Windows Mobile I am just reaffirming my claim that I think the best app for Windows Mobile is built by Google (how ironic). Admittedly the Street View functionality is not immediately obvious and I actually only came across it today as I was searching for a building in the Sydney CBD:

image

Clicking on the Street View button takes you  (surprise, surprise) to the street view, as seen on the web, within the Google maps application:

image

What I can’t believe is how staggeringly fast it is to download, render and navigate within street view mode. As with the online version it downloads a low resolution image initially and then smoothly updates the display when the full image has downloaded.  The red box in the following image shows this.

image

You can of course navigate using the directional pad or using the on screen arrows (when facing along a street).

image

Google Maps for Windows Mobile, Now with Google Latitude

I have to say that the best application for Windows Mobile, just got better.  The newly released version of Google Maps for Windows Mobile not only hosts a new user interface, it also supports Google Latitude.  Essentially Google Latitude, with your permission of course, allows you to track and share your location.  It’s as easy as signing in with your Google account.

image imageimage

Once you’re in you can add and remove friends.  You can of course control how visible your location is via the Privacy tab.

At this stage there is no API available according to postings on the Google Mobile forum.

Get started with the latest version of Google Maps with Latitude by going to http://google.com/latitude on you device.

Why Windows Mobile?

I was just catching up on a couple of blogs and noticed that Paul over at Modaco had an interesting Talking Point where they discuss “What keeps you stuck on Windows Mobile, and what tempts you away?” I tend to agree with a lot of his points but thought I’d add my own commentary, since I think it paints a more realistic story of the future for Windows Mobile.

Pros
- the brilliant Exchange sync story and super productive e-mail client
>> Couldn’t agree more.  The setup, sync and operational side of Email, Calendar and Contacts on Windows Mobile rocks.  Sure the UI looks super dated now and doesn’t work well with touch input but it definitely works.  I suspect that the POOM UI is probably the next cab off the rank for the likes of HTC, Samsung and Sony who all seem to be doing their own custom UIs for the home screen, application navigation etc.


- .net Compact Framework for simple development on the device
>> Again, being a techie I like to be able to write code for my device.  Unfortunately the .NET CF is a little bit heavy for doing serious mobile application development. This definitely contributes to the Windows Mobile problem of being bloated and requiring more hardware than imho it should.


- turn by turn navigation solutions at a low cost
>> Now we are starting to get somewhere – an awesome reason for going with Windows Mobile is there is actually a large number of super cool applications that you can download and/or purchase.  Unfortunately you’ll have to trawl Google to find them as there isn’t a single store to get them from.


- CamerAware!
>> Wish we had this app for Australia.


- an OS i'm familiar with at the very deepest level, and that I find productive
>> This is the same “I’ve always been a Windows user” concept.  Unfortunately it’s not necessarily a good reason for sticking with a platform


- a wide variety of devices with a wide variety of form factors
>> It’s definitely arguable that the iphone form factor isn’t for everyone… but it is cool, slick and looks great!


- high resolution cameras
>> Yes, and this will definitely get better.  I’ve always said that one of the things that a Windows Mobile device manufacturer needs to do for their device to be a consumer device is to wack a serious camera in the back.  Take the 5Mb camera on offer on some Sony devices, combined with an actual flash, this device would allow you to dispense of your camera.

- 20 key and 12 key touchscreen input (iPhone NEEDS this imho!)
>> Yes, I’m a big fan of the slide out keyboard too.  That said I’ve seen people type incredibly quickly and accurately on their iphone.


Cons

- App Store!
>> In how many ways and how often can we tell Microsoft this – we need a better process for developers to build and sell their applications.  I don’t care how great the application is, if you can’t sell it then it may as well not have been written


- applications that co-exist with apps I use on my mac, such as 1password touch and Things iphone
>> Sync’ing is a massive reason that Exchange w Windows Mobile is imho the best enterprise mail solution.  Do this with other applications and you can increase this value.  One of the big things that the Windows Mobile platform offers is a rich development environment that has proper support for background threads – this means that you can be sync’ing data, even when your application isn’t in focus.

- Regular, OTA OS updates
>> Again, this is a request that has been iterated again and again and again.  Instead of 2-3 yearly versions, why not release iteratively.  We’ve already seen two versions of the iPhone and it’s anyone’s guess how many more versions we will see before the next version of Windows Mobile?

The challenge for us Windows Mobile enthusiasts is to work out how we can leverage our deep knowledge of the platform and convert it into a compelling reason/feature/application that sets the Windows Mobile platform apart from its competitors.

IE Mobile 6 for Windows Mobile 6

Somehow I forgot to mention this last week but IE Mobile 6 for Windows Mobile 6 was released.  There are a series of emulators running Windows Mobile 6.1.4 which includes IE Mobile 6 available for download.  Unfortunately you will have to wait for your OEM of choice to upgrade their ROMs before you can make use of the new functionality…… Ho Hum, what’s wrong with building installers that will update applications on the device.