CCAllocator

Maintains a list of available MIDI controllers on a given device and returns an available one when asked. Certain controls may be designated as reserved controls (such as pitch bend and modulation wheel); these will not be allocated until you specifically ask for them by name.

In my MIDI classes, each MIDI channel upon creation initializes its own CCAllocator. In other MIDI classes, if you ask for a MIDI controller (such as in VoicerMIDISocket-addControl) but do not specify a controller number, it will go to the channel's CCAllocator for the next available controller.

If you aren't using my MIDI classes, you can still create your own instances and ask for controllers on your own.

-hjh, jamshark70@dewdrop-world.net

*new(controlNums, controlTypes, reservedTypes)

Creates a new instance.

controlNums: an array of all the controller numbers on your device. A default setting is provided in the init method, which can be customized for your needs.

controlTypes: a list of the types to be associated with these controller numbers. For example, the Novation ReMOTE 25 has knobs, encoders, sliders, pitch bend, a modulation wheel, and a touch sensitive pad. If several controllers in a row have the same type, you can specify the first one and give nil for the rest of them.

reservedTypes: the types in the control types list that should be treated as reserved. If a control is reserved, there should be only one of that type in control types.

For the ReMOTE 25, my default settings are:

controlNums = #[5, 80, 82, 83, 85, 104, 106, 105,

70, 40, 41, 72, 44, 43, 107, 102,

108, 109, 110, 111, 114, 115, 116, 117, 1, \wheel];

controlTypes = #[\knob, nil, nil, nil, nil, nil, nil, nil,

\encoder, nil, nil, nil, nil, nil, nil, nil,

\slider, nil, nil, nil, nil, nil, nil, nil, \mw, \pb];

reservedTypes = #[\mw, \pb];

Giving the pitch bend a control number of \wheel means that this control will be displayed in a voicer GUI as "pb wheel."

In normal usage, you should define allocator prototypes to be associated with MIDI sources. Each MIDI device may have a different prototype. The definitions should go into MIDIPort's onInitAll function. See the MIDIPort help file for details.

To create a MIDI channel that overrides the default CCAllocator for the port, you must explicitly create the channel before putting MIDI responders into it.

// port 0, channel 1 will now use a custom CCAllocator

// other ports/channels will still use the default

MIDIChannel([0, 1], nil, (50..60), [\newtest]);

// uses the MIDIChannel created above

// no need to save the MIDIChannel in a variable (MIDIPort does that for you)

b = BasicMIDIControl(1, nil, { 0 });

b.ccnum.dump;

Instance of CControl { (04E6B170, gc=40, fmt=00, flg=00, set=02)

instance variables [4]

ccnum : Integer 50 // this is the first ccnum specified when the MIDIChannel was created

type : Symbol 'newtest'

buttonnum : nil

index : Integer 0

}

get(type, name)

Get an available controller of the given type (or reserved name). The object returned will be of the type CControl, which contains the controller number as ccnum and the type as type. A CControl also responds to .value with the controller number as an integer (or, if it's a symbol, it's assumed to be the pitch bend wheel). Therefore, your classes can also accept an integer control number as well as CControls by valuing the argument.

free(ccnum)

Locate a MIDI controller that's in use by number and release it for future use. ccnum may be either an integer or a CControl.

freeAll

Re-initializes the allocator.

Example (with my default settings above; output is shown):

a = CCAllocator.new;

a CCAllocator

b = Array.fill(4, { a.get(\encoder) }); // get 4 encoders

[ a CControl, a CControl, a CControl, a CControl ]

b.do({ arg cc; cc.postln });

[ 70, encoder ]

[ 40, encoder ]

[ 41, encoder ]

[ 72, encoder ]

[ a CControl, a CControl, a CControl, a CControl ]

c = Array.fill(25, { a.get }); // get 25 of any type

[ a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CC...etc...

c.do({ arg cc; cc.postln });

[ 5, knob ]

[ 80, knob ]

[ 82, knob ]

[ 83, knob ]

[ 85, knob ]

[ 104, knob ]

[ 106, knob ]

[ 105, knob ]

[ 44, encoder ] // 4 encoders are gone, so they don't show up here

[ 43, encoder ]

[ 107, encoder ]

[ 102, encoder ]

[ 108, slider ]

[ 109, slider ]

[ 110, slider ]

[ 111, slider ]

[ 114, slider ]

[ 115, slider ]

[ 116, slider ]

[ 117, slider ]

nil // there weren't enough controls, so you get nil when you run out

nil

nil

nil

nil

[ a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CControl, a CC...etc...

d = a.get(\mw); d // getting a reserved type gives you the right controller number

[ 1, mw ]

e = a.get(name: \pb) // getting a reserved name

[ wheel, pb ]

a.free(110);

a CCAllocator

a.get;

[ 110, slider ]

a.freeAll;

a CCAllocator

a.get;

[ 5, knob ]