18
Aug 10

Bike ride with Sarah I – 70 miles!

This one was fun, but you can see that we took a few wrong turns. Map here. Onwards and upwards!

I’ve come up with a crazy home-brew way of uploading these maps using a modification of GPS Visualizer which I might blog/whinge about at some point. (It involves XLST, bash and perl scripting at the moment).


15
Jul 10

µWeb, a tiny web server in WCF

It seems a bit insane, but we need to serve up some simple static HTML/CSS/JS assets, and the alternative is bundling Apache httpd with our product, or requiring IIS, both of which are a bit unpalatable.

First, we need a ServiceContract which allows any path to go after our service’s root URL:

IUWebService.cs:

using System;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.IO;

namespace TaskService
{
    [ServiceContract]
    public interface IUWebService
    {
        [OperationContract]
        [WebGet(UriTemplate = "*")]
        Stream GetFile();
    }
}

It’s important to set the UriTemplate to the wildcard, and to make our method have 0 arguments.  This means it won’t try to process the URL and we can grab it verbatim for our own processing.

Now for the implementation,

UWebService.cs:

using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Description;

namespace TaskService
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, IncludeExceptionDetailInFaults = true)]
    public class UWebService : IUWebService
    {
        public Stream GetFile()
        {
            Uri to = OperationContext.Current.IncomingMessageHeaders.To;
            string path = to.AbsolutePath;
            path = path.Substring("/UWebService.svc".Length);
            string basepath = Utils.GetOurLocation();
            DirectoryInfo di = new DirectoryInfo(basepath);
            di = di.Parent;
            di = di.Parent;
            di = di.Parent;
            // Get rid of leading slash
            path = path.Substring(1);
            // Replace / with \
            path = path.Replace("/", "\\");
            path = System.IO.Path.Combine(di.FullName,path);
            // Set headers
            // We have 'borrowed' the most important mime types from apache mime.types
            string ext = new FileInfo(path).Extension;
            string mimetype;
            switch (ext)
            {
                case ".html":
                case ".htm":
                    mimetype = "text/html";
                    break;
                case ".js":
                    mimetype = "application/javascript";
                    break;
                case ".css":
                    mimetype = "text/css";
                    break;
                default:
                    mimetype = "text/plain";
                    break;
            }
            WebOperationContext.Current.OutgoingResponse.ContentType = mimetype;
            WebOperationContext.Current.OutgoingResponse.ContentLength = new FileInfo(path).Length;
            return System.IO.File.Open(path, FileMode.Open);
        }
    }
}

The key points here are getting the Uri of the incoming path, and then munging that path to get the part which is the requested file.  In our product, we are interested in serving up files which are 3 directories above where the executable is running – hence the getParent() calls.  The other notable things are setting the correct MIME type and content length.

Finally we open the file and return the stream.  Currently there is no error checking!

For completeness, this is what Utils.GetOurLocation() does:

        public static string GetOurLocation()
        {
            Uri thisLocation = new Uri(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase));
            return thisLocation.LocalPath;
        }

That’s not quite the complete story – we need a working Web.config and a discussion of why this won’t work in the ASP.NET development server in Visual Studio.

The Web.config:

<system.serviceModel>
  <services>
    <service name="TaskService.UWebService">
      <endpoint address="" behaviorConfiguration="WebHttpBehavior" binding="webHttpBinding" contract="TaskService.IUWebService">
        <identity>
          <dns value="localhost"/>
        </identity>
      </endpoint>
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="WebHttpBehavior">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <bindings>
    <webHttpBinding>
      <binding name="myHttpBinding" >
        <security mode="None"/>
      </binding>
    </webHttpBinding>
  </bindings>
</system.serviceModel>

This is the relevant system.serviceModel fragment. What caught me out is that you need the endpoint behavio[u]r as well as the binding to say that you want plain HTTP rather than XML/SOAP etc.

Now, we should be able to go to a URL, like

http://localhost:51060/UWebService.svc/gui/index.html

and be presented with our HTML UI. However, I found that any requests with dots (‘periods’) in them don’t work. It turns out there are some characters that WCF kindly filters out/chokes on if they are in the request. The grubby details are here, but if you scroll to the bottom, you will see that the problem only occurs if you are using the ASP.Net development server.

Well, we can live with this. I only need the ASP.Net development server to do some occasional debugging, and the rest of the time I use our custom self hosting solution, inspired by this idea, and it works perfectly there.

I didn’t mention this in the introduction, but another reason why this is so useful for me is I can now serve static content and dynamic SOAP/JSON services from the same host and port number. This means that the HTML UI can do clever AJAX/jQuery stuff without cross domain issues or proxying.

Wrapping up, this was easier than I thought, but some of the knowledge of the .NET/WCF stuff is hard-won and often only found in blogs, which was part of my motivation to write this up. Two main TODOs remain before this can be used “in the wild” which are of course security and error checking. Running under a limited service account or checking paths to restrict file system access (especially anything with “..”) are two approaches to ensure you don’t end up exposing the whole file system.


08
Jul 10

NAnt: No string replace in files for you!

A common task in building software is searching for and replacing tokens.  A good example might be the product version or a copyright date – good software developers hate manual, repetitive tasks like updating lots of files.

It turns out that there isn’t a NAnt task for this, but its absence seems to have been blogged about extensively.  The maturity of the various .NET tools reminds me of Java in the pre-1.4 era, and sometimes things like NHibernate and NAnt lag behind their Java counterparts.

Luckily, Cygwin is a pre-requisite for any machine where I need to do ‘real work’, and that includes my build machine.  So for now, I’ll solve the problem with a perl one-liner

#!/bin/sh

#
# greplace
#
# Globally replace one string with another in a set of files
#

/usr/bin/perl -p -i -e "s/$1/$2/g" $3

05
Jul 10

Bike ride with Matt C – Bristol, Wraxall, Chelvey, Airport, Winford, Bristol

Experimenting with how to put these maps up – the map is here, as created with GPS Visualizer and then tweaked a bit.

The GPS logger seemed to stop at around Barrow Gurney, but we got back via Long Ashton.  According to my other bike computer the route was almost exactly 30 miles.

A good fun ride on a nice sunny Saturday morning!


14
Mar 10

xwaxMac 0.5 released

Download here.  It’s been a while since I’ve been a bit busy.

Notable changes are:

  • More robust loading of iTunes libraries
  • Fixed failures where some audio files weren’t loading (one user sent me a WAV which wouldn’t load, and it now does)
  • Upgrade timecode decoder and pitch interpolation code to xwax 0.7 code

Please post any feedback in the blog and I’ll get back to you.


10
Nov 09

CapsAU 1.2 released

pluginThis is the latest version of my “AudioUnits port of the LADSPA (Linux) CAPS Audio Plugin Suite”.  It’s a Universal Binary and will work with 10.4 or later and can be downloaded here.

I’ve resurrected this project after leaving it to fester for a while – the previous release had some pretty serious bugs in it and I’m not sure if anyone except me ever used it.

If you want to see the code, it’s hosted on this project page at SourceForge, but ignore the binaries on there, they’re old and I won’t host binaries on SourceForge in the future.

What effects do you get?  It’s easiest to copy and paste from the original CAPS page, and they can be found below.

The strikethroughs are there for the following reasons: the mono choruses are too boring (you can always throw away one channel in the output); Eq and Plate automatically switch between 1-in, 2-out or 2-in, 2-out depending on the way they are routed; the generators aren’t effects and I was only interested in effects.

You will find the effects under “Zen_Platypus” and the names are as below.  I think that the ‘Emulation’ set are the best of the lot and are capable of some really nice gritty distortion.

  • Generic
    • Eq – classic ten-band equalizer
    • Eq2x2 – stereo version of Eq
    • Compress – a compressor suitable for single instruments
    • Pan – pan and optional width
  • Emulation
    • PreampIII – simplistic tube preamp circuit
    • PreampIV – simplistic tube preamp with tone controls
    • ToneStack – tube preamp tone controls
    • ToneStackLT – tube preamp tone controls 44.1
    • AmpIII – tube amp
    • AmpIV – tube amp with tone controls
    • AmpV – tube amp with power supply modulation
    • AmpVTS – tube amp with a ToneStack circuit
    • CabinetI – emulation of classical speaker cabinets
    • CabinetII – refined version of CabinetI
    • Clip – hard ‘transistor’ clipping
  • Effects
    • ChorusI – a versatile classic
    • StereoChorusI – when one channel is not enough
    • ChorusII – variant with fractal modulation
    • StereoChorusII – stereo variant with fractal modulation
    • PhaserI – another classic
    • PhaserII – variant with fractal modulation
    • SweepVFI – resonant filter modulated by a fractal
    • SweepVFII – resonant filter modulated by a fractal
    • AutoWah – resonant envelope-following filter
    • Scape – stereo delay plus resonant filters, fractal modulation
  • Generators
    • VCOs – sawtooth / triangle / square wave generator
    • VCOd – double VCO with detune and hard sync
    • CEO – chief executive oscillator
    • Sin – testing and tuning helper
    • White – white noisz
    • Lorenz – a fractal singing in a broken voice
    • Roessler – a roaring fractal
  • Reverb
    • JVRev – a digital reverb technology classic
    • Plate – versatile refined digital reverb
    • Plate2x2 – 2-in, 2-out version of Plate

08
Nov 09

xwaxMac 0.4 released

Download here.  Notable new features are in the track display – album titles are now displayed and searchable.  Unicode characters are now displayed properly as well, although you still can’t search using them.

Some fixes have been made to audio file loading – mono files and files at sample rates other than 44.1kHz should now work properly.

xwaxMac 0.4, showing Unicode and album names


05
Nov 09

“Real vinyl” playthrough

Just a quick note that “real vinyl” playthrough has been in xwaxMac for a while now, but I probably haven’t mentioned it.  Hit Ctrl-1, 2 or 3 to enable/disable playthrough for deck 1, 2 or 3.  The scope will disengage so it will look like the deck has frozen, but you will now hear the music from your record (or your timecode if you accidentally left the timecode record on!)

The round-trip latency will be determined by the buffer size, (ie 64 samples/44.1kHz = 1.5ms), which is another reason to set the buffer size as low as your machine will allow (the audio will break up if your machine is too slow).  If you can’t put up with a round-trip latency, then you could use a Y-cable to split the output from the deck, but the latency is negligible and I don’t like faffing around with cables!

In future I might implement an indicator to show whether playthrough is active, and maybe keep the scope on or at least clear it.


04
Nov 09

xwaxMac 0.3 released

Download here.  Many new features have been implemented as per my previous post.  As usual I would be grateful for feedback from testers and developers – just post it here.

A note on recording: if you enable it, your recording will be named recording{YYYYMMDDHHmmSS}.{aiff,m4a}, depending on the format you choose.  An example would be recording20091104175204.aiff.  The time is based on when xwaxMac starts recording.

The idea is that disk space is cheap and you never know when you’re going to come up with your best mix, so you might as well be recording all the time.  Be warned, however, that no disk space checks are made, although I figure that at ~600MB/hr (uncompressed) you won’t run out that fast.  If anyone can think of a better file naming convention, then give me a shout.

Oh yes, and you should also trash your preferences (~/Library/Preferences/org.blench.xwaxMac.plist) as the prefs loader has changed again.

And here are the new preferences hinted at by djchryzis:

xwaxMac 0.3 Preferences


28
Oct 09

xwaxMac svn r79: Recording, new preferences

Once I get this all tidied up I’ll make a binary release.

New features since 0.2 release:

  • Progress bar whilst loading music library (this appears in the background; it needs fixing so that it appears in the foreground)
  • Faster and better lookup of records – type a string and all artists/titles containing that string will be found.
  • Recording.  Every xwaxMac session is recorded as an AAC stream – just plug the output of your mixer into an input device.  Preferences for channels and file name/location still need to be done.

The preferences have changed due to the recording device; if you build this version onwards you will need to trash your old preferences.