+ Patch { playToMixer { arg m, atTime = 0; this.play(m.synthgroup, atTime, m.inbus); } } + Nil { draggedIntoMixerGUI { |gui| gui.mixer = nil; } asMixerChannelGUI { |board| ^MixerChannelGUI(nil, board) } } // needed to allow collections as mixer arguments in MixingBoard-new + Collection { asMixerChannelGUI { |board| ^this.collect({ |mixer| MixerChannelGUI(mixer, board) }) } } + MixerChannel { draggedIntoMixerGUI { |gui| gui.mixer = this; } } + Voicer { // if the voicer's target is a MC, assign it to the gui draggedIntoMixerGUI { |gui| var mc; (mc = bus.tryPerform(\asMixer)).notNil.if({ gui.mixer_(mc); gui.refresh; }); } } + VoicerProxy { // change the voicer's target to the mixer in this gui // does not affect currently playing notes // if the gui is empty, the drag-n-drop will be ignored draggedIntoMixerGUI { |gui| voicer.notNil.if({ voicer.draggedIntoMixerGUI(gui) }); } } // I have to override this core method. Sorry. // If I don't, MixerChannelReconstructor doesn't work. + Server { initTree { // nodeAllocator = NodeIDAllocator(clientID); this.sendMsg("/g_new", 1); tree.value(this); } boot { arg startAliveThread=true; var resp; if (serverRunning, { "server already running".inform; ^this }); if (serverBooting, { "server already booting".inform; ^this }); if (isLocal.not, { "can't boot a remote server".inform; ^this }); serverBooting = true; if(startAliveThread, { this.startAliveThread }); this.newAllocators; // Buffer info support // allow room for protected scope and record buffers bufferArray = Array.newClear(options.numBuffers + 2); this.doWhenBooted({ if(notified, { this.notify; "notification is on".inform; }, { "notification is off".inform; }); serverBooting = false; nodeAllocator = NodeIDAllocator(clientID); this.initTree; }); this.bootServerApp; } }