Monday, June 11, 2012

Developer Developer Developer South West 4.0 - A Retrospective

I'm rather late to the party with this post - Chris Alcock posted his round-up of DDDSW4 links over the weekend. But for my own recollection this post is probably a good idea.

This was my third DDDSW event - but this time was different - I was a speaker not just a delegate.


6:31 AM - 26 May 12 - Half-way around.
The location in Bristol works for me as it's my old stomping ground from University - I studied Computing for Real-Time Systems at UWE under Rob Williams. 


It was a toss-up whether I should go to the Friday speaker dinner or catch up with old friends instead - getting together with the old gang won out, but it was probably for the best it wasn't a 3am finish as has happened in previous years! Still, it's a testament to the friendships that you can create in a small startup that two friends I'd not seen in over a decade joined the usual suspects - and that it felt like we still used to hang out every day.


So Saturday dawned with an early start and a 5km run to wake me up and set me up for the day (10km if you believe RunKeeper - I don't!).


Then off to UWE to check in, just in time for the Speakers' briefing - this might have been intimidating for new speakers but for Guy's delivery which was just the right balance of "check it, check it, check it again" and humour - especially at that early hour.


I think as a delegate whilst you appreciate the some effort that goes into making DDDSW work, I for one had very little idea about just how much required to herd speakers to the right place, get swag organised, manage the rooms, etc. Guy Smith-Ferrier and the team do an amazing job.


So after the speaker's briefing I wandered off to what was to be "my" room for the pretty much the whole day. I was speaking in Track 4 in 2Q43 and didn't want to risk not being prepared, so the first order of the day was to check projector connections and ensure my laptop was ready for action. 


Session 1 - "What's new in Entity Framework v5 (beta 1)" - Geff Lombardi

First up on Track 4 was Geff Lombardi, talking on "What's new in Entity Framework v5 (beta 1)". Geff's talk had a good balance of slides and coding (i.e. not too many of the former), and demo'd the new DB migrations features of EF. I'm not quite sure I've got my head around it, or how (or if) I can apply it to my codebase, but Spatial and Enum support will be the first things I'll play with, closely followed by the EF Power Tools.

All good stuff, but I'll admit my mind was really on the next session - mine! So after Geff finished I set up - doing a quick run-through of my slide deck and pre-loading the IIS apps I was going to demontsrate. As the room filled up the nerves really kicked in - and then we were off. 


Session 2 - "Using your NuGet for Fun & Profit" - Joel Hammond-Turner

For any new speaker I can only recommend practice, practice, practice. I'd run my talk no less than 5 times for my colleagues at work, so it was no surprise that the contingent from Landmark that came to DDDSW4 didn't want to come see it again. But practicing on them paid off when speaking in front of the DDDSW delegates - I soon forgot my nerves and cracked on.

I covered the background to our use of NuGet within Landmark, and the challenges we had had to overcome in packaging our internal libraries as NuGet packages - and then demo'd the NuGet.PackageNPublish tooling we'd developed. There was a nice ripple of appreciation when I pointed out that in the time it took to describe how the tooling worked (about 60 seconds), I'd created a packaging project.

Then I covered the options for hosting private NuGet feeds, including file-shares, NuGet.Server, NuGet.Gallery and the two commercial offerings - and had the fact that I'd missed TeamCity's new NuGet functionality!

Questions were asked and answered and towards the end of the session, we were having more of a round-table discussion than a presentation, with Mike Ackah and John Stovin in particular deep in the fray (and winning swag for their contributions).

I finished off with a quick refresher on the HanselFix for when NuGet.org goes down and announced that the NiGet.PackageNPublish tooling had been released as open source under the Apache 2.0 License by my company, Landmark.

Open-sourcing the tooling drew a round of applause that made the whole exercise in getting my session together worth it - it's been a good couple of months' work getting all the clearances and publishing everything. 


Once I was finished and cleared away I looked at the agenda for the first time to see what to go to next - and my first choice was in 2Q43 again. I felt like I was going to be living in that room for the day!


Session 3 - "Unit testing with Visual Studio 11 Beta" - Richard Fennell

Richard is always an excellent speaker, and this session was no exception, covering the new test runner, the always-on tests (very like NCrunch), and the multiple test runner plug-ins. This latter I would say is probably the stand-out feature - the ability to use the test and mocking framework combination best suited to your testing needs will I'm sure only reduce the friction when unit tests aren't quite first-class citizens in the development process (i.e. you're not doing pure TDD).

Next was lunch time - and the DDDSW team did us proud with a choice of sandwiches, crisps, cake, fruit... and hot pasties! Distinctly NOM time. Catching up with my Landmark colleagues outside by the pond, it was clear that all the other sessions that morning had been as good as the ones I'd been to, and it was on recommendation that I went to my next session


Session 4 - "WebSockets and SignalR" - Chris Alcock

Chris obviously made a good impression on his first go, because his repeat track room was absolutely rammed - all the chairs and all the tables along the back were full, and people were hanging in through the doorway to listen in.

Chris gave a great introduction to WebSockets and contrasted that low-level javascript technology with the "nicer" abstraction offered by SignalR. Talking about this with someone else later on, his use of a sample OTHER than the traditional text chat was a big win. For me (and many others, I'd imagine) the possibilities of calling client methods from the server and vice versa through one service API (SignalR) are endless and exciting - and Chris' demo really peaked my interest.

After Chris's session it was time for one of the regular highlights of the DDDSW experience - the cream tea. The food queue always seems to be an interesting experience - this time running into Johnno Nolan, Mark Kirschstein, and others from the Manchester NxtGen crowd. The one problem with any DDD event seems that there's never enough time to catch up with everyone you want to. I even "dissed" my Landmark colleagues and caught up with Chris Alcock & Dave Sussman in the Speakers Lounge. It was slightly surreal sitting there, not as a delegate wanting to dig for more information but as a speaker just shooting the breeze.

Session 5 - N/A

Yep - I never made it to any of the last sessions of the day... Setting the speaker world to rights with Chris & Dave (there's a Rockney band in there somewhere!) just rolled on into Session 5 - and after about 20 minutes in the heat of the Q-Block rooms forced me outside for only the second real bout of fresh air of the day.


I made it back in for the Close and Prize Draw - getting all 300(ish) delegates into that one room at the end really pressed home what a great event Developer Developer Developer South West is. I missed the geek dinner that night too - rescuing my wife from our children being the greater priority - but still came away with memories of a great day of geekery.


And finally...

I've got to thank the audience for my first-ever DDD session - they were very gentle with me - and from the feedback I received I'm pretty damned happy, averaging 8.0 for subject knowledge and 7.32 for presentation skills. And I know exactly how I'm going to improve and update my NuGet session if it get's chosen for DDD 10 in Reading in September! That one I'm NOT going to miss the speaker or geek dinners, either!

My company, Landmark, deserves thanks too, for sponsoring me and open-sourcing the NuGet.PackageNPublish tooling - giving me a great big comfort-blanket of support.

Even though none of my colleagues came to heckle me!


Thursday, May 03, 2012

Thursday Quickie - Lightswitch Build Issues #2 - XAP Signing

Update: 2015-05-20 - No idea why I never published this Quickie! Three years is way too long for a blog post to languish in the Drafts folder!

Wednesday, May 02, 2012

Wednesday Quickie - Getting rid of those darned connection string parameters

This quickie relates to the parameters used by MSDeploy to transform your web.config when a web application or site is deployed.

By default the deployment targets (Microsoft.Web.Publishing.targets) used when building a deployment package for a web app will automatically generate entries for connection strings. The problem is that it chooses really awful tag names for the parameters - for example:






This gave me a problem as the configuration system we use at Landmark to deploy our web apps can't have any spaces in its parameter tags. Fortunately, there's a quick solution.


It's easy enough to add a Parameters.xml file to your project to provide custom parameters - and in that file it's trivial to include a duplicate connection string parameter definition (that doesn't have spaces in the name).


The final part of the puzzle is to prevent the deployment targets from creating the default connection string entries on build. This is achieved by passing in the following (memorably-named) MSBuild parameter:
/parameter:AutoParameterizationWebConfigConnectionStrings=False
The deployment targets no longer add the connection string parameters by default, so you have to do so explicitly in your Parameters.xml file - but now YOU control the parameter name. Done.



Wednesday, April 25, 2012

Wednesday Quickie - Building Lightswitch Projects in TFS

So I've been fighting with getting my Lightswitch application to build under TFS as part of our (slow) move towards Continuous Build / Continuous Deployment at work... and for weeks I've been banging my head against the wall with the deaded "UnpackExtensionsToProjectDir" error.

And then came the revelation... looking a couple of lines down I found that the real error was being masked - looking at the detailed logs we can see the real culprit:


C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\LightSwitch\v1.0\Microsoft.LightSwitch.targets(1257,9): error MSB4018: The "UnpackExtensionsToProjectDir" task failed unexpectedly.
<SNIP>
[C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj]C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\LightSwitch\v1.0\Microsoft.LightSwitch.targets(1257,9): error MSB4018:    at Microsoft.LightSwitch.ExtensionsReader.ExtensionInformationService.ExtensionInformation.LSPKGPackage.ExtensionDirectoryDeletionFailedAction(IServiceProvider serviceProvider, String directory) [C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj]
<SNIP> 
[C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj]Done Building Project "C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj" (default targets) -- FAILED.Done Building Project "C:\Builds\4\MyApp\Trunk\Sources\Authentication\MyApp.LightswitchApp\MyApp.LightswitchApp.lsproj.metaproj" (default targets) -- FAILED.
By looking at the Microsoft.Lightswitch.targets file, I found that the actual error was that the build process couldn't delete the _Pvt_Extensions directory.


A quick check showed that that particular directory had been added to TFS source control - removing it and the deaded "UnpackExtensionsToProjectDir" error was finally vanquished. (OK - there were a couple of other build errors, but they were easily fixed).

So now I have a green tick beside my Lightswitch application in TFS Build Explorer - WIN!

Tomorrow, my next challenge - getting the thing packaged for MSDeploy deployment.

Thursday, March 15, 2012

Fixing CornerRadius in Silverlight

OK - I know I've not posted in nearly a year... but this time I'm covering one of those "why the frack does it work like that" issues with Silverlight 4.

I hit this one today - I wanted to unify the radii of corners within a Silverlight application to replace the random set of radii used (1, 2, 4, 5, 8, 10, 12, 15 and 20 pixels no less) with a simpler set - small, medium, large and massive.

The problem is that (for whatever reason), the developers of Silverlight decided that we didn't need to be able to create CornerRadius objects in our ResourceDictionaries. Or rather that we could TRY, but that the XAML Loader was never told how to deal with them. Even though the design surfaces in Visual Studio and Expression Blend can quite happily deal with this!

So if you *DO* try then you either get an error saying that you can't set the readonly TopLeft property of a CornerRadius, or if, like me, you do this in your theme.xaml you just get a catastrophic error - somewhere in your project.

So what was the solution?

Well, there was a very good answer to exactly this on Stack Overflow - using a Value Converter to read named resource values from the object for which we want to set the CornerRadius... But I suddenly realised that there was no need to have a "magic string" as keys for the TopLeft etc values - we can just use properties on the value converter ITSELF!

The result is a pretty elegant way to get around a limitation of Silverlight, thus:


<Border x:Name="buttonBorder">

<Border.CornerRadius>

<Binding ElementName="buttonBorder">

<Binding.Converter>

<Converters:DynamicCornerRadiusConverter TopLeft="{StaticResource massiveCornerRadiusValue}"

TopRight="{StaticResource massiveCornerRadiusValue}"

BottomRight="{StaticResource massiveCornerRadiusValue}"

BottomLeft="0.0" />

Binding.Converter>

Binding>

Border.CornerRadius>

…

Border>


Not quite as simple as defining a CornerRadius in a ResourceDictionary, but not bad at all - and certainly it allowed me to do what I wanted - to rationalise my myriad of Radii!

And here's the code:

namespace CheviotConsulting.Common.Silverlight.Converters
{
    using System.Windows;
    using System.Windows.Data;
 
    /// 
    /// Exposes a CornerRadius instance configured for a ValuationProgressButton
    /// 
    public class DynamicCornerRadiusConverter : IValueConverter
    {
        /// 
        /// Gets or sets the top left.
        /// 
        /// The top left.
        public double TopLeft { get; set; }
 
        /// 
        /// Gets or sets the top right.
        /// 
        /// The top right.
        public double TopRight { get; set; }
 
        /// 
        /// Gets or sets the bottom left.
        /// 
        /// The bottom left.
        public double BottomLeft { get; set; }
 
        /// 
        /// Gets or sets the bottom right.
        /// 
        /// The bottom right.
        public double BottomRight { get; set; }
 
        /// 
        /// Gets the corner radius.
        /// 
        /// The resource source.
        /// the corner radius
        private CornerRadius GetCornerRadius(FrameworkElement resourceSource)
        {
            var result = new CornerRadius(this.TopLeft, this.TopRight, this.BottomRight, this.BottomLeft);
            return result;
        }
 
        /// 
        /// Modifies the source data before passing it to the target for display in the UI.
        /// 
        /// The source data being passed to the target.
        /// The  of data expected by the target dependency property.
        /// An optional parameter to be used in the converter logic.
        /// The culture of the conversion.
        /// 
        /// The value to be passed to the target dependency property.
        /// 
        public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return this.GetCornerRadius(value as FrameworkElement);
        }
 
        /// 
        /// Modifies the target data before passing it to the source object.  This method is called only in cref="F:System.Windows.Data.BindingMode.TwoWay"/> bindings.
        /// 
        /// The target data being passed to the source.
        /// The  of data expected by the source object.
        /// An optional parameter to be used in the converter logic.
        /// The culture of the conversion.
        /// 
        /// The value to be passed to the source object.
        /// 
        public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new System.NotImplementedException();
        }
    }
}

Thursday, May 19, 2011

Thursday Quickie - Mocking Events with Moq

There are times when the code under test depends on an event being fired by a component we're mocking. You can explicitly fire a mocked object's event using the following code
            var authService = new Mock<IAuthenticationService>();
authService.Raise(m => m.LoggedIn += null, null as AuthenticationEventArgs);
You can also raise an event on the mock as part of a callback - i.e. fire the event when a method or property on the mock is triggered.
            var authService = new Mock<IAuthenticationService>();
authService.Setup(a => a.LoadUser(null, null))
.Returns(null as LoadUserOperation)
.Callback(() => authService.Raise(m => m.LoggedIn += null, null as AuthenticationEventArgs));
To call a delegate passed into a mocked handler, you just need to do exactly that - the magic is in getting the generics right
            var worker = new Mock<IWorker>();             worker.Setup(w => w.DoWork(It.IsAny<EventHandler<WorkCompletedEventArgs>>()))                   .Callback<EventHandler<WorkCompletedEventArgs>>(c => c(worker.Object, new WorkCompletedEventArgs()))                   .Verifiable();

Monday, February 21, 2011

Tricks & Tips: ListBoxes, TextBoxes and SelectedItems

I ran across this today and thought it was worth sharing. The problem is one that's been found in both Silverlight and WPF, but there doesn't seem to be a nice simple solution for either.

The issue involves a control that can accept focus (e.g. a TextBox) being part of the ItemTemplate of a ListBox control. In this scenario, you can select one ListBoxItem by clicking on the whitespace within the ItemTemplate, but when you click on the focusable control (the TextBox) of another ListBoxItem, then the selection does NOT move along with the focus.

The solution is a dinky little behavior that walks up the Visual tree from the TextBox when it gets focus and selects the parent ListBoxItem.

namespace MyProject.Behaviors

{
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Media;

///
/// Behaviour that allows a control to cause a parent ListBox to become focused.
///

public sealed class ListBoxItemFocusBehaviour : Behavior<Control>
{
///
/// Called after the behaviour is attached to an AssociatedObject.
///

/// Override this to hook up functionality to the AssociatedObject.
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.GotFocus += OnControlFocused;
}

///
/// Called when the behaviour is being detached from its AssociatedObject, but before it has actually occurred.
///

/// Override this to unhook functionality from the AssociatedObject.
protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.GotFocus -= OnControlFocused;
}

///
/// Called when [control focused].
///

/// "sender">The sender.
/// "e">The "System.Windows.RoutedEventArgs"/> instance containing the event data.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "By design - p is re-used for multiple control types.")]
private static void OnControlFocused(object sender, RoutedEventArgs e)
{
var control = sender as Control;
DependencyObject p = control;
while (p != null && !(p is ListBoxItem))
{
p = VisualTreeHelper.GetParent(p);
}

if (p == null)
{
return;
}

((ListBoxItem)p).IsSelected = true;
}
}
}

Alll you have to do is attach this behavior to your focusable control and when it receives focus, its associated ListBoxItem gets selected.
                <TextBox x:Name="MyTextBox>

<Interactivity:Interaction.Behaviors>
<Behaviours:ListBoxItemFocusBehaviour />
<Interactivity:Interaction.Behaviors>
TextBox>
Not forgetting of course to register the appropriate namespaces and reference the System.Windows.Interactivity assembly from the Blend SDK.
xmlns:Behaviours="clr-namespace:MyProject.Behaviors;assembly=MyProject" 
xmlns:Interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Nothing too it!

Monday, February 07, 2011

RIA Services and NHibernate Recipes - Introduction

For the last few weeks I've been working on a new system at work that implements a Silverlight MVVM UI on top of RIA Services. The back end is a SQL Server database that is accessed via NHibernate using LINQ4NHibernate and FluentNHibernate to configure everything.

There has been a fair amount of pain in the process, so prompted by a tweet from @SLColinBlair I've decided to start blogging a series of recipes for using RIA Services and NHibernate together.

As I go, I'm going to create a simple "Client / Project" management application to use throughout which will allow me to blog about each recipe within a common context.

The diagram to the right shows the data structures we'll be starting with.
  • A Client has zero or more Contacts and Projects.
  • A Contact belongs to just one client and has zero or more Responsibilities, each of which is to just one Project.
I will expand the scope of the sample application as we introduced more recipes - any requests will be most welcome on Twitter.

Next time: Getting started - The Clients object.

Friday, January 28, 2011

Quickie: Unwrapping Invocation Exceptions

If you work with dynamic invocation in any way, shape or form you're bound to catch a TargetInvocationException at some time or another. However, the fact that the real exception has been wrapped into a TargetInvocationException can hide a multitude of sins - potentially all sorts of different exception types can get wrapped from all sorts of sources.

One further problem is that it's entirely possible to get nested TargetInvocationExeptions as the call stack unwinds - again masking what the real problem is. This was the precise situation I found myself in with my nicely crafted n-tier WCF-based system.

So to make life just a little easier on myself when dealing with the exceptions thrown whilst performing a dynamic invocation I put together the following extension methods - one that re-wraps an exception and one that un-wraps nested TargetInvocationExceptions.

To use it, we just catch and re-throw, except using the extension methods.
try
{
// Do something dangerous with dynamic invocation
}
catch (TargetInvocationException ex)
{
throw ex.UnwrapTargetInvocationExceptions().ForRethrowing();
}
What you'll get is an exception throw of the same type as the actual fault, regardless of how many nested TargetInvocationExceptions it is wrapped in. Because we're nicely wrapping the exception we also maintain the call stacks to let you trace what's really going on.

Finally, here's the source - use it at your own risk - I've found it handy!

public static class ExceptionExtensions
{
///
/// Returns an exception wrapping an exception, but of the same type a
/// that's exception's INNER exception.
///

///
/// This allows us to write code like
/// throw ex.InnerException.ForRethrowing()
/// to re-throw an inner exception type without losing the stack trace.
///
public static T ForRethrowing(
this T innerException, Exception outerException)
where T: Exception
{
var actualType = innerException.GetType();

var ctorParams = new object[] {
innerException.Message, outerException
};
var result = (T)Activator.CreateInstance(actualType, ctorParams);
return result;
}

///
/// Unwraps an exception from any wrapping target invocation exceptions.
///

public static Exception UnwrapTargetInvocationExceptions(
this Exception exception)
{
var innerException = exception.InnerException;

// not a TargetInvocationException, or no inner exception? Then
// just return the exception itself
if ((innerException == null) ||
(!(exception is TargetInvocationException)))
{
return exception;
}

return innerException.UnwrapTargetInvocationExceptions();
}
}

Monday, January 24, 2011

Getting it right - filming DDD WP7

OK, now they're all available I want describe how I filmed the Developer Developer Developer - WP7 event that was held back in October 2010 at The Printworks in Manchester.

As an entirely community driven event, the day provided 9 sessions that gave a really good introduction to WP7 development - including Andy Wigley's excellent talk on Tombstoning - with NO Microsoft presenters.

The videos are now all up on Channel 9, courtesy of Mike Ormond - and are all in HD to boot.
And now for the trumpet-blowing bit - I was the lunatic that volunteered to film, edit and produce all 6 hours of final video output.

Filming

I filmed the presenter using a Canon XM camera placed at the front of the auditorium - this gave me good footage of the presenter (although Rob Miles enthusiasm as he bounds around the stage makes tracking him a challenge!) as well as a master wide shot against which to synchronise the slide graphics.

A second, smaller Sony HD Handycam was placed in the middle of the back row of the cinema to get a "god's eye view" of proceedings, and to record the screens during demo's. This worked well, but I do think that a camera that has manual focus would have been better, and a direct feed recorded from the screen best of all. Unfortunately that last option requires a £500 converter and some kind of SDI recorder - well beyond the budget of this kind of community event.

Finally I had a second Sanyo HD Handycam for quick pick-up shots of the audience - this really needs a dedicated cameraman / interviewer to make best use of it. I used it in the breaks to get some shots of the outside area where Mike Ormond was running his XAPathon, but the light levels were really too low for any of the footage to be useful. Some of the in-auditorium shots were used as cut-aways in the final edit tho'.

Each presenter was given a second radio pack (in addition to the one for the venue SR system) that was recorded by the Canon - I had two packs, so there was no rushing to swap between presenters. These recorded a good clean audio track against the close-up video which would allow me to sync the recordings from both camera in the edit more easily.

The Sony camera's front stereo mics recorded a good "wild-track" of the audience (and the presenter's voice played through the SR speakers), but regretably the audience levels were never enough to get a clean recording of any questions. This audio did get used at low-levels in the mix to provide some room ambience.

I think the only way to improve the recording of audience questions would be to have 2 or 3 runners with radio stick mics ready to hand them out, or else use a couple of shotgun mics on long booms. That would also allow the question to be piped through the SR system so everyone could hear it clearly as well as allowing it to be recorded.

After the success of filming the Guathon, I wanted to once again get a really clean audio recording of the presenter. As the portable digital recorder I used before wasn't available I used a stereo 1/4" jack to USB audio interface to record the mix audio directly from the Sends of the SR mixing desk into a netbook running Sony Sound Forge Audio Studio. This worked superbly, giving a perfectly clear recording without having to worry about batteries or filling the CF card - seeing "196 hours available" gives a nice warm feeling!

Post Production

After the event, the footage from the Cannon was ingested into my Vaio laptop using a Sony HDV deck over Firewire. Footage from the handycams was pulled straight from the SD cards, and the audio files were just copied over the network from the Netbook onto the Vaio. Then came the hard work - editing in Sony Vegas.

I started by pulling in the master audio files - these were full-length for each session, so gave me a good place to start. Laying the Canon video/audio tracks alongside synchronised the audio for each clip, then did the same for the Sony Handycam footage. This gave me two video tracks (the close-up of the presenter and the "God's eye" view to work with whilst adding the slide graphics exported from Powerpoint as Png's.

Once each session was prepared, the video and slides were merged down into a "Multi-Camera Edit Track". This is a superb feature in Vegas, and lets you easily cut between the three shots as the video is playing. Once the cuts were finalised, it was just a matter of putting a 16 frame cross-fade between each shot, adding top and tail titles and rendering out as a Windows Media file.

Final file sizes were ranged from 700Mb to 1.5Gb per session - 720p targetting a 3.5Mb data rate.

Distribution

This was where Mike Ormond came in - he'd most graciously offered to get the final videos up onto Channel 9 for distribution, and provided access to Microsoft's "big-file-upload" service. He then took each one, uploaded it to C9 for conversion and authored the associated blog posts that are linked above.

Final Thoughts

Was it worth doing?

Absolutely. The DDD sessions are always a superb resource on their subject matter, so allowing those that couldn't be there on the day to see them is highly valuable.

What would you do differently?

First, take a week off from my day-job to do the edit! Fitting this level of complex editing into late-nights and weekends when you've got a young family is hard.

Second, given a larger budget I'd have at least one other cameraman, a second Canon, boom operater / mic runners and record the screen output directly.

Thirdly, I'd try and have Rob Miles tied to the desk! His exuberance makes it damn hard to film as be bounds around and even harder to edit - but that's what makes him such an engaging presenter.

Thanks to everyone involved in setting up this event and letting me record it - may there be many more.