COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :

Go Back   Cockos Incorporated Forums > Other Software Discussion > WDL users forum

Reply
 
Thread Tools Display Modes
Old 05-30-2017, 12:00 PM   #1
br_ck1
Human being with feelings
 
Join Date: Dec 2015
Posts: 39
Default Assign the same Parameter to 2 or more GUI elements

Hi,

could you help me please?

Is it possible in WDL-OL to assign the same plugin Parameter (for example "kVolume") to 2 or 3 or more different IControl GUI elements (each of them using different bitmaps for example) ? Everything preserving overall stability obviously...

Tank you in advance!
br_ck1 is offline   Reply With Quote
Old 05-30-2017, 11:26 PM   #2
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,646
Default

Quote:
Originally Posted by br_ck1 View Post
Is it possible in WDL-OL to assign the same plugin Parameter (for example "kVolume") to 2 or 3 or more different IControl GUI elements (each of them using different bitmaps for example) ? Everything preserving overall stability obviously...
Yeah, sure. And in general they will all update when you automate the parameter. However, you might have to sync the IControls when changing one of the IControls in the GUI.
Tale is offline   Reply With Quote
Old 05-31-2017, 09:54 AM   #3
br_ck1
Human being with feelings
 
Join Date: Dec 2015
Posts: 39
Default

Quote:
Originally Posted by Tale View Post
Yeah, sure. And in general they will all update when you automate the parameter. However, you might have to sync the IControls when changing one of the IControls in the GUI.
Thank you Tale,

For "sync the IControls" you mean inside "OnParamChange()" update the gui for all icontrols right? Or there's a different way ?
br_ck1 is offline   Reply With Quote
Old 05-31-2017, 11:11 PM   #4
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,646
Default

Quote:
Originally Posted by br_ck1 View Post
For "sync the IControls" you mean inside "OnParamChange()" update the gui for all icontrols right? Or there's a different way ?
Another way could be to set a pointer to the other IControl, and then in SetDirty() call the other IControl's SetValueFromPlug().
Tale is offline   Reply With Quote
Old 06-01-2017, 01:41 PM   #5
br_ck1
Human being with feelings
 
Join Date: Dec 2015
Posts: 39
Default

Thank you so much Tale,
br_ck1 is offline   Reply With Quote
Old 06-01-2017, 09:57 PM   #6
earlevel
Human being with feelings
 
Join Date: Dec 2015
Posts: 331
Default

Quote:
Originally Posted by Tale View Post
However, you might have to sync the IControls when changing one of the IControls in the GUI.
In general, no—right? Because: you turn the control, it updates the param, the param updates any controls attached to it (the one you're changing manually doesn't re-send to the param, because it has logic that checks for no change in the control).

I have a plugin that is time based; you can set time with a knob, with a numeric text field, and from a tempo field and associated controls (triplet, etc.). I don't do anything special to make the text field follow the knob, for instance.
earlevel is offline   Reply With Quote
Old 06-02-2017, 04:09 AM   #7
stw
Human being with feelings
 
stw's Avatar
 
Join Date: Apr 2012
Posts: 279
Default

Quote:
Originally Posted by earlevel View Post
In general, no—right? Because: you turn the control, it updates the param, the param updates any controls attached to it (the one you're changing manually doesn't re-send to the param, because it has logic that checks for no change in the control).
I don't think that you're right here. A GUI changed param doesn't send values back to other controls without any further instructions. At least i couldn't find anything like that. I guess txt fields include anything like SetValuefromPlug (i didn't check)? But simply defining the same paramIdx to different controls doesn't sync the GUI.
stw is offline   Reply With Quote
Old 06-02-2017, 10:57 AM   #8
MSK
Human being with feelings
 
Join Date: Jan 2017
Posts: 43
Default

I ran into this problem also, trying to have multiple controls manage the same parameter. The first way I handled it was:

In the custom control, call mPlug -> SetParameterFromGUI(paramID, normalizedValue) to update the parameter (this then calls OnParamChange in the main .cpp).

Then in OnParamChange also pass a changed parameter value to any controls that use it, for example:
Code:
     case (kThreshold):{
      
      double thresh = GetParam(kThreshold) -> Value();
      peakMeter -> SetThreshold(thresh);

    }
The problem with this is that if you have a control that updates the parameter many times in short succession (a slider, for instance), it makes a small change and updates the parameter, which calls OnParamChange and sends the changed value back to the control that made the change, which has by then made a larger change to the parameter that will get reset. This caused some funky behavior.

My solution was to only allow the control to accept new parameter values when it wasn't actively changing that parameter:

Code:
    void SetThreshold(double t){

        if (!clicking){
            // If the user isn't interacting with the control, update the parameter
            threshold = t;
            pcThreshold = (36.0 + t) / 36.0;

        }
    }

This worked pretty well, but it isn't the greatest solution. For instance, if you have a parameter attached to a knob, you have to explicitly set the knob value from within the control, since OnParamChange doesn't update the knobs (understandably so, since it'll usually be a knob calling OnParamChange, as I understand it). So I also had to pass knobs around to every control that needed to handle parameters internally, which got a little nasty to keep track of (but worked).

My new solution (after learning more/better C++) is using a structure that holds all of the relevant information about a parameter. The pointer to this structure can then be sent to any control that needs it, and it handles all the parameter/knob updating stuff.

Here it is:

Code:
struct SmartParam{
    
    IPlugBase* mPlug;
    int paramID;
    IKnobMultiControl* paramKnob;
    double currentValue, normalizedValue, maxValue, minValue;
    
    SmartParam(){}
    SmartParam(IPlugBase* pPlug, int ID, IKnobMultiControl* knob, double cVal, double maxVal, double minVal) : mPlug(pPlug), paramID(ID), paramKnob(knob), currentValue(cVal), maxValue(maxVal), minValue(minVal){ normalizedValue = (maxVal - cVal) / (maxVal - minVal); }
    
    void SetValue(double val){
        
        currentValue = val;
        normalizedValue = (val - minValue) / (maxValue - minValue);
        mPlug -> SetParameterFromGUI(paramID, normalizedValue);
        paramKnob -> SetValueFromPlug(normalizedValue);
        
    }
    
    
};
I haven't completely integrated this into my project yet, but it seems to work pretty well so far. Let me know if you want to use it (you're more than welcome to do so) and have any questions regarding its implementation.

Hope some of this helps!
MSK
MSK is offline   Reply With Quote
Old 06-02-2017, 02:42 PM   #9
earlevel
Human being with feelings
 
Join Date: Dec 2015
Posts: 331
Default

Quote:
Originally Posted by stw View Post
I don't think that you're right here. A GUI changed param doesn't send values back to other controls without any further instructions.
Sorry, left out important details. IGraphics::SetParameterFromPlug is how a parameter is set from the plugin. It sets the values of all controls associated with the parameter. That's what I'm referring to. If the controls change, they are marked dirty and redrawn.

The graphics Draw routine is called regularly, and checks for dirty controls, accumulates an update rectangle, then redraws everything that's in or overlaps the rectangle. You could have a group of controls sitting on top of a big dummy control if you want—setting the dummy dirty will force the others to redraw.

Also, for cases in which you may do the setting of a parameter OnParamChange, or similar, call IGraphics::SetParameterFromGUI. For instance, I have tempo controls that calculate a delay time. When the tempo changes, it changes a tempo parameter for the benefit of the host, then in the OnParamChange handler for the tempo parameter, I calculate a new time parameter, and set it with SetParameterFromGUI. Besides setting the parameter, it updates all controls that are attached to the parameter.

PS—I forgot how horribly named these routines are. SetParameterFromPlug, for instance, doesn't set a parameter. It sets controls associated with a parameter to match the value you supply. The parameter isn't sent—it just updates the controls and redraws them if visible. SetParameterFromGUI exists in the plugin and graphics objects, and it very different.

Last edited by earlevel; 06-02-2017 at 08:10 PM. Reason: Add details about SetParameterFromGUI
earlevel is offline   Reply With Quote
Old 06-03-2017, 04:24 AM   #10
stw
Human being with feelings
 
stw's Avatar
 
Join Date: Apr 2012
Posts: 279
Default

Quote:
Originally Posted by earlevel View Post
Sorry, left out important details...
Yes you're right, naming of these functions can be confusing. Since i stumbled over this very often when i started with IPlug and i guess almost every other beginner will too, i knocked up a short comparison and explanations on corresponding functions. Feel free to comment, expand or correct any mistakes!

Quote:
class IControl:: // called by: ControlPointer->function()

SetValueFromPlug(double value):
Sets the mValue for a (GUI-)IControl. The value is only held by the control and not pushed to the host. Calls SetDirty(false) => The IControl will be redrawn, but value won’t be pushed to the host.
Additionally mDefaultValue is set to value if < 0 (purpose?).

SetValueFromUserInput(double value):
Same as SetValueFromPlug() but calls SetDirty(true) => value will be pushed to the host.

SetDirty(bool pushParamToPlug // true on default):
Sets mDirty = true => The IControl will be redrawn with its actual mValue. mValue is set either by GUI actions, SetValueFromPlug(), or automation.
If pushParamToPlug == true, mPlug->SetParameterFromGUI(mParamIdx, mValue) [don’t mix up with IGraphics::SetParameterFromGUI(int paramIdx, double normalizedValue)] is called => mValue will be pushed to the IControls associated IParam and OnParamChange() is called afterwards.

SetClean():
Sets mDirty = mRedraw. mRedraw is set to true if called by ControlPointer->Redraw() or by IControlPointer->Hide(), otherwise it’s false. This function usually won’t be called by the user but is used inside IGraphics::Draw() to reset mDirty to false if the GUI drawing has be done.



class IGraphics:: // called by: pGraphics->function() / GetGUI()->function()

SetParameterFromPlug(int paramIdx, double value, bool normalized)
Is called by the host when sending automation data to the plug.
Calls IControl::SetValueFromPlug(double value) for all IControls associated with paramIdx => All IControls with the same paramIdx are synced. (misleading naming. Should rather be called something like: SetControlsWithParamIdx)

SetParameterFromGUI(int paramIdx, double normalizedValue)
Calls IControl::SetValueFromUserInput(normalizedValue) for all IControls associated with paramIdx.

SetControlFromPlug(int controlIdx, double normalizedValue)
Calls IControls::SetValueFromPlug(double value) for an IControl with index nr = controlIdx. Can be used in rare cases if you keep track of controlIdx numbers, what you usually don’t.
controlIdx != paramIdx !!

SetAllControlsDirty()
Calls SetDirty(false) for all IControls.



class IPlug:: // called by: Direct function call / mPlug->function()

SetParameterFromGUI(int paramIdx, double normalizedValue)
Sets Params mValue to normalizedValue and pushes it to the host. OnParamChange() is called afterwards. IControls associated with paramIdx are not updated.
Don’t mix up with IGraphics::SetParameterFromGUI(int paramIdx, double normalizedValue)

OnParamReset()
Calls OnParamChange() for all IParams.

RedrawParamControls()
Calls IGraphics::SetParameterFromPlug() for all IParams => All param associated IControls are updated and redrawn.



class IParam:: // called by: GetParam(paramIdx)->function()
The following functions are usually followed by InformHostOfParamChange()


SetNormalized(double normalizedValue)
Sets mValue of returned paramIdx to 'non-normalized' normalizedValue. No further action.

Set(double value)
Sets mValue of returned paramIdx to value. No further action.

Last edited by stw; 06-06-2017 at 01:12 AM.
stw is offline   Reply With Quote
Old 06-03-2017, 11:43 AM   #11
earlevel
Human being with feelings
 
Join Date: Dec 2015
Posts: 331
Default

Nice list!

The only thing I see missing is IPlug::SetParameterFromGUI, and differentiate between IGraphics::SetParameterFromGUI. I just looked at the fact I'm calling IGraphics::SetParameterFromGUI in my OnParamChange, and IPlug::SetParameterFromGUI in my SetChunk override. I had to think about it a bit before I convinced myself that was correct. Annoying duplicity with that one.
earlevel is offline   Reply With Quote
Old 06-03-2017, 08:07 PM   #12
br_ck1
Human being with feelings
 
Join Date: Dec 2015
Posts: 39
Default

Great, thank you for the list and explaination !
br_ck1 is offline   Reply With Quote
Old 06-04-2017, 06:08 AM   #13
stw
Human being with feelings
 
stw's Avatar
 
Join Date: Apr 2012
Posts: 279
Default

Quote:
Originally Posted by earlevel View Post
Nice list!

The only thing I see missing is IPlug::SetParameterFromGUI, and differentiate between IGraphics::SetParameterFromGUI. I just looked at the fact I'm calling IGraphics::SetParameterFromGUI in my OnParamChange, and IPlug::SetParameterFromGUI in my SetChunk override. I had to think about it a bit before I convinced myself that was correct. Annoying duplicity with that one.
You're right i left that out. And i left out all IParam:: value setting functions too. Main purpose of that list was to point out which function should be called (and which not) to keep the GUI in sync with associated params or values. AFAIS IParam:: or IPlug:: Setters don't touch any GUI settings if not followed by e.g. RedrawParamControls(). So it would make thigs even more complicated for beginners.
But on the other hand, it's a good idea to have all things in place. I'll complete the list later...
stw is offline   Reply With Quote
Old 06-04-2017, 10:51 AM   #14
earlevel
Human being with feelings
 
Join Date: Dec 2015
Posts: 331
Default

Quote:
Originally Posted by stw View Post
But on the other hand, it's a good idea to have all things in place. I'll complete the list later...
Not trying to make work for you! I only mentioned SetParameterFromGUI because it exists in two different but similar forms. Even though you list it under IGraphics, you can bet someone will find the other and use it instead. To make matter worse, most people would be calling it from their plugin code, and the other version can be called directly (e.g, SetParameterFromGUI instead of GetGUI->SetParameterFromGUI).

An unfortunate overlap of names—it's a poor choice for the IGraphics version in particular, since it doesn't set a parameter. It forces an update of controls associated with a parameter. That is, IGraphics::SetParameterFromGUI is what you'd call after a parameter changes from the GUI, to ensure all its controls match.

Last edited by earlevel; 06-04-2017 at 10:53 PM.
earlevel is offline   Reply With Quote
Old 06-06-2017, 01:30 AM   #15
stw
Human being with feelings
 
stw's Avatar
 
Join Date: Apr 2012
Posts: 279
Default

Quote:
Originally Posted by earlevel View Post
Not trying to make work for you! I only mentioned SetParameterFromGUI because it exists in two different but similar forms. Even though you list it under IGraphics, you can bet someone will find the other and use it instead. To make matter worse, most people would be calling it from their plugin code, and the other version can be called directly (e.g, SetParameterFromGUI instead of GetGUI->SetParameterFromGUI).
Good point! I updated the list. I hope i didn't miss important information
stw is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 10:53 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.