sc multiple apps

during a recent gig i suddenly felt a need to crossfade between two songs/patches (strange as it seems). as i'd coded my music using RedMst and it in turn makes heavy use of class methods, starting up a new song would disrupt the current music playing (tempo, current index, etc). i also had some master effects running on bus 0 and 1 (ReplaceOut) that belonged to a particular song and i didn't want those for the new one.

so how to isolate patches? i got the idea of running two copies of the supercollider application at the same time. they'd be identical, use the same soundcard and share class library. having two apps running would also be good for safety reasons. if one crashed i could keep on playing with the other. it turned out to be quite easy. the trick is to use the internal server and find a way to visually tell the two applications apart.
dan stowell helped me by implementing thisProcess.pid and i got some great tips from cylob. he used a similar setup for his live performances. here's my take on it... (you'll need a recent version of supercollider (>30oct '08)

1. put the code below into your startup.rtf file. it'll make the secondary app green and shift windows to the right - this only so one can tell them apart.
2. go to supercollider application folder and duplicate the program file (cmd+d). rename the copy "SuperCollider (green)". remember to duplicate again when you've updated your main sc app.
3. important: from now on use internal as the default server in your code. localhost will crosstalk when running multiple apps.

so with a simple duplicate command and minimal change to sc itself (just for cosmetic difference), i can now crossfade my songs.

//put this in startup.rtf...

//--detect secondary application and colour it green
var p, l;
~green= false;
p= Pipe("ps -xw | grep 'SuperCollider (green)' | grep -v grep | awk '{print $1}'", "r");
l= p.getLine;
if(l.notNil and:{l.asInteger==thisProcess.pid}, {~green= true});
p.close;

if(~green.not, {        //for main app (red)
        GUI.skins.put(\redFrik, (
                background: Color.red.alpha_(0.8),
                foreground: Color.black,
                selection: Color.grey,
                unfocus: 0.9,
                fontSpecs: ["Monaco", 9],
                offset: Point(0, 0)
        ));
}, {                    //for secondary app (green)
        GUI.skins.put(\redFrik, (
                background: Color.green.alpha_(0.8),
                foreground: Color.black,
                selection: Color.grey,
                unfocus: 0.9,
                fontSpecs: ["Monaco", 9],
                offset: Point(455, 0)
        ));
        Document.listener.background_(GUI.skins.redFrik.background.blend(Color.grey(0.9), 0.9));
        Document.initAction_{|doc| doc.background_(GUI.skins.redFrik.background.blend(Color.grey(0.9), 0.9))};
        Server.set.do{|x|
                x.window.bounds= x.window.bounds.moveBy(GUI.skins.redFrik.offset.x, 0);
                x.window.view.background_(GUI.skins.redFrik.background.blend(Color.grey(0.9), 0.9));
        };

});
Document.listener.bounds_(Rect(GUI.skins.redFrik.offset.x, GUI.window.screenBounds.height-580, 450, 580));