TDAbletonCompBaseExt Extension
The TDAbletonCompBaseExt
extension is a base class for TDAbleton Components. It provides a structure and utilities for communicating with the TouchDesigner Python Remote Script in Ableton Live.
Writing custom classes derived from TDAbletonCompBaseExt
requires intermediate knowledge of Python, or at least object oriented programming. If you're not familiar with inheritance in Python, there are many tutorials online, this one for example.
See also: TDAbleton, TDAbleton System Components, Creating Custom TDAbleton Components
Glossaryedit
There are a few glossary items worth noting before diving in to TDAbletonCompBaseExt
.
LOM
: The abbreviationLOM
is often used to refer to Ableton's Live Object Model.lomPar
: a TDAbleton custom parameter used to navigate the Live Object Model. Includes:Track
,Device
,Chain1
,Chain1device
,Chain2
,Chain2device
,Chain3
,Chain3device
,Chain4
,Chain4device
,Parameter
song
: In code, an Ableton Live "Set" is referred to as asong
. This is true not only in TDAbleton, but also in Ableton's Live Object Model.aPar
: An Ableton Live parameter. Because both TouchDesigner and the Live Object Model have a concept of "parameters", TouchDesigner usesaPar
to distinguish the two. There are a few exceptions, such as the "Parameter" custom parameter on TDAbleton Components. (See how that's already a bit confusing?)
Promoted vs. Non-Promoted Membersedit
TDAbletonCompBaseExt
promotes (capitalizes) members that may be generally useful to things outside of the TDAbleton Component. Non-promoted members can always be accessed through the extension, e.g. op('abletonComp').ext.TDAbletonCompBaseExt.startConnection()
.
Attributesedit
Not all attributes of TDAbletonCompBaseExt
will be listed here, only the ones meant to be used in customization. Expert users can explore the TDAbletonCompBaseExt
code inside the abletonBase
Component for a deeper look.
Common Methods To Overrideedit
The following methods will be commonly overridden by custom TDAbleton extensions:
setupListeners()
edit
- Set up all listeners used by this Component. Will be called automatically at appropriate times by the TDAbleton system. You will generally want to call the base version at the beginning of your overriding method.
- This is often the only method you will need to override when creating a custom TDAbleton extension. See: Setting Up Listeners.
onAbletonNotify(info)
edit
- Callback from
tdAbleton
master component with important events from Ableton Live. - Override this to create custom reactions to TDAbleton system events. In general, you will want to call the base version of
onAbletonNotify
as well. For an example, see theabletonMIDI
Component's custom extension.info
: dictionary containingnotificationType
key and any other necessary info. CommonnotificationType
s:
- reinit:
tdAbleton
's extension was reinitialized. - connected: reconnected to Ableton.
- disconnected: disconnected from Ableton.
- songInfo: the
SongInfo
object has been changed. - lomNameChanged: a LOM object's name has been changed in Ableton. The
infoDict
contains the newSongInfo
entry for the changed object. - locatorTimeChanged: a locator (aka cue point) time has been changed in Ableton. The
infoDict
contains the locator's updatedSongInfo
entry.
- reinit:
updateLOMPar(lomPar, lomInfo) → currentMenuLabel
edit
- Updates a Live Object Model parameter and returns the resulting menu label (object name) for
lomPar
. - Override this to filter options available in LOM Parameters. Filter options by creating a new OrderedDict with only the options you want from
lomInfo
included. For an example, see theabletonMIDI
Component's custom extension.lomPar
- the parameter being updated.lomInfo
- the associated dictionary of available options.
onOutputsChannelChange(channel, value)
edit
- An OSC output channel has changed
- Override this to react to changes in incoming values from Ableton Live.
channel
- the name of the channel that changed.value
- the new value of that channel.
Commonly Used Methodsedit
The following are the methods used most often in customizing TDAbleton extensions:
LomParInfo(lomParName) → infoDict or ...
edit
- Return infoDict for the LOM object selected in the given par, or a value (which evaluates to False) if there is a problem. The infoDict contains:
'lomInfo'
:SongInfo
entry for LOM object selected in the named parameter.'lomExpression'
: TDA Python expression to object'returnAddress'
: Standard address for OSC replies from TDA
- The other possible return values for
LomParInfo
are:None
: no such parameter0
: parameter is disabledFalse
: not-found object is selected in menu{}
: 'None' is selected in menu
lomParName
- name of the parameter (e.g.'Track'
)
addListener(listener, outPar=None, parMin=None, parMax=None, useBaseOSC=True)
edit
- Add a listener. See: Setting Up Listeners. You will generally want to call the base version at the beginning of your overriding method.
listener
-(lomExpression, property, returnAddress, id, extra=None)
. Theextra
element is an optional string with special instructions. If it is 'noinit', the initial value send will be skipped. This is useful for avoiding CHOP clutter when listening to a large number of channels.outPar
- outgoing parameter for setting listener objectparMir
- outPar minimum valueparMax
- outPar maximum valueuseBaseOSC
- if True, set up listener in built-in oscin. Set to False if you want to build your own oscin.
Utility Methodsedit
The following methods are often useful when writing custom TDAbleton extensions:
clearOSCIn()
edit
- Clear the main incoming data CHOP.
requestRemoteData(code, callback, asRepr=False)
edit
- Request data from Ableton Python Remote Script shell by sending an evaluatable Python code string. Because this code must be sent and replied to via OSC, the return value must be reacted to in a Python callback. Tip: Works the same as if you had entered
code
in the Ableton Console, which is a good place to test your commands.code
: evaluatable Python codecallback
: the callback to call with return data as argumentasRepr
: return data will be formatted by repr()
runRemoteCode(code)
edit
- Runs
code
as Python code inside the TouchDesigner Remote Script (in Ableton). Tip: Works the same as if you had enteredcode
in the Ableton Console, which is a good place to test your commands.code
: executable Python code
edit
- Return a
lomPar
menu label. This is useful because thelomPar
menu labels correspond to LOM object names in Ableton.lomPar
: the parameter to examine
setMenuLabel(lomPar, label)
edit
- Set a
lomPar
to the index with the given menu label.lomPar
: the parameter to setlabel
: the label to set menu to
validChannelName(name) → validName
edit
- Return a valid CHOP Channel name based on a string. This is useful for setting up OSC return addresses that will be received by an OSC In CHOP.
name
: the string to be converted into a valid channel name
Membersedit
The following are members of note when writing custom TDAbleton extensions:
Connected
edit
- (Read Only)True if this Component is connected to Ableton.
OutCHOP
edit
- The Out CHOP that contains the default channel info for the Component. Inside the network, this is
out1
. This member is a shortcut for setting up select CHOPs that use this Component's output.
OSCInCHOP
edit
- The OSC In CHOP used to receive listener channels. In cases with a large number of listeners, efficiency may be increased by setting the
oscaddressscope
parameter to use wildcards instead of multiple specific scopes, which is the default. You can do this by overriding thesetupListeners
and/oraddListener
methods.
OSCInDAT
edit
- The OSC In DAT used to receive other listener information. In cases with a large number of listeners, efficiency may be increased by setting the
addscope
parameter to use wildcards instead of multiple specific scopes, which is the default. You can do this by overriding thesetupListeners
and/oraddListener
methods.
FinalChainPar
edit
- The name of the last LOM Chain parameter with a valid chain selected. This can be 'Track', because an Ableton track is, for all intents and purposes, a chain with extra features.
FinalDevicePar
edit
- The name of the last LOM Device parameter with a valid device selected. This can be 'Track'.
SongInfo
edit
- The
SongInfo
object is a deeply nested OrderedDict containing all available information about the current Ableton Live Set. Note that theSongInfo
object is keyed by Ableton names, which is why TDAbleton does not deal with identically named tracks or identically named devices on the same track. The SongInfo object should not be changed. Do not attempt to print the SongInfo object to the clipboard! It is large enough to cause TouchDesigner to hang for quite a while. If you want to look around in SongInfo, always print items'.keys()
instead of the entire item. For example, you can type this in the textport:
print(op.TDAbleton.SongInfo['scenes'].keys()
- The
SongInfo
object has the following structure:
"""
{
'name': '<song name as defined by TDA Master name>' or None,
'scenes': {
'<scene name>': { # scene info
'name': '<scene name>',
'tempo': scene tempo,
'index': '<scene index>',
'expression': '<LOM expression within parent>',
'ptr': LOM Pointer (not persistent across saves)
}
... all scenes
}
'cuePoints': {
'<cuePoint name>': { # cuePoint info
'name': '<cuePoint name>',
'time': cuePoint time,
'index': '<cuePoint index>',
'expression': '<LOM expression within parent>',
'ptr': LOM Pointer (not persistent across saves)
}
... all cuePoints
}
'tracks': {
'<track name>': { # track info
'name': '<track name>',
'index': track index (if applicable),
'expression': '<LOM expression within parent>',
'hasMIDIInput': True if track has MIDI input,
'hasMIDIOutput': True if track has MIDI output,
'ptr': LOM Pointer (not persistent across saves),
'parentInfo': info of object parent
'clipSlots': [
{ # clipSlot info
'index': <clip slot index>,
'expression': '<LOM expression within parent>',
'ptr': LOM Pointer (not persistent across saves),
'parentInfo': info of object parent',
'clip': {
'name': '<clip name>',
'filepath': '<clip file path>',
'ptr': LOM Pointer (not persistent across saves)
}
... all clipSlots
]
'devices': {
'<device name>': { # device info
'name': '<device name>',
'index': device index (if applicable),
'expression': '<LOM expression within parent>',
'ptr': LOM Pointer (not persistent across saves),
'parentInfo': info of object parent
'aPars': {
'<parameter name>': { # parameter info
'name': '<device name>',
'index': device index (if applicable),
'expression': '<LOM expression within parent>',
'ptr': LOM Pointer (not persistent across saves),
'min': minimum value,
'max': maximum value,
'value': value at time of dump
'parentInfo': info of object parent
},
... all parameters
},
'chainType': 'chains', 'drumpads', or ''
'chains': {
'<chain name>': {
# chain info (exactly like track info),
}
... all chains
}
},
... all devices
'# Mixer #': {
'name': '# MIXER #',
'index': None,
'expression': 'mixer_device',
'ptr': LOM Pointer (not persistent across saves),
'parentInfo': info of object parent
'aPars': {
'Crossfader': {
# parameter info (see above)
},
'Cue Volume': {
# parameter info (see above)
},
'Panning': {
# parameter info (see above)
},
'Track Activator': {
# parameter info (see above)
},
'Volume': {
# parameter info (see above)
},
'Send <send letter>' {
# parameter info (see above)
},
... all sends
},
'chainType: '',
'chains': {}
}
}
... all tracks
},
'Return: <return track name>': {
# track info (see above)
},
... all return tracks
'# Master Track #': {
# track info (see above)
}
}
}
"""