Nick's .NET Travels

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

Installing Vista build 5472.....please wait

After the weekly Geekzone coffee on Wednesday I was suitably enthused to go away and upgrade my Vista laptop from build 5456 to the most recent drop, build 5472.  Of course, this meant a 2.6Gb download, which on my Woosh modem took a little over 24 hours.  Last night around midnight I started the install of build 5472 of Vista.  After entering the product key (which I had remembered to record prior to nuking my only computer) and a few other configuration settings I decided to leave the installation and head to bed.  I woke up this morning to a completed installation.

Before doing anthing I of course stepped through the usual setup process of adding a user, setting up anti-virus (currently beta trialling the Vista version of Pc-cillin from Trend), installing Office 2007 and Groove 2007.  This took just over half an hour, leaving me just 5 minutes to configure Outlook to connect using RPC of HTTP. Overall I was suitably impressed that the whole installation process took a little over an hour of my time (primarily because I slept through the hour or so it takes to install Vista once it has gathered the necessary input - but at least it does this all at the beginning so it can continue without user interruption).

Ok, so I have to complain about one thing that frustrates me in IE7 (both on Vista and WinXP).  As our exchange server is only supposed to be accessible by SoftTeq staff the server uses a self signed certificate.  This of course means that IE7 complains about the certificate when you navigate to outlook webmail. It also means that Outlook can't connect to the server as the certificate is can't be authenticated.  In both cases the usual solution is to add the certificate into the list of Trusted Certificates.  In the past you could do this by clicking View Certificate within IE, then from the certificate information dialog there was a button entitled "Install Certificate".  Perhaps I'm missing it, but I can't find that button in IE7????  In the end I exported the certificate from a machine where it was installed, copied it across and manually installed it.

  • bedcover

    22/05/2011 3:47:55 AM |

    This is the perfect blog for anyone who wants to know about this topic. You know so much its almost hard to argue with you (not that I really would want...HaHa). You definitely put a new spin on a subject thats been written about for years. Great stuff, just great!

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

Nick's .NET Travels

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

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.

Comments are closed