|
05-22-2017, 06:51 AM
|
#1
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Is there the equivalent "ProcessDoubleReplacing" for the GUI thread?
Hi all,
ProcessDoubleReplacing is called for each buffer (sent by DAW) within the audio thread. Is there the same "general/misc" function called by the GUI thread?
Where for example I can sync some IControl display with "audio" variables processed by audio thread (such as refresh Meter by the current output level).
I'd like to avoid calling method/function (such as SetDirty) within audio thread, which run DSP and I'd like to keep it as optimized as possible. Such calling a general function RefreshAdvancedParametersGUI(); which browse all my AdvancedParameters and keep value from IParam to the linked IControl.
Thanks.
|
|
|
05-22-2017, 07:07 AM
|
#2
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
Quote:
Originally Posted by Nowhk
I'd like to avoid calling method/function (such as SetDirty) within audio thread,
|
SetDirty is supposed to just set a boolean flag or such, so calling it from the audio thread shouldn't be harmful. (The flag is then later supposed to be checked by the GUI thread from a timer callback or such to see if the graphics needs to be redrawn etc. The implementation of SetDirty in IControl pretty much just does the flag setting if the pushParamToPlug is set to false when calling.)
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
|
|
|
05-22-2017, 07:18 AM
|
#3
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Quote:
Originally Posted by Xenakios
SetDirty is supposed to just set a boolean flag or such, so calling it from the audio thread shouldn't be harmful. (The flag is then later supposed to be checked by the GUI thread from a timer callback or such to see if the graphics needs to be redrawn etc. The implementation of SetDirty in IControl pretty much just does the flag setting if the pushParamToPlug is set to false when calling.)
|
Ok, but where can I manage the whole logic of GUI? SetDirty is alongside a fixed IControl. What if I'd like to manage the whole graphic? Is there a common function or I need to create a sort of "MasterGUIIControl" a call the SetDirty of that?
|
|
|
05-22-2017, 11:45 PM
|
#4
|
Human being with feelings
Join Date: Dec 2015
Posts: 331
|
Quote:
Originally Posted by Nowhk
ProcessDoubleReplacing is called for each buffer (sent by DAW) within the audio thread. Is there the same "general/misc" function called by the GUI thread?
Where for example I can sync some IControl display with "audio" variables processed by audio thread (such as refresh Meter by the current output level).
|
Sure, OnGUIIdle is the generic GUI processing method. Override it in any control that needs idle processing.
|
|
|
05-22-2017, 11:59 PM
|
#5
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Hi man
Quote:
Originally Posted by earlevel
Sure, OnGUIIdle is the generic GUI processing method. Override it in any control that needs idle processing.
|
So:
1. I make a generic IControl (such as MainGUIController);
2. I override that OnGUIIdle function;
3. I call SetDirty() of MainGUIController (which will call OnGUIIdle);
That's the way?
But do I need point 3. or it will automatically called when GUI thread run?
Not sure about that. I see USE_IDLE_CALLS, which seems I can uncomment it and I don't need SetDirty?
|
|
|
05-23-2017, 12:37 AM
|
#6
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Anyway, I've tried both, uncommenting USE_IDLE_CALLS and call SetDirty() to that IControl... but nothing happens...
Code:
#ifndef MISC_PANEL_H
#define MISC_PANEL_H
#define MISC_PANEL_WIDTH 640
#define MISC_PANEL_HEIGHT 54
class MainIPlug;
class MiscPanel : public IControl
{
public:
MiscPanel(MainIPlug *plug, int x, int y);
~MiscPanel() { }
void OnGUIIdle() {
DBGMSG("Hello World");
}
bool Draw(IGraphics *pGraphics);
private:
MainIPlug *pPlug;
IRECT mRectHelpText;
};
#endif // !MISC_PANEL_H
I never see that "Hello World" in console...
But it seems that if it finds "any" dirty control, it won't call that idle function: https://github.com/olilarkin/wdl-ol/...phics.cpp#L745
Since I've some other controls which are always dirty (i.e. inline bool IsDirty() { return true; }), that OnGUIIdle won't never be called.
What's the purpose of that so? :O
Last edited by Nowhk; 05-23-2017 at 12:48 AM.
|
|
|
05-23-2017, 04:25 AM
|
#7
|
Human being with feelings
Join Date: Feb 2007
Location: Oulu, Finland
Posts: 8,062
|
edit : Maybe not...
__________________
I am no longer part of the REAPER community. Please don't contact me with any REAPER-related issues.
Last edited by Xenakios; 05-23-2017 at 04:38 AM.
|
|
|
05-23-2017, 05:00 AM
|
#8
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Quote:
Originally Posted by Xenakios
edit : Maybe not...
|
Lol that OnIdle seems to be the right place, but I don't know how to deal with it. Maybe should I edit IPlug and call OnGUIIdle even if dirty? Not sure...
|
|
|
05-23-2017, 06:28 AM
|
#9
|
Human being with feelings
Join Date: May 2015
Location: Serbia
Posts: 654
|
Of you want to use this inside IControl class use this:
IsDirty()
{
// Your code
return mDirty;
}
|
|
|
05-23-2017, 11:53 AM
|
#10
|
Human being with feelings
Join Date: Dec 2015
Posts: 331
|
Quote:
Originally Posted by Nowhk
I see USE_IDLE_CALLS, which seems I can uncomment it and I don't need SetDirty?
|
You do need to define USE_IDLE_CALLS. The suggesting, in the code, to uncomment the line in IPlugBase.h isn't a very good one—you might not want it on every plugin, so modifying the framework doesn't make sense. Define it in the project, in Xcode and VS.
My old comment (may no longer be true) in my own code says that only VST and RTAS supported idle calls in the original wdl-ol I downloaded. I added that capability to my own version for AAX. So AU may not have it. All the calls are there, but if there is no mechanism to call it in place, nothing will happen.
|
|
|
05-24-2017, 01:10 AM
|
#11
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Quote:
Originally Posted by earlevel
You do need to define USE_IDLE_CALLS. The suggesting, in the code, to uncomment the line in IPlugBase.h isn't a very good one—you might not want it on every plugin, so modifying the framework doesn't make sense. Define it in the project, in Xcode and VS.
My old comment (may no longer be true) in my own code says that only VST and RTAS supported idle calls in the original wdl-ol I downloaded. I added that capability to my own version for AAX. So AU may not have it. All the calls are there, but if there is no mechanism to call it in place, nothing will happen.
|
Here OnGUIIdle is never called, neither if I use USE_IDLE_CALLS.
I think the right way is just to override that IsDirty(), as Youlean suggested. It doesn't "sound" like the appropriate/suitable function, but it seems its always called when the GUI Thread run (few lines of code above OnGUIIdle).
Thanks
|
|
|
05-24-2017, 03:50 AM
|
#12
|
Human being with feelings
Join Date: May 2015
Location: Serbia
Posts: 654
|
You should use OnGUIIdle inside your plugin class, not control class.
|
|
|
05-24-2017, 05:38 AM
|
#13
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Quote:
Originally Posted by Youlean
You should use OnGUIIdle inside your plugin class, not control class.
|
Uhm... why? I'll use it for things related to the GUI thread, not the audio one. It says:
Code:
// Uncomment to enable IPlug::OnIdle() and IGraphics::OnGUIIdle().
So I guess it should works for both audio end gui thread. But it doesn't at all (due to that "dirty" that (for some other IControl) will always result in at least 1 true... (not sure at all why that behaviour).
|
|
|
05-24-2017, 05:53 PM
|
#14
|
Human being with feelings
Join Date: Dec 2015
Posts: 331
|
Quote:
Originally Posted by Nowhk
Here OnGUIIdle is never called, neither if I use USE_IDLE_CALLS.
I think the right way is just to override that IsDirty(), as Youlean suggested. It doesn't "sound" like the appropriate/suitable function, but it seems its always called when the GUI Thread run (few lines of code above OnGUIIdle).
Thanks
|
You have the source code, look at it.
OnGUIIdle is a method of IControl. Look at what calls it. It's IGraphics::IsDirty. Look at what calls IGraphics::IsDirty. It's a timer driven event loop.
In other words, IPlug regularly—when it's doing nothing else (idle)—checks the controls to see if anything is dirty, and returns the if and where info, to take further action. But IGraphics::IsDirty also has this interesting code:
Code:
#ifdef USE_IDLE_CALLS
if (dirty)
{
mIdleTicks = 0;
}
else if (++mIdleTicks > IDLE_TICKS)
{
OnGUIIdle();
mIdleTicks = 0;
}
#endif
That is, if something is dirty, IGraphics::OnGUIIdle is called—but only after a little time elapses, to limit the rate.
What does IGraphics::OnGUIIdle do? If calls OnGUIIdle for each control:
Code:
void IGraphics::OnGUIIdle()
{
int i, n = mControls.GetSize();
IControl** ppControl = mControls.GetList();
for (i = 0; i < n; ++i, ++ppControl)
{
IControl* pControl = *ppControl;
pControl->OnGUIIdle();
}
}
There you have it. OnGUIIdle is called if USE_IDLE_CALLS is defined, and while a control is not dirty (it's not idle if something is dirty), but not more often than IDLE_TICKS.
Overriding OnGUIIdle for your control is what you want if you want a control to do something while idle. If it's not working, you will have to set breakpoints or other methods to see what's really happening.
|
|
|
05-25-2017, 12:12 AM
|
#15
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Quote:
Originally Posted by earlevel
That is, if something is dirty, IGraphics::OnGUIIdle is called—but only after a little time elapses, to limit the rate.
|
Nope As I said above, if any of the controls I have is always dirty (on some IControl I have inline bool IsDirty() { return true; });) that function OnGUIIdle will never be called.
Because there's always "dirty", so OnGUIIdle never reach the call...
|
|
|
05-25-2017, 12:14 AM
|
#16
|
Human being with feelings
Join Date: May 2015
Location: Serbia
Posts: 654
|
Quote:
Originally Posted by Nowhk
Uhm... why? I'll use it for things related to the GUI thread, not the audio one.
|
Sorry my mistake. Earlevel has explained this very well.
|
|
|
05-25-2017, 10:16 AM
|
#17
|
Human being with feelings
Join Date: Dec 2015
Posts: 331
|
Quote:
Originally Posted by Nowhk
Nope As I said above, if any of the controls I have is always dirty (on some IControl I have inline bool IsDirty() { return true; });) that function OnGUIIdle will never be called.
Because there's always "dirty", so OnGUIIdle never reach the call...
|
You now know how IPlug works, for OnGUIIdle, you now know that you need a design change.
|
|
|
05-25-2017, 11:41 PM
|
#18
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Quote:
Originally Posted by earlevel
You now know how IPlug works, for OnGUIIdle, you now know that you need a design change.
|
I've learned that some stuff (made by experienced people) are as they are for some reasons
I wouldn't change a design that will create other problems elsewhere.
For the moment I keep IsDirty as function
Thanks
|
|
|
05-26-2017, 12:52 AM
|
#19
|
Human being with feelings
Join Date: Dec 2015
Posts: 331
|
Quote:
Originally Posted by Nowhk
I wouldn't change a design that will create other problems elsewhere.
For the moment I keep IsDirty as function
|
By all means, do as you wish. But then you must understand, if you keep the interface busy permanently, then it's never idle, and no use looking at OnGUIIdle.
I don't understand the part about "will create other problems elsewhere." You're basically handling it in the same place (part of the code flow) as you would via OnGUIIdle, except that the latter is moderated by a frame rate limit. That means your code handling it is called far more often than is likely necessary. If it takes a significant amount of time to process, it could hold up other things that may need to be more responsive. Since visual feedback does quite well limited to 25-30 fps, it's usually a good idea to limit it and make more time available to other things.
|
|
|
05-26-2017, 01:41 AM
|
#20
|
Human being with feelings
Join Date: Mar 2016
Posts: 234
|
Quote:
Originally Posted by earlevel
By all means, do as you wish. But then you must understand, if you keep the interface busy permanently, then it's never idle, and no use looking at OnGUIIdle.
I don't understand the part about "will create other problems elsewhere." You're basically handling it in the same place (part of the code flow) as you would via OnGUIIdle, except that the latter is moderated by a frame rate limit. That means your code handling it is called far more often than is likely necessary. If it takes a significant amount of time to process, it could hold up other things that may need to be more responsive. Since visual feedback does quite well limited to 25-30 fps, it's usually a good idea to limit it and make more time available to other things.
|
I see Thanks!
Anyway, I feel "fluid" in IPlug using FPS of 100:
Code:
IGraphics *pGraphics = MakeGraphics(this, GUI_WIDTH, GUI_HEIGHT, 100);
It seems 60 is (sometimes) steppy, with ASIO 256.
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 08:03 AM.
|