WDL GUI parameters : MIDI automation

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Hello, I'm a newbe using WDL-OL.

I'm getting crazy because I would like to "link" a MIDI message to a GUI Parameter, but I can't figure out how to do it.

I think the method SetDirty() is somewhere involved, but I do not understand where exactly...

I have a GUI parameter in the constructor :

Code: Select all

IControl_knobMainVolume = new IKnobMultiControl(this, kMainVolumeX, kMainVolumeY, kMainVolume, &knob_0001);

pGraphics->AttachControl(IControl_knobMainVolume);

AttachGraphics(pGraphics);

//the knob appear and works correctly
Then in "ProcessDoubleReplacing" :

Code: Select all

//... if a midi "control change 7" message occurs -> :

GetParam(kMainVolume)->Set(pMsg->mData2); //this work fine, the parameter is linked to CC#7
If I "manually" turn the knob from the GUI, the volume changes properly.
If I send a MIDI cc#7 message, the volume changes properly.

But, when I send a MIDI cc#7 message (also if the volume changes properly), the knob image remains unchanged (mid position), it doesn't follow the value set with MIDI slider.

I know I have to do something with SetDirty() , Draw() , and or other methods, do anyone knows how to do it? Or if there's some resource on the internet that explains this thing...

Thank you in advance,
bruno @ Xhun Audio || www.xhun-audio.com || Twitter || Instagram
Image

Post

you'd be better off asking on the WDL forum

Post

Even if you do get this working, you don't really want to interact directly with GUI code inside the audio thread (due to locks, memory allocations, non-deterministic stuff that may lock up the real-time thread).

Instead, either flag controls that need redrawing, and then regularly check from the message thread if anything has to be updated. Can also be done using a sort of message lock-free fifo.

Post

hibrasil wrote:you'd be better off asking on the WDL forum
okay.

Waiting for WDL forum access confirmation...
bruno @ Xhun Audio || www.xhun-audio.com || Twitter || Instagram
Image

Post

Mayae wrote:Even if you do get this working, you don't really want to interact directly with GUI code inside the audio thread (due to locks, memory allocations, non-deterministic stuff that may lock up the real-time thread).

Instead, either flag controls that need redrawing, and then regularly check from the message thread if anything has to be updated. Can also be done using a sort of message lock-free fifo.
Hi Mayae, you're right... In WDL, GUI side should be (*maybe*) accessed using GetGUI()->..., so your suggestion is to make something similar to this :

Inside "ProcessMidiMsg" method :

Code: Select all

IControl_knobMainVolume->SetDirty();
or...

Code: Select all

GetGUI()->SetParameterFromPlug();//...
bruno @ Xhun Audio || www.xhun-audio.com || Twitter || Instagram
Image

Post

Ok, I got it.

For people that may ask about this in the future, the answer is simply :

GetGUI()->SetControlFromPlug(ParamIdx, Value);

Since this is executed in the "ProcessDoubleReplacing" each time a midi message (cc#7) is picked from the midi queue, so it is executed in the DSP thread, right? Is there any way to make it be executed in the GUI thread to safe CPU?

*maybe* using : if(GetGUI())

Code: Select all


 if(GetGUI()) GetGUI()->SetControlFromPlug(ParamIdx, Value);//?????

I tried to accede to Cockos forum but the confirmation email never arrived.
Someone here knows about the if(GetGUI()) addition?
bruno @ Xhun Audio || www.xhun-audio.com || Twitter || Instagram
Image

Post

don't have time to really explain it, but here is how you can update a parameter and linked control in response to a MIDI CC, handled in OnMIDIMsg() or when unpacked from the queue in ProcessDoubleReplacing()

Code: Select all

                  double val = pMsg->ControlChange(pMsg->ControlChangeIdx());
                  GetParam(paramIdx)->SetNormalized(val);
                  GetGUI()->SetParameterFromPlug(paramIdx, val, true);
                  OnParamChange(paramIdx);

Post

hibrasil wrote:don't have time to really explain it, but here is how you can update a parameter and linked control in response to a MIDI CC, handled in OnMIDIMsg() or when unpacked from the queue in ProcessDoubleReplacing()

Code: Select all

                  double val = pMsg->ControlChange(pMsg->ControlChangeIdx());
                  GetParam(paramIdx)->SetNormalized(val);
                  GetGUI()->SetParameterFromPlug(paramIdx, val, true);
                  OnParamChange(paramIdx);
Thank you so much for your help! When you'll find some spare time, can you tell me the difference (no docs came with WDL, neither //comments)?

Before your help, I used (see the comments) :

Code: Select all

double val = pMsg->ControlChange(pMsg->ControlChangeIdx()); //obviously the same as you suggested
GetParam(paramIdx)->SetNormalized(val); //I used Set() instead of SetNormalized() , what difference exactly?
GetGUI()->SetParameterFromPlug(paramIdx, val, true); //I used SetControlFromPlug() instead of SetParameterFromPlug() , what difference exactly?
OnParamChange(paramIdx); //why calling this exactly?
I don't want to bother you, as you know WDL comes with very few docs, I just would like to learn WDL details as deeply as I can, so it can be helpful in the future...
bruno @ Xhun Audio || www.xhun-audio.com || Twitter || Instagram
Image

Post

//I used Set() instead of SetNormalized() , what difference exactly?

I'm sure you know the answer to this. Normalized is in the range 0-1, Set() would set the parameter's non-normalized value. IMidiMsg::ControlChange() returns a normalized value, which is why i used IParam:: SetNormalized() to update the value.

//I used SetControlFromPlug() instead of SetParameterFromPlug() what difference exactly?
IGraphics::SetParameterFromPlug() will update all controls that are linked to that parameter (could be more than one)

//OnParamChange(paramIdx); //why calling this exactly?
YourPlugin::OnParamChange() is not normally called by you, but in this case you have manually updated the parameter's value, and may want to call YourPlugin::OnParamChange() to propagate the changes to your DSP

Post

hibrasil wrote://I used Set() instead of SetNormalized() , what difference exactly?

I'm sure you know the answer to this. Normalized is in the range 0-1, Set() would set the parameter's non-normalized value. IMidiMsg::ControlChange() returns a normalized value, which is why i used IParam:: SetNormalized() to update the value.

//I used SetControlFromPlug() instead of SetParameterFromPlug() what difference exactly?
IGraphics::SetParameterFromPlug() will update all controls that are linked to that parameter (could be more than one)

//OnParamChange(paramIdx); //why calling this exactly?
YourPlugin::OnParamChange() is not normally called by you, but in this case you have manually updated the parameter's value, and may want to call YourPlugin::OnParamChange() to propagate the changes to your DSP
Thank you so much for the clarification Oliver,
bruno @ Xhun Audio || www.xhun-audio.com || Twitter || Instagram
Image

Post Reply

Return to “DSP and Plugin Development”