Dronetronics VJ Set, Taipei.

Here is a pic from my first VJ outing, for Dronetronics, in Taipei, back in December. IMG_0340_4-cropped Lars from Dronetronics got in contact 2 hours before the gig, to see if I had anything for a gig at a studio not far away.   I quickly repurposed my smilies test vis (see previous post) to be suitable for Drone Music.
  • Removing the smilies
  • Added functionality to change the graphic when a button was pressed
  • Removed the OSC control - due to how sensitive the APC Mini sliders were, it looked quite amateurish (as they pick up every jolt as you move).
  • Put in new graphics (here, I only had time to find some black and white ideograms of a skull and a 'warning') sign plus an "X" I drew in the two minutes before the gig.
  • Added an option for graphics to wrap around (in the taxi on the way to the gig).
In the end, it was a great learning experience VJing for the first time, from the tech through to the setup. With thanks to Dronetronics and the studio crew at UUMouth Studio.   Sourcecode for the vis will go up shortly.

Adding files to the django auto refresh

Django runserver and the app django-autotest are both good as they'll restart when modifcations are made to files in the app they will restart, however not *all* files will trigger a restart. Wanting to get some other files noticed, I added some in the __init__.py of my app, so it looked like this:
try:
    from django.conf import settings

    if settings.DEBUG:
        import forms, util, tests
except:
    pass
This seemed to be working fine until I swapped to postgres and tried to do syncdb .. and reset, uh oh ! Postgres said (names changed to protect the innocent):
2012-05-10 09:47:57 BST STATEMENT:
                    SELECT c.relname
                    FROM pg_catalog.pg_class c
                    LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
                    WHERE c.relkind IN ('r', 'v', '')
                        AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
                        AND pg_catalog.pg_table_is_visible(c.oid)
2012-05-10 09:47:57 BST LOG:  could not receive data from client: Connection reset by peer
2012-05-10 09:47:57 BST LOG:  unexpected EOF on client connection
2012-05-10 09:49:14 BST ERROR:  relation "sandwich_maker_filling" does not exist at character 72
2012-05-10 09:49:14 BST STATEMENT:  SELECT "sandwich_maker_filling"."id", "sandwich_maker_filling"."name" FROM "sandwich_maker_filling"
2012-05-10 09:49:14 BST ERROR:  current transaction is aborted, commands ignored until end of transaction block
And django wasn't too happy either:
Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/core/management/base.py", line 196, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/core/management/base.py", line 371, in handle
    return self.handle_noargs(**options)
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/core/management/commands/syncdb.py", line 60, in handle_noargs
    tables = connection.introspection.table_names()
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/db/backends/__init__.py", line 896, in table_names
    return self.get_table_list(cursor)
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/introspection.py", line 33, in get_table_list
    AND pg_catalog.pg_table_is_visible(c.oid)""")
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/db/backends/util.py", line 40, in execute
    return self.cursor.execute(sql, params)
  File "/home/stu/.virtualenvs/the_app/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 52, in execute
    return self.cursor.execute(query, args)
django.db.utils.DatabaseError: current transaction is aborted, commands ignored until end of transaction block
In the end the solution was simple, just check for the args where we need the refresh to happen automatically:
## Automatically reload when forms or tests changed
try:
    from django.conf import settings

    if settings.DEBUG:
        import sys
        if sys.argv == ['manage.py', 'autotest'] or sys.argv == ['manage.py', 'runserver']:
                # Need to check params as otherwise this can break syncdb, reset and
                # Friends !!
                import forms, util, tests
except:
    pass
Hopefully this will be helpful to somebody with a similar error or that wants autotest or runserver to see more files.   This article was particularly helpful in debugging this:  debugging django syncdb

Simple python spectrograph with shoebot

Seeing"Realtime FFT Graph of Audio WAV File or Microphone Input with Python..."  on python.reddit.com reminded me of one I'd built in python with shoebot. While it works OK, I feel like I'm missing a higher level audio library (especially having seen Minim, for C++ and Java). To run it in shoebot:
sbot -w audiobot.bot

audiobot.bot

# Major library imports
import atexit
import pyaudio
from numpy import zeros, short, fromstring, array
from numpy.fft import fft

NUM_SAMPLES = 512
SAMPLING_RATE = 11025

def setup():
    size(350, 260)
    speed(SAMPLING_RATE / NUM_SAMPLES)

_stream = None

def read_fft():
    global _stream
    pa = None

    def cleanup_audio():
        if _stream:
            _stream.stop_stream()
            _stream.close()
        pa.terminate()

    if _stream is None:
        pa = pyaudio.PyAudio()
        _stream = pa.open(format=pyaudio.paInt16, channels=1,
                           rate=SAMPLING_RATE,
                           input=True, frames_per_buffer=NUM_SAMPLES)
        atexit.register(cleanup_audio)

    audio_data  = fromstring(_stream.read(NUM_SAMPLES), dtype=short)
    normalized_data = audio_data / 32768.0

    return fft(normalized_data)[1:1+NUM_SAMPLES/2]

def flatten_fft(scale = 1.0):
    """
    Produces a nicer graph, I'm not sure if this is correct
    """
    for i, v in enumerate(read_fft()):
        yield scale * (i * v) / NUM_SAMPLES

def triple(audio):
    '''return bass/mid/treble'''
    c = audio.copy()
    c.resize(3, 255 / 3)
    return c

def draw():
    '''Draw 3 different colour graphs'''
    global NUM_SAMPLES
    audio = array(list(flatten_fft(scale = 80)))
    freqs = len(audio)
    bass, mid, treble = triple(audio)

    colours = (0.5, 1.0, 0.5), (1, 1, 0), (1, 0.2, 0.5)

    fill(0, 0, 1)
    rect(0, 0, WIDTH, 400)
    translate(50, 200)

    for spectrum, col in zip((bass, mid, treble), colours):
        fill(col)
        for i, s in enumerate(spectrum):
            rect(i, 0, 1, -abs(s))
        else:
            translate(i, 0)

    audio = array(list(flatten_fft(scale = 80)))

A simple cairo draw queue using closures

Often it's useful to be able to store up drawing commands so you can use them later somewhere else (or even just pass them to another thread). This is a simple drawing model, implemented in cairo, hopefully somebody will find it useful. Queue
class DrawQueue:
    '''
    A list of draw commands, stored as callables that, are
    passed a set of parameters to draw on from the canvas
    implementation.
    '''
    def __init__(self, render_callables = None):
        self.render_callables = render_callables or deque()

    def append(self, render_callable):
        '''
        Add a render callable to the queue
        '''
        self.render_callables.append(render_callable)

    def render(self, cairo_ctx):
        '''
        Call all the render callables with cairo_ctx
        '''
        for render_callable in self.render_callables:
            render_callable(cairo_ctx)
The queue just accepts callables (any old function), and calls them when you call render, passing them a cairo context you pass in. To get useful functions you can call closure functions like these:
def paint_closure():
    def paint(ctx):
        ctx.paint()
    return paint

def fill_closure():
    def fill(ctx):
        ctx.fill()
    return fill

def set_source_rgb_closure(r, g, b):
    def set_source_rgb(ctx):
        ctx.set_source_rgb(r, g, b)
    return set_source_rgb

def moveto_closure(x, y):
    def moveto(ctx):
        ctx.move_to(x, y)
    return moveto

def rectangle_closure(x, y, w, h):
    def rectangle(ctx):
        ctx.rectangle(x, y, w, h)
    return rectangle
Adding commands to the queue is simple:
dq = DrawQueue()
dq.append(set_source_rgb_closure(1, 1, 1))
dq.append(paint_closure())
dq.append(moveto_closure(10, 0))
dq.append(rectangle_closure(0, 0, 20, 20))
dq.append(set_source_rgb_closure(0, 0, 0))
dq.append(fill_closure())
This is the same drawing model I'm using in my branch of shoebot, I'm hoping to expand it to be multithreaded; while a foreground thread adds commands a background thread is executing them. Here it is all put together in a simple example to draw a black rectangle
from collections import deque
import cairo

class DrawQueue:
    '''
    A list of draw commands, stored as callables that, are
    passed a set of parameters to draw on from the canvas
    implementation.
    '''
    def __init__(self, render_callables = None):
        self.render_callables = render_callables or deque()

    def append(self, render_callable):
        '''
        Add a render callable to the queue
        '''
        self.render_callables.append(render_callable)

    def render(self, cairo_ctx):
        '''
        Call all the render callables with cairo_ctx
        '''
        for render_callable in self.render_callables:
            render_callable(cairo_ctx)

#### drawing closures
def paint_closure():
    def paint(ctx):
        ctx.paint()
    return paint

def fill_closure():
    def fill(ctx):
        ctx.fill()
    return fill

def set_source_rgb_closure(r, g, b):
    def set_source_rgb(ctx):
        ctx.set_source_rgb(r, g, b)
    return set_source_rgb

def moveto_closure(x, y):
    def moveto(ctx):
        ctx.move_to(x, y)
    return moveto

def rectangle_closure(x, y, w, h):
    def rectangle(ctx):
        ctx.rectangle(x, y, w, h)
    return rectangle

#### /drawing closures

dq = DrawQueue()

# Add some commands to the drawing queue
dq.append(set_source_rgb_closure(1, 1, 1))
dq.append(paint_closure())
dq.append(moveto_closure(10, 0))
dq.append(rectangle_closure(0, 0, 20, 20))
dq.append(set_source_rgb_closure(0, 0, 0))
dq.append(fill_closure())

# Create a surface and context
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 200, 200)
ctx = cairo.Context(surface)

# run defered rendering
dq.render(ctx)

surface.write_to_png('output.png')

Using Cairo to generate SVG in Django

Cairo is a 2D vector graphics api used by Firefox, Gtk and other desktop projects. I'm going to show here that it can also be used to generate web content, using Django. I'm going to port two examples from the Michael Urmans Cairo Tutorial for PyGTK Programmers. To understand the cairo and it's drawing model I'd recommend his his Cairo Tutorial for Python Programmers.
Note: In this example I'll be generating SVGs...  as I.E. (as of 2010) does not support them, you might want to generate PNG or PDF - if you need to do this with cairo, look for one of the many cairo tutorials on the web.
The example django project can be downloaded at the end of the article. (more…)

Some useful scripts for windows.

Stoyan of PHPIED.com has found the joy using javascript for scripting in the OS... I've put up a few scripts I find useful in windows (download at the end of the article):
  • addpath.js - Add a path to the registry path.
  • dt.cmd - Change to desktop folder.
  • e.cmd - Open explorer in current or specified folder.
  • regpath.js  - Output the path stored in the registry.
  • updateenvironment.js - Updates running apps with any changed settings in the registry.
And a couple that use python and pywin32:
  • ccwd.py - Copy the current working directory to the clipboard
  • cpath.py - Copy the current path to the clipboard
All of have acompanying batch files to run them, I generally have everything in a folder c:\usr\cmd, but they should work from anywhere in the path. Download  cmd.zip

Using Java2Python to port a JavaCairo tutorial

I recently came across Java2Python.  As I'm interested in Cairo I thought it would be interesting to try porting one of the example tutorials from ZetCode. I'll run through the steps involved in porting then try and reach some conclusions at the end :).

1. Get setup

This is easiest in Linux, I'm running Ubuntu (in vmware), and installed
antlr 2.x
python2.5.x
sun java6
pygtk
java-gnome
You can install them like this:
# sudo apt-get install antlr python2.5 sun-java6-bin libjava-gnome-java
Then install Python2Java with easy_install
# sudo easy_install-2.5 java2python
To test if it's working run j2py -i.  It should complain there is no file:
# j2py -i
Usage: j2py [options]

j2py: error: -i option requires an argument
If you get any other errors your missing some packages.

2. Get the Java Code from the Simple Example.

Save the 'simple.java' example as 'GSimple.java' If java-gnome is running ok, compiling and running it you should see a window:
# javac GSimple.java
# java GSimple
gsimple
Now we'll run through the code, it's important to understand what it does before we port it... (more…)