12#include <OpenGL/CGLMacro.h>
13#include <QuartzCore/CoreImage.h>
14#include <QuartzCore/CoreVideo.h>
16#pragma clang diagnostic push
17#pragma clang diagnostic ignored "-Wdocumentation"
18#include <json-c/json.h>
19#pragma clang diagnostic pop
48@implementation VuoRunnerCocoa (Conversion)
57+ (id)cocoaObjectWithVuoValue:(json_object *)vuoValue ofType:(
string)type
59 if (type ==
"VuoBoolean")
62 return [NSNumber numberWithBool:v];
64 if (type ==
"VuoList_VuoBoolean")
68 NSMutableArray *a = [[NSMutableArray new] autorelease];
69 for (
unsigned long i=0; i<count; ++i)
70 [a addObject:[NSNumber numberWithBool:VuoListGetValue_VuoBoolean(l, i+1)]];
74 if (type ==
"VuoInteger")
77 return [NSNumber numberWithLong:v];
79 if (type ==
"VuoList_VuoInteger")
83 NSMutableArray *a = [[NSMutableArray new] autorelease];
84 for (
unsigned long i=0; i<count; ++i)
85 [a addObject:[NSNumber numberWithLong:VuoListGetValue_VuoInteger(l, i+1)]];
89 if (type ==
"VuoReal")
92 return [NSNumber numberWithDouble:v];
94 if (type ==
"VuoList_VuoReal")
98 NSMutableArray *a = [[NSMutableArray new] autorelease];
99 for (
unsigned long i=0; i<count; ++i)
100 [a addObject:[NSNumber numberWithDouble:VuoListGetValue_VuoReal(l, i+1)]];
104 if (type ==
"VuoText")
108 NSString *s = [NSString stringWithUTF8String:v];
112 if (type ==
"VuoList_VuoText")
116 NSMutableArray *a = [[NSMutableArray new] autorelease];
117 for (
unsigned long i=0; i<count; ++i)
118 [a addObject:[NSString stringWithUTF8String:VuoListGetValue_VuoText(l, i+1)]];
122 if (type ==
"VuoColor")
125 CGFloat c[4] = {v.r, v.g, v.b, v.a};
126 return [NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace] components:c count:4];
128 if (type ==
"VuoList_VuoColor")
132 NSMutableArray *a = [[NSMutableArray new] autorelease];
133 for (
unsigned long i=0; i<count; ++i)
136 CGFloat c[4] = {v.r, v.g, v.b, v.a};
137 [a addObject:[NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace] components:c count:4]];
142 if (type ==
"VuoImage")
146 NSImage *im = [
self nsImageWithVuoImage:v];
150 if (type ==
"VuoList_VuoImage")
154 NSMutableArray *a = [[NSMutableArray new] autorelease];
155 for (
unsigned long i=0; i<count; ++i)
159 [a addObject:[
self nsImageWithVuoImage:v]];
165 if (type ==
"VuoPoint2d")
168 return [NSValue valueWithPoint:NSMakePoint(v.x, v.y)];
170 if (type ==
"VuoList_VuoPoint2d")
174 NSMutableArray *a = [[NSMutableArray new] autorelease];
175 for (
unsigned long i=0; i<count; ++i)
178 [a addObject:[NSValue valueWithPoint:NSMakePoint(v.x, v.y)]];
183 if (type ==
"VuoPoint3d")
186 size_t s =
sizeof(double)*3;
187 double *d = (
double *)malloc(s);
191 return [NSData dataWithBytesNoCopy:d length:s];
193 if (type ==
"VuoList_VuoPoint3d")
197 NSMutableArray *a = [[NSMutableArray new] autorelease];
198 for (
unsigned long i=0; i<count; ++i)
201 size_t s =
sizeof(double)*3;
202 double *d = (
double *)malloc(s);
206 [a addObject:[NSData dataWithBytesNoCopy:d length:s]];
215 string allowedValuesFunctionName = itemType +
"_getAllowedValues";
216 typedef void *(*allowedValuesFunctionType)(void);
217 allowedValuesFunctionType allowedValuesFunction = (allowedValuesFunctionType)dlsym(RTLD_SELF, allowedValuesFunctionName.c_str());
218 if (allowedValuesFunction)
219 if (json_object_is_type(vuoValue, json_type_array))
221 unsigned long arrayLength = json_object_array_length(vuoValue);
223 return [[NSArray new] autorelease];
225 else if (json_object_is_type(json_object_array_get_idx(vuoValue, 0), json_type_string))
227 NSMutableArray *a = [[NSMutableArray new] autorelease];
228 for (
unsigned long i = 0; i < arrayLength; ++i)
229 [a addObject:[NSString stringWithUTF8String:json_object_get_string(json_object_array_get_idx(vuoValue, i))]];
236 string allowedValuesFunctionName = type +
"_getAllowedValues";
237 typedef void *(*allowedValuesFunctionType)(void);
238 allowedValuesFunctionType allowedValuesFunction = (allowedValuesFunctionType)dlsym(RTLD_SELF, allowedValuesFunctionName.c_str());
239 if (allowedValuesFunction)
240 if (json_object_is_type(vuoValue, json_type_string))
241 return [NSString stringWithUTF8String:json_object_get_string(vuoValue)];
243 VUserLog(
"Type %s isn't supported yet. Please https://vuo.org/contact us if you'd like support for this type.", type.c_str());
250static void VuoRunnerCocoa_doNothingCallback(
VuoImage imageToFree)
261+ (json_object *)vuoValueWithCocoaObject:(
id)value
267 if ([value respondsToSelector:@selector(vuoValue)])
268 return [value vuoValue];
271 if (strcmp(object_getClassName(value),
"__NSCFType") == 0)
273 CFTypeID type = CFGetTypeID(value);
275 if (type == CGColorGetTypeID())
277 NSColorSpace *nscs = [[NSColorSpace alloc] initWithCGColorSpace:CGColorGetColorSpace((CGColorRef)value)];
278 NSColor *color = [NSColor colorWithColorSpace:nscs components:CGColorGetComponents((CGColorRef)value) count:CGColorGetNumberOfComponents((CGColorRef)value)];
280 return [color vuoValue];
283 if (type == CGImageGetTypeID())
285 CGImageRef cgimage = (CGImageRef)value;
287 if (CGImageGetAlphaInfo(cgimage) != kCGImageAlphaPremultipliedLast)
289 VUserLog(
"Error: Alpha option %d isn't supported yet. Please use kCGImageAlphaPremultipliedLast, and https://vuo.org/contact us if you'd like support for other alpha options.", CGImageGetAlphaInfo(cgimage));
293 if (CGImageGetBitmapInfo(cgimage) & kCGBitmapFloatComponents)
295 VUserLog(
"Error: Floating-point pixel values aren't supported yet. Please use integer pixel values, and https://vuo.org/contact us if you'd like support for floating-point pixel values.");
299 if (CGImageGetBitsPerComponent(cgimage) != 8)
301 VUserLog(
"Error: BitsPerComponent=%lu isn't supported yet. Please use 8 bits per component, and https://vuo.org/contact us if you'd like support for other bit depths.", CGImageGetBitsPerComponent(cgimage));
305 if (CGImageGetBitsPerPixel(cgimage) != 32)
307 VUserLog(
"Error: BitsPerPixel=%lu isn't supported yet. Please use 32 bits per pixel, and https://vuo.org/contact us if you'd like support for other bit depths.", CGImageGetBitsPerPixel(cgimage));
311 unsigned long width = CGImageGetWidth(cgimage);
312 unsigned long height = CGImageGetHeight(cgimage);
313 if (CGImageGetBytesPerRow(cgimage) != width*4)
315 VUserLog(
"Error: BytesPerRow must be width*4. https://vuo.org/contact us if you'd like support for inexact strides.");
328 CGDataProviderRef provider = CGImageGetDataProvider(cgimage);
329 CFDataRef data = CGDataProviderCopyData(provider);
331 char *bitmapData = (
char *)CFDataGetBytePtr(data);
332 int bytesPerRow = width*4;
333 char *flippedBitmapData = (
char *)malloc(bytesPerRow*height);
336 for (
unsigned long y = 0; y < height; ++y)
337 memcpy(flippedBitmapData + bytesPerRow * (height - y - 1), bitmapData + bytesPerRow * y, bytesPerRow);
349 if (type == CVPixelBufferGetTypeID())
351 CVPixelBufferRef cvpb = (CVPixelBufferRef)value;
353 if (CVPixelBufferIsPlanar(cvpb))
355 VUserLog(
"Error: Planar buffers aren't supported yet. Please use chunky buffers, and https://vuo.org/contact us if you'd like support for planar buffers.");
359 if (CVPixelBufferGetPixelFormatType(cvpb) != kCVPixelFormatType_32BGRA)
361 unsigned long pf = CVPixelBufferGetPixelFormatType(cvpb);
362 VUserLog(
"Error: Pixel format %lu isn't supported yet. Please use kCVPixelFormatType_32BGRA, and https://vuo.org/contact us if you'd like support for other pixel formats.", pf);
366 unsigned long width = CVPixelBufferGetWidth(cvpb);
367 unsigned long height = CVPixelBufferGetHeight(cvpb);
368 if (CVPixelBufferGetBytesPerRow(cvpb) != width*4)
370 VUserLog(
"Error: BytesPerRow must be width*4. https://vuo.org/contact us if you'd like support for inexact strides.");
374 CVReturn ret = CVPixelBufferLockBaseAddress(cvpb, kCVPixelBufferLock_ReadOnly);
375 if (ret != kCVReturnSuccess)
377 VUserLog(
"CVPixelBufferLockBaseAddress() failed: %d", ret);
381 const unsigned char *pixels = (
const unsigned char *)CVPixelBufferGetBaseAddress(cvpb);
384 VUserLog(
"Error: CVPixelBufferGetBaseAddress() returned NULL.");
388 CVPixelBufferRetain(cvpb);
392 ret = CVPixelBufferUnlockBaseAddress(cvpb, kCVPixelBufferLock_ReadOnly);
393 if (ret != kCVReturnSuccess)
395 VUserLog(
"CVPixelBufferUnlockBaseAddress() failed: %d", ret);
404#pragma clang diagnostic push
405#pragma clang diagnostic ignored "-Wdeprecated-declarations"
406 if (type == CVOpenGLTextureGetTypeID())
408 CVOpenGLTextureRef cvgl = (CVOpenGLTextureRef)value;
410 GLuint name = CVOpenGLTextureGetName(cvgl);
413 VUserLog(
"Error: CVOpenGLTextureGetName() returned 0.");
417 GLfloat lowerLeft[2];
418 GLfloat lowerRight[2];
419 GLfloat upperRight[2];
420 GLfloat upperLeft[2];
421 CVOpenGLTextureGetCleanTexCoords(cvgl, lowerLeft, lowerRight, upperRight, upperLeft);
423 unsigned int width = abs((
int)(lowerRight[0] - lowerLeft[0]));
424 unsigned int height = abs((
int)(upperLeft[1] - lowerLeft[1]));
428 GLenum target = CVOpenGLTextureGetTarget(cvgl);
429 if (target == GL_TEXTURE_2D)
431 else if (target == GL_TEXTURE_RECTANGLE_ARB)
435 VUserLog(
"Error: GL texture target %d isn't supported yet. Please use GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB, and https://vuo.org/contact us if you'd like support for other targets.", target);
444#pragma clang diagnostic pop
446 NSString *typeDescription = (NSString *)CFCopyTypeIDDescription(type);
447 VUserLog(
"Error: Unknown CFType '%s'", [typeDescription UTF8String]);
448 [typeDescription release];
452 VUserLog(
"Error: Unknown type '%s' for object '%s'", object_getClassName(value), [[value description] UTF8String]);
461+ (NSImage *)nsImageWithVuoImage:(
VuoImage)vi
467 unsigned int bytesPerRow = 4 * vi->pixelsWide;
468 NSBitmapImageRep *nbi = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
469 pixelsWide:vi->pixelsWide
470 pixelsHigh:vi->pixelsHigh
475 colorSpaceName:NSDeviceRGBColorSpace
476 bytesPerRow:bytesPerRow
482 unsigned char *bitmapData = [nbi bitmapData];
484 glBindTexture(GL_TEXTURE_2D, vi->glTextureName);
485 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmapData);
486 glBindTexture(GL_TEXTURE_2D, 0);
490 unsigned char *tmp = (
unsigned char *)malloc(bytesPerRow);
491 for (
unsigned long y = 0; y < vi->pixelsHigh / 2; ++y)
493 memcpy(tmp, bitmapData + bytesPerRow * y, bytesPerRow);
494 memcpy(bitmapData + bytesPerRow * y, bitmapData + bytesPerRow * (vi->pixelsHigh - y - 1), bytesPerRow);
495 memcpy(bitmapData + bytesPerRow * (vi->pixelsHigh - y - 1), tmp, bytesPerRow);
499 NSImage *ni = [[NSImage alloc] initWithSize:[nbi size]];
500 [ni addRepresentation:nbi];
502 return [ni autorelease];
507@implementation NSNumber (VuoRunnerCocoaConversion)
515- (json_object *)vuoValue
517 char type = [
self objCType][0];
522 if (type ==
'f' || type ==
'd')
525 if (type ==
'c' || type ==
'i' || type ==
's' || type ==
'l' || type ==
'q'
526 || type ==
'C' || type ==
'I' || type ==
'S' || type ==
'L' || type ==
'Q')
529 VUserLog(
"Error: Unknown type '%s'", [self objCType]);
534@implementation NSString (VuoRunnerCocoaConversion)
542- (json_object *)vuoValue
548@implementation NSColor (VuoRunnerCocoaConversion)
556- (json_object *)vuoValue
558 CGFloat c[4] = {0,0,0,1};
559 NSColor *color = [
self colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
560 [color getComponents:c];
565@implementation CIColor (VuoRunnerCocoaConversion)
573- (json_object *)vuoValue
575 NSColorSpace *nscs = [[NSColorSpace alloc] initWithCGColorSpace:[
self colorSpace]];
576 NSColor *color = [NSColor colorWithColorSpace:nscs components:[
self components] count:[
self numberOfComponents]];
578 return [color vuoValue];
582@implementation NSImage (VuoRunnerCocoaConversion)
590- (json_object *)vuoValue
592 float scale = [
self recommendedLayerContentsScale:0];
593 unsigned int pixelsWide = [
self size].width * scale;
594 unsigned int pixelsHigh = [
self size].height * scale;
596 NSBitmapImageRep *nbir = [[NSBitmapImageRep alloc]
597 initWithBitmapDataPlanes: NULL
598 pixelsWide:pixelsWide
599 pixelsHigh:pixelsHigh
604 colorSpaceName:NSDeviceRGBColorSpace
605 bytesPerRow:pixelsWide*4
608 NSGraphicsContext *ngc = [NSGraphicsContext graphicsContextWithBitmapImageRep:nbir];
609 [NSGraphicsContext saveGraphicsState];
610 [NSGraphicsContext setCurrentContext:ngc];
611 [
self drawInRect:NSMakeRect(0,0,pixelsWide,pixelsHigh) fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1 respectFlipped:YES hints:nil];
613 [NSGraphicsContext setCurrentContext:nil];
614 [NSGraphicsContext restoreGraphicsState];
616 json_object *js = [nbir vuoValue];
622@implementation NSBitmapImageRep (VuoRunnerCocoaConversion)
630- (json_object *)vuoValue
633 unsigned char *bitmapData = [
self bitmapData];
634 unsigned long width = [
self size].width;
635 unsigned long height = [
self size].height;
636 unsigned long bytesPerRow = width * 4;
637 unsigned char *bitmapDataFlipped = (
unsigned char *)malloc(bytesPerRow * height);
638 for (
unsigned long y = 0; y < height; ++y)
639 for (
unsigned long x = 0; x < width; ++x)
642 bitmapDataFlipped[bytesPerRow * (height - y - 1) + x * 4 + 2] = bitmapData[bytesPerRow * y + x * 4 + 0];
643 bitmapDataFlipped[bytesPerRow * (height - y - 1) + x * 4 + 1] = bitmapData[bytesPerRow * y + x * 4 + 1];
644 bitmapDataFlipped[bytesPerRow * (height - y - 1) + x * 4 + 0] = bitmapData[bytesPerRow * y + x * 4 + 2];
645 bitmapDataFlipped[bytesPerRow * (height - y - 1) + x * 4 + 3] = bitmapData[bytesPerRow * y + x * 4 + 3];
656@implementation NSValue (VuoRunnerCocoaConversion)
664- (json_object *)vuoValue
666 NSPoint p = [
self pointValue];
671@implementation NSData (VuoRunnerCocoaConversion)
679- (json_object *)vuoValue
681 double p[3] = {0,0,0};
682 [
self getBytes:p length:sizeof(double)*3];
687@implementation NSArray (VuoRunnerCocoaConversion)
695- (json_object *)vuoValue
697 json_object *arrayJson = json_object_new_array();
698 for (
id item in self)
700 json_object *itemJson = [item vuoValue];
701 json_object_array_add(arrayJson, itemJson);