COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :
Old 07-31-2013, 04:45 PM   #1
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default wdl-ol and gcc

some months ago, oli larkin hinted me that his "version" of wdl builds with Code::Blocks / gcc, so now i decided to give it a try
well, i couldn't find any traces of .cbp projects, never mind
i imported the existing msvc projects into C::B and ran the compiler (mingw)

turns out there were some bugs in the windows-related code
gcc complained about a number of places in the code where the address of a variable returned by a function was used

i had to modify that to make it compile
good, then i tried to compile one of the example plugin projects - didn't quite work
finally the "IPlugEffect" project compiled and worked

from there i managed to make a compressor plugin, it requires some polishing now but in overal it works
however, i spotted something just now
when the GUI is focused, and the mouse cursor is NOT on a control (like knobs) but just on the plain background, and if i turn the mousewheel - BAM - crashes the DAW
i tried in two different DAWs - identical

is that a fault in my plugin, a fault in wdl, or a side effect of the stuff i had to modify in the lib?
antto is offline   Reply With Quote
Old 08-01-2013, 05:22 AM   #2
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

the exact errors are:
WDL\IPlug\IGraphicsWin.cpp|218|error: taking address of temporary
WDL\IPlug\IGraphicsWin.cpp|225|error: taking address of temporary
WDL\IPlug\IGraphicsWin.cpp|233|error: taking address of temporary
WDL\IPlug\IGraphicsWin.cpp|247|error: taking address of temporary
WDL\IPlug\IGraphicsWin.cpp|252|error: taking address of temporary
WDL\IPlug\IGraphicsWin.cpp|272|error: taking address of temporary

which is about this: &GetMouseMod(wParam)
does that compile with MSVC?!
antto is offline   Reply With Quote
Old 08-01-2013, 12:44 PM   #3
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
does that compile with MSVC?!
Yes, it does, and with Intel's compiler as well.

I think it also used to compile with GCC in Code::Blocks. On Mac OS X the GCC that comes with Xcode 3 gives a warning saying something like "this will be a hard error in the future" (which IMHO would be totally lame). I guess for Code::Blocks the future is now?
Tale is offline   Reply With Quote
Old 08-01-2013, 02:14 PM   #4
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

well, taking the address of a struct returned by a function, and then passing it into a number of objects (via virtual methods) as a non-const pointer, is kind of.. weird IMO

but anyway
i don't think that's a side effect of my surgery
the actual crash happened only when i use the mousewheel over two controls
in my compressor, i have knobs, and two animated bitmaps, one of them is an LED, the other one is a VU-meter arrow
they are not "linked" to a parameter, they are just for visual feedback

so when i use the mousewheel over a knob - it moves the knob
but when i do it over the LED or VU meter - BAM crash
antto is offline   Reply With Quote
Old 08-01-2013, 03:30 PM   #5
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

You could try to add a no-op OnMouseWheel() to the offending controls. The default IControl::OnMouseWheel() makes sense for knobs and sliders, but for other controls not so much.

BTW, I assume the controls have a valid paramIdx or -1 assigned to them?
Tale is offline   Reply With Quote
Old 08-01-2013, 11:41 PM   #6
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

at first i tried with paramIdx above kNumParams
then i tried with negative..
it always crashes

now i did something else.. SetTargetRect() to a rect of size 0, so that it won't catch the mouse
antto is offline   Reply With Quote
Old 08-02-2013, 02:28 AM   #7
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
at first i tried with paramIdx above kNumParams
then i tried with negative..
it always crashes
For a control not linked to a parameter the paramIdx should be -1. If paramIdx != -1 IPlug will call GetParam(paramIdx), expecting it to return a valid IParam pointer, but which will be invalid for out of range paramIdx values.

BTW, I have just downloaded the latest Code::Blocks, and I have compiled the original IPlugExample both against my IPlug and Oli's IPlug, and both don't crash when I use the mouse wheel, no matter how hard I try.
Tale is offline   Reply With Quote
Old 08-02-2013, 03:24 AM   #8
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

with paramIdx -1 i think it didn't crash, BUT the mousewheel was actually turning the animation as if it's a knob
in other words, my VU-meter arrow is controlled from the audio process() function, and at the same time the mousewheel was also trying to control it

Code::Blocks is just an IDE
the compile errors come from the compiler, in my case, mingw/gcc
the problems were in IGraphicsWin.cpp

i have no idea what the differences are between "wdl" "wdl-ol" or your version of wdl
antto is offline   Reply With Quote
Old 08-02-2013, 03:40 AM   #9
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
with paramIdx -1 i think it didn't crash, BUT the mousewheel was actually turning the animation as if it's a knob
in other words, my VU-meter arrow is controlled from the audio process() function, and at the same time the mousewheel was also trying to control it
That is a known issue, which is why I said the default OnMouseWheel() doesn't make sense for some controls, e.g. for IBitmapControl. If you don't need any mouse interaction, then clearing the target rectangle will indeed work. If you do need e.g. OnMouseDown(), then you can subclass the control, and override OnMouseWheel() with a no-op:

Code:
void MyControl::OnMouseWheel(int x, int y, IMouseMod* pMod, int d) {}
Quote:
Originally Posted by antto View Post
Code::Blocks is just an IDE
the compile errors come from the compiler, in my case, mingw/gcc
the problems were in IGraphicsWin.cpp
Yeah, I know. The latest Code::Blocks comes with GCC 4.7.1, so I had to add -fpermissive to downgrade the errors to warnings.

Quote:
Originally Posted by antto View Post
i have no idea what the differences are between "wdl" "wdl-ol" or your version of wdl
WDL-OL has more targets (VST3, RTAS, AAX) and probably more features. My WDL/IPlug is what I use to build the Combo Model V & F organ plug-ins.
Tale is offline   Reply With Quote
Old 08-02-2013, 07:37 AM   #10
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

okay, i get the point now
personally i use win32 VST2, don't care about VST3
AU is desireable, since my impression is that it's common on osx, as for the other formats, i haven't heard most of them
antto is offline   Reply With Quote
Old 08-02-2013, 10:06 AM   #11
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
AU is desireable, since my impression is that it's common on osx
Yeah, it is. FYI, most Mac OS X hosts support both AU and VST, except Logic and GarageBand, which support AU only.

Quote:
Originally Posted by antto View Post
as for the other formats, i haven't heard most of them
RTAS and AAX are formats exclusively supported by Pro Tools, which natively doesn't support VST or AU.
Tale is offline   Reply With Quote
Old 08-02-2013, 01:41 PM   #12
Banned
Human being with feelings
 
Banned's Avatar
 
Join Date: Mar 2008
Location: Unwired (probably in the proximity of Amsterdam)
Posts: 4,868
Default

Quote:
Originally Posted by Tale View Post
Yeah, it is. FYI, most Mac OS X hosts support both AU and VST, except Logic and GarageBand, which support AU only. [...]
Numerology is another Mac-only host that supports only AU (standalone; it can be used both as VST / AU plug-in, too).

Btw, any chance of porting VB-303 to a cross-platform IPlug codebase, antto? (I guess not, but one can dream, right? )
__________________
˙lɐd 'ʎɐʍ ƃuoɹʍ ǝɥʇ ǝɔıʌǝp ʇɐɥʇ ƃuıploɥ ǝɹ,noʎ
Banned is offline   Reply With Quote
Old 08-02-2013, 03:42 PM   #13
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

VB-303 - no, it's gonna be too much work, it's not worth it

i have a polysynth project which i coded as a single SE module (so the whole thing is within one bunch of classes) and i'd rather try to put THAT into IPlug
that has way more parameters (3x 6-segment envelopes.. just to name a few) so it's still gonna be a great pain, but at least that's worth it
antto is offline   Reply With Quote
Old 08-03-2013, 06:48 AM   #14
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

speaking about it..
i need your recommendation or advice, since i'm not too familiar with IPlug
i have a polysynth basically in a single class, it is quite isolated, it expects all parameters in 0.0 to 1.0 fashion (and does scaling and shaping on its own) and has voice management and everything, so i basically just need to connect the "end points" (params, and midi processing)


the Question is.. chunks or not?

because it has 93 parameters already, and it's not quite finished yet, i expect them to end up quite above 100..
antto is offline   Reply With Quote
Old 08-03-2013, 12:19 PM   #15
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
the Question is.. chunks or not?

because it has 93 parameters already, and it's not quite finished yet, i expect them to end up quite above 100..
I don't think the number of parameters would be an issue (not much anyway), but if you do chunks you can store everything in such a way that it will be much easier to add or remove parameters later on.
Tale is offline   Reply With Quote
Old 08-04-2013, 06:32 AM   #16
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

for chunks, i had implemented some classes for storing parameters into chunks, where each param had an "id" additionally to the value
the idea was, when your synth saves the params, it saves them with their IDs (so the actual order doesn't matter much)
then, in a future version of the synth, you can remove some parameters, and/or add new ones
so as long as you keep the IDs "unique" - old presets will still work
the function which loads the chunk uses these IDs to figure out which actual parameter the value goes to
i could probably use these classes here maybe, but it's complicated to set them up, and my head hurts when i think about it ;]

there's another problem with so many params that they become hard to fit on screen

this is the current state of the polysynth, there are many things missing (effects section, "master" controls, ...)
also, people generally don't accept this due to the controls/text being "too tiny" .. so i would probably scale it by 125 percent, which makes it about 960 pixels wide, and that's kinda too much for me, i'd like to fit it in up to 900 pixels width if possible

is it possible to make "paged" GUI or have the GUI in a smaller window with something like a horizontal scroller?

Last edited by antto; 08-04-2013 at 06:38 AM.
antto is offline   Reply With Quote
Old 08-04-2013, 08:33 AM   #17
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
is it possible to make "paged" GUI or have the GUI in a smaller window with something like a horizontal scroller?
Sure, you hide/unhide controls as you please. In fact that is what I do in Combo Model V (& F):


Organ view


Settings view


Tuning view

I have added a SetGuiState(state) method to my plug-in that hide/unhides controls depending on the selected state. In my constructor I add all controls for all pages, and I then call SetGuiState() to initialize the GUI. When you click on the organ, settings or tuning button I again call SetGuiState() to switch to the selected state.
Tale is offline   Reply With Quote
Old 08-05-2013, 06:56 AM   #18
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

as i thought about it more, i must use chunks, because the synth has a "PCM" osc, which is supposed to work with .wav files
so i either have to store the filename into the VST patch memory, or store the whole audio data instead

i see that there is functionality for poping out a FileOpen dialog, so that's good
however, i'm not exactly sure which way to do it



if the wav file would be loaded from disk (which is nicer) i want to keep all such files into a root directory, preferably in a subfolder relative to the vst dll
something like: ..\VstPlugins\thesynth\wavs\
and then, in the actual preset, i'll only store the filepath relative to that
like "xyz\dingdong.wav" where "xyz" can be a subfolder (you know, if someone decides to make a whole bank of presets with custom wavs he'll keep them in their own sub-folder)
and that will be added to the "root" dir like: ..\VstPlugins\thesynth\ + wavs\ + xyz\dingdong.wav

however, i'll need a function to get the dll directory
also, i have no idea if this scheme will work on osx (because i might eventually want to make an osxVST version of this synth at some point)
the nice thing is that presets will be kept small, and all these wavs will be reusable by the user



the other variant is to reserve a place in the preset (chunk) for the whole audio data, instead of the filename
currently my pcm osc is limited to use a wavetable of (max) 128000 samples, so that's 500kB (if i store them as float)
the nice thing is that i will not care about any directories and stuff
the downside is that the user won't be able to reuse the wav from another preset (or take it and modify it in a wav editor)



in any case, i will supply a bunch of example .wavs which the user can use as a starting point to make his own

any advice is highly welcome
antto is offline   Reply With Quote
Old 08-05-2013, 01:12 PM   #19
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
i see that there is functionality for poping out a FileOpen dialog, so that's good
however, i'm not exactly sure which way to do it
Something like this should work:

Code:
WDL_String file;
const char* dir = "";
mPlug->GetGUI()->PromptForFile(&file, IGraphics::kFileOpen, dir, "wav");
if (file.GetLength())
{
	FILE* f = fopen(file.Get(), "rb");
	// ...
}
Quote:
Originally Posted by antto View Post
however, i'll need a function to get the dll directory
also, i have no idea if this scheme will work on osx (because i might eventually want to make an osxVST version of this synth at some point)
You can call PluginPath() to get the plug-in path:

Code:
WDL_String path;
GetGUI->PluginPath(&path);
This works on both Windows and Mac OS X.
Tale is offline   Reply With Quote
Old 08-05-2013, 02:26 PM   #20
Banned
Human being with feelings
 
Banned's Avatar
 
Join Date: Mar 2008
Location: Unwired (probably in the proximity of Amsterdam)
Posts: 4,868
Default

Quote:
Originally Posted by antto View Post
[...] also, i have no idea if this scheme will work on osx (because i might eventually want to make an osxVST version of this synth at some point) [...]
Don't even think about doing that on OS X. Unlike with Windows, where apparently people are used to put all sorts of stuff into the same folders as the plug-ins themselves (and/or use different paths/folders for plug-ins), on OS X that is simply 'not done'. For AU plug-ins, you're not even allowed to use subfolders for the plug-ins themselves, they have to be in

/Library/Audio/Plug-Ins/Components

(or ~/Library/Audio/Plug-Ins/Components if installing for a single user only - but it is *very* uncommon to use this)

Speaking for myself, whenever I see a plug-in install attempting to put other stuff in there (e.g. "put your registration key in the same folder as the plug-in" or some random randomplugname.dat file), I take it as a clear sign that the developer has no idea what he's doing (on OS X, anyway) and just trash the offending product. Fortunately, that is *very* rare.

What most well-established plug-in vendors seem to do, and what I thus would suggest you should (try to) do as well, is either create your own subfolder in

/Library/Audio/Plug-Ins

(and/) or create your own subfolder in

/Library/Application\ Support

---

Now, I should add that I have no idea if/how the IPlug framework can be helpful to do this sort of OS X-specific stuff, as I'm a noob at using IPlug myself, but perhaps someone else can chime in?
__________________
˙lɐd 'ʎɐʍ ƃuoɹʍ ǝɥʇ ǝɔıʌǝp ʇɐɥʇ ƃuıploɥ ǝɹ,noʎ
Banned is offline   Reply With Quote
Old 08-06-2013, 01:17 AM   #21
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

obviously i don't know what i'm doing, i have no mac/osx/iAnything
and it makes me want to not bother with anything OSX at all

i guess the easiest approach would be if the audio data is always stored in the preset itself (about 500kB per preset)

EDIT:
so which function do i need to implement for using chunks?
SerializeState()
UnserializeState()
anything else?
and what exactly is the purpose for this ByteChunk thing?

and to check if i understand correctly
if i use chunks
- on instance load, the host will send a chunk instead of individually setting the value of each param
- on instance save, the host will request a chunk instead of individually grabbing the value of each param
- when a param (knob) on my own GUI is moved - i'll still get OnParamChange()
- when a param is automated in the host - i'll still get OnParamChange()
- the host will use the param names (as always) to create a list of automatable parameters shown to the user

Last edited by antto; 08-06-2013 at 01:54 AM.
antto is offline   Reply With Quote
Old 08-06-2013, 02:09 AM   #22
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
i guess the easiest approach would be if the audio data is always stored in the preset itself (about 500kB per preset)
Are you planning on including VST presets within your plug-in? Because the full state of your plug-in includes all included preset slots, so if you would include 32 presets your would have to store 32 x 500kB = 16000kB.

Quote:
Originally Posted by antto View Post
so which function do i need to implement for using chunks?
SerializeState()
UnserializeState()
anything else?
There are a few others (SerializePresets, SerializeParam), but I don't know how exactly these are implemented in WDL-OL.

Quote:
Originally Posted by antto View Post
and what exactly is the purpose for this ByteChunk thing?
This:

Code:
// ByteChunk* pChunk
for (int i = 0; i < kNumParams; ++i)
{
	double v = GetParam(i)->Value();
	if (pChunk->Put(&v) <= 0) return false;
}
Quote:
Originally Posted by antto View Post
and to check if i understand correctly
if i use chunks
- on instance load, the host will send a chunk instead of individually setting the value of each param
- on instance save, the host will request a chunk instead of individually grabbing the value of each param
- when a param (knob) on my own GUI is moved - i'll still get OnParamChange()
- when a param is automated in the host - i'll still get OnParamChange()
- the host will use the param names (as always) to create a list of automatable parameters shown to the user
Yes, i.e. only loading/saving changes, nothing else.
Tale is offline   Reply With Quote
Old 08-06-2013, 02:45 AM   #23
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

so this ByteChunk thing is dynamically created "on the go" ?
i would rather store the params as 32bit float (and int, for those which are of integer type)

then the chunk is read using this ByteChunk thing in the same order i guess
antto is offline   Reply With Quote
Old 08-06-2013, 03:03 AM   #24
olilarkin
Human being with feelings
 
olilarkin's Avatar
 
Join Date: Apr 2009
Location: Huddersfield, UK
Posts: 1,153
Default

have a look at the IPlugChunks example in WDL-OL.

Code:
// this over-ridden method is called when the host is trying to store the plug-in state and needs to get the current data from your algorithm
bool IPlugChunks::SerializeState(ByteChunk* pChunk)
{
  TRACE;
  IMutexLock lock(this);
  double v;

  // serialize the multi-slider state state before serializing the regular params
  for (int i = 0; i< NUM_SLIDERS; i++)
  {
    v = mSteps[i];
    pChunk->Put(&v);
  }

  return IPlugBase::SerializeParams(pChunk); // must remember to call SerializeParams at the end
}

// this over-ridden method is called when the host is trying to load the plug-in state and you need to unpack the data into your algorithm
int IPlugChunks::UnserializeState(ByteChunk* pChunk, int startPos)
{
  TRACE;
  IMutexLock lock(this);
  double v = 0.0;

  // unserialize the multi-slider state before unserializing the regular params
  for (int i = 0; i< NUM_SLIDERS; i++)
  {
    v = 0.0;
    startPos = pChunk->Get(&v, startPos);
    mSteps[i] = v;
  }

  // update values in control, will set dirty
  if(mMSlider)
    mMSlider->SetState(mSteps);

  return IPlugBase::UnserializeParams(pChunk, startPos); // must remember to call UnserializeParams at the end
}
__________________
VirtualCZ | pMix | Endless Series | iPlug2 | Linkedin | Facebook
Available for Audio Dev tuition via Skype (IPlug/JUCE/C++)

Last edited by olilarkin; 08-06-2013 at 03:14 AM.
olilarkin is offline   Reply With Quote
Old 08-06-2013, 04:36 AM   #25
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

wait, so SerializeParams(pChunk) actually adds all params in the chunk?
antto is offline   Reply With Quote
Old 08-06-2013, 04:38 AM   #26
olilarkin
Human being with feelings
 
olilarkin's Avatar
 
Join Date: Apr 2009
Location: Huddersfield, UK
Posts: 1,153
Default

Quote:
Originally Posted by antto View Post
wait, so SerializeParams(pChunk) actually adds all params in the chunk?
yes, first you put in all your custom data, then IPlug serializes all the param values on the end when you call SerializeParams()
__________________
VirtualCZ | pMix | Endless Series | iPlug2 | Linkedin | Facebook
Available for Audio Dev tuition via Skype (IPlug/JUCE/C++)
olilarkin is offline   Reply With Quote
Old 08-06-2013, 05:25 AM   #27
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

nice, so i only put the "exotic" stuff manually, and it can contain variable sized data from patch to patch (since it's dynamic)

my own chunk classes were concentrated around static preset structure, where everything was supposed to be known at compile time

however, this still leaves one problem - adding and removing parameters in a future version of the plugin will make old presets load incorrectly
so i will still want to store the parameters myself (without calling SerializeParams())

i would instead use a small structure like this:
Code:
struct PARAM
{
    PARAM(const uint16_t ID, const float F) : id(ID), f(F)
    { }
    uint16_t id;
    union
    {
        int32_t i;
        float f;
    };
};
where "id" is going to be a unique ID for each parameter
so in a future version of the plugin, if i want to remove a parameter - i will just skip it from the chunk (since it's stored with that ID) and if i want to add a new parameter - it will use a new unique ID which won't be present in presets from the older version
antto is offline   Reply With Quote
Old 08-06-2013, 09:55 AM   #28
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

it appears SetCanAutomate(false) doesn't quite work
the given parameter still appears in the Host list of parameters
is there a way to have a parameter "hidden" from the host?
antto is offline   Reply With Quote
Old 08-06-2013, 10:26 AM   #29
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

Quote:
Originally Posted by antto View Post
the given parameter still appears in the Host list of parameters
is there a way to have a parameter "hidden" from the host?
Not report it as a parameter? If you are going to use chunks you can store whatever you like, so you don't have to include all actual parameters in he list of plug-in parameters.
Tale is offline   Reply With Quote
Old 08-06-2013, 11:01 AM   #30
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

yeah, i just noticed that in my other plugin, which doesn't use chunks
i have a switch there which wasn't supposed to be automatable, but it is
i know that if i use chunks it's all up to me
antto is offline   Reply With Quote
Old 08-06-2013, 11:54 PM   #31
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

i'm scratching my head..
i need to make a parameter with N options
and i need to have one or two buttons to cycle thru the options

say a waveform parameter (thus integer type), with 10 possible options, which will be displayed with a bitmap, but this bitmap will not be clickable, it will just sit there to show the selected waveform
and then, two buttons for ++ and -- to cycle the parameter
any ideas?
antto is offline   Reply With Quote
Old 08-07-2013, 12:19 AM   #32
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 2,932
Default

You can easily get/set the value of control A from control B (using GetValue and SetValueFromPlug), so if you pass a pointer to control A to the (customized) constructor of control B, you can use this pointer to get/set the value.

Alternatively you could enumerate all your controls, and then add them in that exact order, in which case you can pass the control index of control A to control B, and get/set the value through mPlug->GetGUI()->GetControl(idx).
Tale is offline   Reply With Quote
Old 08-08-2013, 05:31 AM   #33
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

pff, finally i think i got it working:
Code:
class INonClickable : public IBitmapControl
{
public:
  INonClickable(IPlugBase* pPlug, int x, int y, int paramIdx, IBitmap* pBitmap,
                 IChannelBlend::EBlendMethod blendMethod = IChannelBlend::kBlendNone)
    : IBitmapControl(pPlug, x, y, paramIdx, pBitmap, blendMethod) {}

  ~INonClickable() {}
  void OnMouseDblClick(int x, int y, IMouseMod* pMod) {}
  void OnMouseWheel(int x, int y, IMouseMod* pMod, int d) {}
  void OnMouseDown(int x, int y, IMouseMod* pMod) {}
  void OnMouseUp(int x, int y, IMouseMod* pMod) {}
  void OnMouseDrag(int x, int y, int dX, int dY, IMouseMod* pMod) {}
  //void OnMouse(int x, int y, IMouseMod* pMod) {}
  int GetNumFrames() const { return mBitmap.N; }
  int GetCurFrame()
  {
      return (int)floor(0.5 + mValue * (mBitmap.N - 1.0));
  }
  void SetCurFrame(int n)
  {
      assert(mBitmap.N > 1);

      while (n < mBitmap.N) { n += mBitmap.N; }
      n %= mBitmap.N;
      mValue = (double)(n) / (double)(mBitmap.N - 1);
      mPlug->SetParameterFromGUI(mParamIdx, mValue);
      SetDirty();
  }
};

class IIncrementButton : public IControl
{
public:
  IIncrementButton(IPlugBase* pPlug, int x, int y, int paramIdx, IBitmap* pBitmap,
                    INonClickable* target, int incDirection,
                 IChannelBlend::EBlendMethod blendMethod = IChannelBlend::kBlendNone)
    : IControl(pPlug, IRECT(x, y, pBitmap), paramIdx, blendMethod),
    mTarget(target), mIncDirection(incDirection), mBitmap(*pBitmap) { mDblAsSingleClick = true; }

  ~IIncrementButton() {}
  //void OnMouseDblClick(int x, int y, IMouseMod* pMod) {}
  void OnMouseWheel(int x, int y, IMouseMod* pMod, int d) {}
  void OnMouseDown(int x, int y, IMouseMod* pMod)
  {
      mValue = 1.0;
      SetDirty();
      mTarget->SetCurFrame(mTarget->GetCurFrame() + mIncDirection);
  }
  virtual bool Draw(IGraphics* pGraphics)
  {
      int i = 1;
      if (mBitmap.N > 1)
      {
        i = 1 + int(0.5 + mValue * (double) (mBitmap.N - 1));
        i = BOUNDED(i, 1, mBitmap.N);
      }
      return pGraphics->DrawBitmap(&mBitmap, &mRECT, i, &mBlend);
  }

  void OnMouseUp(int x, int y, IMouseMod* pMod)
  {
      mValue = 0.0;
      SetDirty();
  }
  void OnMouseDrag(int x, int y, int dX, int dY, IMouseMod* pMod) {}
  //void OnMouse(int x, int y, IMouseMod* pMod) {}
protected:
    IBitmap mBitmap;
    INonClickable* mTarget;
    int mIncDirection;
};
So the INonClickable is attached to the actual parameter (waveform display) and doesn't respond to any mouse action
then, a dummy button IIncrementButton is used which will "scroll" the waveform parameter when clicked
two buttons can be used with that same waveform parameter, where one of them will have incDirection=1 (for ++) and the other incDirection=-1 (for --)
antto is offline   Reply With Quote
Old 08-10-2013, 04:30 AM   #34
antto
Human being with feelings
 
Join Date: Nov 2008
Posts: 108
Default

hm.. i think framesAreHoriztonal=true doesn't work
or i'm doing something wrong
antto 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 06:17 AM.


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