loading un official components from qc plug-in.

dust's picture

so this is a general question in regards to the qc runtime environment. so i have lost a lot of sleep trying to get a QC plugin to load an external audio unit plugin from a component bundle. all is not at a loss because the journey down this road has enabled me to learn a lot more about audio unit programing than i originally intended while trying to make a simple AU Host.

what is happening is during the qc runtime of the plugin qc apparently only loads up and registers only "apple" core audio units. which are located in directory /System/Library/Components/

the audio units i am trying to load are located in the /Library/Audio/Plug-Ins/Components directory.

what is strange to me is that if i run my plugin as an application in the console everything works, but once i run the code using qc to with the same code qc will only find apple components. it seems the issue is with the quartz runtime environment.

does anybody know what the trick is to circumnavigate this issue making it possible to load external components ? i find it hard to believe that this would not be possible. i know QC is intended for motion graphics but given that context i would also like to be able to load my camera component bundle up as well so QC will recognize my camera but i'm reluctant to even try that given the headaches i'm getting trying to load up a simple AU graph.

i have implemented various methods in an attempt to load up components that normally are automatically loaded.

some methods i have tried. load NSbundle from path. load NSPlugin from path. load Component from FSPath load Component from CFURL load Component from resource etc...

i have wrote a script that dynamically registers all the components in a given path. I have used instruments file activity to verify that quartz composer does in-fact find the directory and not only does it find the directory but registers all the components in that path dynamically all in one shot. this is the call Instruments verifies.

"CFURLCreateDataAndPropertiesFromResources" /Library/Audio/Plug-ins/

So i know my code is working one because it works in the console standalone and 2 because Instruments verifies that qc is actually doing what i asked it do.

All is not at a loss i have figured out how to make an official and un official plugin. i have made an AU factory to instantiate Audio unit parameters, i also have learned how to load the views into a qc patch settings nib, which is cool because 1 you get parameters to automate and 2 you also get the GUI made by the manufacturer of the audio unit.

it is great an all that this works in the context of an application bundle but that really defeats the purpose of me making an AU Host plugin for QC. I mean Garage Band and Au Lab come for free as it is which are easy enough to integrate into the multi task environment with qc but still....

so given all that the system core audio components and effects that qc recognizes are very powerful but i don't find a plugin of this type to be very effective if i can't load my own component up in qc let alone someone else's component. given that everybody uses the core audio unit component manager and CA API this is pretty standard stuff for the desktop and iphone. i am not using any external libs or frameworks its all apple API so I am confident that this is entirely possible.

any suggestions from anybody that knows c, c++, obj c, obj c++, qc etc...

i feel that people would find this type of plugin very useful and most defiantly will share it.

cwright's picture
Re: loading un official components from qc plug-in.

the QC environment doesn't do anything regarding component loading -- it's the same in and out of QC.

I have a single test AU (non-apple) on hand, and it successfully gets loaded from /Library/Audio/Plug-Ins/Components/ as well as ~/Library/Audio/Plug-Ins/Components/

Perhaps check your enumeration code? Component enumeration is ridiculously contrived and error-prone.

dust's picture
Re: loading un official components from qc plug-in.

yeah the enumeration codes are essential. there are a few ways to get them. open the component resource file and look for them if you know what you are looking for, and or run a validation from the terminal which gives me to much info.

right now i just loop through a found component description and print the component type, subtype and manufacturer. usually i set the initial component description to search for type 'aumu' i am more interested in getting the virtual synths to work. if i set the component search types to 0; i get a really long list and have to wait while it prints so making a search component description is essential.

well this is good news that qc will load components other than core audio system stuff.

so on your system are you explicitly entering the enumeration codes or using find next component ?

are you loading the unit from a bundle with path ? are you using the @rpath or FS-script.

or are you just letting the Component Manager do its thing like its supposed to and picking your component out from a list ?

are you using the official or un official classes ? i noticed the un official takes a little longer to load than the official.

i was hoping its just a setting in the x code build tab or something seeing every thing works as app.

i will clean up one of the many plugin projects i have created and upload it maybe you or someone can have a look ?

im taking a break right now and making a IR pass filter for ps3 eye camera that would be cool to use in QC. maybe i will have more luck loading a QT component.

i will test on another system to make sure my computers not messed up.

cwright's picture
Re: loading un official components from qc plug-in.

I use FindNextComponent -- be sure to zero out your ComponentDescription thing, and set as little as possible, otherwise you might miss some. In my test, I just set .componentType to kAudioUnitType_{Output|Effect|etc etc.}.

r_path only works when you're linking code -- I don't think that applies to non-linked resources (bundles etc.).

I was only using skanky SDK - I really don't spend any time in the official api because it's annoying and lame.

If you're wanting to load a component from within your bundle (as a resource), perhaps you should try "RegisterComponentFileRef" ? You'll need to convert your component path (inside your bundle's resources folder) to an FSRef, but otherwise I think that'll load it up for you?

(man, I wish they'd modernize these things, and get rid of components... so archaic in otherwise-pretty obj-c code :)

dust's picture
Re: loading un official components from qc plug-in.

i have tried RegisterComponentFileRef both with a user defined path and a plugin bundle path. i have used a CFBundleRef and a CFURLRef like this.

mainBundleRef = CFBundleGetMainBundle(); mainBundleRef = CFBundleCreate(allocator, bundleURL);

also i have tried CFGetFSRef from a FSRef as well as the Cocoa method of alloc bundle from path using dlopen ?

im with you on this component and core audio api being not pretty and well dated. i found mixing the c++ api's with obj-c works well but gets confusing when i forget to load up the cocoa framework.

actually i just found out about the openFrameworks QCPlugin addon. Im going to try and use OFX and see if that makes a difference. i would think i should be able to do this with standard apple frameworks.

here is a skanky sdk component printer patch maybe it will work on your computer, maybe its SL thing im not sure.

going to try with OFX and build for tiger with gcc 4.0 and see if that makes a difference.

QCAU.zip80.84 KB

cwright's picture
Re: loading un official components from qc plug-in.

main bundle in a QC plugin will give you QC's bundle, not your plugin's -- that may be part of your problem. please don't bother with dlopen unless you're extraordinarily talented and know what you're doing (dlopen is the very low-level way of loading plugins, there's no real reason to use it instead of NSBundle/CFBundle in this context).

to load the component using RegisterComponentFileRef, I don't think you need the bundle at all, just an FSRef (created from the path to the component you're trying to load) -- Component Manager should do the loading for you automagically.

I don't think oFX will help with component loading, but I could be mistaken.

Looking over your code briefly, I'm pretty sure the mainBundle thing is wrong, which causes the loading to never happen (you're using QC's bundle, not your plugin's) -- also, you're expecting only one AU per component file -- I think a component can have multiple units per component file (I'm really rusty on that though, so it's possible I'm incorrect -- not important for this problem really, but just a detail).

dust's picture
Re: loading un official components from qc plug-in.

yes a component can have multiple units. for example the core audio component that QC recognizes has 73 units inside of it. they are declared in the components .rscr file. it seems almost all components not just the audio components have to comply to this type of structure in order for the component manager to recognize them. in addition i think its mandatory to register your components enum codes with apple. i'm not really sure why but i suppose if you did not do this you could be getting some sort of namespace enum code collision conflicts or something.

after your suggestion of trying to load the component from the plugin bundle i changed the CFBundleRef to the get the main bundle thinking that would be the plugin not QC so that does seem to make since as to why the component can't be found. actually i don't really want to use the the bundle stuff at all. i had my code set up that way because thats how apple suggests registering components from a directory with CFCreateBunldRef using a CFURLRef. then using those references to create a FSRef that you use to register a component with.

i have been using FSRef in the DLS synth plugin to load banks so i will try just using a FSRef to register the bundle. Actually with the RegisterComponentFileRef it uses the .plist and .rsrc to register the component as whole then you use the component description to graph your au nodes out so you can here the sounds. Like I said I have been able to do all of this by building an application, so I have the au graphing and midi sysex stuff down just trying to get QC to register my component is my problem. i will try and nock out all the BundleRef stuff and just make a FSRef from a char* string and see if that works.

Do you think if I am using just a FSRef that I will be using a path to the component to or to the component exe or to the components resource file ?

i will try all 3 and see if that works