0 Comments

My work and family commitments mean I rarely get to make it to developer conferences, so I really appreciate the fact that NDC make all their session videos available for free on Vimeo.

The most recent set to go up are the ones from NDC Oslo, and as usual, I’ve bookmarked far more than I could possibly get round to watching (even at 1.5x). But I thought I’d share some of the sessions I’ve found most helpful so far.

0 Comments

After more or less ignoring the whole “WinRT” thing (except for making an experimental WinRT port of NAudio), since Windows 10 came out I have been getting to grips with the new UWP platform. I’ve been particularly focusing on the audio side of things, and I’ve got a Pluralsight course in the pipeline which I hope to share more about very soon.

But the question I want to ask is, why would anyone want to create a UWP application? What’s the point? So I’ll start with a few of the reasons why you might avoid creating UWP applications, and then try to make a positive case for when it would make sense.

Reasons to avoid UWP

1. It’s Windows 10 Only. Although Windows 10 has picked up a decent amount of market share in its first year, there’s no question that Windows 7 remains the most popular version of Windows out there. And there are plenty stuck on other versions from XP through to 8.1. UWP applications require Windows 10 and above, so the question is, can you afford to target only a small segment of the market, even if it is steadily growing?

2. Desktop Apps are Dead. Well, according to some people anyway. The truth is, much more can be done in the browser than ever before, and we are even seeing the rise of hybrid desktop/web technologies such as electron that are blurring the boundaries. However, I still think there are a category of applications that fit better as a “native” desktop application, particularly when integration with the operating system and devices is important.

3. It’s Yet Another New Thing to Learn.The pace of change in this industry just seems to be getting faster and faster, and UWP brings a whole new set of APIs requiring us to relearn things like how to interact with the file system. Now it turns out actually not to be too hard if you already knew WPF (more on that later), but for those not already using XAML, there’s quite a lot of new concepts you’re going to have to get familiar with.

Reasons to use UWP

1. Target Multiple Device Families Probably the biggest selling point for UWP applications is that your application automatically runs on all the Windows 10 device family from regular desktop Windows, to Windows mobile, XBOX One, embedded IoT devices (even Raspberry Pi) and the HoloLens. Now of course your app might not make sense on all of these platforms, and it will likely need a bit of tweaking to fit the constraints and capabilities of each of those platforms, but Microsoft are to be commended for having finally created one API to rule them all.

2. Bring Your WPF KnowledgeIf you are already a WPF developer, then you will find the transition is actually pretty smooth. The XAML side of things will be completely familiar to you and it is just a few new APIs to learn.

3. It’s the Future of WindowsIf you don’t care about targeting multiple device families, you could argue that UWP is irrelevant – just build a regular win32 or .NET app and have it run across all versions of Windows back to Windows 7 and even earlier in some cases. But Microsoft are betting big on this new API, and if you want access to the latest and greatest features of Windows as they become available, whether that’s voice recognition or inking support, then UWP is the place you want to be. (Having said that I expect the old win32 APIs will die a very slow and lingering death over the next 20 years or so)

4. Sell Your App Through the Store It’s true that the Windows 10 store hasn’t really taken off yet. Many of us “old” hands are used to downloading our apps from random websites and installing them manually. But a new generation is growing up who are used to getting all their new apps through the store because that’s how it works on their phone and tablet. So being in the store will become increasingly important. It also matters because there is greater trust for apps available in the store, which brings me onto my final reason for using UWP.

5. It’s a Much More Secure Programming ModelOne of the first things that hits you about writing UWP apps is what a pain it is to read and write files, or access things like the microphone. You have to get the user’s explicit permission before you can do anything that could potentially compromise their private data. And that’s actually a good thing. As malware and ransomware become more prevalent, it may not be long before people start locking down their Windows PCs so that only apps from the store can be loaded (a similar situation to where we already are on phones).

So those are my five reasons to use UWP. Of course, the reasons not to may outweigh them for your app. I think the main candidates for UWP apps are rich client line of business applications (where the customer is running Windows 10), casual games (where there is benefit in targeting multiple device families), and applications that benefit from accessing operating system features.

What did I miss? Can you envisage yourself creating a UWP application, or will you be avoiding it? Let me know in the comments.

In my last post, I talked about handling the FileCompleted event from an AudioFileInputNode in a UWP application. Since this event is raised from a background thread, it’s important to get back onto the Dispatcher thread before making any updates to the overall AudioGraph, or changing the UI.

In UWP, this can be done by calling RunAsync on the Dispatcher. (By the way if you’re in a ViewModel then you can get at the Dispatcher with the rather cumbersome CoreApplication.MainView.CoreWindow.Dispatcher static property)

private async void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        // code here runs on dispatcher thread
    });
}

Now this works fine, but there is a nice alternative you can use if you’re working with Reactive Extensions. Rx makes it really easy for us to say that we want to observe an event on the Dispatcher thread. We do of course need to turn the event into an Observable first, which can be done with a call to Observable.FromEventPattern (which admittedly is a little bit cumbersome itself), but then we can say we want to observe it on the current SynchronizationContext (which is the Dispatcher thread in UWP).

Here’s a simple example:

Observable.FromEventPattern<EventHandler, EventArgs>(
h => audioEngine.FileCompleted += h,
h => audioEngine.FileCompleted -= h)
.ObserveOn(SynchronizationContext.Current)
.Subscribe(f => OnPlaybackCompleted());

Now our event handler method OnPlaybackCompleted will run on the correct thread. Of course, on its own this may not seem a great improvement to using Dispatcher.RunAsync, but the benefit is that now it is an Observable, we can also make use of all the powerful composability that Rx brings.

0 Comments

I’ve been playing with the new UWP AudioGraph API recently and one of the things I wanted to try was fire and forget audio playback (for fire and forget with NAudio see my post here). This is where you want to play lots of individual pre-recorded sounds, such as in a game, and just want to trigger the beginning of playback in a single line of code and have cleanup handled for you automatically.

Let’s start by creating our AudioGraph, and an AudioDeviceOutputNode, and then we’ll actually start the graph, despite not having anything to play yet. The audio graph is quite happy to play silence.

private AudioGraph audioGraph;
private AudioDeviceOutputNode outputNode;

public MainPage()
{
    this.InitializeComponent();
    this.Loaded += OnLoaded;
}

private async void OnLoaded(object sender, RoutedEventArgs e)
{
    var result = await AudioGraph.CreateAsync(new AudioGraphSettings(AudioRenderCategory.Media));
    if (result.Status != AudioGraphCreationStatus.Success) return;
    audioGraph = result.Graph;
    var outputResult = await audioGraph.CreateDeviceOutputNodeAsync();
    if (outputResult.Status != AudioDeviceNodeCreationStatus.Success) return;
    outputNode = outputResult.DeviceOutputNode;
    audioGraph.Start();
}

Now we’ll create a helper file that will load a sound file bundled with the application, create an AudioFileInputNode from it, connect it to the output device node so it starts playing, and then subscribe to its FileCompleted event. In the FileCompleted event handler, we can remove the AudioFileInputNode from the graph and dispose it. Note that we have to do this on the UI thread which we can ensure by using Dispatcher.RunAsync.

private async Task PlaySound(string file)
{
    var bassFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/{file}"));
    var fileInputNodeResult = await audioGraph.CreateFileInputNodeAsync(bassFile);
    if (fileInputNodeResult.Status != AudioFileNodeCreationStatus.Success) return;
    var fileInputNode = fileInputNodeResult.FileInputNode;
    fileInputNode.FileCompleted += FileInputNodeOnFileCompleted;

    fileInputNode.AddOutgoingConnection(outputNode);
}

private async void FileInputNodeOnFileCompleted(AudioFileInputNode sender, object args)
{
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        sender.RemoveOutgoingConnection(outputNode);
        sender.FileCompleted -= FileInputNodeOnFileCompleted;
        sender.Dispose();
    });
}

Now we can trigger sounds very easily:

private async void buttonBass_Click(object sender, RoutedEventArgs e)
{
    await PlaySound("bass.wav");
}

private async void buttonBrass_Click(object sender, RoutedEventArgs e)
{
    await PlaySound("brass.wav");
}

This design allows for multiple instances of the same sound to be playing at once. If you don’t need that, you might be able to come up with a more efficient model that just keeps a single instance of an AudioFileInputNode for each sound and reset its position back to zero when you need to replay it. But this technique seems to perform just fine in the simple tests I’ve run it with.

0 Comments

The way you access files on disk in UWP applications is through the StorageFile API. This allows you to read files but only from folders you have the rights to read from, which is pretty locked down in UWP. This is of course a good thing, but what if you want to ship a static data file with your application and access it as a StorageFile from inside the application.

It took me a while to work out how you can do this, so I thought I’d share the solution I found.

First of all, add your bundled data file into your project, for example in the Assets folder. Here, I’ve added in an MP3 file:

image

Now, make sure that the build action is set to Content. The Copy to Output Directory flag does not need to be set to copy.

image

Now, when we want to access this as a stored file, we use the StorageFile.GetFileFromApplicationUriAsync method and pass in a specially formatted Uri with the ms-appx:// protocol, like this:

var storageFile = await StorageFile.GetFileFromApplicationUriAsync(
    new Uri("ms-appx:///Assets/GuitarTest1.mp3"));

And that’s all there is to it. The StorageFile you get is of course read-only, but it can be passed to any API that expects a StorageFile.

Hope someone else finds this helpful, and do let me know in the comments if there is a better way to ship bundled content with your UWP applications.