About a year ago I started investigating if it would be possible to create an immersive, engaging and realistic virtual presence experience for live theatre. The general idea would be to construct a live 3D representation of a stage, then allow a remote audience to select where they would like to see the show from. Perhaps virtual cameras could be used by a live video production team to broadcast a show with pre-defined edits, but without cameras interrupting the view or distracting the audience that is physically present in the theatre at the time. Those viewing remotely could use a Virtual Reality headset to watch the show, looking around them as they wanted, or even getting up and moving around without the risk of verbal abuse and projectiles being thrown at them. Continue reading “Virtual Theatre”
As I have discovered, if you search for information on how to apply video projection in a theatre context, there’s not a lot of stuff out there. To be clear, I’m talking about live performance theatre, not movie theatres … because for the latter it’s pretty clear that projection is a major part of the whole thing. In the spirit of sharing a little, but also to put my own thoughts into some form of order, I’m going to write a few articles on what I’ve found, and some ideas of how to apply video projection to amateur theatre productions. Continue reading “Projection in Theatre – The Challenges”
EDIT: The configuration below has now been superceded by LANCache.
About twice a year I help set up and run a local LAN Party at a Rugby club on the outskirts of town. Compared to more widely known events, ours is tiny in comparison – typically 20-30 people – all squeezed into the club house.
One thing that a LAN party needs to be a success, particularly in the last few years, is a solid connection to the internet so that multi-player server lists can be retrieved, DRM systems can unlock, updates can download, and people can sign into Steam. Guests might also wish to have more general net access for the web, email, IM etc. One of the issues with smaller venues, however, is that they generally have no need for a fast, reliable internet service – the cheapest consumer-grade connection will normally suffice. In some cases, the geography of the less expensive locations – required for small parties – tends to impose technical limits on what services are available anyway. In our case, the clubhouse has an ADSL connection which syncs at about 2Mbit on a good (dry) day.
This is going to be the first post based on what I get up to in my day job at the Digital Marketing Agency, Freestyle Interactive, working on the Partners team. There could be more to follow, particularly when I come across something generally interesting.
Freestyle is a digital agency, and the core of an agency business model revolves around time spent on client projects. To track this time, we have an in-house time recording system called Traffic (not to be confused with the commercially available system by the same name). It’s a fairly old system now, and it was originally built in a combination of clasic ASP, SQL server stored procs returning XML, and XSLT for the presentation layer. You can guess how much I ‘love’ working with that system.
Now I’m rebuilding Traffic from the ground up inside Partners, the Digital Asset Management system that we produce. In the process I’m hoping to improve the interface and make people a little less resentful of having to record what they are doing.
The first phase of the redevelopment is to build the timesheet entry user interface, and supporting logic/data access layer.
The old timesheet interface required a start & stop time for each task, due to integration requirements with our 3rd party accounting system. In the new version, I hoped to get away from this to just recording the duration of a task.
Each person in the agency seems to use Traffic slightly differently. This includes how people prefer to record their time. I wanted to provide a way that people can quickly enter time against their tasks, including adding more time to a task already in their timesheet; so I came up with the idea of a single field supporting simple time arithemetic operations, with minute-level resolution.
2h + 5m + 1:05 = 03:10 (3 hours, 10 minutes)
Pass the Parser
As far as I was aware, there wasn’t anything out there designed to do this. Having done a module on compilers at Durham, I was keen to write a parser and interpreter to do the job. I’m now very much a .Net developer, and with it being quite a while since writing YACC grammars, I looked for a solution that allowed me to port the principles learnt aver 8 years ago to my favourite platform. I found exactly this in Irony.
Irony is a very clever bit of kit that allows the creation of a grammar using famililar C# syntax, which is then transformed into a parser/lexer. Not only that, but it also provides a framework for very easily writing an interpreter. It’s just so awesome.
It does, however, assume you know how compiler generators work, with all the associated terminology of parsing, lexing, tokens etc. Documentation is a bit thin on the ground, however the source comes complete with many examples and some utilities to test and run both the examples and any custom grammars you care to write. I used this tutorial on creating a calculator using Irony to help me figure it out, along with one of the samples.
It will take me far too long to explain how Compiler Compilers work to the uninitiated, so I’m going to assume that you know all that stuff already.
The grammar I’ve defined accepts time in different formats:
- Hour portion, alone, in english notation:
decimal part hours permitted, e.g. 1.5 hr = 1 hr 30 mins
- Minute portion, alone, in english notation:
- Hour & minute portions together, in english notation:
- Hour & minute portions in colon notation:
01:35 = 1 hr 35 mins
- Hour & minute portions in dot notation:
1.5 = 1 hr 50 mins
The first task is to separate the terminals from the non-terminals. So the above translates to this:
var number = new NumberLiteral("number", NumberOptions.AllowLetterAfter);
var HOUR_SINGLE = ToTerm("h");
var HOUR_SHORT = ToTerm("hr");
var HOUR_LONG = ToTerm("hour");
var HOURS_SHORT = ToTerm("hrs");
var HOURS_LONG = ToTerm("hours");
var MINUTE_SINGLE = ToTerm("m");
var MINUTE_SHORT = ToTerm("min");
var MINUTE_LONG = ToTerm("minute");
var MINUTES_SHORT = ToTerm("mins");
var MINUTES_LONG = ToTerm("minutes");
var COLON = ToTerm(":");
var PLUS = ToTerm("+");
var MINUS = ToTerm("-");
var hourSymbol = new NonTerminal("hourSymbol");
var minuteSymbol = new NonTerminal("minuteSymbol");
var hourValue = new NonTerminal("hourValue", typeof(HourValueNode));
var minuteValue = new NonTerminal("minuteValue", typeof(MinuteValueNode));
var colonTimeValue = new NonTerminal("colonTimeValue", typeof(ColonTimeValueNode));
var hourMinuteTimeValue = new NonTerminal("hourMinuteTimeValue", typeof(HourMinuteTimeValueNode));
var binExpr = new NonTerminal("binExpr", typeof(BinaryOperationNode));
var binOperator = new NonTerminal("binOperator");
var unExpr = new NonTerminal("unExpr", typeof(UnaryOperationNode));
var unOperator = new NonTerminal("unOperator");
var timeValue = new NonTerminal("timeValue");
var expression = new NonTerminal("expression", typeof(ExpressionNode));
var timePartSeparatorSymbol = new NonTerminal("timePartSeparatorSymbol");
Then the rules are defined on the non-terminals, declaring the pattern that terminals and other non-terminals are expected.
hourSymbol.Rule = HOUR_SINGLE | HOUR_SHORT | HOUR_LONG | HOURS_SHORT | HOURS_LONG;
hourValue.Rule = number + hourSymbol;
minuteSymbol.Rule = MINUTE_SINGLE | MINUTE_SHORT | MINUTE_LONG | MINUTES_SHORT | MINUTES_LONG;
minuteValue.Rule = number + minuteSymbol;
colonTimeValue.Rule = number + COLON + number;
hourMinuteTimeValue.Rule = hourValue + minuteValue;
timeValue.Rule = hourValue | minuteValue | colonTimeValue | hourMinuteTimeValue;
expression.Rule = timeValue | binExpr | unExpr;
binOperator.Rule = PLUS | MINUS;
binExpr.Rule = expression + binOperator + expression;
unOperator.Rule = PLUS | MINUS;
unExpr.Rule = binOperator + timeValue;
In the non-terminals section, you’ll notice that some of the definitions include the types of some classes. This is part of the interpreter framework that allows you to define custom nodes in the Abstract Syntax Tree. It all works using the visitor pattern. Here’s an example of one of the classes,
public class HourMinuteTimeValueNode : AstNode
private AstNode HoursNode;
private AstNode MinutesNode;
public override void Init(Irony.Ast.AstContext context, Irony.Parsing.ParseTreeNode treeNode)
HoursNode = AddChild("Hours", treeNode.ChildNodes);
MinutesNode = AddChild("Minutes", treeNode.ChildNodes);
protected override object DoEvaluate(Irony.Interpreter.ScriptThread thread)
return (int)HoursNode.Evaluate(thread) + (int)MinutesNode.Evaluate(thread);
Init method is called to transform the
ParseTree nodes (in the treeNode.ChildNodes collection) into a sub-tree in the AST. When the interpreter is run,
DoEvaluate executes the operations that allow you to ‘run’ your parsed input. On this node I’m simply combining the hours and minutes parts to return an integer value representing the combined whole number of minutes.
There are several general purpose helper AST node types included in Irony, such as
BinaryOperationNode. Using this class, for instance, I didn’t need to implement any addition/subtraction logic – it magically just worked. The only custom node classes I used were to convert each different form of acceptable duration expression into an integer value of minutes.
With the grammar and custom AST nodes written, the only thing left to do is use it.
First, the grammar is ‘compiled’:
LanguageData language = new LanguageData(_grammar);
Parser parser = new Parser(language);
Next, the parser instance is fed the input string, and returns a
ParseTree parseTree = parser.Parse(expression);
If you don’t want to interpret, then you could stop at this point. I want to get a single value from the input expression, though, so:
ScriptApp app = new ScriptApp(language);
ScriptThread thread = new ScriptThread(app);
int minutes = (int)app.Evaluate(parseTree);
Et voilà! Note that you don’t always have to return a value – if you’re writing your own executable language, for example, there could very well be no returned result with all I/O, calculations etc. handled in your custom AST nodes.
This code is provided with blessings from my boss. If you want to show your gratitude, and think your organisation could use a system to organise your files, then please check out the Freestyle Partners Digital Asset Management (DAM) system.
Earlier this year I went on a 5 week journey to Antarctica, via South Georgia and the Falkland Islands (and Ascension Island, sort of). It’s taken nearly 2 months, but I’ve finally finished processing my photos and managed to upload a very small selection of them for all to see. In all I took over 11,000 photos and about 60GB of video which I’ve yet to start editing.
There’s lots to tell about the adventure, and who knows – I might even write some posts about it.
Back when I lived with my parents, I had a great time building various projects, which even won me a car. I put a lot of hard work and money into building a rack from scratch, creating a whole-house-audio system from various parts along with the software, and wiring up the house for networking.
Well, the time has come to dismantle many of my projects. My parents are itching to put my old room back to use, and I need to gather as much cash as I can for an exciting excursion to the other side of the world next year. I have felt some tears forming, but I just remind myself what it is in aid of and all of the unknown projects that are yet to come.
I have started listing much of the equipment on eBay. If you’re interested in home automation, want to build your own rack, or you have a professional need for some of the AV equipment then please take a look and bid on things that take your fancy.
More equipment will be added tomorrow – mostly the PCs that I no longer use. This includes 2 rackmounts and an old gaming rig.
Not long before Christmas, as part of a new AV system, I installed an Acer Aspire Revo as a frontend for my now well established MythTV setup. This works great, but it did set me back a fair amount.
The SqueezeBox series of devices from Logitech has got to be one of the best media streamer ranges out there. Not long after I moved into my flat I bought a SqueezeBox Boom and it is awesome. Fantastic audio quality with an almost impossible amount of bass from a small single-unit stereo now sat next to my bed.
The downside to the SqueezeBox devices is that the quality comes at a price, one which is impossible to justify at the moment. However, it happened that the following year O2 were having a fire sale of their Joggler device. I snapped one up for the bargain amount of £50 with the intention of using it as a home automation controller.
Well, the automation dream also comes at an even less justifiable cost and so the Joggler has been sitting idle in a drawer waiting for a project to bring it back to life. Thanks to the UKHA mailing list it now has a purpose. My Joggler has been reborn as a budget SqueezePlayer having followed some really easy steps.
With it connected to my surround amp, I can now stream music from my existing SqueezeBox Server and even control it remotely with a web browser. One less bit of idle kit, one new feature, and at £100 less than it would otherwise cost.
The Joggler is a popular device for customising, and there are Ubuntu builds available for it (rather than the onboard O2 OS). If you want to play with one, they are no longer available for sale from O2, so you will need to look on eBay or similar.
Yep, after far too much procrastination, the successor to my first WordPress theme is here.
It has taken a week of evenings to convert it from a layered Photoshop design into HTML and CSS. The previous version of KillerLight was based on the code of the K2 theme, and ended up being heavily customised. This time around, version 2 is based upon Thematic and very little in the way of HTML changes has been made – just a few more wrapping divs here and there. This should lead to a very robust theme.
Gone is the animated header background, at least in this version. It caused far too many complaints and confusion, although I still think the idea is sound provided the animation is subtle.
I’m going to submit the theme to WordPress.org’s themes directory soon, and once approved (fingers crossed) it should be easy for people to find and install into their WordPress v3 site.
More information can be found on the Idea Cog website, where information about the theme is being hosted.
EDIT: Until the theme is available on wordpress.org, you can find a download link on this post.