Hey everyone, just as a preface, I'm pretty new to wdl-ol and C++ (I have a bit of experience writing Android apps in Java). I really appreciate the community here - it's been tremendously helpful so far.
I'm working on some plugins, and looking forward I'd really like to include some spiffier drawing, ideally through Cairo. So far I've been unable to install/include Cairo in my Xcode project - but I don't really have experience using libraries, especially not for C++ and in Xcode, so I'm not really sure where to go next.
However it's geared toward developing on Windows with Visual Studio, and I haven't been able to get it working. When trying to build the App (linking as either an executable or a dynamic library) I'm getting Mach-O linker errors:
Undefined symbols for architecture x86_64:
"_cairo_arc", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_create", referenced from:
MyCairoControl::MyCairoControl(IPlugBase*, IRECT) in MachoBogusCairoTest.o
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_curve_to", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_destroy", referenced from:
MyCairoControl::~MyCairoControl() in MachoBogusCairoTest.o
"_cairo_fill", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_image_surface_create", referenced from:
MyCairoControl::MyCairoControl(IPlugBase*, IRECT) in MachoBogusCairoTest.o
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_image_surface_get_data", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_move_to", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_paint", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_restore", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_save", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_set_line_width", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_set_operator", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_set_source_rgba", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_stroke", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_stroke_preserve", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
"_cairo_surface_destroy", referenced from:
MyCairoControl::~MyCairoControl() in MachoBogusCairoTest.o
"_cairo_surface_flush", referenced from:
MyCairoControl:raw(IGraphics*) in MachoBogusCairoTest.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It looks to me like I haven't even included the Cairo library, or at least I've included the wrong one.
Do I need to make a build of Cairo specifically for OS X (I've tried this, but I'll admit I have pretty much no idea what I'm doing)?
I think I've checked all the Cairo related threads here, but nothing has been particularly illuminating for me.
If anyone has time, could you let me know (in as much detail as you can bear) how to get Cairo up and running on OS X? Thanks for your time!
Bump. I too have been having difficulty getting Cairo to link to my projects, following that same tutorial, I have arrived at the same set of errors. If anyone could shed some light here, it would be much appreciated.
Thanks gstuff. I'm still getting some linker errors, but there are less. I added the libraries using under the general tab of the build settings for the target, included the header files in the project, and I included cairo.h in my plugin header file.
The build succeeds without any cairo related code, but if I add:
Undefined symbols for architecture x86_64:
"___bzero", referenced from:
_composite_glyphs in cairo.a(cairo-image-compositor.o)
__cairo_image_spans_and_zero in cairo.a(cairo-image-compositor.o)
__cairo_image_finish_spans_and_zero in cairo.a(cairo-image-compositor.o)
_bits_image_fetch_untransformed_repeat_none in pixman-1.a(pixman-bits-image.o)
__cairo_scaled_glyph_lookup in cairo.a(cairo-scaled-font.o)
__cairo_scaled_font_glyph_device_extents in cairo.a(cairo-scaled-font.o)
__pixman_implementation_create in pixman-1.a(pixman-implementation.o)
...
"___sincos_stret", referenced from:
__cairo_default_context_arc in cairo.a(cairo-default-context.o)
__cairo_arc_in_direction in cairo.a(cairo-arc.o)
__cairo_arc_segment in cairo.a(cairo-arc.o)
_cairo_matrix_init_rotate in cairo.a(cairo-matrix.o)
_cairo_matrix_rotate in cairo.a(cairo-matrix.o)
__cairo_pen_init in cairo.a(cairo-pen.o)
"__tlv_bootstrap", referenced from:
_fast_path_cache in pixman-1.a(pixman-implementation.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Interestingly, this: int cV = cairo_version(); doesn't cause problems.
Does the order that the libraries are listed under the build settings matter? I'm not sure what to try next. Any insight would be greatly appreciated.
Many thanks for your libs!
i could successfully staticly link my plugin to cairo with them, unfortunately it works only when the os is newer then 10.9, but beside of that, great!
all the best
styro
My project compiles as is, so you just need to just go through it and mimic the settings. Did you add the same 4 static libs?
cairo.a
pixman-1.a
png.a
freetype.a
When I try and compile your project I get the error: "IGraphics.h" not found. In my project, I've included those four libraries. Do I need to tell Xcode to link them statically? If so, how? Thanks!
To link a static lib, you just need to just need to drag the .a files into General -> Link Frameworks and Libraries or Build Phases > Linked Frameworks and Libraries. Or see Google.
what was somehow confusing that in my first attempts to link with these libs
___sincos_stret
was unresoved...
after some searching i found that i had to set the baseSDK to latest (OSX 10.9 on xcode 5.1.1 on a maverics notebook, osx 10.11 on xcode 7.2.1 a virtual box install of el Capitan) and the deploy to 10.8, then it linked! (after i changed some other stuff (<tr1/functional> had to be changed to <functional> and some typedefs had to be adjusted accordingly)).
Ive gotten everything to compile, (linking the static libraries, making a control file, including the headers, etc)
but while my build succeeds, the app wont launch, (I haven't tried AU or VST yet), and if I try to launch the built app im getting "PowerPC applications are no longer supported"; is this to say that the Cairo library is depreciated?
When build succeeds, I am receiving "Found an unexpected Mach-O header code: 0x72613c21".
I have been following the examples laid out by wordpress above. Install macports, Install Cairo and dependencies with Macports, import everything via search and changed the Mach-O linker type to Static Library...
Also the AU builds, and will appear in Ableton, but will not launch
Any help is appreciated!!
Last edited by CaptnWillie; 02-27-2017 at 12:59 PM.
I found some stuff online regarding the errors I was experiencing, but nothing very helpful.
I remedied the problem by duplicating an existing project, adding the libraries in the search paths, linking the static libraries and including a class that calls methods in Cairo, it worked!
Oh, well done getting it sorted! I've been hacking away at it for ages but didn't succeed. Closest I got was having everything compile but when I opened the plugin in Ableton or AU Lab it would crash instantly.
Got graphics running really nicely in Windows but getting them working on Mac is my main hurdle at the moment. Just to check we're on the same page, can I ask what versions of XCode/WDL/Cairo you're using? Also what Base SDK and Deployment target is set to in your project. Thanks!
Oh, well done getting it sorted! I've been hacking away at it for ages but didn't succeed. Closest I got was having everything compile but when I opened the plugin in Ableton or AU Lab it would crash instantly.
Got graphics running really nicely in Windows but getting them working on Mac is my main hurdle at the moment. Just to check we're on the same page, can I ask what versions of XCode/WDL/Cairo you're using? Also what Base SDK and Deployment target is set to in your project. Thanks!
Im using xcode 8.2.1, SDK to 10.11 deploying to 10.9 (I dont think this matters) the latest release of Cairo installed and upgraded with macports: sudo port install cairo +univestal
make sure you link binary w libraries in your /opt/local/lib/ or /usr/local/lib/ and also point to your header files in /opt/local/include/ etc.
// And we render
cairo_surface_flush(surface);
unsigned int *data = (unsigned int * ) cairo_image_surface_get_data(surface);
// This section is for compatibility. Windows draws differently than Mac.
#ifdef _WIN32
LICE_WrapperBitmap WrapperBitmap = LICE_WrapperBitmap(data, width, height, width, false);
IBitmap result(&WrapperBitmap, width, height);
pGraphics->DrawBitmap(&result, &rect);
#elif defined(__APPLE__)
for(int i = 0; i < (width * height); ++i)
{
// argb to bgra aaaaaaaa rrrrrrrr gggggggg bbbbbbbb to bbbbbbbb gggggggg rrrrrrrr aaaaaaaa
*data = (*data >> 24) | (*data << 24) | ((*data &0xFF0000) >> 8) | ((*data &0xFF00) << 8);
// ___a b__a b_ra bgra
data = data + 1;
}
data = data - (int) (width * height);
LICE_WrapperBitmap WrapperBitmap = LICE_WrapperBitmap(data, width, height, width, false);
IBitmap result(&WrapperBitmap, width, height);
pGraphics->DrawBitmap(&result, &this->mRECT);
#endif
// And we render
return pGraphics->DrawBitmap(&result, &this->mRECT);
};
It still won't work in Ableton, the AU won't work quite yet as the VST won't either... and I can control the position of the graphic with a control knob, but I want to be able to import 2 knobs now, and I'm not quite sure how to do that, where I used kGain through my main project, but I have other parameters, I want to draw a graphic to the position of my release, which is the next hurdle.
let me know if you have any way of handing off more than one handle!
double position = (this->GetParam()->GetMax() - this->GetParam()->Value()) * this->mRECT.H() / 100.;
So basically, I want to define a position for both the kGain and the msetThresh that I have in another class in my xcode project. I don't know how to hand them both to MyCairoControl.h, only one at a time.
And here is my full MyCairoControl.h:
Code:
#ifndef __MY_CAIRO_CONTROL_H__
#define __MY_CAIRO_CONTROL_H__
// In case you forget it
#ifndef CAIRO_OSX_STATIC_BUILD
#define CAIRO_OSX_STATIC_BUILD
#endif
#include <cairo.h>
#include "IControl.h"
#include "HypeCompress.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
class MyCairoControl : public IControl {
protected:
cairo_surface_t *surface;
cairo_t *cr;
public:
MyCairoControl(IPlugBase *pPlug, IRECT pR, int paramIdx) : IControl(pPlug, pR, paramIdx) {
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, this->mRECT.W(), this->mRECT.H());
cr = cairo_create(surface);
};
// destroys old Cairo graphics surface to redraw
~MyCairoControl() {
cairo_destroy(cr);
cairo_surface_destroy(surface);
};
// always redraws graphics
bool IsDirty() { return true; };
bool Draw(IGraphics* pGraphics) {
// We clear the surface
cairo_save(cr);
cairo_set_source_rgba(cr, 0, 0, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_paint(cr);
cairo_restore(cr);
// Links the position of the top of the curve with the value of the THRESHOLD knob
double position = (this->GetParam()->GetMax() - this->GetParam()->Value()) * this->mRECT.H() / 100.;
// creates graphics surface
// cairo_surface_t *surface;
// cairo_t *cr;
// surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, this->mRECT.W(), this->mRECT.H());
// cr = cairo_create(surface);
// We define the main color to use, a red color (cr, R, G, B, Opacity)
cairo_set_source_rgba(cr, 0, .9, 1, 1);
// We draw two bezier lines with one point at top
cairo_set_line_width(cr, 4.);
// First bezier, 0 to middle of graphic
// NOTE that 0:0 coordinate is the top/left corner
// And cairo is position to 0 not where the IControl is placed
// So the bottom/left is at 0 - height position
double width = (double)this->mRECT.W();
double height = (double)this->mRECT.H();
// This is the 0 - half X path
cairo_move_to(cr, 0, height);
cairo_line_to(cr, position, height - position);
// This is the half - full width X path
cairo_move_to(cr, position, height - position);
cairo_line_to(cr, width, height - position);
// Render
cairo_stroke(cr);
// FILL FOR GAIN
cairo_set_source_rgba(cr, 1, 0., 0.7, 0.75);
cairo_set_line_width(cr, 10.);
// This is the 0 - half X path
cairo_move_to(cr, 0, height);
cairo_line_to(cr, 0, position);
// This is the half - full width X path
cairo_move_to(cr, position, 0);
cairo_line_to(cr, width, height - position);
cairo_close_path (cr);
cairo_stroke (cr);
// Now we draw the center points
// We make it more red
cairo_set_source_rgba(cr, 1, 0., 0.7, 0.75);
cairo_set_line_width(cr, 10.);
// Make the circle and fill it
cairo_arc(cr, position, height - position, 4., 0, 2 * M_PI);
cairo_stroke_preserve(cr);
cairo_fill(cr);
// And we render
cairo_surface_flush(surface);
unsigned int *data = (unsigned int * ) cairo_image_surface_get_data(surface);
// This section is for compatibility. Windows draws differently than Mac.
#ifdef _WIN32
LICE_WrapperBitmap WrapperBitmap = LICE_WrapperBitmap(data, width, height, width, false);
IBitmap result(&WrapperBitmap, width, height);
pGraphics->DrawBitmap(&result, &rect);
#elif defined(__APPLE__)
for(int i = 0; i < (width * height); ++i)
{
// argb to bgra aaaaaaaa rrrrrrrr gggggggg bbbbbbbb to bbbbbbbb gggggggg rrrrrrrr aaaaaaaa
*data = (*data >> 24) | (*data << 24) | ((*data &0xFF0000) >> 8) | ((*data &0xFF00) << 8);
// ___a b__a b_ra bgra
data = data + 1;
}
data = data - (int) (width * height);
LICE_WrapperBitmap WrapperBitmap = LICE_WrapperBitmap(data, width, height, width, false);
IBitmap result(&WrapperBitmap, width, height);
pGraphics->DrawBitmap(&result, &this->mRECT);
#endif
// And we render
return pGraphics->DrawBitmap(&result, &this->mRECT);
};
};
#endif
Thanks for the info! Just wondering, you say the AU and VST don't quite work, are you only able to run the app version at the moment?
As for your other question, if I understand right you can add extra methods to your mycairocontrol.h and use those to set the private variables of the class.
Now, although this is the way I'm successfully doing it in my project, I'm not 100% sure this is the correct way, so if anyone has any amendments I'd love to hear them!
Thanks for the info! Just wondering, you say the AU and VST don't quite work, are you only able to run the app version at the moment?
As for your other question, if I understand right you can add extra methods to your mycairocontrol.h and use those to set the private variables of the class.
Now, although this is the way I'm successfully doing it in my project, I'm not 100% sure this is the correct way, so if anyone has any amendments I'd love to hear them!
Perfect! Thank you! I'll have to try that in a moment. I am relatively new to C++. And yes, you are correct that the App is the only thing that builds at the moment... but that amendment to MyCairoControl.h is what allowed it to even work on the app on mac.
I'm not entirely sure why it won't work in ableton as vst or au... VST won't even show up and AU will prompt a message that Ableton couldn't load.
I'm quite new as well! Well, I'm back to coding after a long hiatus. There's lots of concepts to get my head around but it's gradually clicking into place through reading and experimentation.
Shame that it's only the app working so far, but it's a definite start! I'll have a crack with the info you've provided and see if I get anywhere, and hopefully someone can chime in with some extra info to get things moving. Once it's sorted I might be tempted to write something resembling a tutorial, because it's proving a tricky thing to get going so far!
I'm quite new as well! Well, I'm back to coding after a long hiatus. There's lots of concepts to get my head around but it's gradually clicking into place through reading and experimentation.
Shame that it's only the app working so far, but it's a definite start! I'll have a crack with the info you've provided and see if I get anywhere, and hopefully someone can chime in with some extra info to get things moving. Once it's sorted I might be tempted to write something resembling a tutorial, because it's proving a tricky thing to get going so far!
It certainly has. I've been working off an amalgamation of the wordpress tutorial Ive found above, the very limited Cairo instructions, and whatever information I can glean from this forum.
Would love to check back in with you shortly to see if either of us have been able to get the AU or VST in place. They worked on the project that I duplicated before I included Cairo stuff... so hopefully they just require a little kick in the right direction to get working like the app.
I will release cairo support with my framework soon, but I still need to fix some bugs... Anyways you can see my plugin that uses cairro with GUI resize-scale functikn here:
Thanks for the info! Just wondering, you say the AU and VST don't quite work, are you only able to run the app version at the moment?
As for your other question, if I understand right you can add extra methods to your mycairocontrol.h and use those to set the private variables of the class.
Now, although this is the way I'm successfully doing it in my project, I'm not 100% sure this is the correct way, so if anyone has any amendments I'd love to hear them!
So i'm trying to call them into my cairo drawing header MyCairoControl.h, from a class Envelope.cpp, I have called them into my main routine in a similar matter, but how do I call them into the header where Im doing all my Cairo at the moment which is then called into the main routine?
but what I am having trouble with, is passing a reference for all of these parameters to my Cairo header MyCairoControl.h; I can pass kGain or msetThresh or whichever ONE parameter I choose following the directions in the wordpress tutorial, but I am finding difficulty referencing all my parameters, which I would like to use to draw my compressor knee with cairo: i.e. use the threshold to set position of the knee, using the ratio to set the height of the transfer function after the knee.
I hope I made everything clear enough! I can take a little screen capture video of my project and walk you guys around if you want haha. Like I said, Im pretty new so any help is really appreciated
Personally I'd have it so that whenever a control is changed, it updates the mThreshold value in your simplecomp.cpp, and passes the value to the mycairocontrol.h, which then copies it to its own mThreshold variable.
The mycairocontrol draw() method will be automatically called when it needs to be called, and that uses its own variables of mThreshold, mRatio etc.
processReplacing() in simplecomp.cpp will be using its own Threshold variable.
and in simplecomp.cpp's onParamChange, you'd have
Code:
case kThresh:
mGain = GetParam(kThresh)->Value() / 100.;
pMyControl->setThresh(GetParam(kThresh)->Value());
break;
Now, similar things can be achieved using pointers, but I'm not fully sure on dealing with those. It's along the same lines as what I was asking in this thread, but I never got a clear answer to my question!
Personally I'd have it so that whenever a control is changed, it updates the mThreshold value in your simplecomp.cpp, and passes the value to the mycairocontrol.h, which then copies it to its own mThreshold variable.
The mycairocontrol draw() method will be automatically called when it needs to be called, and that uses its own variables of mThreshold, mRatio etc.
processReplacing() in simplecomp.cpp will be using its own Threshold variable.
and in simplecomp.cpp's onParamChange, you'd have
Code:
case kThresh:
mGain = GetParam(kThresh)->Value() / 100.;
pMyControl->setThresh(GetParam(kThresh)->Value());
break;
Now, similar things can be achieved using pointers, but I'm not fully sure on dealing with those. It's along the same lines as what I was asking in this thread, but I never got a clear answer to my question!
Thanks again for the help. My partner and I have been able to get your methods working in our project.
One question that I still have is that he and I are unable to trade projects back and forth - we use the same copy of xcode, SDKs, library installations and directories, and mach-O linker type, but when we try to share a project in xcode, we always get a linker error with
Code:
linker command failed with exit code 1 (use -v to see invocation)
You could try clicking Clean Project, that'd be my first call.
You say the directories are the same, are they also located at the same place on the hard drive? ie, both at c:/wdl-ol
It's really weird - we have been keeping our projects inside the IPlugExamples folder in WDL-OL, and library paths, so that shouldn't matter.
we can both compile and run the demo projects and some projects downloaded online, but it is the sharing of projects that isn't compatible.
Also we haven't had any luck getting the VST or the AU to load correctly in Ableton. It will show up when searched for the AU, but it will return "Ableton could not load plug in" if we try to drop it into a track, and then it will crash ableton.
Other than that, drawing with Cairo has been great and things are looking super
Im the one who wrote down the article at the first place. First of all I don't have so much time about audio plugin that's why I'm not there so often, sorry for that.
Second, cairo is supported on mac, no problem on this, it's the based of too many projects now to be dropped (notably it's part of Gecko, the Firefox engine...).
So if there is a problem with it, it's you/your computer not cairo.
Now, honestly cairo is a bitch, a real one, to compile and have it working is a huge pain in the ass, that's why I wrote down this article + give library pre-compiled (so people avoid all that shit as much as possible).
What you read, took me 2/3 -almost full- days to figure it out, so compiling it is not easy at all. But once setup correctly, it works like a charm.
I would recommand you to also follow Youlean works, he as stepped up the whole cairo stuff to a new level, check what he has done (I think he has release something no?) because that would be a much more clean approach to cairo stuff in general (as his work is based on mine + days of days of work on top of this).
Hope this helps you a little, last but not least, don't give up, it's rewarding
I will try to release cairo support in my fork until end of this week... This will also be 1.0.0 version of my version of IPlug. There will be some bugs, but this will be sorted in the future.
Im the one who wrote down the article at the first place. First of all I don't have so much time about audio plugin that's why I'm not there so often, sorry for that.
Second, cairo is supported on mac, no problem on this, it's the based of too many projects now to be dropped (notably it's part of Gecko, the Firefox engine...).
So if there is a problem with it, it's you/your computer not cairo.
Now, honestly cairo is a bitch, a real one, to compile and have it working is a huge pain in the ass, that's why I wrote down this article + give library pre-compiled (so people avoid all that shit as much as possible).
What you read, took me 2/3 -almost full- days to figure it out, so compiling it is not easy at all. But once setup correctly, it works like a charm.
I would recommand you to also follow Youlean works, he as stepped up the whole cairo stuff to a new level, check what he has done (I think he has release something no?) because that would be a much more clean approach to cairo stuff in general (as his work is based on mine + days of days of work on top of this).
Hope this helps you a little, last but not least, don't give up, it's rewarding
Awesome, you guys are the best. Thank you sincerely for the documentation so far, Ive got Cairo to compile and I love working with it, and I'm hoping to continue working with it
Quote:
Originally Posted by Youlean
I will try to release cairo support in my fork until end of this week... This will also be 1.0.0 version of my version of IPlug. There will be some bugs, but this will be sorted in the future.
Thanks a lot Youlean, I'm looking forward to it!
In the meantime, we have been successful in getting operational graphics acting as peak meters, and a compression knee with Cairo and our plugin using buffers and for loops, but we haven't exactly determined the best method to do any sense of fading, i.e. the peak jitters around a lot, and either alpha fading over time or some kind of peak fall time would be great to try to figure out. Any tips?
So I've stumbled across this and wondered if the drawing and animation we are doing with Cairo is to blame that it doesn't load in Ableton or other DAWs.
which states a new thread that does the redrawing with some kind of autobrake to only permit the drawing function on certain defined framerates.
Basically I think by changing parameters and reading in audio, it is drawing far too many frames, eating away at my CPU, looking very jittery, etc.
Does anyone have any insight into this issue, or any methods they have used to get the AU or VST to build correctly? Our plugin worked fine in ableton and DAWs until we started including Cairo for the drawing.
any tips you can share on smoothing your graphics / meters?
Cairo drawing with above method is slow and that's why you might have a problem. My framework should be a lot faster (I can't remember but it might be even 5x faster)...
Cairo drawing with above method is slow and that's why you might have a problem. My framework should be a lot faster (I can't remember but it might be even 5x faster)...
You are the best. I really do appreciate the help.
It compiled right out of the zip, and loaded into ableton without a hitch! I'm going to commute my projects into your framework, and hopefully i'll still be singing the same tune.
You are the best. I really do appreciate the help.
It compiled right out of the zip, and loaded into ableton without a hitch! I'm going to commute my projects into your framework, and hopefully i'll still be singing the same tune.