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

THIS IS A BAD IDEA :point_up: :nerd_face:

Within callbacks it is very unhealthy (semantically wrong) to create hostaccess objects (MR_HostObject). “GetByIndex” is an example of creating a MR_HostObject, that must be done outside the callbacks. We have to implement a kind of “alarm”-system for those cases I’m afraid. Of cause that’s our fault and not yours.

Shift buttons are best adapted by using a SubPageArea + two SubPages. It is again a bit counter-intuitive, but works. That way when press+hold the shift button, the SubPage “Shift” is activated and by using “mapToValueRange(1, 0)” you can react on releasing the shift button, it inverts the internal process value.

var knob = deviceDriver.mSurface.makeKnob(0, 0, 2, 1)
var shiftButton = deviceDriver.mSurface.makeButton(2, 0, 2, 1)

var subPageAreaFunctionMode = page.makeSubPageArea('Function Mode')
var subPageFuncModMain = subPageAreaFunctionMode.makeSubPage('Main')
var subPageFuncModShift = subPageAreaFunctionMode.makeSubPage('Shift')

var selectedtrackChannel = page.mHostAccess.mTrackSelection.mMixerChannel

// if NOT SHIFTED control the selected track volume
page.makeValueBinding(knob.mSurfaceValue, selectedtrackChannel.mValue.mVolume)
    .setSubPage(subPageFuncModMain)

// if SHIFT IS ACTIVE control the selected track pan
page.makeValueBinding(knob.mSurfaceValue, selectedtrackChannel.mValue.mPan)
    .setSubPage(subPageFuncModShift)

// if NOT SHIFTED and shift button is pressed down, activate sub page 'Shift' 
page.makeActionBinding(shiftButton.mSurfaceValue, subPageFuncModShift.mAction.mActivate)
    .setSubPage(subPageFuncModMain)

// if SHIFT IS ACTIVE and shift button is released, activate sub page 'Main'
page.makeActionBinding(shiftButton.mSurfaceValue, subPageFuncModMain.mAction.mActivate)
    .mapToValueRange(1, 0) // handle value inverted to react on releasing the button
    .setSubPage(subPageFuncModShift)

4 Likes

Hi @axeleon, can you please add the label “midi-remote” to this topic as well?

1 Like

yeah, i’ve also had weird loops :joy:

That code was an example just to understand how to force a value, I understood from this thread that I have to use the CustomValueVariable

1 Like

That is correct. However you can make the callbacks be per-page. I have done this in TypeScript because I get confused with all the procedural abstraction. I just can’t abide. But you can work it out I suppose.

I seriously don’t know how people keep things strait without OO abstraction. It creates really messy and hard to understand code, and when you come back to it after a week it’s even more difficult than the first time around.

I’m really hoping for Either TypeScript or even ES6 in the future.

class EventManager {
    pagename;
    functorEventDisplayValueChange;
    functorEventHostTitle;
    functorEventProcessValueChange;

    constructor(pagename) {
        this.pagename = pagename;
        this.functorEventDisplayValueChange = null;
        this.functorEventHostTitle = null;
        this.functorEventProcessValueChange = null;
    }
}

abstract class PageAwareEncoder {
    element;
    eventManagers;
    eventDisplayValueChangeRegistered;
    eventHostTitleRegistered;
    eventProcessValueChangeRegistered;
    currentpage;

    functorDisplayValueChange;
    functorHostTitle;
    functorProcessValueChange;

    constructor() {
        this.element = null;
        this.eventManagers = {};
        this.eventDisplayValueChangeRegistered = false;
        this.eventHostTitleRegistered = false;
        this.eventProcessValueChangeRegistered = false;
        this.currentpage = "";
        this.functorDisplayValueChange = null;
        this.functorHostTitle = null;
        this.functorProcessValueChange = null;
    }

    resetPage(name) {
        this.currentpage = name;
        this._setFunctorTitleChange();
        this._setFunctorDisplayValueChanged();
        this._setFunctorProcessValueChanged();
    }

   _getEventManager(pageName) {
       var eventManager = this.eventManagers[pageName];
       var isUndefined = "" + typeof eventManager;
       if (isUndefined == "undefined") {
           return null;
       }
       return eventManager;
   }

   _makeEventManagerIfNeeded(pageName) {
       var eventManager = this._getEventManager(pageName);
       if (null == eventManager) {
           eventManager = new EventManager(pageName);
           this.eventManagers[pageName] = eventManager;
       }
       return eventManager;
   }

   registerEventDisplayValueChange(pageName, functor){
       var eventManager = this._makeEventManagerIfNeeded(pageName);
       eventManager.functorEventDisplayValueChange = functor;
       if( this.eventDisplayValueChangeRegistered == false) {
           this.eventDisplayValueChangeRegistered = true;
           this.element.mSurfaceValue.mOnDisplayValueChange =
           function(activeDevice, valueString) {
               this._handleDisplayValueChanged(activeDevice, valueString);
           }.bind(this);
       }
   }

   registerEventHostTitle(pageName, functor){
       var eventManager = this._makeEventManagerIfNeeded(pageName);
       eventManager.functorHostTitle = functor;
       if( this.eventHostTitleRegistered == false) {
           this.eventHostTitleRegistered = true;
           this.element.mSurfaceValue.mOnTitleChange =
           function (activeDevice, value, units) {
                   this._handleTitleChange(activeDevice, value, units);
           }.bind(this);
       }
   }

   registerEventProcessValueChange(pageName, functor){
       var eventManager = this._makeEventManagerIfNeeded(pageName);
       eventManager.functorProcessValueChange = functor;
       if( this.eventProcessValueChangeRegistered == false) {
           this.eventProcessValueChangeRegistered = true;
           this.element.mSurfaceValue.mOnProcessValueChange =
           function(activeDevice, value) {
               this._handleProcessValueChanged(activeDevice, value);
           }.bind(this);
       }
   }

   _setFunctorTitleChange() {
       this.functorHostTitle = null;
       var eventManager = this._getEventManager(this.currentpage);
       if(null != eventManager) {
           this.functorHostTitle = eventManager.functorHostTitle;
       }
   }

   _setFunctorDisplayValueChanged(){
       this.functorDisplayValueChange = null;
       var eventManager = this._getEventManager(this.currentpage);
       if(null != eventManager) {
           this.functorDisplayValueChange = eventManager.functorEventDisplayValueChange;
       }
   }

   _setFunctorProcessValueChanged(){
       this.functorProcessValueChange = null;
       var eventManager = this._getEventManager(this.currentpage);
       if(null != eventManager) {
           this.functorProcessValueChange = eventManager.functorProcessValueChange;
       }
   }

   _handleTitleChange(activeDevice, value, units) {
       if(null != this.functorHostTitle) {
          this.functorHostTitle(activeDevice, value, units);
       }
   }

   _handleDisplayValueChanged(activeDevice, valueString){
       if(null != this.functorDisplayValueChange) {
           this.functorDisplayValueChange(activeDevice, valueString);
       }
   }

   _handleProcessValueChanged(activeDevice, value){
       if(null != this.functorProcessValueChange) {
           this.functorProcessValueChange(activeDevice, value);
       }
   }
}

Thank-you. This was very helpful. I was able to solve my problem for clearing pushencoder LEDs prior to shifting the bank left on my Mackie C4.

-Ron