This style works really well when you have a lot of control over the device and how it behaves. But when you don’t, you have to make up the difference in the code.
What would be wonderful is if the incoming MIDI could be modified as it can in Logic JS Scripting. That would open up the ability to do just about anything.
While I agree with you on the value specific triggers, I think stepping up a level in design would help to solve a lot of the complexity.
To simplify what I want to say I am going to use the word Encoder for any hardware widget, whether it is an Encoder or Button, because the word Controller has a defined meaning when discussing code.
As it is the events are bound to the Surface Element which is bound to the Encoder, and this is where the complexity comes in.
If it were more like:
Hardware Encoder : register incoming events
Cubase Endpoint : register outgoing events
Hardware Encoder → Callback → Cubase Endpoint method (no binding required!)
Cubase Endpoint → Callback → Hardware Encoder method (no binding required!)
But there is a secondary GUI, but we don’t need events from that!!! So it could be a completely separate entity. In fact having the Elements bound doesn’t make a lot of sense. For example, in the example above the knob in question shows up as “No Mapping”.
The whole idea of binding can make sense, but as you try and do something more interesting it starts to become a special case.
So binding the Element to an object that you make or to a pre-defined object makes more sense.
That would be that built in Elements can automatically register for events from Hardware Encoders or Cubase Endpoints, or if you extend the correct type, you can then insert your own with it’s own behavior.
But this is all OO. which of course makes it so much easier to think about.
Unfortunately the term Model, View, Controller, has been improperly used more than it has been used correctly. The Model in this case is the Element, The view is the Element, the Controller is the Element. The Element is everything. One can argue that the binding is the model, but you can’t get events from the binding so, everything has to go through the Element.
In telemetry based systems Visual Proxy concept tends to work a lot better, You have a Model Controller, and a View Controller. And you have them facing both directions. Both incoming and outgoing. That is the model that would work best here I think.