10 #define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
16 #include <OpenGL/CGLMacro.h>
17 #include <QuartzCore/CoreImage.h>
19 #include <dispatch/dispatch.h>
46 @property dispatch_queue_t runnerQueue;
48 @property (retain) NSURL *compositionURL;
49 @property (retain) NSString *compositionString;
50 @property (retain) NSString *compositionSourcePath;
51 @property (retain) NSString *compositionProcessName;
56 @property set<VuoRunner::Port *> *changedPorts;
60 @synthesize runnerQueue;
62 @synthesize compositionURL;
63 @synthesize compositionString;
64 @synthesize compositionSourcePath;
65 @synthesize compositionProcessName;
70 @synthesize changedPorts;
82 + (void)setGlobalRootContext:(CGLContextObj)context
111 + (BOOL)isComposition:(NSURL *)compositionURL compliantWithProtocol:(
VuoProtocol *)protocol
124 + (BOOL)isCompositionString:(NSString *)compositionString compliantWithProtocol:(
VuoProtocol *)protocol
126 VuoRunnerCocoa *runner = [[
VuoRunnerCocoa alloc] initWithCompositionString:compositionString name:@"" sourcePath:nil protocol:protocol];
137 - (id)initWithComposition:(NSURL *)theCompositionURL protocol:(
VuoProtocol *)theProtocol
140 NSString *s = [NSString stringWithContentsOfURL:theCompositionURL encoding:NSUTF8StringEncoding error:&error];
143 NSLog(
@"[VuoRunnerCocoa initWithComposition:protocol:] Error reading composition: %@", error);
148 self = [
self initWithCompositionString:s name:[theCompositionURL lastPathComponent] sourcePath:nil protocol:theProtocol];
152 self.compositionURL = theCompositionURL;
160 - (id)initWithCompositionString:(NSString *)theCompositionString name:(NSString *)processName sourcePath:(NSString *)sourcePath protocol:(
VuoProtocol *)theProtocol
162 if (!(
self = [super init]))
165 self.protocol = theProtocol;
167 self.runnerQueue = dispatch_queue_create(
"org.vuo.runner.cocoa", NULL);
170 self.compositionString = theCompositionString;
171 const char *compositionCString = [
self.compositionString UTF8String];
178 self.compositionProcessName = processName;
179 self.compositionSourcePath = sourcePath;
182 self.compositionName = [NSString stringWithUTF8String:metadata.getName().c_str()];
183 self.compositionDescription = [NSString stringWithUTF8String:metadata.getDescription().c_str()];
184 self.compositionCopyright = [NSString stringWithUTF8String:metadata.getCopyright().c_str()];
186 self.changedPorts =
new set<VuoRunner::Port *>();
196 dispatch_sync(
self.runnerQueue, ^{
203 dispatch_release(
self.runnerQueue);
204 [compositionURL release];
205 [compositionString release];
206 [compositionSourcePath release];
207 [compositionName release];
208 [compositionDescription release];
209 [compositionCopyright release];
210 delete self.changedPorts;
214 - (void)compileAndRun
218 dispatch_sync(
self.runnerQueue, ^{
220 if (
self.compositionURL)
222 [[
self.compositionURL path] UTF8String],
226 [
self.compositionString UTF8String],
227 [
self.compositionProcessName UTF8String],
228 [
self.compositionSourcePath UTF8String],
236 self.runner->start();
237 self.runner->subscribeToEventTelemetry(
"");
241 vector<VuoRunner::Port *> allInputPorts =
self.runner->getPublishedInputPorts();
242 std::copy_if(allInputPorts.begin(), allInputPorts.end(), std::inserter(*
self.changedPorts,
self.changedPorts->begin()),
259 dispatch_sync(
self.runnerQueue, ^{
260 if (
self.runner && !
self.runner->isStopped())
269 - (NSString *)description
271 return [NSString stringWithFormat:@"VuoRunnerCocoa(\"%@\")", compositionName];
283 NSMutableArray *portsArray = [[NSMutableArray new] autorelease];
284 vector<VuoRunner::Port *> ports =
self.runner->getPublishedInputPorts();
285 for (vector<VuoRunner::Port *>::iterator it = ports.begin(); it != ports.end(); ++it)
286 if (
self.protocol && !
self.protocol->
hasInputPort((*it)->getName()))
287 [portsArray addObject:[NSString stringWithUTF8String:(*it)->getName().c_str()]];
300 NSMutableArray *portsArray = [[NSMutableArray new] autorelease];
301 vector<VuoRunner::Port *> ports =
self.runner->getPublishedOutputPorts();
302 for (vector<VuoRunner::Port *>::iterator it = ports.begin(); it != ports.end(); ++it)
303 if (
self.protocol && !
self.protocol->
hasOutputPort((*it)->getName()))
304 [portsArray addObject:[NSString stringWithUTF8String:(*it)->getName().c_str()]];
337 - (NSDictionary *)detailsForPort:(NSString *)portName
339 const char *portNameCString = [portName UTF8String];
340 VuoRunner::Port *port =
self.runner->getPublishedInputPortWithName(portNameCString);
343 port =
self.runner->getPublishedOutputPortWithName(portNameCString);
348 NSMutableDictionary *details = [[NSMutableDictionary new] autorelease];
350 details[@"title"] = [NSString stringWithUTF8String:port->getName().c_str()];
352 details[@"type"] = [NSString stringWithUTF8String:port->getType().c_str()];
359 if (json_object_object_get_ex(js,
"default", &o))
363 details[@"default"] = cocoaObject;
366 if (json_object_object_get_ex(js,
"suggestedMin", &o))
370 details[@"suggestedMin"] = cocoaObject;
373 if (json_object_object_get_ex(js,
"suggestedMax", &o))
377 details[@"suggestedMax"] = cocoaObject;
380 if (json_object_object_get_ex(js,
"suggestedStep", &o))
384 details[@"suggestedStep"] = cocoaObject;
387 if (json_object_object_get_ex(js,
"menuItems", &o))
389 NSMutableArray *menuItems = [NSMutableArray new];
391 int itemCount = json_object_array_length(o);
392 for (
int i = 0; i < itemCount; ++i)
394 json_object *item = json_object_array_get_idx(o, i);
397 if (json_object_is_type(item, json_type_object))
400 json_object_object_get_ex(item,
"value", &value);
402 json_object_object_get_ex(item,
"name", &name);
405 if (json_object_is_type(value, json_type_string))
406 valueNS = [NSString stringWithUTF8String:json_object_get_string(value)];
407 else if (json_object_is_type(value, json_type_int))
408 valueNS = [NSNumber numberWithLong:json_object_get_int64(value)];
410 const char *summary = json_object_get_string(name);
413 @"name": [NSString stringWithUTF8String:summary],
416 else if (json_object_is_type(item, json_type_string))
417 menuItem = [NSString stringWithUTF8String:json_object_get_string(item)];
420 [menuItems addObject:menuItem];
423 details[@"menuItems"] = menuItems;
439 NSMutableDictionary *properties = [[NSMutableDictionary new] autorelease];
441 vector<VuoRunner::Port *> ports =
self.runner->getPublishedInputPorts();
442 for (vector<VuoRunner::Port *>::iterator it = ports.begin(); it != ports.end(); ++it)
443 if (
self.protocol && !
self.protocol->
hasInputPort((*it)->getName()))
445 json_object *portValue =
self.runner->getPublishedInputPortValue(*it);
446 const char *valueAsString = json_object_to_json_string_ext(portValue, JSON_C_TO_STRING_PLAIN);
447 properties[[NSString stringWithUTF8String:(*it)->getName().c_str()]] = [NSString stringWithUTF8String:valueAsString];
459 - (BOOL)setInputValuesWithPropertyList:(
id)propertyList
464 __block BOOL ok = YES;
465 __block map<VuoRunner::Port *, json_object *> m;
466 [(NSDictionary *)propertyList enumerateKeysAndObjectsUsingBlock:^(NSString *portName, NSString *value, BOOL *stop) {
467 VuoRunner::Port *port = self.runner->getPublishedInputPortWithName([portName UTF8String]);
474 json_object *valueJson = json_tokener_parse([value UTF8String]);
484 runner->setPublishedInputPortValues(m);
488 self.changedPorts->insert(kv.first);
489 json_object_put(kv.second);
510 - (BOOL)setInputValues:(NSDictionary *)namesAndValues
516 map<VuoRunner::Port *, json_object *> m;
517 for (NSString *portName in namesAndValues)
519 VuoRunner::Port *port =
self.runner->getPublishedInputPortWithName([portName UTF8String]);
526 id value = namesAndValues[portName];
537 self.runner->setPublishedInputPortValues(m);
541 self.changedPorts->insert(kv.first);
542 json_object_put(kv.second);
555 - (BOOL)setInputJSON:(NSDictionary *)namesAndJSON
561 map<VuoRunner::Port *, json_object *> m;
562 for (NSString *portName in namesAndJSON)
564 VuoRunner::Port *port =
self.runner->getPublishedInputPortWithName([portName UTF8String]);
571 id nsValue = namesAndJSON[portName];
575 if (port->
getType() ==
"VuoImage")
577 if (json_object_get_type(value) == json_type_string)
579 char *s = strdup(json_object_get_string(value));
583 NSLog(
@"Error: Couldn't load image '%s'.\n", s);
597 self.runner->setPublishedInputPortValues(m);
600 self.changedPorts->insert(kv.first);
622 - (id)valueForOutputPort:(NSString *)portName
627 VuoRunner::Port *port =
self.runner->getPublishedOutputPortWithName([portName UTF8String]);
631 json_object *valueJson =
self.runner->getPublishedOutputPortValue(port);
644 - (GLuint)glTextureWithTarget:(GLuint)target forOutputPort:(NSString *)portName outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh
649 VuoRunner::Port *port =
self.runner->getPublishedOutputPortWithName([portName UTF8String]);
653 json_object *valueJson =
self.runner->getPublishedOutputPortValue(port);
657 json_object_put(valueJson);
659 if (target == GL_TEXTURE_RECTANGLE_ARB)
664 vuoImage = newVuoImage;
667 if (outputPixelsWide)
669 if (outputPixelsHigh)
696 - (GLuint)glTextureFromProvider:(GLuint (^)(NSUInteger pixelsWide, NSUInteger pixelsHigh))provider forOutputPort:(NSString *)portName outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh ioSurface:(IOSurfaceRef *)outputIOSurface
701 VuoRunner::Port *port =
self.runner->getPublishedOutputPortWithName([portName UTF8String]);
705 json_object *valueJson =
self.runner->getPublishedOutputPortValue(port);
707 GLuint (^provider2)(
unsigned int,
unsigned int) = ^GLuint(
unsigned int pixelsWide,
unsigned int pixelsHigh){
708 return provider(pixelsWide, pixelsHigh);
710 unsigned int outputPixelsWide2, outputPixelsHigh2;
712 *outputPixelsWide = outputPixelsWide2;
713 *outputPixelsHigh = outputPixelsHigh2;
714 return outputTexture;
724 + (BOOL)canOpenComposition:(NSURL *)compositionURL
726 return [
self isComposition:compositionURL compliantWithProtocol:VuoProtocol::getProtocol(VuoProtocol::imageFilter)];
732 + (BOOL)canOpenCompositionString:(NSString *)compositionString
734 return [
self isCompositionString:compositionString compliantWithProtocol:VuoProtocol::getProtocol(VuoProtocol::imageFilter)];
743 - (id)initWithComposition:(NSURL *)aCompositionURL
748 [
self compileAndRun];
762 - (id)initWithCompositionString:(NSString *)aCompositionString name:(NSString *)name sourcePath:(NSString *)sourcePath
767 [
self compileAndRun];
777 static void VuoRunnerCocoa_doNothingCallback(
VuoImage imageToFree)
784 - (BOOL)executeWithGLTexture:(GLuint)textureName target:(GLuint)target pixelsWide:(
unsigned long)pixelsWide pixelsHigh:(
unsigned long)pixelsHigh atTime:(NSTimeInterval)time
790 VuoRunner::Port *port =
self.runner->getPublishedInputPortWithName(
"image");
796 map<VuoRunner::Port *, json_object *> m;
798 self.runner->setPublishedInputPortValues(m);
799 json_object_put(valueJson);
801 self.changedPorts->insert(port);
804 return [
self executeAtTime:time];
810 - (BOOL)executeAtTime:(NSTimeInterval)time
815 VuoRunner::Port *timePort =
self.runner->getPublishedInputPortWithName(
"time");
819 map<VuoRunner::Port *, json_object *> m;
820 m[timePort] = valueJson;
821 self.runner->setPublishedInputPortValues(m);
822 json_object_put(valueJson);
824 self.changedPorts->insert(timePort);
827 self.runner->firePublishedInputPortEvent(*
self.changedPorts);
828 self.changedPorts->clear();
830 self.runner->waitForFiredPublishedInputPortEvent();
847 - (NSImage *)filterNSImage:(NSImage *)image atTime:(NSTimeInterval)time
851 if (![
self executeAtTime:time])
871 - (GLuint)filterGLTexture:(GLuint)textureName target:(GLuint)target pixelsWide:(NSUInteger)pixelsWide pixelsHigh:(NSUInteger)pixelsHigh atTime:(NSTimeInterval)time outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh
873 if (![
self executeWithGLTexture:textureName target:target pixelsWide:pixelsWide pixelsHigh:pixelsHigh atTime:time])
907 - (GLuint)filterGLTexture:(GLuint)textureName target:(GLuint)target pixelsWide:(NSUInteger)pixelsWide pixelsHigh:(NSUInteger)pixelsHigh atTime:(NSTimeInterval)time withTextureProvider:(GLuint (^)(NSUInteger pixelsWide, NSUInteger pixelsHigh))provider outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh ioSurface:(IOSurfaceRef *)outputIOSurface
909 if (![
self executeWithGLTexture:textureName target:target pixelsWide:pixelsWide pixelsHigh:pixelsHigh atTime:time])
927 @synthesize previousSuggestedPixelsWide;
928 @synthesize previousSuggestedPixelsHigh;
933 + (BOOL)canOpenComposition:(NSURL *)compositionURL
935 return [
self isComposition:compositionURL compliantWithProtocol:VuoProtocol::getProtocol(VuoProtocol::imageGenerator)];
941 + (BOOL)canOpenCompositionString:(NSString *)compositionString
943 return [
self isCompositionString:compositionString compliantWithProtocol:VuoProtocol::getProtocol(VuoProtocol::imageGenerator)];
952 - (id)initWithComposition:(NSURL *)aCompositionURL
957 [
self compileAndRun];
961 self.previousSuggestedPixelsWide = NSUIntegerMax;
962 self.previousSuggestedPixelsHigh = NSUIntegerMax;
974 - (id)initWithCompositionString:(NSString *)aCompositionString name:(NSString *)name sourcePath:(NSString *)sourcePath
979 [
self compileAndRun];
989 - (BOOL)executeWithSuggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time
994 VuoRunner::Port *timePort =
self.runner->getPublishedInputPortWithName(
"time");
995 VuoRunner::Port *widthPort =
self.runner->getPublishedInputPortWithName(
"width");
996 VuoRunner::Port *heightPort =
self.runner->getPublishedInputPortWithName(
"height");
998 map<VuoRunner::Port *, json_object *> m;
1002 if (suggestedPixelsWide !=
self.previousSuggestedPixelsWide)
1005 self.previousSuggestedPixelsWide = suggestedPixelsWide;
1007 if (suggestedPixelsHigh !=
self.previousSuggestedPixelsHigh)
1010 self.previousSuggestedPixelsHigh = suggestedPixelsHigh;
1013 self.runner->setPublishedInputPortValues(m);
1016 self.changedPorts->insert(kv.first);
1017 json_object_put(kv.second);
1020 self.runner->firePublishedInputPortEvent(*
self.changedPorts);
1021 self.changedPorts->clear();
1023 self.runner->waitForFiredPublishedInputPortEvent();
1038 - (NSImage *)generateNSImageWithSuggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time
1040 if (![
self executeWithSuggestedPixelsWide:suggestedPixelsWide pixelsHigh:suggestedPixelsHigh atTime:time])
1055 - (GLuint)generateGLTextureWithTarget:(GLuint)target suggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh
1057 if (![
self executeWithSuggestedPixelsWide:suggestedPixelsWide pixelsHigh:suggestedPixelsHigh atTime:time])
1085 - (GLuint)generateGLTextureWithProvider:(GLuint (^)(NSUInteger pixelsWide, NSUInteger pixelsHigh))provider suggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh ioSurface:(IOSurfaceRef *)outputIOSurface
1087 if (![
self executeWithSuggestedPixelsWide:suggestedPixelsWide pixelsHigh:suggestedPixelsHigh atTime:time])
1100 - (
VuoImage)generateVuoImageWithSuggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time
1102 if (![
self executeWithSuggestedPixelsWide:suggestedPixelsWide pixelsHigh:suggestedPixelsHigh atTime:time])
1106 VuoRunner::Port *port =
self.runner->getPublishedOutputPortWithName(
"outputImage");
1110 json_object *valueJson =
self.runner->getPublishedOutputPortValue(port);
1112 json_object_put(valueJson);