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()]];
334 - (NSDictionary *)detailsForPort:(NSString *)portName
336 const char *portNameCString = [portName UTF8String];
337 VuoRunner::Port *port =
self.runner->getPublishedInputPortWithName(portNameCString);
340 port =
self.runner->getPublishedOutputPortWithName(portNameCString);
345 NSMutableDictionary *details = [[NSMutableDictionary new] autorelease];
347 details[@"title"] = [NSString stringWithUTF8String:port->getName().c_str()];
349 details[@"type"] = [NSString stringWithUTF8String:port->getType().c_str()];
356 if (json_object_object_get_ex(js,
"default", &o))
360 details[@"default"] = cocoaObject;
363 if (json_object_object_get_ex(js,
"suggestedMin", &o))
367 details[@"suggestedMin"] = cocoaObject;
370 if (json_object_object_get_ex(js,
"suggestedMax", &o))
374 details[@"suggestedMax"] = cocoaObject;
377 if (json_object_object_get_ex(js,
"suggestedStep", &o))
381 details[@"suggestedStep"] = cocoaObject;
384 if (json_object_object_get_ex(js,
"menuItems", &o))
386 NSMutableArray *menuItems = [NSMutableArray new];
388 int itemCount = json_object_array_length(o);
389 for (
int i = 0; i < itemCount; ++i)
391 json_object *item = json_object_array_get_idx(o, i);
394 json_object_object_get_ex(item,
"value", &value);
396 json_object_object_get_ex(item,
"name", &name);
398 const char *key = json_object_get_string(value);
399 const char *summary = json_object_get_string(name);
400 NSDictionary *menuItem = @{
401 @"value": [NSString stringWithUTF8String:key],
402 @"name": [NSString stringWithUTF8String:summary],
404 [menuItems addObject:menuItem];
407 details[@"menuItems"] = menuItems;
423 NSMutableDictionary *properties = [[NSMutableDictionary new] autorelease];
425 vector<VuoRunner::Port *> ports =
self.runner->getPublishedInputPorts();
426 for (vector<VuoRunner::Port *>::iterator it = ports.begin(); it != ports.end(); ++it)
427 if (
self.protocol && !
self.protocol->
hasInputPort((*it)->getName()))
429 json_object *portValue =
self.runner->getPublishedInputPortValue(*it);
430 const char *valueAsString = json_object_to_json_string_ext(portValue, JSON_C_TO_STRING_PLAIN);
431 properties[[NSString stringWithUTF8String:(*it)->getName().c_str()]] = [NSString stringWithUTF8String:valueAsString];
443 - (BOOL)setInputValuesWithPropertyList:(
id)propertyList
448 __block BOOL ok = YES;
449 __block map<VuoRunner::Port *, json_object *> m;
450 [(NSDictionary *)propertyList enumerateKeysAndObjectsUsingBlock:^(NSString *portName, NSString *value, BOOL *stop) {
451 VuoRunner::Port *port = self.runner->getPublishedInputPortWithName([portName UTF8String]);
458 json_object *valueJson = json_tokener_parse([value UTF8String]);
468 runner->setPublishedInputPortValues(m);
472 self.changedPorts->insert(kv.first);
473 json_object_put(kv.second);
494 - (BOOL)setInputValues:(NSDictionary *)namesAndValues
500 map<VuoRunner::Port *, json_object *> m;
501 for (NSString *portName in namesAndValues)
503 VuoRunner::Port *port =
self.runner->getPublishedInputPortWithName([portName UTF8String]);
510 id value = namesAndValues[portName];
521 self.runner->setPublishedInputPortValues(m);
525 self.changedPorts->insert(kv.first);
526 json_object_put(kv.second);
539 - (BOOL)setInputJSON:(NSDictionary *)namesAndJSON
545 map<VuoRunner::Port *, json_object *> m;
546 for (NSString *portName in namesAndJSON)
548 VuoRunner::Port *port =
self.runner->getPublishedInputPortWithName([portName UTF8String]);
555 id nsValue = namesAndJSON[portName];
559 if (port->
getType() ==
"VuoImage")
561 if (json_object_get_type(value) == json_type_string)
563 char *s = strdup(json_object_get_string(value));
567 NSLog(
@"Error: Couldn't load image '%s'.\n", s);
581 self.runner->setPublishedInputPortValues(m);
584 self.changedPorts->insert(kv.first);
606 - (id)valueForOutputPort:(NSString *)portName
611 VuoRunner::Port *port =
self.runner->getPublishedOutputPortWithName([portName UTF8String]);
615 json_object *valueJson =
self.runner->getPublishedOutputPortValue(port);
628 - (GLuint)glTextureWithTarget:(GLuint)target forOutputPort:(NSString *)portName outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh
633 VuoRunner::Port *port =
self.runner->getPublishedOutputPortWithName([portName UTF8String]);
637 json_object *valueJson =
self.runner->getPublishedOutputPortValue(port);
641 json_object_put(valueJson);
643 if (target == GL_TEXTURE_RECTANGLE_ARB)
648 vuoImage = newVuoImage;
651 if (outputPixelsWide)
653 if (outputPixelsHigh)
680 - (GLuint)glTextureFromProvider:(GLuint (^)(NSUInteger pixelsWide, NSUInteger pixelsHigh))provider forOutputPort:(NSString *)portName outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh ioSurface:(IOSurfaceRef *)outputIOSurface
685 VuoRunner::Port *port =
self.runner->getPublishedOutputPortWithName([portName UTF8String]);
689 json_object *valueJson =
self.runner->getPublishedOutputPortValue(port);
691 GLuint (^provider2)(
unsigned int,
unsigned int) = ^GLuint(
unsigned int pixelsWide,
unsigned int pixelsHigh){
692 return provider(pixelsWide, pixelsHigh);
694 unsigned int outputPixelsWide2, outputPixelsHigh2;
696 *outputPixelsWide = outputPixelsWide2;
697 *outputPixelsHigh = outputPixelsHigh2;
698 return outputTexture;
708 + (BOOL)canOpenComposition:(NSURL *)compositionURL
710 return [
self isComposition:compositionURL compliantWithProtocol:VuoProtocol::getProtocol(VuoProtocol::imageFilter)];
716 + (BOOL)canOpenCompositionString:(NSString *)compositionString
718 return [
self isCompositionString:compositionString compliantWithProtocol:VuoProtocol::getProtocol(VuoProtocol::imageFilter)];
727 - (id)initWithComposition:(NSURL *)aCompositionURL
732 [
self compileAndRun];
746 - (id)initWithCompositionString:(NSString *)aCompositionString name:(NSString *)name sourcePath:(NSString *)sourcePath
751 [
self compileAndRun];
761 static void VuoRunnerCocoa_doNothingCallback(
VuoImage imageToFree)
768 - (BOOL)executeWithGLTexture:(GLuint)textureName target:(GLuint)target pixelsWide:(
unsigned long)pixelsWide pixelsHigh:(
unsigned long)pixelsHigh atTime:(NSTimeInterval)time
774 VuoRunner::Port *port =
self.runner->getPublishedInputPortWithName(
"image");
780 map<VuoRunner::Port *, json_object *> m;
782 self.runner->setPublishedInputPortValues(m);
783 json_object_put(valueJson);
785 self.changedPorts->insert(port);
788 return [
self executeAtTime:time];
794 - (BOOL)executeAtTime:(NSTimeInterval)time
799 VuoRunner::Port *timePort =
self.runner->getPublishedInputPortWithName(
"time");
803 map<VuoRunner::Port *, json_object *> m;
804 m[timePort] = valueJson;
805 self.runner->setPublishedInputPortValues(m);
806 json_object_put(valueJson);
808 self.changedPorts->insert(timePort);
811 self.runner->firePublishedInputPortEvent(*
self.changedPorts);
812 self.changedPorts->clear();
814 self.runner->waitForFiredPublishedInputPortEvent();
831 - (NSImage *)filterNSImage:(NSImage *)image atTime:(NSTimeInterval)time
835 if (![
self executeAtTime:time])
855 - (GLuint)filterGLTexture:(GLuint)textureName target:(GLuint)target pixelsWide:(NSUInteger)pixelsWide pixelsHigh:(NSUInteger)pixelsHigh atTime:(NSTimeInterval)time outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh
857 if (![
self executeWithGLTexture:textureName target:target pixelsWide:pixelsWide pixelsHigh:pixelsHigh atTime:time])
891 - (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
893 if (![
self executeWithGLTexture:textureName target:target pixelsWide:pixelsWide pixelsHigh:pixelsHigh atTime:time])
911 @synthesize previousSuggestedPixelsWide;
912 @synthesize previousSuggestedPixelsHigh;
917 + (BOOL)canOpenComposition:(NSURL *)compositionURL
919 return [
self isComposition:compositionURL compliantWithProtocol:VuoProtocol::getProtocol(VuoProtocol::imageGenerator)];
925 + (BOOL)canOpenCompositionString:(NSString *)compositionString
927 return [
self isCompositionString:compositionString compliantWithProtocol:VuoProtocol::getProtocol(VuoProtocol::imageGenerator)];
936 - (id)initWithComposition:(NSURL *)aCompositionURL
941 [
self compileAndRun];
945 self.previousSuggestedPixelsWide = NSUIntegerMax;
946 self.previousSuggestedPixelsHigh = NSUIntegerMax;
958 - (id)initWithCompositionString:(NSString *)aCompositionString name:(NSString *)name sourcePath:(NSString *)sourcePath
963 [
self compileAndRun];
973 - (BOOL)executeWithSuggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time
978 VuoRunner::Port *timePort =
self.runner->getPublishedInputPortWithName(
"time");
979 VuoRunner::Port *widthPort =
self.runner->getPublishedInputPortWithName(
"width");
980 VuoRunner::Port *heightPort =
self.runner->getPublishedInputPortWithName(
"height");
982 map<VuoRunner::Port *, json_object *> m;
986 if (suggestedPixelsWide !=
self.previousSuggestedPixelsWide)
989 self.previousSuggestedPixelsWide = suggestedPixelsWide;
991 if (suggestedPixelsHigh !=
self.previousSuggestedPixelsHigh)
994 self.previousSuggestedPixelsHigh = suggestedPixelsHigh;
997 self.runner->setPublishedInputPortValues(m);
1000 self.changedPorts->insert(kv.first);
1001 json_object_put(kv.second);
1004 self.runner->firePublishedInputPortEvent(*
self.changedPorts);
1005 self.changedPorts->clear();
1007 self.runner->waitForFiredPublishedInputPortEvent();
1022 - (NSImage *)generateNSImageWithSuggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time
1024 if (![
self executeWithSuggestedPixelsWide:suggestedPixelsWide pixelsHigh:suggestedPixelsHigh atTime:time])
1039 - (GLuint)generateGLTextureWithTarget:(GLuint)target suggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time outputPixelsWide:(NSUInteger *)outputPixelsWide pixelsHigh:(NSUInteger *)outputPixelsHigh
1041 if (![
self executeWithSuggestedPixelsWide:suggestedPixelsWide pixelsHigh:suggestedPixelsHigh atTime:time])
1069 - (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
1071 if (![
self executeWithSuggestedPixelsWide:suggestedPixelsWide pixelsHigh:suggestedPixelsHigh atTime:time])
1084 - (
VuoImage)generateVuoImageWithSuggestedPixelsWide:(NSUInteger)suggestedPixelsWide pixelsHigh:(NSUInteger)suggestedPixelsHigh atTime:(NSTimeInterval)time
1086 if (![
self executeWithSuggestedPixelsWide:suggestedPixelsWide pixelsHigh:suggestedPixelsHigh atTime:time])
1090 VuoRunner::Port *port =
self.runner->getPublishedOutputPortWithName(
"outputImage");
1094 json_object *valueJson =
self.runner->getPublishedOutputPortValue(port);
1096 json_object_put(valueJson);