Recently on the list, there was a question regarding creating your own protocols for QC. This is perhaps a 3+ part problem, and I've only addressed 1. Never the less, it's a good start I think :)
The Parts:
- The Edit Conformance Information menu (I've addressed this one)
- The Composition Repository patch (not addressed)
- The New From Template Dialog (not addressed)
Making a new protocol is actually really simple. Using our "Skanky SDK" template makes it a snap.
Create a new project. Remove the CustomPatch.h, CustomPatch.m, CustomPatchUI.h, and CustomPatch.m files in the Patches directory (we don't need them for this exercise). The function we'll be working on is registerNodesWithManager:
, located in CustomPatchPrincipal.m. Remove references and #imports of these files too.
Add these following lines before the @implementation
line:
@interface QCCompositionRepository: NSObject
@end
This tells the compiler a bit about the Compo Repo that we're working with (actually, it doesn't say much at all, just that it's an extant class).
Next, clear out the registerNodesWithManager
function. We're not adding patches, so we don't need any of the auto-generated stuff in there.
Next, the protocol dictionary construction!:
// add and remove your specific keys to the
// appropriate structs -- Use the port's class
// as the object, and a name that follows the pattern
[optionalInputDict setObject:[QCStructurePort class]
forKey:@"_protocolInput_OptionalInputStruct"];
[requiredInputDict setObject:[QCStructurePort class]
forKey:@"_protocolInput_RequiredInputStruct"];
[optionalOutputDict setObject:[QCStructurePort class]
forKey:@"_protocolInput_OptionalOutputStruct"];
[requiredOutputDict setObject:[QCStructurePort class]
forKey:@"_protocolInput_RequiredOutputStruct"];
// here we set some metadata about the protocol:
// the display name (in the conformance dialog),
// and whether or not we allow consumer patches.
// (True in this example)
[infoDict
setObject:@"My Protocol's Display Name"
forKey:@"name"];
[infoDict
setObject
:[NSNumber numberWithBool
:TRUE
] forKey:@"allowConsumers"];
// We add the required and optional inputs
// to the protocol dictionary...
[infoDict setObject:optionalInputDict
forKey:@"optionalInputKeys"];
[infoDict setObject:requiredInputDict
forKey:@"requiredInputKeys"];
[infoDict setObject:optionalOutputDict
forKey:@"optionalOutputKeys"];
[infoDict setObject:requiredOutputDict
forKey:@"requiredOutputKeys"];
// the we register it!
[[QCCompositionRepository sharedCompositionRepository]
registerProtocol:@"com.MyCompanyName.My-Protocol-Name"
withDescription:infoDict];
// here you should release all the dictionaries.
// I'm lazy though, so you'll have to write that
// yourself.
Feel free to use this code however you want. If you do though, please drop me a line or comment on this post, so I know I didn't waste all this time for nothing :)
Hi Chris,
I am not sure if this is what I think it is - would it be possible with this to write a custom protocol to export image data from Quartz Composer over the network, for instance?
Let's say, to play out a visual composition onto a LED wall? :-)
I would be interested in getting in touch with you, yet I can't seem to find any email address for you...
you can join me at info at multimedial dot de.
Looking forward to your answer,
C. Leske
@multimedial: @cwright wrote that post 4.5 years ago; he no longer works for Kosada/Kineme.
If you want to send image data over the network, your best option is probably to use the
Render In Image
patch to produce image data (instead of rendering it to screen), and either send it over the network by writing a consumer node, or by converting the image to a data stream using Kineme DataTools and POSTing it to an HTTP server using Kineme NetworkTools.To send an image to an LED wall, you can either:
Render In Image
connected toImage PixelS
connected to Kineme ArtNetTools.To add some clarification to what Chris means by custom protocols, he's not referring to a custom data type that happens at the port/noodle level.
What he's referring to are the built in "composition types" (templates) that QC has. You can access most of them via the Templates option in the QC Editor.
Protocols suggest:
-Certain execution modes. For instance, Image Filters have no consumers, and are basically processors. Graphic Animation compositions always have consumers.
-Getting info from specific sources, to serve a niche purpose. Music Visualizers can get audio info, Graphic Animations can receive Pace and X/Y mouse position info, etc.
-Certain patches being loaded on the associated template compositions. Usually the patches loaded on the templates are optional, but there may be embargoes on adding patches with certain processor modes (a Consumer patch can't be on the root level of an Image Filter, for example).
Compositions that are placed in any of the Composition folders (in any of the three Libraries), can be queried by protocol type, and loaded by custom apps you make. So, you could have an app that filters images, and query the Composition Repository for compositions that only conform to the Image Filter protocol. Since you know that every Image Filter protocol composition has an image out, you can make certain assumptions about execution mode, and your ability to pass an image through. This is really a pretty handy function of QC, and is somewhat analogous with the way one can load Core Image filters by calling certain categories.