Skip to content

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, position returns 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.

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