Vuo 2.4.4
Loading...
Searching...
No Matches
VuoRunnerCocoa+Conversion.mm
Go to the documentation of this file.
1
11
12#include <OpenGL/CGLMacro.h>
13#include <QuartzCore/CoreImage.h>
14#include <QuartzCore/CoreVideo.h>
15
16#pragma clang diagnostic push
17#pragma clang diagnostic ignored "-Wdocumentation"
18#include <json-c/json.h>
19#pragma clang diagnostic pop
20
21#include <dlfcn.h>
22#include <vector>
23#include "VuoStringUtilities.hh"
24#include "VuoType.hh"
25
26extern "C" {
27#include "VuoHeap.h"
28#include "VuoGlContext.h"
29
30#include "VuoBoolean.h"
31#include "VuoColor.h"
32#include "VuoImage.h"
33#include "VuoInteger.h"
34#include "VuoPoint2d.h"
35#include "VuoPoint3d.h"
36#include "VuoReal.h"
37#include "VuoText.h"
38#include "VuoList_VuoBoolean.h"
39#include "VuoList_VuoColor.h"
40#include "VuoList_VuoImage.h"
41#include "VuoList_VuoInteger.h"
42#include "VuoList_VuoPoint2d.h"
43#include "VuoList_VuoPoint3d.h"
44#include "VuoList_VuoReal.h"
45#include "VuoList_VuoText.h"
46}
47
48@implementation VuoRunnerCocoa (Conversion)
49
57+ (id)cocoaObjectWithVuoValue:(json_object *)vuoValue ofType:(string)type
58{
59 if (type == "VuoBoolean")
60 {
62 return [NSNumber numberWithBool:v];
63 }
64 if (type == "VuoList_VuoBoolean")
65 {
67 unsigned long count = VuoListGetCount_VuoBoolean(l);
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)]];
71 return a;
72 }
73
74 if (type == "VuoInteger")
75 {
77 return [NSNumber numberWithLong:v];
78 }
79 if (type == "VuoList_VuoInteger")
80 {
82 unsigned long count = VuoListGetCount_VuoInteger(l);
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)]];
86 return a;
87 }
88
89 if (type == "VuoReal")
90 {
91 VuoReal v = VuoReal_makeFromJson(vuoValue);
92 return [NSNumber numberWithDouble:v];
93 }
94 if (type == "VuoList_VuoReal")
95 {
97 unsigned long count = VuoListGetCount_VuoReal(l);
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)]];
101 return a;
102 }
103
104 if (type == "VuoText")
105 {
106 VuoText v = VuoText_makeFromJson(vuoValue);
107 VuoRetain(v);
108 NSString *s = [NSString stringWithUTF8String:v];
109 VuoRelease(v);
110 return s;
111 }
112 if (type == "VuoList_VuoText")
113 {
115 unsigned long count = VuoListGetCount_VuoText(l);
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)]];
119 return a;
120 }
121
122 if (type == "VuoColor")
123 {
124 VuoColor v = VuoColor_makeFromJson(vuoValue);
125 CGFloat c[4] = {v.r, v.g, v.b, v.a};
126 return [NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace] components:c count:4];
127 }
128 if (type == "VuoList_VuoColor")
129 {
131 unsigned long count = VuoListGetCount_VuoColor(l);
132 NSMutableArray *a = [[NSMutableArray new] autorelease];
133 for (unsigned long i=0; i<count; ++i)
134 {
136 CGFloat c[4] = {v.r, v.g, v.b, v.a};
137 [a addObject:[NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace] components:c count:4]];
138 }
139 return a;
140 }
141
142 if (type == "VuoImage")
143 {
144 VuoImage v = VuoImage_makeFromJson(vuoValue);
145 VuoRetain(v);
146 NSImage *im = [self nsImageWithVuoImage:v];
147 VuoRelease(v);
148 return im;
149 }
150 if (type == "VuoList_VuoImage")
151 {
153 unsigned long count = VuoListGetCount_VuoImage(l);
154 NSMutableArray *a = [[NSMutableArray new] autorelease];
155 for (unsigned long i=0; i<count; ++i)
156 {
158 VuoRetain(v);
159 [a addObject:[self nsImageWithVuoImage:v]];
160 VuoRelease(v);
161 }
162 return a;
163 }
164
165 if (type == "VuoPoint2d")
166 {
167 VuoPoint2d v = VuoPoint2d_makeFromJson(vuoValue);
168 return [NSValue valueWithPoint:NSMakePoint(v.x, v.y)];
169 }
170 if (type == "VuoList_VuoPoint2d")
171 {
173 unsigned long count = VuoListGetCount_VuoPoint2d(l);
174 NSMutableArray *a = [[NSMutableArray new] autorelease];
175 for (unsigned long i=0; i<count; ++i)
176 {
177 VuoPoint2d v = VuoListGetValue_VuoPoint2d(l, i+1);
178 [a addObject:[NSValue valueWithPoint:NSMakePoint(v.x, v.y)]];
179 }
180 return a;
181 }
182
183 if (type == "VuoPoint3d")
184 {
185 VuoPoint3d v = VuoPoint3d_makeFromJson(vuoValue);
186 size_t s = sizeof(double)*3;
187 double *d = (double *)malloc(s);
188 d[0] = v.x;
189 d[1] = v.y;
190 d[2] = v.z;
191 return [NSData dataWithBytesNoCopy:d length:s];
192 }
193 if (type == "VuoList_VuoPoint3d")
194 {
196 unsigned long count = VuoListGetCount_VuoPoint3d(l);
197 NSMutableArray *a = [[NSMutableArray new] autorelease];
198 for (unsigned long i=0; i<count; ++i)
199 {
200 VuoPoint3d v = VuoListGetValue_VuoPoint3d(l, i+1);
201 size_t s = sizeof(double)*3;
202 double *d = (double *)malloc(s);
203 d[0] = v.x;
204 d[1] = v.y;
205 d[2] = v.z;
206 [a addObject:[NSData dataWithBytesNoCopy:d length:s]];
207 }
208 return a;
209 }
210
211 // Maybe it's a list of enum values?
213 {
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))
220 {
221 unsigned long arrayLength = json_object_array_length(vuoValue);
222 if (!arrayLength)
223 return [[NSArray new] autorelease];
224
225 else if (json_object_is_type(json_object_array_get_idx(vuoValue, 0), json_type_string))
226 {
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))]];
230 return a;
231 }
232 }
233 }
234
235 // Maybe it's an enum?
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)];
242
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());
244 return nil;
245}
246
250static void VuoRunnerCocoa_doNothingCallback(VuoImage imageToFree)
251{
252}
253
261+ (json_object *)vuoValueWithCocoaObject:(id)value
262{
263 if (!value)
264 return NULL;
265
266 // Is this a Vuo-compatible NSObject (or CFType that's toll-free bridged to one)?
267 if ([value respondsToSelector:@selector(vuoValue)])
268 return [value vuoValue];
269
270 // Is this a (non-toll-free bridged) CFType?
271 if (strcmp(object_getClassName(value), "__NSCFType") == 0)
272 {
273 CFTypeID type = CFGetTypeID(value);
274
275 if (type == CGColorGetTypeID())
276 {
277 NSColorSpace *nscs = [[NSColorSpace alloc] initWithCGColorSpace:CGColorGetColorSpace((CGColorRef)value)];
278 NSColor *color = [NSColor colorWithColorSpace:nscs components:CGColorGetComponents((CGColorRef)value) count:CGColorGetNumberOfComponents((CGColorRef)value)];
279 [nscs release];
280 return [color vuoValue];
281 }
282
283 if (type == CGImageGetTypeID())
284 {
285 CGImageRef cgimage = (CGImageRef)value;
286
287 if (CGImageGetAlphaInfo(cgimage) != kCGImageAlphaPremultipliedLast)
288 {
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));
290 return NULL;
291 }
292
293 if (CGImageGetBitmapInfo(cgimage) & kCGBitmapFloatComponents)
294 {
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.");
296 return NULL;
297 }
298
299 if (CGImageGetBitsPerComponent(cgimage) != 8)
300 {
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));
302 return NULL;
303 }
304
305 if (CGImageGetBitsPerPixel(cgimage) != 32)
306 {
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));
308 return NULL;
309 }
310
311 unsigned long width = CGImageGetWidth(cgimage);
312 unsigned long height = CGImageGetHeight(cgimage);
313 if (CGImageGetBytesPerRow(cgimage) != width*4)
314 {
315 VUserLog("Error: BytesPerRow must be width*4. https://vuo.org/contact us if you'd like support for inexact strides.");
316 return NULL;
317 }
318
319// NSString *colorSpaceName = (NSString *)CGColorSpaceCopyName(CGImageGetColorSpace(cgimage));
320// if (![colorSpaceName isEqualToString:(NSString *)kCGColorSpaceSRGB])
321// {
322// VUserLog("Error: Colorspace '%s' isn't supported yet. Please use kCGColorSpaceSRGB, and https://vuo.org/contact us if you'd like support for other colorspaces.", [colorSpaceName UTF8String]);
323// [colorSpaceName release];
324// return NULL;
325// }
326// CFRelease(colorSpaceName);
327
328 CGDataProviderRef provider = CGImageGetDataProvider(cgimage);
329 CFDataRef data = CGDataProviderCopyData(provider);
330
331 char *bitmapData = (char *)CFDataGetBytePtr(data);
332 int bytesPerRow = width*4;
333 char *flippedBitmapData = (char *)malloc(bytesPerRow*height);
334
335 // Flip the image data (CGImage is unflipped, but VuoImage_makeFromBuffer() expects flipped).
336 for (unsigned long y = 0; y < height; ++y)
337 memcpy(flippedBitmapData + bytesPerRow * (height - y - 1), bitmapData + bytesPerRow * y, bytesPerRow);
338
339 CFRelease(data);
340
341 VuoImage vi = VuoImage_makeFromBuffer(flippedBitmapData, GL_RGBA, width, height, VuoImageColorDepth_8, ^(void *buffer){ free(flippedBitmapData); });
342 VuoRetain(vi);
343
344 json_object *js = VuoImage_getInterprocessJson(vi);
345 VuoRelease(vi);
346 return js;
347 }
348
349 if (type == CVPixelBufferGetTypeID())
350 {
351 CVPixelBufferRef cvpb = (CVPixelBufferRef)value;
352
353 if (CVPixelBufferIsPlanar(cvpb))
354 {
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.");
356 return NULL;
357 }
358
359 if (CVPixelBufferGetPixelFormatType(cvpb) != kCVPixelFormatType_32BGRA)
360 {
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);
363 return NULL;
364 }
365
366 unsigned long width = CVPixelBufferGetWidth(cvpb);
367 unsigned long height = CVPixelBufferGetHeight(cvpb);
368 if (CVPixelBufferGetBytesPerRow(cvpb) != width*4)
369 {
370 VUserLog("Error: BytesPerRow must be width*4. https://vuo.org/contact us if you'd like support for inexact strides.");
371 return NULL;
372 }
373
374 CVReturn ret = CVPixelBufferLockBaseAddress(cvpb, kCVPixelBufferLock_ReadOnly);
375 if (ret != kCVReturnSuccess)
376 {
377 VUserLog("CVPixelBufferLockBaseAddress() failed: %d", ret);
378 return NULL;
379 }
380
381 const unsigned char *pixels = (const unsigned char *)CVPixelBufferGetBaseAddress(cvpb);
382 if (!pixels)
383 {
384 VUserLog("Error: CVPixelBufferGetBaseAddress() returned NULL.");
385 return NULL;
386 }
387
388 CVPixelBufferRetain(cvpb);
389 VuoImage vi = VuoImage_makeFromBuffer(pixels, GL_BGRA, width, height, VuoImageColorDepth_8, ^(void *buffer){ CVPixelBufferRelease(cvpb); });
390 VuoRetain(vi);
391
392 ret = CVPixelBufferUnlockBaseAddress(cvpb, kCVPixelBufferLock_ReadOnly);
393 if (ret != kCVReturnSuccess)
394 {
395 VUserLog("CVPixelBufferUnlockBaseAddress() failed: %d", ret);
396 return NULL;
397 }
398
399 json_object *js = VuoImage_getInterprocessJson(vi);
400 VuoRelease(vi);
401 return js;
402 }
403
404#pragma clang diagnostic push
405#pragma clang diagnostic ignored "-Wdeprecated-declarations"
406 if (type == CVOpenGLTextureGetTypeID())
407 {
408 CVOpenGLTextureRef cvgl = (CVOpenGLTextureRef)value;
409
410 GLuint name = CVOpenGLTextureGetName(cvgl);
411 if (!name)
412 {
413 VUserLog("Error: CVOpenGLTextureGetName() returned 0.");
414 return NULL;
415 }
416
417 GLfloat lowerLeft[2];
418 GLfloat lowerRight[2];
419 GLfloat upperRight[2];
420 GLfloat upperLeft[2];
421 CVOpenGLTextureGetCleanTexCoords(cvgl, lowerLeft, lowerRight, upperRight, upperLeft);
422
423 unsigned int width = abs((int)(lowerRight[0] - lowerLeft[0]));
424 unsigned int height = abs((int)(upperLeft[1] - lowerLeft[1]));
425// VLog("%dx%d",width,height);
426
427 VuoImage vi;
428 GLenum target = CVOpenGLTextureGetTarget(cvgl);
429 if (target == GL_TEXTURE_2D)
430 vi = VuoImage_makeClientOwned(name, GL_RGBA, width, height, VuoRunnerCocoa_doNothingCallback, NULL);
431 else if (target == GL_TEXTURE_RECTANGLE_ARB)
432 vi = VuoImage_makeClientOwnedGlTextureRectangle(name, GL_RGBA, width, height, VuoRunnerCocoa_doNothingCallback, NULL);
433 else
434 {
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);
436 return NULL;
437 }
438
439 VuoRetain(vi);
440 json_object *js = VuoImage_getInterprocessJson(vi);
441 VuoRelease(vi);
442 return js;
443 }
444#pragma clang diagnostic pop
445
446 NSString *typeDescription = (NSString *)CFCopyTypeIDDescription(type);
447 VUserLog("Error: Unknown CFType '%s'", [typeDescription UTF8String]);
448 [typeDescription release];
449 return NULL;
450 }
451
452 VUserLog("Error: Unknown type '%s' for object '%s'", object_getClassName(value), [[value description] UTF8String]);
453 return NULL;
454}
455
461+ (NSImage *)nsImageWithVuoImage:(VuoImage)vi
462{
463 if (!vi)
464 return nil;
465
466 // Allocate memory to store the image data.
467 unsigned int bytesPerRow = 4 * vi->pixelsWide;
468 NSBitmapImageRep *nbi = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
469 pixelsWide:vi->pixelsWide
470 pixelsHigh:vi->pixelsHigh
471 bitsPerSample:8
472 samplesPerPixel:4
473 hasAlpha:YES
474 isPlanar:NO
475 colorSpaceName:NSDeviceRGBColorSpace
476 bytesPerRow:bytesPerRow
477 bitsPerPixel:0];
478 if (!nbi)
479 return nil;
480
481 // Download the image data from the GPU.
482 unsigned char *bitmapData = [nbi bitmapData];
483 VuoGlContext_perform(^(CGLContextObj cgl_ctx){
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);
487 });
488
489 // Flip the image data (OpenGL returns flipped data, but NSBitmapImageRep assumes it is not flipped).
490 unsigned char *tmp = (unsigned char *)malloc(bytesPerRow);
491 for (unsigned long y = 0; y < vi->pixelsHigh / 2; ++y)
492 {
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);
496 }
497 free(tmp);
498
499 NSImage *ni = [[NSImage alloc] initWithSize:[nbi size]];
500 [ni addRepresentation:nbi];
501 [nbi release];
502 return [ni autorelease];
503}
504
505@end
506
507@implementation NSNumber (VuoRunnerCocoaConversion)
515- (json_object *)vuoValue
516{
517 char type = [self objCType][0];
518
519 if (type == 'B')
520 return VuoBoolean_getJson([self boolValue]);
521
522 if (type == 'f' || type == 'd')
523 return VuoReal_getJson([self doubleValue]);
524
525 if (type == 'c' || type == 'i' || type == 's' || type == 'l' || type == 'q'
526 || type == 'C' || type == 'I' || type == 'S' || type == 'L' || type == 'Q')
527 return VuoInteger_getJson([self longLongValue]);
528
529 VUserLog("Error: Unknown type '%s'", [self objCType]);
530 return NULL;
531}
532@end
533
534@implementation NSString (VuoRunnerCocoaConversion)
542- (json_object *)vuoValue
543{
544 return VuoText_getJson([self UTF8String]);
545}
546@end
547
548@implementation NSColor (VuoRunnerCocoaConversion)
556- (json_object *)vuoValue
557{
558 CGFloat c[4] = {0,0,0,1};
559 NSColor *color = [self colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
560 [color getComponents:c];
561 return VuoColor_getJson(VuoColor_makeWithRGBA(c[0], c[1], c[2], c[3]));
562}
563@end
564
565@implementation CIColor (VuoRunnerCocoaConversion)
573- (json_object *)vuoValue
574{
575 NSColorSpace *nscs = [[NSColorSpace alloc] initWithCGColorSpace:[self colorSpace]];
576 NSColor *color = [NSColor colorWithColorSpace:nscs components:[self components] count:[self numberOfComponents]];
577 [nscs release];
578 return [color vuoValue];
579}
580@end
581
582@implementation NSImage (VuoRunnerCocoaConversion)
590- (json_object *)vuoValue
591{
592 float scale = [self recommendedLayerContentsScale:0];
593 unsigned int pixelsWide = [self size].width * scale;
594 unsigned int pixelsHigh = [self size].height * scale;
595
596 NSBitmapImageRep *nbir = [[NSBitmapImageRep alloc]
597 initWithBitmapDataPlanes: NULL
598 pixelsWide:pixelsWide
599 pixelsHigh:pixelsHigh
600 bitsPerSample:8
601 samplesPerPixel:4
602 hasAlpha:YES
603 isPlanar:NO
604 colorSpaceName:NSDeviceRGBColorSpace
605 bytesPerRow:pixelsWide*4
606 bitsPerPixel:32];
607
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];
612 [ngc flushGraphics];
613 [NSGraphicsContext setCurrentContext:nil];
614 [NSGraphicsContext restoreGraphicsState];
615
616 json_object *js = [nbir vuoValue];
617 [nbir release];
618 return js;
619}
620@end
621
622@implementation NSBitmapImageRep (VuoRunnerCocoaConversion)
630- (json_object *)vuoValue
631{
632 // Flip the image data (OpenGL expects flipped data, but NSBitmapImageRep is not flipped).
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)
640 {
641 // Swizzle RGBA -> BGRA (so the GPU doesn't have to swizzle during each fetch)
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];
646 }
647
648 VuoImage vi = VuoImage_makeFromBuffer(bitmapDataFlipped, GL_BGRA, width, height, VuoImageColorDepth_8, ^(void *buffer){ free(buffer); });
649 VuoRetain(vi);
650 json_object *json = VuoImage_getInterprocessJson(vi);
651 VuoRelease(vi);
652 return json;
653}
654@end
655
656@implementation NSValue (VuoRunnerCocoaConversion)
664- (json_object *)vuoValue
665{
666 NSPoint p = [self pointValue];
667 return VuoPoint2d_getJson(VuoPoint2d_make(p.x, p.y));
668}
669@end
670
671@implementation NSData (VuoRunnerCocoaConversion)
679- (json_object *)vuoValue
680{
681 double p[3] = {0,0,0};
682 [self getBytes:p length:sizeof(double)*3];
683 return VuoPoint3d_getJson(VuoPoint3d_make(p[0], p[1], p[2]));
684}
685@end
686
687@implementation NSArray (VuoRunnerCocoaConversion)
695- (json_object *)vuoValue
696{
697 json_object *arrayJson = json_object_new_array();
698 for (id item in self)
699 {
700 json_object *itemJson = [item vuoValue];
701 json_object_array_add(arrayJson, itemJson);
702 }
703 return arrayJson;
704}
705@end