Is there any way to force the value of a component?

is there any way to force the value of a component? Example, by pressing a button, I want to bypass the sends of the selected track. My code for retrieving all the sends in the trace is this

button1.mSurfaceValue.mOnProcessValueChange = function(activeDevice, value){
    var size=page.mHostAccess.mTrackSelection.mMixerChannel.mSends.getSize();
    for (let index = 0; index < size; index++) {
        page.mHostAccess.mTrackSelection.mMixerChannel.mSends.getByIndex(index).mOn//   what??
        
    }    
}.bind(page);

At the moment I have not put any conditions on the input value, however i canā€™t find a way to force the value of page.mHostAccess.mTrackSelection.mMixerChannel.mSends.getByIndex(index).mOn there is a way to do it or am I fantasizing too much?

thank you

Hi,

Which component do you mean?

Do you mean to press the button on your hardware? If you mean this, do following in the HOST MAPPING area:

var size=page.mHostAccess.mTrackSelection.mMixerChannel.mSends.getSize()
for (let index = 0; index < size; index++) {
	page.makeValueBinding(button1.mSurfaceValue, selectedTrackChannel.mSends.getByIndex(index).mOn).setTypeToggle()
}

This will bypass all Sends of the selected track. Is it, what do you want to achieve?

Maybe that wasnā€™t the correct example. What you did is correct (thatā€™s what I wanted), but you got it thanks to the binding. But I would like to change the value, example of track ā€˜Xā€™ to value ā€˜Xā€™ manually. Thank you

Hi,

Iā€™m sorry, I still didnā€™t get your use case.

no problem, I also realized that a controller (knob, button etc) can drive only one value. Your example only bypasses the last send. The other sends are overwritten.

Hi,

Sorry, I copied part of your codeā€¦ What if you use var instead of let in the for loop?

What do you mean by overwritten, please? This should change the state of all Send Levels of the given track.

I didnā€™t run the first code I published because I realized I couldnā€™t go on. I used ā€œvarā€ and not ā€œletā€

no, it doesnā€™t work. example

page.makeValueBinding(button1.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(0).mOn).setTypeToggle() // CMD1
page.makeValueBinding(button1.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(1).mOn).setTypeToggle() //CMD2

CMD2 overwrites CMD1 so in this case the bypass will occur only on the last send ā€œbutton1.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex (1)ā€

What value is your hardware sending?

You can create custom variables using makeCustomValueVariable(name)

Then update those custom variables upon hardware changes (.mOnProcessValueChange) within the create elements code.

Then you bind controls to the custom variables, not directly to the hardware receives.

i.e.
[Hardware button] > [Custom Variable Trigger] > [Cubase bind]
Rather than
[Hardware button] > [Cubase bind]

By inserting the custom variable trigger, This allows you to control/manipulate pre-bind.

Furthermore, If you store that state you can force the values to cycle on each press for specific toggles. i.e. this is what I done for EQ Types that have different values per band.

A rough example is as follows:-

    var kkjoy_click = surface.makeButton(0, 0, 0, 0)
    kkjoy_click.mSurfaceValue.mMidiBinding.setInputPort(midiInput)
        .bindToControlChange(CTRL_CHAN, JOY_CLICK[0])

    kkjoy_trig_click = surface.makeCustomValueVariable('kkjoy_trig_click')

    kkjoy_click.mSurfaceValue.mOnProcessValueChange = function (activeDevice, value) {
        kkjoy_trig_click.setProcessValue(activeDevice, 1);
    }

You can see that my hardware control is defined as kkjoy_click, but when that hardware is pressed (mOnProcessValueChange) it sets the value of the custom variable kkjoy_trig_click, and that trigger is bound to commands, not the hardware object, i.e.:-

    page.makeCommandBinding(kkjoy_trig_click, 'Preset', 'Open/Close Browser')

The value being sent is defined via .setProcessValue, example:
kkjoy_trig_click.setProcessValue(activeDevice, 1); ā† Would send value ā€˜1ā€™.
kkjoy_trig_click.setProcessValue(activeDevice, 0.5); ā† Would send value ā€˜0.5ā€™.

Does that make sense?

This can also be used to trigger different actions based on clockwise/anti knob movements of the same Midi CC assignments. i.e.:

    var kkpage_btn = surface.makeButton(0, 0, 0, 0)
    kkpage_btn.mSurfaceValue.mMidiBinding.setInputPort(midiInput)
        .bindToControlChange(CTRL_CHAN, 49)

    kkpage_trig_left = surface.makeCustomValueVariable('kkpage_trig_left')
    kkpage_trig_right = surface.makeCustomValueVariable('kkpage_trig_right')
    
    kkpage_btn.mSurfaceValue.mOnProcessValueChange = function (activeDevice, value) {
        if (value * 127 == 127) {
            kkpage_trig_left.setProcessValue(activeDevice, 1);
        } else if (value * 127 == 1) {
            kkpage_trig_right.setProcessValue(activeDevice, 1);
        }
    }

You can see based on that code that receiving a value of 127 will trigger (kkpage_trig_left) set to ā€˜1ā€™, and (kkpage_trig_right) also set to ā€˜1ā€™- even though they are received on the same CC49.

Again, those turns can be bound as separate elements once the triggers exist:-

    page.makeActionBinding(kkpage_trig_left, deviceDriver.mAction.mPrevPage)
    page.makeActionBinding(kkpage_trig_right, deviceDriver.mAction.mNextPage)
2 Likes

Youā€™ve bound button1 twice in that example.

1 Like

this is great, thatā€™s what i was looking for.
in fact the only way was to create knobs that I didnā€™t have on the hardware.

Thank you !!

yes because I was simulating the ā€œforā€ cycle posted by @Martin.Jirsak . I understand that the link is 1 to 1.

Ah, I didnā€™t know you could bind the same control twice. It just looked wrong when I read it, must admit not tried binding in that way.

you can do it but it doesnā€™t work :slight_smile: , I will be overwritten

1 Like

Hi,

I think itā€™s specified like this. You cannot bind one controller multiple times (multiple function to one controller). Therefore I use the for loop to apply the function to all Sends.

If you do it like this you are just re-binding the same hardware control. Once the loop is finished only the last binding is valid.

The binding also happens just once, not every time you change the value either from Cubase or the hardware controller.

But I may be wrong.

Hi,

Oh, I see.

Then the only way would be, if there would be a command to Bypass all Sends of Selected Track. What you can do via Project Logical Editor:

Filter Target
( Container Type is | Equal | Track | And
Property | Property is set | Is Selected )

Action Target
Track Operation | Sends Bypass | Toggle

Function
Transform

Using the CustomValueVariable everything works, thanks

2 Likes

You could also use the makeCustomValueVariable to create (8?) triggers from one hw control, and then bind those triggers to whatever you want.

If you created them as an array, you can bind via an array too (obviously) which is programmatically cleaner in this example.

Itā€™s not documented too well, but I picked up on a post that Jochen made a few weeks back and ran with it. :slight_smile:

Hi,

Sorry, I still donā€™t got it with the makeCustomValueVariable. Could you please help me to understand this part (@skijumptoes )? My use case is:

  • Action Button
  • Shift Button
  • If Shift Button is On, Action Button controls Solo
  • If Shift Button is Off, Action Button controls Mute

Thank you

Must admit iā€™ve not tried emulating shift buttons yet.

But thinking as I type, you should be able to:

  1. Create your shift button, and using onvaluechange store the state of that shift into a device state that you can recall. i.e.
    surfaceElements.shiftBtn = surface.makeButton(0, 0, 0, 0)
    surfaceElements.shiftBtn.mSurfaceValue.mMidiBinding.setInputPort(midiInput)
        .bindToControlChange(MIDI_CH, MIDI_CC)
    
    surfaceElements.shiftBtn.mSurfaceValue.mOnProcessValueChange = function (activeDevice, value) {
        if (value * 127 == 127) { //Whatever value your ON State is
            activeDevice.setState('shiftBtnState',1)
        } else if (value * 127 == 1) { //Off state
            activeDevice.setState('shiftBtnState',0)
        }
    }
  1. Then create your hardware action button and create two triggers for it via makeCustomValueVariable (One for shifted, one for normal) that can respond based on the device state set via the shift button.
    surfaceElements.actBtn1 = surface.makeButton(0, 0, 0, 0)
    surfaceElements.actBtn1.mSurfaceValue.mMidiBinding.setInputPort(midiInput)
        .bindToControlChange(MIDI_CH, MIDI_CC)

    surfaceElements.trig_actBtn1 = surface.makeCustomValueVariable('trig_actBtn1 ')
    surfaceElements.trig_actBtn1Shift = surface.makeCustomValueVariable('trig_actBtn1Shift')
    
    surfaceElements.actBtn1.mSurfaceValue.mOnProcessValueChange = function (activeDevice, value) {
        var shiftState = activeDevice.getState('shiftBtnState') //Read state
        if (shiftState == 1) {
            //Shifted
            surfaceElements.trig_actBtn1Shift.setProcessValue(activeDevice, 1);
        } else {
            //Normal
            surfaceElements.trig_actBtn1.setProcessValue(activeDevice, 1);
        }
    }

Just bind those triggers to the controls you need. i.e.

page.makeValueBinding(surfaceElements.trig_actBtn1,hostMixerBankChannel.mValue.mMute)
page.makeValueBinding(surfaceElements.trig_actBtn1Shift,hostMixerBankChannel.mValue.mSolo)

Not tried it, by the way, but thatā€™s the approach Iā€™d take with customVariables. I believe you can use subpages that may be better though? Iā€™ve not even tried those out yet. But this example maybe helps explain how customvariables can be used as triggers a little clearer?

One thing to note is that you need to ensure that triggers can be globally accessed via the js, hence why if you append them to the surfaceElements object itā€™s easier. (Or whatever is used in your mapping).

1 Like