View Full Version : Problems with ICaptionControl on OSX 10.5
I added a couple of ICaptionControl's to the example, like this:
bitmap = pGraphics->LoadIBitmap(FADER_ID, FADER_FN);
pGraphics->AttachControl(new IFaderControl(this, kGainL_X, kGainL_Y, kFader_Len, kGainL, &bitmap, kVertical));
IRECT r1(kGainL_X, 190, kGainL_X+50, 199 );
IText txt(&COLOR_WHITE);
pGraphics->AttachControl(new ICaptionControl(this, &r1, kGainL, &txt, true));
pGraphics->AttachControl(new IFaderControl(this, kGainR_X, kGainR_Y, kFader_Len, kGainR, &bitmap, kVertical));
IRECT r2(kGainR_X, 190, kGainR_X+50, 199 );
pGraphics->AttachControl(new ICaptionControl(this, &r2, kGainR, &txt, true));
First of all the text appeared upside down, mirrored and in the wrong place. I fixed that by changing a couple of lines in IGraphicsMac.mm to set flipped to YES:
NSGraphicsContext* destGC = [NSGraphicsContext graphicsContextWithGraphicsPort:destCtx->ctx flipped:YES];
and change the position of the rectangle (I'm not too sure about this one, because I don't understand what yAdj is meant to do):
NSRect r = { pR->L, pR->T + yAdj, pR->W(), pR->H() };
But there are still problems with the values updating. In the AU in Garage Band the text doesn't get updated until you close and reopen the plugin window. In the VST it gets updated most of the time, but there are various ways of getting it not to, it seems to be something to do with releasing the mouse button when the mouse isn't still over the control. For instance, if you pull the fader right down and keep moving the mouse further down, then release, the text doesn't update.
Any ideas?
Talking to myself...
OK I built it on windows too, and the caption doesn't update there either when you move the fader (in Reaper or Sonar).
And after seeing the windows layout it was clear the Mac one was still wrong. The Mac version was drawing the text at the bottom of the rectangle, and the windows one at the top.
This is what I ended up with in IGraphicsMac.mm to make the mac one look like the windows one (for my simple test anyway):
NSRect r = { pR->L, pR->T, pR->W(), pR->H() };
NSString* str = ToNSString(cStr);
[str drawWithRect:r options: NSStringDrawingUsesDeviceMetrics | NSStringDrawingUsesLineFragmentOrigin attributes: mTxtAttrs];
NSStringDrawingUsesLineFragmentOrigin seems to make it draw starting a the top. I didn't use the mysterious yAdj parameter. However the font did come out 1px shorter on the Mac, not sure why that is.
I have figured out the updating, turns out the fact that it was updating at all (in Ableton Live) was the strange thing, as there's no code in there to update an ICaptionControl when a different control is moved. Live must have been sending the parameter change back to the plugin to make this update happen.
So to get it working how I wanted I added a new member mReadOut to IControl which is just a pointer to another control which should be marked dirty when this control is dirty. Then you can do:
IControl *pFR = new IFaderControl(this, kGainR_X, kGainR_Y, kFader_Len, kGainR, &bitmap, kVertical);
pGraphics->AttachControl(pFR);
IControl *pCR = new ICaptionControl(this, &r2, kGainR, &txt, true);
pGraphics->AttachControl(pCR);
pFR->attachReadOut(pCR);
In IControl.cpp I just have:
void IControl::SetDirty(bool pushParamToPlug)
{
mValue = BOUNDED(mValue, mClampLo, mClampHi);
mDirty = true;
if (pushParamToPlug && mPlug && mParamIdx >= 0) {
mPlug->SetParameterFromGUI(mParamIdx, mValue);
}
if ( mReadOut ) {
mReadOut->SetDirty(false);
}
}
Does this sound sensible??
Edit: an updated version of this is now part of my IPlug additions:
http://forum.cockos.com/showthread.php?t=52820
------------------------------------------------------------------
I decided that readout stuff was crap, and I needed something more general so I could get informed when a control changed. So I implemented a simple observer/subject thing and
made IControl inherit from that, so observers can just register (update gets called from SetDirty)
It's here if anyone's interested:
#ifndef _ISUBJECT_
#define _ISUBJECT_
#include "../ptrlist.h"
/*
* This is based on the Observer design pattern.
* Example: if you want to be able to watch an IControl, then
* IControl should be a public ISubject and should call Notify when it
* is changed. An observer should be a IObserverInterface and call
* Register to register itself with the IControl.
* The update has no parameters, so the observer needs to
* keep track of who it's watching (if this is a problem the update
* method could be changed to deliver a pointer to the subject).
*
* If there are no observers the overhead should just be one extra compare
* (mpObs is NULL). Observers are stored in a WDL_PtrList.
*/
// The Abstract Observer Interface
class IObserverInterface
{
public:
virtual void Update() = 0;
};
// The Subject
class ISubject
{
public:
ISubject() : mpObs(NULL) {}
~ISubject() { delete mpObs; }
void RegisterObserver(IObserverInterface* ob) {
// wdl pointer list has 32 byte granularity as we don't expect many observers
if ( ! mpObs) mpObs = new WDL_PtrList<IObserverInterface>(32);
mpObs->Add(ob);
}
void RemoveObserver(IObserverInterface* ob) {
// note: it is safe to call remove even if you didn't register
// find will return -1 and delete will do nothing
if (mpObs) {
mpObs->Delete(mpObs->Find(ob));
}
}
protected:
void inline NotifyObservers() {
if (mpObs) {
int n = mpObs->GetSize();
for (int i = 0; i < n; ++i) {
IObserverInterface* ob = mpObs->Get(i);
ob->Update();
}
}
}
private:
WDL_PtrList<IObserverInterface> *mpObs;
};
#endif
I found I couldn't really call remove because the IControls get destroyed before my objects when the sequencer exits.
And the changes to IControl.h :
#include "ISubject.h"
class IControl : public ISubject
And in IControl.cpp at the end of SetDiry
NotifyObservers();
lorcan
09-30-2009, 01:54 PM
I've had the same problem under Win, and noticed the caption gets updated when the caption IRect intersects with the fader/knob of the parameter.
If the IRect is outside, it doesn't redraw.
I found out implementing void PLUG_CLASS_NAME::OnParamChange(int paramIdx) and doing a GetGUI()->SetParameterFromPlug(kParam, param_value); forces a redraw.
Strange ... is this a bug ?
Anyway, WDL is great nonetheless !
Jeffos
10-25-2009, 03:38 AM
I confirm this issue (Win).
Thanks for the solutions given here, however they don't work either (!?). The attachReadOut() solution indeed updates the caption but it always looks like "" and lorcan's one smells like deadlock...
I didn't tried the observer solution, though.
Jeffos
10-26-2009, 06:13 AM
ok, the attachReadOut() idea works if the ICaption's rectangle is graphically above the control's one, no matter if they intersect or not... don't ask me why (yet). thanks cc_ !
That is strange. I don't know why that is, I didn't use the readout stuff for very long before I moved on.
I much prefer the Observer solution (it's a genuine Design Pattern even :) ) as it is much more flexible and you can use a Text field to do the displaying.
Also I do not quite understand what ICaptionControl is intended to do - for instance it mostly works as a display, but you can (if I remember correctly) still use it to change the value with the mouse wheel. Maybe that's a bug though?
lorcan
01-17-2010, 04:16 PM
Strangely enough, I haven't encountered any deadlocks (yet ?). There must some kind of test in the update function that prevents this. Of course this may not be the optimal solution in terms of CPU usage.
Jeffos
01-23-2010, 06:56 AM
cc_, lorcan, I see I didn't reply.. yes, forget about that: I was still suckIPluging at that time!
cc_, it works perfectly:
http://stash.reaper.fm/4453/sendR%E9aControl2.gif
I prefer "observing", but in that one I used the "read out" idea: simple other way to chain controls (here: captions + when graying + the multi-bitmap for faders, dynamically sized)
my error, I think, was a confusion between IRECT(x1,y1,x2,y2) vs IRECT(x1,y1,width,height) the latter being ko for text/captions.
lorcan, probably a user error too: re-did the test, no pb (but this isn't the way I refresh, just checked: I don't do anything particular but I remember I tweaked my IPlug a bit..)
but guys!? do you know how to disable anti-aliasing on text ? easy with other controls, still struggling for text..
Astralp
01-23-2010, 05:41 PM
CC, so you are successfully using IPlug on OSX? The example project as AU crashes garageband for me, I wish i knew why... The plug tests ok via the commandline tool.
I have not had any crashes with IPlug on OSX. I have mostly used VST, but I have tried AU a bit.
Did you get debugging working? It's pretty easy, you just tell xcode the path to the executable (which would be Garageband or Reaper or whatever), set a breakpoint in your plugin code and then Run the executable from the menu in xcode. I don't remember the exact steps because I only set it up once months ago and then copied the project for each new plug, but let me know if you can't figure it out.
Astralp
01-24-2010, 12:22 PM
Hi cc thanks for responding. No I didn't, I've become sidetracked with messing around with the native AU projects. I will give it another go, I would love to get it working. I also have the same sorts of probs with VSTs too.
Jeffos: nice to see it all working!
but guys!? do you know how to disable anti-aliasing on text ? easy with other controls, still struggling for text..
There's no way for a particular bit of text. If you want to hack the IPlug files to turn it off on all text, for Win you'll need to modify the CreateFont call in IGraphicsWin.cpp (look in MS's docs for CreateFont to find out which parameter to set) and for OSX search for antialias in IGraphicsMac.mm and make it always true.
Jeffos
01-25-2010, 12:42 AM
There's no way for a particular bit of text. If you want to hack the IPlug files to turn it off on all text
haaa.. that's exactly the answer what I didn't want to hear! I don't thank you for that one cc_ :D !! I guess we can avoid to disable anti-aliasing for -all- texts thanks to bvesco's "Improved font rendering" cool mod (http://forum.cockos.com/showthread.php?t=31080) but for Win only..
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.