NamedControl
Overview
Controls on a Control Panel Group, and the module parameters they are mapped to, can be read and written from the Control Panel Group's script using the NamedControl interface.
On a standalone Control Panel Group, the same name also identifies the control to the Remote Control API. Turn on Remote Enable for the control, and external systems can reach it by name using the Cognio Control Protocol. Controls on a Managed Device are available to its script only.
NamedControl.
| Return Type | Return Range | Comment | |
|---|---|---|---|
NamedControl.GetText(name) |
String | String | Gets the Text of the Named Control |
NamedControl.SetText(name, value) |
Function | Sets the Text of the Named Control | |
NamedControl.GetValue(name) |
Float | User adjustable range | Gets the Value of the Named Control |
NamedControl.SetValue(name, value) |
Function | Sets the Value of the Named Control | |
NamedControl.GetPosition(name) |
Float | 0-1 | Gets the Position of the Named Control |
NamedControl.SetPosition(name, position) |
Function | 0-1 | Sets the Position of the Named Control |
NamedControl.ModifyValue(name, offset) |
Function | Modify the Value of the Named Control by an offset | |
NamedControl.GetChanged(name) |
Bool | Allows you to ask if a Control value has changed | |
NamedControl.SubscribeText(name) |
Function | Subscribe to a Control to get changes | |
NamedControl.EventHandler(name, value) |
Event Handler | Handle Changes from Subscribed Controls | |
NamedControl.GetProperty(name, propertyName) |
Varies | Gets the value of a Control's Property | |
NamedControl.SetProperty(name, propertyName, v1...vN) |
nil or String | Sets the value of a Control's Property |
Each function takes the control's name as its first argument. This is the control's Script/Remote Name, or Script Name for a control on a Managed Device, set in the Function tab of the Modifier Panel. See Name the Controls the Script Uses.
Give every control a unique name. If two controls share a name, the script uses the first one placed. Copying and pasting a control copies its name too, so rename the copy.
For more about these control properties, see Scripting and Remote Access.
The NamedControl API works differently for each control type. Control types are described in detail here.
NamedControl.GetText(name)
Returns a String of the Text displayed on the control with the provided name.
print(NamedControl.GetText("myLabel")) >> Ben
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
NamedControl.SetText(name, value)
Sets the Text displayed on the control with the provided name, using the provided text.
NamedControl.SetText("myLabel", "Ben") -- Set Label to Ben
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
Remember that for Labels and Video Stream, you will use the .SetText function, while for all others control types, you will use .SetValue or .SetPosition described below.
All controls can have their text set to a static value using the Properties Panel.
NamedControl.GetValue(name)
Returns a Float of the Value of the control with the provided name.
print(NamedControl.GetValue("myFader")) >> 40
The float value returned is the control's actual value, within the range specified by the Minimum and Maximum items in the Properties Panel for the control. Minimum refers to the value at minimum control position; similarly, Maximum is the value at the maximum control position. The values can be inverted if its desired to have the control operate backward. The Taper affects how Position maps to Value (see GetPosition / SetPosition), not a direct Value read or write.
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
NamedControl.SetValue(name, value)
Sets the Value of the control with the provided name, to the specified value.
NamedControl.SetValue("myFader", 50) >> Fader value set to 50
The value is the control's actual value, within the range specified by the Minimum and Maximum items in the Properties Panel for the control. Minimum refers to the value at minimum control position; similarly, Maximum is the value at the maximum control position. The values can be inverted if its desired to have the control operate backward. The Taper affects how Position maps to Value (see GetPosition / SetPosition), not a direct Value read or write.
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
Remember that while most controls use the .SetValue function, you will instead use .SetText for labels and Video Stream controls as described below above.
NamedControl.GetPosition(name)
Returns a Float of the Position of the control with the provided name.
print(NamedControl.GetPosition("myFader")) >> 0.4
The Position is a 0-1 representation of where the Value sits between the control's Minimum and Maximum (from the Properties Panel). It is a linear mapping — Position = (Value − Minimum) / (Maximum − Minimum) — always clamped to the 0-1 range, and inverted controls (Minimum greater than Maximum) are handled automatically.
Because the mapping is linear, Position does not apply the control's Taper. For controls that use a non-linear taper (such as a logarithmic fader), the Position will therefore not match the physical knob or fader location. Use Position when you want a value normalized across the control's range, and Value when you want the control's actual value.
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
NamedControl.SetPosition(name, position)
Sets the Position of the control with the provided name, to the specified value.
NamedControl.SetPosition("myFader", .5) >> Fader position set to .5
Again, the Position is a 0-1 value mapped linearly across the control's Minimum and Maximum — Value = (Position × (Maximum − Minimum)) + Minimum — and is clamped to the 0-1 range, with inverted controls handled automatically. Because the mapping is linear, it does not apply the control's Taper, so for controls with a non-linear taper (such as a logarithmic fader) a given Position will not correspond to the physical knob or fader location.
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
NamedControl.ModifyValue(name, offset)
Sometimes you may need to modify the value by an offset. This is great for up/down increment/decrement buttons.
NamedControl.ModifyValue("myFader", 1) >> Fader value increased by 1
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
NamedControl.GetChanged(name)
Returns a 1 if the Value or Text of the control with the provided name has changed since the last time it was checked, otherwise 0.
print(NamedControl.GetChanged("myFader")) >> 1
This is a convenient alternative to storing a control's previous value and comparing it on each pass (see Example 2 below). Checking GetChanged clears the changed flag, so each change is only reported once. A subsequent call will return 0 until the control changes again.
Note
GetChanged and SubscribeText share the same internal "changed" flag for a control, and checking either one clears it. Do not use both on the same control, or they will steal change notifications from each other — a change consumed by GetChanged will not trigger the EventHandler, and vice versa. Pick one mechanism per control.
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
NamedControl.SubscribeText(name)
To monitor a control for changes, you first need to subscribe to the control by Script Name.
NamedControl.SubscribeText("source") -- Subscribe to the control called "source"
Then you will need to used NamedControl.EventHandler(name, value) to handle the event when the control changes.
Note
Subscribed controls and GetChanged share the same internal "changed" flag for a control. If you also call GetChanged on a subscribed control, whichever runs first clears the flag and the other will miss the change. Do not use both mechanisms on the same control — pick one.
NamedControl.EventHandler(name, value)
This event handler handles changes to subscribed controls.
function MyHandler(controlName, value)
if controlName == "source" then -- Handle the particular source
NamedControl.SetValue("dest", value)
end
end
NamedControl.EventHandler = MyHandler -- Handler for NamedControl changes
NamedControl.SubscribeText("source") -- Subscribe to the "source"
This can also be done with an anonomous founction:
NamedControl.EventHandler = function (controlName, value) -- Handler for NamedControl changes
if controlName == "source" then -- Handle the particular source
NamedControl.SetValue("dest", value)
end
end
NamedControl.SubscribeText("source") -- Subscribe to the "source"
It's important to note that the value returned is a string. So if you need to test equality with a number (e.g. 0 or 1) you will need to convert it like this:
if (tonumber(value)) == 1.0 then
This works for the following control types:
| Control | Function |
|---|---|
| Fader | |
| Meter | |
| Knob | |
| Button | |
| Radio Button | |
| Toggle | |
| LED | |
| Readout | |
| Drop List | |
| Label |
NamedControl.GetProperty(name, propertyName)
Used to Get Properties from a Control or CPG. It has the following arguments and Return Values.
Arguments:
- name - the user assigned "script name" for a control or control panel group.
- property - a property from the table of properties supported.
Return Values:
- the value of the property: a number, Boolean, or string, as shown in the properties table. Properties with more than one value return all of them, in order. For example,
positionreturns the column and the row. - nil if the name or property isn't recognized.
local col, row = NamedControl.GetProperty("MyFader", "position")
print(col, row) >> 2 4
NamedControl.SetProperty(name, propertyName, v1...vN)
Used to Set Properties for a Control or CPG. It has the following arguments and Return Values.
Arguments:
- name - the user assigned "script name" for a control or control panel group.
- property - a property from the table of properties supported.
- value, one or more values as supported by the specified property.
Return Values:
- nil if the property was set.
- a String describing the error if the property wasn't set. The property stays unchanged.
| Error String | Cause |
|---|---|
Control Not Found |
No control or control panel group has the provided name. |
Unknown Property |
The property isn't supported, or is read-only. |
Argument Count |
Too few values were provided for the property. |
Wrong Type |
A value is the wrong type, such as a string where a number is required. |
Out of Range |
A value is outside the allowed range, or the control wouldn't fit on the control panel. |
Internal Error |
The property couldn't be set for another reason. |
local err = NamedControl.SetProperty("MyFader", "visible", false)
if err then
print("SetProperty failed: " .. err)
end
Control Properties
The following properties are supported by individual controls in a control panel group when using NamedControl.GetProperty(name, propertyName) or NamedControl.SetProperty(name, propertyName, v1...vN).
| Property | Read-only | Value(s) | Possible Errors |
|---|---|---|---|
| col | No | int/double - Zero-based column of the control on the control panel. Double is truncated to integer, must entirely fit on control panel. | Argument Count, Out of Range, Wrong Type |
| row | No | int/double - Zero-based row of the control on the control panel. Double is truncated to integer, must entirely fit on control panel. | Argument Count, Out of Range, Wrong Type |
| cols | No | int/double - Width of the control, in columns. Double is truncated to integer, must entirely fit on control panel. | Argument Count, Out of Range, Wrong Type |
| rows | No | int/double - Height of the control, in rows. Double is truncated to integer, must entirely fit on control panel. | Argument Count, Out of Range, Wrong Type |
| position | No | col, row - see above. | Argument Count, Out of Range, Wrong Type |
| shape | No | col, row, cols, rows - see above. | Argument Count, Out of Range, Wrong Type |
| panel | No | int/double - Zero-based number of the panel containing the control. Must be less than the number of panels. | Argument Count, Out of Range, Wrong Type |
| visible | No | Boolean - If the control is visible. | Argument Count, Wrong Type |
| label | No | String - The control's label. For some control types, extra segments set the option or button text. See Setting Labels and Option Text. | Argument Count, Wrong Type |
Setting Labels and Option Text
Use the label property to change a control's label from a script. For Radio Buttons, Drop Lists, and Buttons, the same string can also change the text of each option or button state.
-- Change the overall label and button text on a 3 position radio button
NamedControl.SetProperty("MyRadioButton", "label", "Choose|OptA|OptB|OptC")
Separate the string into segments with |:
- First segment (
Choose) - the control's own label. This is shown on every control type. - Remaining segments - used only by some control types:
- Radio Button and Drop List - one option per segment, in order (
OptA,OptB,OptC). The number of segments sets the number of options. Text typed into the Option Text fields in the Modifier Panel takes priority over the script for that option. - Button - the second segment is the text for the off state and the third segment is the text for the on state. Any further segments are ignored. The script text replaces the button's text in the Modifier Panel, and turns on Text for that state if it's off. Leave a segment empty to keep that state's existing text, for example
"Power||ON". - All other controls - extra segments are ignored.
- Radio Button and Drop List - one option per segment, in order (
A label with no | changes only the control's own label:
NamedControl.SetProperty("MyFader", "label", "Mic 1")
GetProperty returns the label in the same |-separated form:
print(NamedControl.GetProperty("MyRadioButton", "label")) >> Choose|OptA|OptB|OptC
Note
Because | separates segments, you can't use it as a literal character in a label set from a script.
Control Panel Group Properties
The following properties are supported by the entire control panel group.
| Property | Read-only | Value(s) | Possible Errors |
|---|---|---|---|
| rows | Yes | int - Height of the control panel, in rows. | Unknown Property |
| cols | Yes | int - Width of the control panel, in columns. | Unknown Property |
| panel | Yes | int - Always returns 1. Setting the displayed panel from a script isn't supported. | Internal Error |
| panels | Yes | int - The number of panels | Unknown Property |
Usage Examples
The following examples illustrate how these can be used:
Example 1 - General Usage with Polling
A common way to use named controls is to poll them using a timer. Every TimerClick period, the values of the inputs are read, some processing is performed, and the user interface is updated. This takes the form of the example below:
function TimerClick ()
newValue = NamedControl.GetValue("MyFader")
-- Do some processing
newValue = newValue * 0.8
NamedControl.SetValue("MyMeter", newValue)
end
MyTimer = Timer.New()
MyTimer.EventHandler = TimerClick
MyTimer:Start(0.5) -- Update the UI every 0.5 sec
Example 2 - Storing Values and Comparing
It's important to be as efficient as possible during these TimerClick() functions. Any UI processing that doesn't update regularly, should be checked and handled separately. And you only want to update the controls on screen if they have changed.
In most cases, you will want to store the current state of a control and compare it with the updated state of the control at the next timer click. You can then perform some action based on the new value. If it hasn't changed, you can skip a bunch of work. So Example 1 can be rewritten as.
currentValue = 0
function TimerClick ()
newValue = NamedControl.GetValue("MyFader")
if newValue ~= currentValue then --Compare Values
-- Do some processing
newValue = newValue * 0.8
NamedControl.SetValue("MyMeter", newValue)
currentValue = newValue --Update for the next pass
end
end
MyTimer = Timer.New()
MyTimer.EventHandler = TimerClick
MyTimer:Start(0.5)
While this uses more code, it is more efficient because we are only doing the processing and updating the UI when needed.
Example 3 - Self-Clearing Latching Button
In most cases, we recommend using a self-clearing Latching Button over a Momentary Button. This is because changes to a momentary button could be missed or misinterpreted, especially with slower timer intervals.
For example, if you pressed a momentary button and released it after one TimerClick but before the next, the action will be missed. Even at the fastest supported interval of 0.25 seconds, this can still happen. And you don't want to have to run your timer at fast speeds just to try to catch these, as that will use up significantly more CPU than you might otherwise need. To ensure presses aren't missed, it is best to use a Latching Button with code to clear its state after its value is read.
function TimerClick ()
newValue = NamedControl.GetValue("MyButton")
if newValue == 1 then --Check if pressed
-- Do some stuff when the button is pressed
-- Reset the button by turning it off
NamedControl.SetValue("MyButton", 0)
end
end
MyTimer = Timer.New()
MyTimer.EventHandler = TimerClick
MyTimer:Start(0.5)
Example 4 - Long Press Momentary Buttons
One good use for a Momentary Button is for implementing buttons that have different functions when held for long periods of time. For example, a button could have a different function when pressed for 5 seconds than 2 and in which there is a separate feedback mechanism to the user that the button press has been accepted. This still requires that the shortest acceptable press be longer than the Timer interval.
--Button Times
resultOneTime = 2000
resultTwoTime = 5000 --should be longer than resultOneTime
--State Variables
startTime = System.GetTime()
timeElapsed = 0
resultOneComplete = false
resultTwoComplete = false
runInProgress = false
function TimerClick ()
newButtonValue = NamedControl.GetValue("ButtonAction")
--Check if run in progress and button is pressed
if runInProgress == false and newButtonValue == 1 then
--Clear Results
resultOneComplete = false
resultTwoComplete = false
--start measuring time from now
startTime = System.GetTime()
timeElapsed = 0
--start run
runInProgress = true
elseif runInProgress == true and newButtonValue == 1 then
timeElapsed = System.GetTime() - startTime
if timeElapsed >= resultTwoTime then
--Do work when Time Two is reached
resultTwoComplete = 1
end
elseif runInProgress == true and newButtonValue == 0 then
if timeElapsed >= resultOneTime and timeElapsed < resultTwoTime then
--Do work when Time One is reached and button is released
resultOneComplete = 1
end
--end run
runInProgress = false
--stop measuring time
timeElapsed = 0
end
--update the UI
end
MyTimer = Timer.New()
MyTimer.EventHandler = TimerClick
MyTimer:Start(.25)
Example 5 - Radio Buttons
Because Radio Buttons return floats for NamedControl.GetValue and 16 bit math is used, the returned value may not exactly match the corresponding integer value. As such, a rounding function as shown below should be used.
--Handling 3 position Radio Button
if (0 == math.floor(NamedControl.GetValue("Button #1") + .5)) then
print("Position 1")
elseif (1 == math.floor(NamedControl.GetValue("Button #1") + .5)) then
print("Position 2")
elseif (2 == math.floor(NamedControl.GetValue("Button #1") + .5)) then
print("Position 3")
else
print("Button value"..NamedControl.GetValue("Button #1"))
end