diff --git a/README.md b/README.md index dacecf4..880183e 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ -atemOSC -======= +atemOSC v2.0 +============ This is a Mac OS X application, providing an interface to control an ATEM video switcher via OSC. -The code is based on the *SwitcherPanel*-Democode (Version 3.1) provided by Blackmagic. +The code is based on the *SwitcherPanel*-Democode (Version 3.1) provided by Blackmagic. Additionally the control of a tally-light interface via Arduino is provided. ![atemOSC](https://github.com/danielbuechele/atemOSC/raw/master/atemOSC.jpg) +- [VVOSC](http://code.google.com/p/vvopensource/) is used as OSC-framework. +- [AMSerialPort](https://github.com/smokyonion/AMSerialPort) is used for Arduino-connection -VVOSC is used as OSC-framework. +The current version is built for Mac OS 10.8 SDK. A compiled and runnable version of the atemOSC is included. Caution: The software lacks of many usability features (like input validation). ---------- diff --git a/arduino-tally/arduino-tally.ino b/arduino-tally/arduino-tally.ino new file mode 100644 index 0000000..9bff88e --- /dev/null +++ b/arduino-tally/arduino-tally.ino @@ -0,0 +1,23 @@ +int incomingByte = 0; // for incoming serial data + +int cams[] = {6,9,10,11}; + +void setup() { + Serial.begin(9600); // opens serial port, sets data rate to 9600 bps +} + +void loop() { + + // send data only when you receive data: + if (Serial.available() > 0) { + // read the incoming byte: + incomingByte = Serial.read(); + + for (int i = 0;i + + + + BuildMachineOSBuild + 11E53 + CFBundleDevelopmentRegion + English + CFBundleExecutable + VVBasics + CFBundleGetInfoString + 156 + CFBundleIdentifier + com.vidvox.VVBasics + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 156 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E2002 + DTPlatformVersion + GM + DTSDKBuild + 10K549 + DTSDKName + macosx10.6 + DTXcode + 0432 + DTXcodeBuild + 4E2002 + + diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Resources/VVCrashReporter.nib b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Resources/VVCrashReporter.nib new file mode 100644 index 0000000..4c7b505 Binary files /dev/null and b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Resources/VVCrashReporter.nib differ diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/VVBasics b/atemOSC.app/Contents/Frameworks/VVBasics.framework/VVBasics deleted file mode 120000 index b4f88c3..0000000 --- a/atemOSC.app/Contents/Frameworks/VVBasics.framework/VVBasics +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/VVBasics \ No newline at end of file diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/VVBasics b/atemOSC.app/Contents/Frameworks/VVBasics.framework/VVBasics new file mode 100755 index 0000000..e9d2e6b Binary files /dev/null and b/atemOSC.app/Contents/Frameworks/VVBasics.framework/VVBasics differ diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current deleted file mode 120000 index 8c7e5a6..0000000 --- a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current +++ /dev/null @@ -1 +0,0 @@ -A \ No newline at end of file diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutLockArray.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutLockArray.h new file mode 100644 index 0000000..deaf284 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutLockArray.h @@ -0,0 +1,185 @@ + +#if IPHONE +#import +#else +#import +#endif +#import + + + +/// Similar to NSMutableArray, but thread-safe. Internally, uses an NSMutableArray and a rwlock. +/* +This class exists because NSMutableArray is not thread-safe by default: if you call methods on it from two different threads at the same time, it will try to execute both, often crashing in the process. I found myself writing a lot of lock/array pairs, so simplified everything by combining them into a single class. MutLockArray has methods which allow you to work with a mutable array in a transparent and thread-safe manner- it will automatically establish the read-/write-locks necessary to perform the relevant task. By avoiding the "lock" methods, you can also work with the array without performing any locking- so you can get a read-/write-lock, perform a number of actions, and then unlock. + +It is important to remember, when working with it, that MutLockArray is NOT a subclass of NSMutableArray; rather, it is a subclass of NSObject with an instance of an NSMutableArray and a rwlock for working with it safely. This means that you can't pass an instance of MutLockArray to anything which is expecting to be passed an NSMutableArray- internally, apple's frameworks will probably be doing some dark voodoo bullshit which will result in a spectacular failure. If you want to work with an actual NSMutableArray, check out the "array", "createArrayCopy", and "lockCreateArrayCopy" methods below. + +...and remember- when looking for stuff in an NSMutableArray, the array will use the "isEqualTo:" comparator method, which is slower than comparing the address of two pointers. if you know the pointer address hasn't changed (if you're *not* working with NSStrings), use the "indexOfIdenticalPtr", "removeIdenticalPtr", etc. methods to work with the array. +*/ + +@interface MutLockArray : NSObject { + NSMutableArray *array; + pthread_rwlock_t arrayLock; +} + +/// Creates and returns an auto-released MutLockArray with a given capacity. The capacity may be 0. ++ (id) arrayWithCapacity:(NSUInteger)c; +/// Inits and returns a MutLockArray with a given capacity; the capacity may be 0. +- (id) initWithCapacity:(NSUInteger)c; +- (id) init; + +/// Establishes a read-lock for the array; multiple read locks may exist simultaneously (if it's not changing, anything can look at the contents of the array). This method does not return until it has been able to get the lock. +- (void) rdlock; +- (BOOL) tryRdLock; // returns YES if i got a read-lock successfully! +/// Establishes a write-lock for the array. Only one write-lock may exist at any given time, and all read-locks must be relinquished before the write-lock may be established (if you're going to change the array, nothing else can be changing or observing it). +- (void) wrlock; +/// Unlocks the array. +- (void) unlock; + +/// Returns the NSMutableArray with everything in it. This returns the actual array, so be careful- it's possible to do something which ISN'T threadsafe with this... +- (NSMutableArray *) array; +/// Returns an NSMutableArray which was created by calling "mutableCopy" on my array. Again, it's possible to do something which ISN'T threadsafe by calling this... +- (NSMutableArray *) createArrayCopy; +/// Returns an NSMutableArray which was created while a read-lock was established; this is threadsafe. +- (NSMutableArray *) lockCreateArrayCopy; + +/// Calls "addObject" on my array; not threadsafe. +- (void) addObject:(id)o; +/// Establishes a write-lock, then calls "addObject" on self; threadsafe. +- (void) lockAddObject:(id)o; +/// Calls "addObjectsFromArray" on my array; not threadsafe. +- (void) addObjectsFromArray:(id)a; +/// Establishes a write-lock, then calls "addObjectsFromArray" on self; threadsafe. +- (void) lockAddObjectsFromArray:(id)a; +/// Calls "addObjectsFromArray" on my array; not threadsafe. +- (void) replaceWithObjectsFromArray:(id)a; +/// Establishes a write-lock, then calls "replaceWithObjectsFromArray" on self; threadsafe. +- (void) lockReplaceWithObjectsFromArray:(id)a; +/// Calls "insertObject:atIndex:" on my array; not threadsafe. +- (void) insertObject:(id)o atIndex:(NSUInteger)i; +/// Establishes a write-lock, then calls "insertObject:atIndex:" on self; threadsafe. +- (void) lockInsertObject:(id)o atIndex:(NSUInteger)i; +/// Calls "removeAllObjects" on my array; not threadsafe. +- (void) removeAllObjects; +/// Establishes a write-lock, then calls "removeAllObjects" on self; threadsafe. +- (void) lockRemoveAllObjects; +/// Calls "objectAtIndex:0" on my array; not threadsafe. +- (id) firstObject; +/// Establishes a read-lock, then calls "firstObject" on self; threadsafe +- (id) lockFirstObject; +/// Calls "removeObjectAtIndex:0" on my array; not threadsafe +- (void) removeFirstObject; +/// Establishes a write-lock, then calls "removeFirstObject" on self; threadsafe. +- (void) lockRemoveFirstObject; +/// Calls "lastObject" on my array; not threadsafe. +- (id) lastObject; +/// Establishes a read-lock, then calls "lastObject" on self; threadsafe. +- (id) lockLastObject; +/// Calls "removeLastObject" on my array; not threadsafe. +- (void) removeLastObject; +/// Establishes a write-lock, then calls "removeLastObject" on self; threadsafe. +- (void) lockRemoveLastObject; +/// Calls "removeObject:" on my array; not threadsafe. +- (void) removeObject:(id)o; +/// Establishes a write-lock, then calls "removeObject:" on self; threadsafe. +- (void) lockRemoveObject:(id)o; +/// Calls "removeObjectAtIndex:" on my array; not threadsafe. +- (void) removeObjectAtIndex:(NSUInteger)i; +/// Establishes a write-lock, then calls "removeObjectAtIndex:" on self; threadsafe. +- (void) lockRemoveObjectAtIndex:(NSUInteger)i; +/// Calls "removeObjectsAtIndexes:" on my array; not threadsafe. +- (void) removeObjectsAtIndexes:(NSIndexSet *)i; +/// Establishes a write-lock, then calls "removeObjectsAtIndexes:" on self; threadsafe. +- (void) lockRemoveObjectsAtIndexes:(NSIndexSet *)i; +/// Calls "removeObjectsInArray:" on my array; not threadsafe. +- (void) removeObjectsInArray:(NSArray *)otherArray; +/// Establishes a write-lock, then calls "removeObjectsInArray:" on self; threadsafe. +- (void) lockRemoveObjectsInArray:(NSArray *)otherArray; +/// Calls "removeIdenticalPtrsInArray:" on my array; not threadsafe +- (void) removeIdenticalPtrsInArray:(NSArray *)a; +/// Establishes a write-lock, then calls "removeIdenticalPtrsInArray:" on self; threadsafe. +- (void) lockRemoveIdenticalPtrsInArray:(NSArray *)a; + +/// Calls "replaceObjectsAtIndexes:withObjects" on my array; not threadsafe. +- (void) replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects; +// Establishes a write-lock, then calls "replaceObjectsAtIndexes:withObjects on self; threadsafe +- (void) lockReplaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects; + +/// Calls "valueForKey:" on my array; not threadsafe. +- (id) valueForKey:(NSString *)key; +/// Establishes a read-lock, then calls "valueForKey:" on self; threadsafe. +- (id) lockValueForKey:(NSString *)key; + + +/// Calls "containsObject:" on my array; not threadsafe. +- (BOOL) containsObject:(id)o; +/// Establishes a read-lock, then calls "containsObject:" on self; threadsafe. +- (BOOL) lockContainsObject:(id)o; +/// Calls "objectAtIndex:" on my array; not threadsafe. +- (id) objectAtIndex:(NSUInteger)i; +/// Establishes a read-lock, then calls "objectAtIndex:" on self; threadsafe. +- (id) lockObjectAtIndex:(NSUInteger)i; +/// Calls "objectsAtIndexes:" on my array; not threadsafe. +- (NSArray *) objectsAtIndexes:(NSIndexSet *)indexes; +/// Establishes a read-lock, then calls "objectsAtIndexes:" on self; threadsafe. +- (NSArray *) lockObjectsAtIndexes:(NSIndexSet *)indexes; +/// Calls "indexOfObject:" on my array; not threadsafe. +- (NSUInteger) indexOfObject:(id)o; +/// Establishes a read-lock, then calls "indexOfObject:" on self; threadsafe. +- (NSUInteger) lockIndexOfObject:(id)o; + + +/// Enumerates through my array- compares the address of each item in the array to the passed pointer. Unlike NSMutableArray, this method does NOT call isEqualTo:, it's just a simple == operator. +- (BOOL) containsIdenticalPtr:(id)o; +/// Establishes a read-lock, then calls "containsIdenticalPtr:" on self; threadsafe. +- (BOOL) lockContainsIdenticalPtr:(id)o; +/// Enumerates through my array- compares the address of each item in the array to the passed pointer. Unlike NSMutableArray, this method does NOT call isEqualTo:, it's just a simple == operator. +- (long) indexOfIdenticalPtr:(id)o; +/// Establishes a read-lock, then calls "indexOfIdenticalPtr:" on self; threadsafe. +- (long) lockIndexOfIdenticalPtr:(id)o; +/// Locates an item in my array by enumerating through it and comparing the address of each item in the array to the passed ptr, and then deletes the matching item from the array; not threadsafe. +- (void) removeIdenticalPtr:(id)o; +/// Establishes a write-lock, then calls "removeIdenticalPtr:" on self; threadsafe. +- (void) lockRemoveIdenticalPtr:(id)o; + +// Calls "filteredArrayUsingPredicate:" on my array; not threadsafe +- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate; +// Establishes a read-lock, then calls "filteredArrayUsingPredicate:" on self; threadsafe +- (NSArray *) lockFilteredArrayUsingPredicate:(NSPredicate *)predicate; + +/// Calls "makeObjectsPerformSelector:" on my array; not threadsafe. +- (void) makeObjectsPerformSelector:(SEL)s; +/// Establishes a read-lock, then calls "makeObjectsPerformSelector:" on self; threadsafe. +- (void) lockMakeObjectsPerformSelector:(SEL)s; +/// Calls "makeObjectsPerformSelector:withObject:" on my array; not threadsafe. +- (void) makeObjectsPerformSelector:(SEL)s withObject:(id)o; +/// Establishes a read-lock, then calls "makeObjectsPerformSelector:withObject:" on self; threadsafe. +- (void) lockMakeObjectsPerformSelector:(SEL)s withObject:(id)o; + + + +/* +- (void) makeCopyPerformSelector:(SEL)s; +- (void) lockMakeCopyPerformSelector:(SEL)s; +- (void) makeCopyPerformSelector:(SEL)s withObject:(id)o; +- (void) lockMakeCopyPerformSelector:(SEL)s withObject:(id)o; +*/ + + + +/// Calls "sortUsingSelector:" on my array; not threadsafe. +- (void) sortUsingSelector:(SEL)s; +/// Establishes a write-lock, then calls "sortUsingSelector:" on self; threadsafe. +- (void) lockSortUsingSelector:(SEL)s; + +/// Calls "sortUsingDescriptors:" on my array; not threadsafe. +- (void) sortUsingDescriptors:(NSArray *)descriptors; +/// Establishes a write-lock, then calls "sortUsingDescriptors:" on self; threadsafe. +- (void) lockSortUsingDescriptors:(NSArray *)descriptors; + +- (NSEnumerator *) objectEnumerator; +- (NSEnumerator *) reverseObjectEnumerator; +- (long) count; +- (long) lockCount; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutLockDict.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutLockDict.h new file mode 100644 index 0000000..e162293 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutLockDict.h @@ -0,0 +1,56 @@ + +#if IPHONE +#import +#else +#import +#endif +#import + + + +/// MutLockDict is a thread-safe version of NSMutableDictionary. +/*! +This class exists because NSMutableDictionary is not thread-safe by default: if you call methods on it from two different threads at the same time, it will try to execute both, often crashing in the process. This class has methods which allow you to work with a mutable dictionary in a transparent and thread-safe manner. +*/ + +@interface MutLockDict : NSObject { + NSMutableDictionary *dict; + pthread_rwlock_t dictLock; +} + ++ (id) dictionaryWithCapacity:(NSUInteger)c; ++ (id) dictionaryWithDict:(NSDictionary *)d; +- (id) initWithCapacity:(NSUInteger)c; + +- (void) rdlock; +- (void) wrlock; +- (void) unlock; + +- (NSMutableDictionary *) dict; +- (NSMutableDictionary *) createDictCopy; +- (NSMutableDictionary *) lockCreateDictCopy; + +- (void) setObject:(id)o forKey:(NSString *)s; +- (void) lockSetObject:(id)o forKey:(NSString *)s; +- (void) setValue:(id)v forKey:(NSString *)s; +- (void) lockSetValue:(id)v forKey:(NSString *)s; +- (void) removeAllObjects; +- (void) lockRemoveAllObjects; +- (id) objectForKey:(NSString *)k; +- (id) lockObjectForKey:(NSString *)k; +- (void) removeObjectForKey:(NSString *)k; +- (void) lockRemoveObjectForKey:(NSString *)k; +- (void) addEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (void) lockAddEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (NSArray *) allKeys; +- (NSArray *) lockAllKeys; +- (NSArray *) allValues; +- (NSArray *) lockAllValues; + +- (void) lockMakeObjectsPerformSelector:(SEL)s; +- (void) makeObjectsPerformSelector:(SEL)s; + +- (NSUInteger) count; +- (NSUInteger) lockCount; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutNRLockArray.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutNRLockArray.h new file mode 100644 index 0000000..9ad1138 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutNRLockArray.h @@ -0,0 +1,50 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import "MutLockArray.h" +#import "ObjectHolder.h" + + + +/// Subclass of MutLockArray; this class does NOT retain the objects in its array! +/* +this class exists because i frequently find myself in situations where i want to add an instance of an object to an array/dict/[any class which retains the passed instance], but i don't actually want the item to be retained. + +Instead of adding (and therefore retaining) objects to an array like my superclass, this class makes an ObjectHolder for objects which are added to it (so they don't get retained), and adds the ObjectHolder to me. when other classes ask me for the index of an object, or ask for the object at a particular index, i'll find the relevant ObjectHolder and then return the object it's storing. +*/ + +@interface MutNRLockArray : MutLockArray { + +} + ++ (id) arrayWithCapacity:(NSUInteger)c; + +- (NSMutableArray *) createArrayCopy; +- (NSMutableArray *) lockCreateArrayCopyFromObjects; +- (NSMutableArray *) createArrayCopyFromObjects; +- (void) addObject:(id)o; +- (void) addObjectsFromArray:(id)a; +- (void) replaceWithObjectsFromArray:(id)a; +- (void) insertObject:(id)o atIndex:(NSUInteger)i; +- (id) lastObject; +- (void) removeObject:(id)o; +- (BOOL) containsObject:(id)o; +- (id) objectAtIndex:(NSUInteger)i; +- (NSArray *) objectsAtIndexes:(NSIndexSet *)indexes; +- (NSUInteger) indexOfObject:(id)o; +- (BOOL) containsIdenticalPtr:(id)o; +- (long) indexOfIdenticalPtr:(id)o; +- (void) removeIdenticalPtr:(id)o; + +// these methods exist because the lookup cost for an ObjectHolder can be significant for high-performance applications- these methods get the object from the ObjectHolder and call the method directly on it! +- (void) bruteForceMakeObjectsPerformSelector:(SEL)s; +- (void) lockBruteForceMakeObjectsPerformSelector:(SEL)s; +- (void) bruteForceMakeObjectsPerformSelector:(SEL)s withObject:(id)o; +- (void) lockBruteForceMakeObjectsPerformSelector:(SEL)s withObject:(id)o; + + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutNRLockDict.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutNRLockDict.h new file mode 100644 index 0000000..f4f757f --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/MutNRLockDict.h @@ -0,0 +1,39 @@ +// +// MutNRLockDict.h +// VVOpenSource +// +// Created by David Lublin on 12/22/09. +// Copyright 2009 Vidvox. All rights reserved. +// + +#if IPHONE +#import +#else +#import +#endif + +#import "MutLockDict.h" +#import "ObjectHolder.h" + + + +/// Subclass of MutLockDict; this class does NOT retain the objects in its array! +/* +this class exists because i frequently find myself in situations where i want to add an instance of an object to an array/dict/[any class which retains the passed instance], but i don't actually want the item to be retained. + +Instead of adding (and therefore retaining) objects to an array like my superclass, this class makes an ObjectHolder for objects which are added to it (so they don't get retained), and adds the ObjectHolder to me. when other classes ask me for the index of an object, or ask for the object at a particular index, i'll find the relevant ObjectHolder and then return the object it's storing. +*/ + + +@interface MutNRLockDict : MutLockDict { + +} + + +- (void) setObject:(id)o forKey:(NSString *)s; +- (void) setValue:(id)v forKey:(NSString *)s; +- (id) objectForKey:(NSString *)k; +- (void) addEntriesFromDictionary:(id)otherDictionary; +- (NSArray *) allValues; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/NamedMutLockArray.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/NamedMutLockArray.h new file mode 100644 index 0000000..54e75d0 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/NamedMutLockArray.h @@ -0,0 +1,31 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "VVBasicMacros.h" +#import "MutLockArray.h" + + + + +/* + // only difference between this and MutLockArray is the "name" variable. +*/ + + + + +@interface NamedMutLockArray : MutLockArray { + NSString *name; +} + ++ (id) arrayWithCapacity:(int)c; ++ (id) create; + +- (NSComparisonResult) nameCompare:(NamedMutLockArray *)comp; + +@property (assign, readwrite) NSString *name; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/ObjectHolder.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/ObjectHolder.h new file mode 100644 index 0000000..64c397f --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/ObjectHolder.h @@ -0,0 +1,38 @@ + +#if IPHONE +#import +#else +#import +#endif + + + + +/* + created for working with the MutNRLockArray class. + + basically, you create an instance of this class and give it a reference to an + instance of an object. the instance is NOT retained- but you're now free to + pass ObjectHolder to stuff which will otherwise retain/release it without + worrying about whether the passed instance is retained/released. + + if you call a method on an instance of ObjectHolder and the ObjectHolder + class doesn't respond to that method, the instance will try to call the + method on its object. this means that working with ObjectHolder should- + theoretically, at any rate- be transparent... +*/ + + + + +@interface ObjectHolder : NSObject { + BOOL deleted; + id object; +} + ++ (id) createWithObject:(id)o; +- (id) initWithObject:(id)o; + +@property (assign,readwrite) id object; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVAssertionHandler.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVAssertionHandler.h new file mode 100644 index 0000000..47cdeef --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVAssertionHandler.h @@ -0,0 +1,31 @@ + +#if IPHONE +#import +#else +#import +#endif + + + + +#define USE_CUSTOM_ASSERTION_HANDLER \ +{ \ + NSThread *__currentThread = [NSThread currentThread]; \ + NSDictionary *__threadDict = (__currentThread==nil) ? nil : [__currentThread threadDictionary]; \ + if (__threadDict != nil) { \ + VVAssertionHandler *__newAH = [[VVAssertionHandler alloc] init]; \ + if (__newAH != nil) { \ + [__threadDict setValue:__newAH forKey:@"NSAssertionHandler"]; \ + [__newAH release]; \ + __newAH = nil; \ + } \ + } \ +} + + + +@interface VVAssertionHandler : NSAssertionHandler { + +} + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVBasicMacros.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVBasicMacros.h new file mode 100644 index 0000000..6eab4c6 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVBasicMacros.h @@ -0,0 +1,229 @@ + +// macros for checking to see if something is nil, and if it's not releasing and setting it to nil +#define VVRELEASE(item) {if (item != nil) { \ + [item release]; \ + item = nil; \ +}} +#define VVAUTORELEASE(item) {if (item != nil) { \ + [item autorelease]; \ + item = nil; \ +}} + + + +// macros for making a CGRect from an NSRect +#define NSMAKECGRECT(n) CGRectMake(n.origin.x, n.origin.y, n.size.width, n.size.height) +#define NSMAKECGPOINT(n) CGPointMake(n.x, n.y) +#define NSMAKECGSIZE(n) CGSizeMake(n.width, n.height) +// macros for making an NSRect from a CGRect +#define CGMAKENSRECT(n) NSMakeRect(n.origin.x, n.origin.y, n.size.width, n.size.height) +#define CGMAKENSSIZE(n) NSMakeSize(n.width,n.height) + +// macro for quickly printing out the dimensions of a rect (and a name/id so you can distinguish between them) +#define NSRectLog(n,r) NSLog(@"%@, (%f,%f) : %fx%f",n,r.origin.x,r.origin.y,r.size.width,r.size.height) +#define NSPointLog(n,r) NSLog(@"%@, (%f,%f)",n,r.x,r.y) +#define NSSizeLog(n,s) NSLog(@"%@, %fx%f",n,s.width,s.height) + +// macros for quickly making numbers and values +#define NUMINT(i) [NSNumber numberWithInt:i] +#define NUMFLOAT(f) [NSNumber numberWithFloat:f] +#define NUMBOOL(b) [NSNumber numberWithBool:b] +#define NUMDOUBLE(d) [NSNumber numberWithDouble:d] +#define VALSIZE(s) [NSValue valueWithSize:s] +#define VALRECT(r) [NSValue valueWithRect:r] + +// macro for quickly archiving and object +#define ARCHIVE(a) [NSKeyedArchiver archivedDataWithRootObject:a] +#define UNARCHIVE(a) [NSKeyedUnarchiver unarchiveObjectWithData:a] + +// macro for quickly making colors +#define VVDEVCOLOR(r,g,b,a) [NSColor colorWithDeviceRed:r green:g blue:b alpha:a] +#define VVCALCOLOR(r,g,b,a) [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a] + +// nice little macro for strings +#define VVSTRING(n) ((NSString *)[NSString stringWithString:n]) +#define VVFMTSTRING(f, ...) ((NSString *)[NSString stringWithFormat:f, ##__VA_ARGS__]) +#define VVDATASTRING(n) ((NSData *)[[NSString stringWithString:n] dataUsingEncoding:NSUTF8StringEncoding]) +#define VVDATAFMTSTRING(f, ...) ((NSData *)[[NSString stringWithFormat:f, ##__VA_ARGS__] dataUsingEncoding:NSUTF8StringEncoding]) + +// macros for quickly making arrays because.....well, it's the wiimote, and i'm fucking tired of typing. so there. +#define OBJARRAY(f) [NSArray arrayWithObject:f] +#define OBJSARRAY(f, ...) [NSArray arrayWithObjects:f, ##__VA_ARGS__, nil] +#define MUTARRAY [NSMutableArray arrayWithCapacity:0] + +// macros for quickly making dicts +#define OBJDICT(o,k) [NSDictionary dictionaryWithObject:o forKey:k] +#define OBJSDICT(o, ...) [NSDictionary dictionaryWithObjectsAndKeys:o,#__VA_ARGS__, nil] +#define MUTDICT [NSMutableDictionary dictionaryWithCapacity:0] + +// calculating the distance between two NSPoints or similar structs +#define POINTDISTANCE(a,b) fabs(sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y))) + + +// this is a macro for drawing an NSRect in opengl +#define GLDRAWRECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_QUADS,0,4); \ +} + + + +// this is a macro for stroking an NSRect in opengl +#define GLSTROKERECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x-0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y-0.5, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,8); \ +} +/* +#define GLSTROKERECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,8); \ +} +*/ + + +// this is a macro for drawing a line connecting two points +#define GLDRAWLINE(p,q) \ +{ \ + GLfloat vvMacroVertices[]={ \ + p.x, p.y, 0.0, \ + q.x, q.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,2); \ +} + + + +// this is a macro for drawing a diamond specified by a point and radius in opengl +#define GLDRAWDIAMOND(p,r) \ +{ \ + GLfloat vvMacroVertices[] = { \ + p.x-r, p.y, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x, p.y-r, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_QUADS,0,4); \ +} + + + +// this is a macro for stroking an diamond around a point in opengl +#define GLSTROKEDIAMOND(p,r) \ +{ \ + GLfloat vvMacroVertices[] = { \ + p.x-r, p.y, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x, p.y-r, 0.0, \ + p.x, p.y-r, 0.0, \ + p.x-r, p.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINE_LOOP,0,8); \ +} + + +// this is a macro for drawing a texture of a specified size in a rect +#define GLDRAWTEXSIZEDINRECT(t,s,r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0,s.height, \ + s.width,s.height, \ + s.width,0.0, \ + 0.0,0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWFLIPPEDTEXSIZEDINRECT(t,s,r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0, 0.0, \ + s.width, 0.0, \ + s.width, s.height, \ + 0.0, s.height}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWTEXSIZEDINRECTATZ(t,s,r,z) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, z, \ + r.origin.x, r.origin.y+r.size.height, z}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0,s.height, \ + s.width,s.height, \ + s.width,0.0, \ + 0.0,0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWFLIPPEDTEXSIZEDINRECTATZ(t,s,r,z) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, z, \ + r.origin.x, r.origin.y+r.size.height, z}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0, 0.0, \ + s.width, 0.0, \ + s.width, s.height, \ + 0.0, s.height}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVBasics.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVBasics.h new file mode 100644 index 0000000..b36c65a --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVBasics.h @@ -0,0 +1,55 @@ + +#import "VVBasicMacros.h" + +#import "VVThreadLoop.h" +#import "VVAssertionHandler.h" +#import "VVStopwatch.h" +#import "ObjectHolder.h" +#import "MutLockArray.h" +#import "MutLockDict.h" +#import "MutNRLockArray.h" +#import "MutNRLockDict.h" +#import "NamedMutLockArray.h" + +#if !IPHONE + #import "VVCURLDL.h" + #import "VVSprite.h" + #import "VVSpriteManager.h" + #import "VVSpriteView.h" + #import "VVSpriteControl.h" + #import "VVSpriteControlCell.h" + #import "VVSpriteGLView.h" + #import "VVCrashReporter.h" + //#import "NSHostAdditions.h" +#endif + +/* + the following stuff is for doxygen +*/ + +/*! +\mainpage + +\htmlonly + + + +Introduction +

+VVBasics is an Objective-c framework with a number of classes which perform functions that i need regularly- but, for whatever reason, aren't provided by the stock frameworks. Expect pretty much everything to link against this framework for one reason or another- macros, useful classes, etc- and expect this framework to continuously grow as I start to open-source more and more of my bag of tricks. +

+ +\endhtmlonly +*/ diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCURLDL.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCURLDL.h new file mode 100644 index 0000000..39d4c9b --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCURLDL.h @@ -0,0 +1,72 @@ + +/* + this class offers a very limited, very simple cocoa interface to libcurl for doing extremely + basic http transfer ops + + basically, this class exists because at this time NSURLConnection is problematic and + top-heavy, and i wanted an easy, effective, and reliable interface for handling the extremely + limited set of http data transfer operations required by my frameworks/apps. + + this class was meant to be used as a one-shot throwaway; that is, you're meant to create an + instance of this class which will be auto-released as soon as the autorelease pool is + popped. the instance you create is meant to be used once, and then thrown away- THIS WILL + PROBABLY BREAK IF YOU TRY TO USE THE SAME INSTANCE TO PERFORM MORE THAN ONE TRANSFER. +*/ + + +#import +#import + + + + +@protocol VVCURLDLDelegate +- (void) dlFinished:(id)h; +@end + + + + +@interface VVCURLDL : NSObject { + NSString *urlString; + CURL *curlHandle; + + NSMutableData *responseData; + + struct curl_slist *headerList; // nil by default- if non-nil, supplied to the handle as CURLOPT_HTTPHEADER + NSMutableData *postData; // if non-nil, simply posted as CURLOPT_POSTFIELDS + struct curl_httppost *firstFormPtr; // if postData was nil but this isn't, posted as CURLOPT_HTTPPOST + struct curl_httppost *lastFormPtr; + + BOOL returnOnMain; + BOOL performing; + CURLcode err; +} + ++ (id) createWithAddress:(NSString *)a; +- (id) initWithAddress:(NSString *)a; + +- (void) perform; +- (void) performAsync:(BOOL)as withDelegate:(id )d; +- (void) _performAsyncWithDelegate:(id )d; +- (void) _performWithDelegate:(id )d; + +//- (struct curl_slist *) headerList; +//- (struct curl_httppost *) firstFormPtr; +//- (struct curl_httppost *) lastFormPtr; +- (void) appendDataToPOST:(NSData *)d; +- (void) appendStringToPOST:(NSString *)s; + +- (void) writePtr:(void *)ptr size:(size_t)s; + +@property (assign,readwrite) struct curl_slist *headerList; +@property (assign,readwrite) struct curl_httppost *firstFormPtr; +@property (assign,readwrite) struct curl_httppost *lastFormPtr; +@property (assign,readwrite) BOOL returnOnMain; +@property (readonly) NSMutableData *responseData; +@property (readonly) NSString *responseString; +@property (readonly) CURLcode err; + +@end + +size_t vvcurlWriteFunction(void *ptr, size_t size, size_t nmemb, void *stream); diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporter.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporter.h new file mode 100644 index 0000000..0dc9c90 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporter.h @@ -0,0 +1,101 @@ + +#import +#import +#include "AvailabilityMacros.h" +#import +#import +#import "VVCURLDL.h" +#import "MutLockArray.h" + + + + +/// The crash reporter's delegate must adhere to this protocol +/*! + This protocol exists largely because it's conceivable that objects will want to know when the crash reporter- which uploads asynchronously- has finished sending its data to the remote server. +*/ +@protocol OldVVCrashReporterDelegate +- (void) crashReporterCheckDone; +@end + +@protocol VVCrashReporterDelegate +- (void) crashReporterCheckDone:(BOOL)foundLogs; // "new"- 'f' designates whether crash reports were found or not +@end + + + +/// Simple class which automatically uploads crash logs and other relevant diagnostic information automatically made available by os x to a remote server. +/*! +it's been my experience that most apps crash much more frequently on end-users than the app's developers would guess. the simplest and easiest way to improve the end-user's experience is to have the application check their machine for crash logs- which are generated automatically by os x whenever an application crashes- and send them to the developer. + +this class exists so i have a really easy way to make my apps send their crash logs to me; the goal here is to make it as easy as possible to get all the information i need to troubleshoot a problem with as little work on the user's part as possible. it also sends a basic system profile, anything the app- and ONLY the app, not other apps- recently printed to the console log, and optional description/email fields to facilitate communication directly with the user. this data is then uploaded to a given URL using an HTTP POST. + +on the server side, i use a PHP page which sanitizes the POST data (i can't stress how important this step is) and works with it. i've included a sample PHP page that simply dumps the received data to a file on disk (and optionally emails someone) with this project. + +HOW TO USE THIS CLASS: + + 1)- create an instance of this class + + 2)- set the instance's delegate, uploadURL, and developerEmail. these are necessary! + + 3)- call "check" on the instance. when it's done, it calls "crashReporterCheckDone" on the + delegate. that's it- you're done. +*/ + +@interface VVCrashReporter : NSObject { + NSString *uploadURL; // does NOT includes http:// + NSString *developerEmail; + id delegate; // must respond to VVCrashReporterDelegate protocol + MutLockArray *crashLogArray; + NSMutableDictionary *systemProfilerDict; + NSString *consoleLog; + int jobSize; // used to update progress indicator/label + int jobCurrentIndex; // used to update progress indicator/label + int currentCrashLogTimeout; // countdown for timeout of sending/receiving data for a specific crash log + NSTimer *currentCrashLogTimer; + + IBOutlet NSWindow *window; + IBOutlet NSButton *replyButton; + IBOutlet NSView *emailFieldHolder; + IBOutlet NSTextField *emailField; + IBOutlet NSTextView *descriptionField; + IBOutlet NSTextField *submittingLabel; // non-editable. 'submitting', 'getting machine profile', etc. + IBOutlet NSProgressIndicator *progressIndicator; // indicates progress through all crash logs to be submitted + IBOutlet NSTextField *countdownLabel; // non-editable; countdown so user knows app hasn't hung + + NSNib *theNib; + NSArray *nibTopLevelObjects; +} + ++ (NSString *) _stringForSystemProfilerDataType:(NSString *)t; + +/// This is the main method- when you call 'check', the crash reporter looks for crash logs, gets a basic system profile, and collects anything your applications has dumped to the console log. +- (void) check; +- (void) openCrashReporter; +- (IBAction) replyButtonClicked:(id)sender; +- (IBAction) doneClicked:(id)sender; +- (void) sendACrashLog; +- (void) closeCrashReporter; + +- (NSString *) _nibName; +- (BOOL) _assembleCrashLogs; // assembles the array of crash logs, returns a YES if logs were found and have to be sent in +- (NSString *) _consoleLogString; +- (NSMutableDictionary *) _systemProfilerDict; + +- (void) updateCrashLogTimeout:(NSTimer *)t; + +// VVCURLDLDelegate method- this class will be the delegate of multiple VVCURLDL instances +- (void) dlFinished:(id)h; + +/// Sets the developer email address; this is displayed if the user has a problem connecting to the internet/the server the crash reporter is supposed to be connecting to +- (void) setDeveloperEmail:(NSString *)n; +- (NSString *) developerEmail; +/// This is the URL of the php/cgi/etc. page which the crash data will be POSTed to +- (void) setUploadURL:(NSString *)n; +- (NSString *) uploadURL; + +/// The crash reporter's delegate is notified when the check has completed +@property (assign,readwrite) id delegate; +@property (readonly) NSButton *replyButton; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporterDescriptionField.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporterDescriptionField.h new file mode 100644 index 0000000..f39f0f5 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporterDescriptionField.h @@ -0,0 +1,15 @@ +#import + + +/* + this class exists solely to prevent users from pasting or dragging huge amounts of text (like + crash/console logs!) into the description field of the crash reporter. sounds weird, but trust + me- it's necessary. +*/ + + +@interface VVCrashReporterDescriptionField : NSTextView { + +} + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporterEmailField.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporterEmailField.h new file mode 100644 index 0000000..fb883f8 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVCrashReporterEmailField.h @@ -0,0 +1,14 @@ +#import +#import + + +/* + this class exists solely to prevent users from pasting huge amounts of text into the email field +*/ + + +@interface VVCrashReporterEmailField : NSTextField { + +} + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSprite.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSprite.h new file mode 100644 index 0000000..34246be --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSprite.h @@ -0,0 +1,104 @@ + +/* Always with the sprites... + + sprite |sprīt| + noun + 1 an elf or fairy. + 2 a computer graphic that may be moved on-screen and otherwise manipulated as a single entity. + 3 a faint flash, typically red, sometimes emitted in the upper atmosphere over a thunderstorm owing to the collision of high-energy electrons with air molecules. + ORIGIN Middle English : alteration of sprit, a contraction of spirit . */ + +#import +#include + + + + +typedef enum _VVSpriteEventType { + VVSpriteEventNULL = 0, + VVSpriteEventDown = 1, + VVSpriteEventDrag = 2, + VVSpriteEventUp = 3, + VVSpriteEventDouble = 4, + VVSpriteEventRightDown = 5, + VVSpriteEventRightUp = 6 +} VVSpriteEventType; + + + + +@interface VVSprite : NSObject { + BOOL deleted; + BOOL locked; // whether or not i should respond to mouse input. DOESN'T AFFECT ANYTHING IN THIS CLASS! variable exists for the user's convenience, and is otherwise superfluous! + BOOL hidden; // whether or not the sprite should draw. DOESN'T AFFECT ANYTHING IN THIS CLASS! variable exists for the user's convenience, and is otherwise superfluous! + BOOL dropFromMultiSpriteActions; // only valid if sprite manager's allowMultiSpriteInteraction' is YES. NO by default. if YES, then if you mousedown on this and any other sprite, this sprite gets dropped from the mousedown. used for allowing multi-sprite interaction to prevent clicks from hitting "background" sprites (which have this set to YES) + long spriteIndex; + id manager; // the VVSpriteManager i exist within- NOT retained! + id delegate; // NOT retained! + SEL drawCallback; // delegate method; passed a ptr to this sprite! + SEL actionCallback; // delegate method; passed a ptr to this sprite! + + NSRect rect; // the sprite i'm tracking + NSBezierPath *bezierPath; // retained. nil by default, set to nil if you call setRect: on this instance. if non-nil, this path is used instead of "rect" for determining mouse action and drawing intersection! + OSSpinLock pathLock; + + int lastActionType; // updated whenever an action is received + NSPoint lastActionCoords; // coords at which last action took place + BOOL lastActionInBounds; // whether or not the last action was within my bounds + BOOL trackingFlag; // whether or not i'm tracking stuff + NSPoint mouseDownCoords; // absolute coords of mousedown + NSPoint lastActionDelta; // change between most-recently-received action coords and last received coords + NSPoint mouseDownDelta; // change between mousedown loc and most-recently received coords + long mouseDownModifierFlags; + + id userInfo; // RETAINED! for storing a random thing... + id NRUserInfo; // NOT RETAINED! for storing something that *shouldn't* be retained... + id safeString; // nil on init- many sprites need formatted text, this is a convenience variable... +} + ++ (id) createWithRect:(NSRect)r inManager:(id)m; +- (id) initWithRect:(NSRect)r inManager:(id)m; + +- (void) prepareToBeDeleted; + +- (BOOL) checkPoint:(NSPoint)p; +- (BOOL) checkRect:(NSRect)r; + +- (void) receivedEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m; +- (void) mouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) rightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) rightMouseUp:(NSPoint)p; +- (void) mouseDragged:(NSPoint)p; +- (void) mouseUp:(NSPoint)p; +- (void) draw; + +- (void) bringToFront; +- (void) sendToBack; + +@property (assign, readwrite) BOOL locked; +@property (assign, readwrite) BOOL hidden; +@property (assign, readwrite) BOOL dropFromMultiSpriteActions; +@property (readonly) long spriteIndex; +@property (readonly) id manager; +@property (assign, readwrite) id delegate; +@property (assign, readwrite) SEL drawCallback; +@property (assign, readwrite) SEL actionCallback; + +@property (assign, readwrite) NSRect rect; +//@property (retain,readwrite) NSBezierPath *path; +- (void) setBezierPath:(NSBezierPath *)n; +- (NSBezierPath *) safelyGetBezierPath; +- (NSRect) spriteBounds; // special method- either returns "rect" or (if path is non-nil) the bounds of the bezier path! +@property (readonly) VVSpriteEventType lastActionType; +@property (readonly) NSPoint lastActionCoords; +@property (readonly) BOOL lastActionInBounds; +@property (readonly) BOOL trackingFlag; +@property (readonly) NSPoint mouseDownCoords; +@property (readonly) NSPoint lastActionDelta; +@property (readonly) NSPoint mouseDownDelta; +@property (readonly) long mouseDownModifierFlags; +@property (assign,readwrite) id userInfo; +@property (assign,readwrite) id NRUserInfo; +@property (assign,readwrite) id safeString; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteControl.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteControl.h new file mode 100644 index 0000000..2ed78b7 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteControl.h @@ -0,0 +1,49 @@ + +#import +#import "VVSpriteManager.h" +#include + + + + +extern int _maxSpriteControlCount; +extern int _spriteControlCount; + + + + +@interface VVSpriteControl : NSControl { + BOOL deleted; + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + + OSSpinLock propertyLock; + NSEvent *lastMouseEvent; + NSColor *clearColor; + BOOL drawBorder; + NSColor *borderColor; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED +} + +- (void) generalInit; + +- (void) prepareToBeDeleted; + +- (void) finishedDrawing; + +- (void) updateSprites; + +@property (readonly) BOOL deleted; +@property (readonly) VVSpriteManager *spriteManager; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) BOOL mouseIsDown; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteControlCell.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteControlCell.h new file mode 100644 index 0000000..fc8e151 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteControlCell.h @@ -0,0 +1,11 @@ + +#import + + + + +@interface VVSpriteControlCell : NSActionCell { + +} + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteGLView.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteGLView.h new file mode 100644 index 0000000..a47b6a2 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteGLView.h @@ -0,0 +1,82 @@ + +#import +#import "VVSpriteManager.h" +#import +#import +#import + + + + +typedef enum { + VVFenceModeEveryRefresh = 0, // every time a display callback runs, drawing commands are sent to the GPU. + VVFenceModeDBSkip = 1, // the apple gl fence extension is used to make sure that drawing commands for the back buffer have finished before more drawing commands are sent to the back buffer (the front buffer can receive commands, though) + VVFenceModeSBSkip = 2, // the apple gl fence extension is used to make sure that drawing commands for the single buffer have finished before more drawing commands are sent to it + VVFenceModeFinish = 3 // glFinish is used instead of glFlush +} VVFenceMode; + +typedef enum { + VVFlushModeGL = 0, // glFlush() + VVFlushModeCGL = 1, // CGLFlushDrawable() + VVFlushModeNS = 2, // [context flushBuffer] + VVFlushModeApple = 3, // glFlushRenderAPPLE() + VVFlushModeFinish = 4 // glFinish() +} VVFlushMode; + + + + +@interface VVSpriteGLView : NSOpenGLView { + BOOL deleted; + + BOOL initialized; + //BOOL needsReshape; + pthread_mutex_t glLock; + + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + NSEvent *lastMouseEvent; + GLfloat clearColor[4]; + BOOL drawBorder; + GLfloat borderColor[4]; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED + + VVFlushMode flushMode; + + VVFenceMode fenceMode; + GLuint fenceA; + GLuint fenceB; + BOOL waitingForFenceA; + BOOL fenceADeployed; + BOOL fenceBDeployed; + OSSpinLock fenceLock; +} + +- (void) generalInit; +- (void) prepareToBeDeleted; + +- (void) initializeGL; +- (void) finishedDrawing; +//- (void) reshapeGL; +- (void) updateSprites; + +- (void) _lock; +- (void) _unlock; +//- (void) lockSetOpenGLContext:(NSOpenGLContext *)n; + +@property (readonly) BOOL deleted; +@property (assign,readwrite) BOOL initialized; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) VVSpriteManager *spriteManager; +@property (readonly) BOOL mouseIsDown; +@property (assign, readwrite) VVFlushMode flushMode; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteManager.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteManager.h new file mode 100644 index 0000000..b8f0dc4 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteManager.h @@ -0,0 +1,57 @@ + +#import +#import "VVSprite.h" +#import "MutLockArray.h" + + + + +@interface VVSpriteManager : NSObject { + BOOL deleted; + BOOL allowMultiSpriteInteraction; // NO by default- if YES, clicking/dragging/etc works with multiple sprites! + BOOL multiSpriteExecutesOnMultipleSprites; // only relevant if multi-sprite interaction is YES. this is NO by default- if it's YES all sprites in "spritesInUse" will receive an action callback when any of them get an action method. if this is NO then only the sprite that "caught" the interaction will receive an action callback! + MutLockArray *spriteArray; // searched from beginning to end, so order is like z-index! + VVSprite *spriteInUse; // array of VVSprite objects currently tracking drag info + MutLockArray *spritesInUse; // ONLY VALID IF MULTI SPRITE INTERACTION IS YES! array of VVSprite o + long spriteIndexCount; +} + +- (void) prepareToBeDeleted; + +// return YES if the mousedown occurred on one or more sprites +- (BOOL) receivedMouseDownEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m visibleOnly:(BOOL)v; +- (void) receivedOtherEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m; +- (BOOL) localMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localVisibleMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localRightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localVisibleRightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) localRightMouseUp:(NSPoint)p; +- (void) localMouseDragged:(NSPoint)p; +- (void) localMouseUp:(NSPoint)p; +- (void) terminatePresentMouseSession; // call this and sprites will stop responding to the mouse until it is clicked again + +- (id) newSpriteAtBottomForRect:(NSRect)r; +- (id) newSpriteAtTopForRect:(NSRect)r; +- (long) getUniqueSpriteIndex; + +- (VVSprite *) spriteAtPoint:(NSPoint)p; +- (VVSprite *) visibleSpriteAtPoint:(NSPoint)p; +- (VVSprite *) spriteForIndex:(long)i; +- (void) removeSpriteForIndex:(long)i; +- (void) removeSprite:(id)z; +- (void) removeSpritesFromArray:(NSArray *)array; +- (void) removeAllSprites; +//- (void) moveSpriteToFront:(VVSprite *)z; + +- (void) draw; +- (void) drawRect:(NSRect)r; + +- (VVSprite *) spriteInUse; +- (void) setSpriteInUse:(VVSprite *)z; + +@property (assign,readwrite) BOOL allowMultiSpriteInteraction; +@property (assign,readwrite) BOOL multiSpriteExecutesOnMultipleSprites; +@property (readonly) MutLockArray *spriteArray; +@property (readonly) MutLockArray *spritesInUse; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteView.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteView.h new file mode 100644 index 0000000..a8d17a0 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVSpriteView.h @@ -0,0 +1,48 @@ + +#import +#import "VVSpriteManager.h" +#include + + + + +extern int _spriteViewCount; + + + + +@interface VVSpriteView : NSView { + BOOL deleted; + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + + OSSpinLock propertyLock; + NSEvent *lastMouseEvent; + NSColor *clearColor; + BOOL drawBorder; + NSColor *borderColor; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED +} + +- (void) generalInit; + +- (void) prepareToBeDeleted; + +- (void) finishedDrawing; + +- (void) updateSprites; + +@property (readonly) BOOL deleted; +@property (readonly) VVSpriteManager *spriteManager; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) BOOL mouseIsDown; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVStopwatch.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVStopwatch.h new file mode 100644 index 0000000..a1f9c35 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVStopwatch.h @@ -0,0 +1,35 @@ + +#if IPHONE +#import +#else +#import +#endif +#include +#import + + + +/// This class is used to measure how long it takes to do things; much easier to work with than NSDate. + +@interface VVStopwatch : NSObject { + struct timeval startTime; + OSSpinLock timeLock; +} + +/// Returns an auto-released instance of VVStopwatch; the stopwatch is started on creation. ++ (id) create; + +/// Starts the stopwatch over again +- (void) start; +/// Returns a float representing the time (in seconds) since the stopwatch was started +- (double) timeSinceStart; +/// Sets the stopwatch's starting time as an offset to the current time +- (void) startInTimeInterval:(NSTimeInterval)t; +/// Populates the passed timeval struct with the current timeval +- (void) copyStartTimeToTimevalStruct:(struct timeval *)dst; +/// Populates the starting time with the passed timeval struct +- (void) setStartTimeStruct:(struct timeval *)src; + +@end + +void populateTimevalWithFloat(struct timeval *tval, double secVal); diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVThreadLoop.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVThreadLoop.h new file mode 100644 index 0000000..0a6342f --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Headers/VVThreadLoop.h @@ -0,0 +1,63 @@ + +#if IPHONE +#import +#else +#import +#endif +#include +#import +#include + + + + +/// Simple class for spawning a thread which executes at a specified interval- simpler and easier to work with than NSThread/NSTimer in multi-threaded programming environments. +/*! +When started, an instance of this class will spawn a thread and repeatedly execute a method on that thread. If it was passed a target and selector on creation, the selector will be called on the target every time the thread executes. If it's more convenient to subclass VVThreadLoop and work with your custom subclass, leave the target/selector nil and VVThreadLoop will call "threadProc" on itself- just override this method (it's empty anyway) in your subclass and do whatever you want in there. + +You can change the execution interval, and VVThreadLoop also examines how long it takes to execute your code and adjusts in an attempt to ensure that the interval is accurate (sleep-time is interval-duration minus proc-execution-duration) +*/ + + + + +@interface VVThreadLoop : NSObject { + double interval; + double maxInterval; + BOOL running; + BOOL bail; + BOOL paused; + BOOL executingCallback; + + OSSpinLock valLock; // ONLY used for quickly accessing 'running', 'bail', 'paused', and 'executingCallback' in a threadsafe fashion + + id targetObj; //! + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Resources/Info.plist b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Resources/Info.plist new file mode 100644 index 0000000..29822ba --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Resources/Info.plist @@ -0,0 +1,38 @@ + + + + + BuildMachineOSBuild + 11E53 + CFBundleDevelopmentRegion + English + CFBundleExecutable + VVBasics + CFBundleGetInfoString + 156 + CFBundleIdentifier + com.vidvox.VVBasics + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 156 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E2002 + DTPlatformVersion + GM + DTSDKBuild + 10K549 + DTSDKName + macosx10.6 + DTXcode + 0432 + DTXcodeBuild + 4E2002 + + diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Resources/VVCrashReporter.nib b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Resources/VVCrashReporter.nib new file mode 100644 index 0000000..4c7b505 Binary files /dev/null and b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/Resources/VVCrashReporter.nib differ diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/VVBasics b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/VVBasics new file mode 100755 index 0000000..e9d2e6b Binary files /dev/null and b/atemOSC.app/Contents/Frameworks/VVBasics.framework/Versions/Current/VVBasics differ diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutLockArray.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutLockArray.h new file mode 100644 index 0000000..deaf284 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutLockArray.h @@ -0,0 +1,185 @@ + +#if IPHONE +#import +#else +#import +#endif +#import + + + +/// Similar to NSMutableArray, but thread-safe. Internally, uses an NSMutableArray and a rwlock. +/* +This class exists because NSMutableArray is not thread-safe by default: if you call methods on it from two different threads at the same time, it will try to execute both, often crashing in the process. I found myself writing a lot of lock/array pairs, so simplified everything by combining them into a single class. MutLockArray has methods which allow you to work with a mutable array in a transparent and thread-safe manner- it will automatically establish the read-/write-locks necessary to perform the relevant task. By avoiding the "lock" methods, you can also work with the array without performing any locking- so you can get a read-/write-lock, perform a number of actions, and then unlock. + +It is important to remember, when working with it, that MutLockArray is NOT a subclass of NSMutableArray; rather, it is a subclass of NSObject with an instance of an NSMutableArray and a rwlock for working with it safely. This means that you can't pass an instance of MutLockArray to anything which is expecting to be passed an NSMutableArray- internally, apple's frameworks will probably be doing some dark voodoo bullshit which will result in a spectacular failure. If you want to work with an actual NSMutableArray, check out the "array", "createArrayCopy", and "lockCreateArrayCopy" methods below. + +...and remember- when looking for stuff in an NSMutableArray, the array will use the "isEqualTo:" comparator method, which is slower than comparing the address of two pointers. if you know the pointer address hasn't changed (if you're *not* working with NSStrings), use the "indexOfIdenticalPtr", "removeIdenticalPtr", etc. methods to work with the array. +*/ + +@interface MutLockArray : NSObject { + NSMutableArray *array; + pthread_rwlock_t arrayLock; +} + +/// Creates and returns an auto-released MutLockArray with a given capacity. The capacity may be 0. ++ (id) arrayWithCapacity:(NSUInteger)c; +/// Inits and returns a MutLockArray with a given capacity; the capacity may be 0. +- (id) initWithCapacity:(NSUInteger)c; +- (id) init; + +/// Establishes a read-lock for the array; multiple read locks may exist simultaneously (if it's not changing, anything can look at the contents of the array). This method does not return until it has been able to get the lock. +- (void) rdlock; +- (BOOL) tryRdLock; // returns YES if i got a read-lock successfully! +/// Establishes a write-lock for the array. Only one write-lock may exist at any given time, and all read-locks must be relinquished before the write-lock may be established (if you're going to change the array, nothing else can be changing or observing it). +- (void) wrlock; +/// Unlocks the array. +- (void) unlock; + +/// Returns the NSMutableArray with everything in it. This returns the actual array, so be careful- it's possible to do something which ISN'T threadsafe with this... +- (NSMutableArray *) array; +/// Returns an NSMutableArray which was created by calling "mutableCopy" on my array. Again, it's possible to do something which ISN'T threadsafe by calling this... +- (NSMutableArray *) createArrayCopy; +/// Returns an NSMutableArray which was created while a read-lock was established; this is threadsafe. +- (NSMutableArray *) lockCreateArrayCopy; + +/// Calls "addObject" on my array; not threadsafe. +- (void) addObject:(id)o; +/// Establishes a write-lock, then calls "addObject" on self; threadsafe. +- (void) lockAddObject:(id)o; +/// Calls "addObjectsFromArray" on my array; not threadsafe. +- (void) addObjectsFromArray:(id)a; +/// Establishes a write-lock, then calls "addObjectsFromArray" on self; threadsafe. +- (void) lockAddObjectsFromArray:(id)a; +/// Calls "addObjectsFromArray" on my array; not threadsafe. +- (void) replaceWithObjectsFromArray:(id)a; +/// Establishes a write-lock, then calls "replaceWithObjectsFromArray" on self; threadsafe. +- (void) lockReplaceWithObjectsFromArray:(id)a; +/// Calls "insertObject:atIndex:" on my array; not threadsafe. +- (void) insertObject:(id)o atIndex:(NSUInteger)i; +/// Establishes a write-lock, then calls "insertObject:atIndex:" on self; threadsafe. +- (void) lockInsertObject:(id)o atIndex:(NSUInteger)i; +/// Calls "removeAllObjects" on my array; not threadsafe. +- (void) removeAllObjects; +/// Establishes a write-lock, then calls "removeAllObjects" on self; threadsafe. +- (void) lockRemoveAllObjects; +/// Calls "objectAtIndex:0" on my array; not threadsafe. +- (id) firstObject; +/// Establishes a read-lock, then calls "firstObject" on self; threadsafe +- (id) lockFirstObject; +/// Calls "removeObjectAtIndex:0" on my array; not threadsafe +- (void) removeFirstObject; +/// Establishes a write-lock, then calls "removeFirstObject" on self; threadsafe. +- (void) lockRemoveFirstObject; +/// Calls "lastObject" on my array; not threadsafe. +- (id) lastObject; +/// Establishes a read-lock, then calls "lastObject" on self; threadsafe. +- (id) lockLastObject; +/// Calls "removeLastObject" on my array; not threadsafe. +- (void) removeLastObject; +/// Establishes a write-lock, then calls "removeLastObject" on self; threadsafe. +- (void) lockRemoveLastObject; +/// Calls "removeObject:" on my array; not threadsafe. +- (void) removeObject:(id)o; +/// Establishes a write-lock, then calls "removeObject:" on self; threadsafe. +- (void) lockRemoveObject:(id)o; +/// Calls "removeObjectAtIndex:" on my array; not threadsafe. +- (void) removeObjectAtIndex:(NSUInteger)i; +/// Establishes a write-lock, then calls "removeObjectAtIndex:" on self; threadsafe. +- (void) lockRemoveObjectAtIndex:(NSUInteger)i; +/// Calls "removeObjectsAtIndexes:" on my array; not threadsafe. +- (void) removeObjectsAtIndexes:(NSIndexSet *)i; +/// Establishes a write-lock, then calls "removeObjectsAtIndexes:" on self; threadsafe. +- (void) lockRemoveObjectsAtIndexes:(NSIndexSet *)i; +/// Calls "removeObjectsInArray:" on my array; not threadsafe. +- (void) removeObjectsInArray:(NSArray *)otherArray; +/// Establishes a write-lock, then calls "removeObjectsInArray:" on self; threadsafe. +- (void) lockRemoveObjectsInArray:(NSArray *)otherArray; +/// Calls "removeIdenticalPtrsInArray:" on my array; not threadsafe +- (void) removeIdenticalPtrsInArray:(NSArray *)a; +/// Establishes a write-lock, then calls "removeIdenticalPtrsInArray:" on self; threadsafe. +- (void) lockRemoveIdenticalPtrsInArray:(NSArray *)a; + +/// Calls "replaceObjectsAtIndexes:withObjects" on my array; not threadsafe. +- (void) replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects; +// Establishes a write-lock, then calls "replaceObjectsAtIndexes:withObjects on self; threadsafe +- (void) lockReplaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects; + +/// Calls "valueForKey:" on my array; not threadsafe. +- (id) valueForKey:(NSString *)key; +/// Establishes a read-lock, then calls "valueForKey:" on self; threadsafe. +- (id) lockValueForKey:(NSString *)key; + + +/// Calls "containsObject:" on my array; not threadsafe. +- (BOOL) containsObject:(id)o; +/// Establishes a read-lock, then calls "containsObject:" on self; threadsafe. +- (BOOL) lockContainsObject:(id)o; +/// Calls "objectAtIndex:" on my array; not threadsafe. +- (id) objectAtIndex:(NSUInteger)i; +/// Establishes a read-lock, then calls "objectAtIndex:" on self; threadsafe. +- (id) lockObjectAtIndex:(NSUInteger)i; +/// Calls "objectsAtIndexes:" on my array; not threadsafe. +- (NSArray *) objectsAtIndexes:(NSIndexSet *)indexes; +/// Establishes a read-lock, then calls "objectsAtIndexes:" on self; threadsafe. +- (NSArray *) lockObjectsAtIndexes:(NSIndexSet *)indexes; +/// Calls "indexOfObject:" on my array; not threadsafe. +- (NSUInteger) indexOfObject:(id)o; +/// Establishes a read-lock, then calls "indexOfObject:" on self; threadsafe. +- (NSUInteger) lockIndexOfObject:(id)o; + + +/// Enumerates through my array- compares the address of each item in the array to the passed pointer. Unlike NSMutableArray, this method does NOT call isEqualTo:, it's just a simple == operator. +- (BOOL) containsIdenticalPtr:(id)o; +/// Establishes a read-lock, then calls "containsIdenticalPtr:" on self; threadsafe. +- (BOOL) lockContainsIdenticalPtr:(id)o; +/// Enumerates through my array- compares the address of each item in the array to the passed pointer. Unlike NSMutableArray, this method does NOT call isEqualTo:, it's just a simple == operator. +- (long) indexOfIdenticalPtr:(id)o; +/// Establishes a read-lock, then calls "indexOfIdenticalPtr:" on self; threadsafe. +- (long) lockIndexOfIdenticalPtr:(id)o; +/// Locates an item in my array by enumerating through it and comparing the address of each item in the array to the passed ptr, and then deletes the matching item from the array; not threadsafe. +- (void) removeIdenticalPtr:(id)o; +/// Establishes a write-lock, then calls "removeIdenticalPtr:" on self; threadsafe. +- (void) lockRemoveIdenticalPtr:(id)o; + +// Calls "filteredArrayUsingPredicate:" on my array; not threadsafe +- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate; +// Establishes a read-lock, then calls "filteredArrayUsingPredicate:" on self; threadsafe +- (NSArray *) lockFilteredArrayUsingPredicate:(NSPredicate *)predicate; + +/// Calls "makeObjectsPerformSelector:" on my array; not threadsafe. +- (void) makeObjectsPerformSelector:(SEL)s; +/// Establishes a read-lock, then calls "makeObjectsPerformSelector:" on self; threadsafe. +- (void) lockMakeObjectsPerformSelector:(SEL)s; +/// Calls "makeObjectsPerformSelector:withObject:" on my array; not threadsafe. +- (void) makeObjectsPerformSelector:(SEL)s withObject:(id)o; +/// Establishes a read-lock, then calls "makeObjectsPerformSelector:withObject:" on self; threadsafe. +- (void) lockMakeObjectsPerformSelector:(SEL)s withObject:(id)o; + + + +/* +- (void) makeCopyPerformSelector:(SEL)s; +- (void) lockMakeCopyPerformSelector:(SEL)s; +- (void) makeCopyPerformSelector:(SEL)s withObject:(id)o; +- (void) lockMakeCopyPerformSelector:(SEL)s withObject:(id)o; +*/ + + + +/// Calls "sortUsingSelector:" on my array; not threadsafe. +- (void) sortUsingSelector:(SEL)s; +/// Establishes a write-lock, then calls "sortUsingSelector:" on self; threadsafe. +- (void) lockSortUsingSelector:(SEL)s; + +/// Calls "sortUsingDescriptors:" on my array; not threadsafe. +- (void) sortUsingDescriptors:(NSArray *)descriptors; +/// Establishes a write-lock, then calls "sortUsingDescriptors:" on self; threadsafe. +- (void) lockSortUsingDescriptors:(NSArray *)descriptors; + +- (NSEnumerator *) objectEnumerator; +- (NSEnumerator *) reverseObjectEnumerator; +- (long) count; +- (long) lockCount; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutLockDict.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutLockDict.h new file mode 100644 index 0000000..e162293 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutLockDict.h @@ -0,0 +1,56 @@ + +#if IPHONE +#import +#else +#import +#endif +#import + + + +/// MutLockDict is a thread-safe version of NSMutableDictionary. +/*! +This class exists because NSMutableDictionary is not thread-safe by default: if you call methods on it from two different threads at the same time, it will try to execute both, often crashing in the process. This class has methods which allow you to work with a mutable dictionary in a transparent and thread-safe manner. +*/ + +@interface MutLockDict : NSObject { + NSMutableDictionary *dict; + pthread_rwlock_t dictLock; +} + ++ (id) dictionaryWithCapacity:(NSUInteger)c; ++ (id) dictionaryWithDict:(NSDictionary *)d; +- (id) initWithCapacity:(NSUInteger)c; + +- (void) rdlock; +- (void) wrlock; +- (void) unlock; + +- (NSMutableDictionary *) dict; +- (NSMutableDictionary *) createDictCopy; +- (NSMutableDictionary *) lockCreateDictCopy; + +- (void) setObject:(id)o forKey:(NSString *)s; +- (void) lockSetObject:(id)o forKey:(NSString *)s; +- (void) setValue:(id)v forKey:(NSString *)s; +- (void) lockSetValue:(id)v forKey:(NSString *)s; +- (void) removeAllObjects; +- (void) lockRemoveAllObjects; +- (id) objectForKey:(NSString *)k; +- (id) lockObjectForKey:(NSString *)k; +- (void) removeObjectForKey:(NSString *)k; +- (void) lockRemoveObjectForKey:(NSString *)k; +- (void) addEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (void) lockAddEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (NSArray *) allKeys; +- (NSArray *) lockAllKeys; +- (NSArray *) allValues; +- (NSArray *) lockAllValues; + +- (void) lockMakeObjectsPerformSelector:(SEL)s; +- (void) makeObjectsPerformSelector:(SEL)s; + +- (NSUInteger) count; +- (NSUInteger) lockCount; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutNRLockArray.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutNRLockArray.h new file mode 100644 index 0000000..9ad1138 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutNRLockArray.h @@ -0,0 +1,50 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import "MutLockArray.h" +#import "ObjectHolder.h" + + + +/// Subclass of MutLockArray; this class does NOT retain the objects in its array! +/* +this class exists because i frequently find myself in situations where i want to add an instance of an object to an array/dict/[any class which retains the passed instance], but i don't actually want the item to be retained. + +Instead of adding (and therefore retaining) objects to an array like my superclass, this class makes an ObjectHolder for objects which are added to it (so they don't get retained), and adds the ObjectHolder to me. when other classes ask me for the index of an object, or ask for the object at a particular index, i'll find the relevant ObjectHolder and then return the object it's storing. +*/ + +@interface MutNRLockArray : MutLockArray { + +} + ++ (id) arrayWithCapacity:(NSUInteger)c; + +- (NSMutableArray *) createArrayCopy; +- (NSMutableArray *) lockCreateArrayCopyFromObjects; +- (NSMutableArray *) createArrayCopyFromObjects; +- (void) addObject:(id)o; +- (void) addObjectsFromArray:(id)a; +- (void) replaceWithObjectsFromArray:(id)a; +- (void) insertObject:(id)o atIndex:(NSUInteger)i; +- (id) lastObject; +- (void) removeObject:(id)o; +- (BOOL) containsObject:(id)o; +- (id) objectAtIndex:(NSUInteger)i; +- (NSArray *) objectsAtIndexes:(NSIndexSet *)indexes; +- (NSUInteger) indexOfObject:(id)o; +- (BOOL) containsIdenticalPtr:(id)o; +- (long) indexOfIdenticalPtr:(id)o; +- (void) removeIdenticalPtr:(id)o; + +// these methods exist because the lookup cost for an ObjectHolder can be significant for high-performance applications- these methods get the object from the ObjectHolder and call the method directly on it! +- (void) bruteForceMakeObjectsPerformSelector:(SEL)s; +- (void) lockBruteForceMakeObjectsPerformSelector:(SEL)s; +- (void) bruteForceMakeObjectsPerformSelector:(SEL)s withObject:(id)o; +- (void) lockBruteForceMakeObjectsPerformSelector:(SEL)s withObject:(id)o; + + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutNRLockDict.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutNRLockDict.h new file mode 100644 index 0000000..f4f757f --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/MutNRLockDict.h @@ -0,0 +1,39 @@ +// +// MutNRLockDict.h +// VVOpenSource +// +// Created by David Lublin on 12/22/09. +// Copyright 2009 Vidvox. All rights reserved. +// + +#if IPHONE +#import +#else +#import +#endif + +#import "MutLockDict.h" +#import "ObjectHolder.h" + + + +/// Subclass of MutLockDict; this class does NOT retain the objects in its array! +/* +this class exists because i frequently find myself in situations where i want to add an instance of an object to an array/dict/[any class which retains the passed instance], but i don't actually want the item to be retained. + +Instead of adding (and therefore retaining) objects to an array like my superclass, this class makes an ObjectHolder for objects which are added to it (so they don't get retained), and adds the ObjectHolder to me. when other classes ask me for the index of an object, or ask for the object at a particular index, i'll find the relevant ObjectHolder and then return the object it's storing. +*/ + + +@interface MutNRLockDict : MutLockDict { + +} + + +- (void) setObject:(id)o forKey:(NSString *)s; +- (void) setValue:(id)v forKey:(NSString *)s; +- (id) objectForKey:(NSString *)k; +- (void) addEntriesFromDictionary:(id)otherDictionary; +- (NSArray *) allValues; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/NamedMutLockArray.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/NamedMutLockArray.h new file mode 100644 index 0000000..54e75d0 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/NamedMutLockArray.h @@ -0,0 +1,31 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "VVBasicMacros.h" +#import "MutLockArray.h" + + + + +/* + // only difference between this and MutLockArray is the "name" variable. +*/ + + + + +@interface NamedMutLockArray : MutLockArray { + NSString *name; +} + ++ (id) arrayWithCapacity:(int)c; ++ (id) create; + +- (NSComparisonResult) nameCompare:(NamedMutLockArray *)comp; + +@property (assign, readwrite) NSString *name; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/ObjectHolder.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/ObjectHolder.h new file mode 100644 index 0000000..64c397f --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/ObjectHolder.h @@ -0,0 +1,38 @@ + +#if IPHONE +#import +#else +#import +#endif + + + + +/* + created for working with the MutNRLockArray class. + + basically, you create an instance of this class and give it a reference to an + instance of an object. the instance is NOT retained- but you're now free to + pass ObjectHolder to stuff which will otherwise retain/release it without + worrying about whether the passed instance is retained/released. + + if you call a method on an instance of ObjectHolder and the ObjectHolder + class doesn't respond to that method, the instance will try to call the + method on its object. this means that working with ObjectHolder should- + theoretically, at any rate- be transparent... +*/ + + + + +@interface ObjectHolder : NSObject { + BOOL deleted; + id object; +} + ++ (id) createWithObject:(id)o; +- (id) initWithObject:(id)o; + +@property (assign,readwrite) id object; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVAssertionHandler.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVAssertionHandler.h new file mode 100644 index 0000000..47cdeef --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVAssertionHandler.h @@ -0,0 +1,31 @@ + +#if IPHONE +#import +#else +#import +#endif + + + + +#define USE_CUSTOM_ASSERTION_HANDLER \ +{ \ + NSThread *__currentThread = [NSThread currentThread]; \ + NSDictionary *__threadDict = (__currentThread==nil) ? nil : [__currentThread threadDictionary]; \ + if (__threadDict != nil) { \ + VVAssertionHandler *__newAH = [[VVAssertionHandler alloc] init]; \ + if (__newAH != nil) { \ + [__threadDict setValue:__newAH forKey:@"NSAssertionHandler"]; \ + [__newAH release]; \ + __newAH = nil; \ + } \ + } \ +} + + + +@interface VVAssertionHandler : NSAssertionHandler { + +} + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVBasicMacros.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVBasicMacros.h new file mode 100644 index 0000000..6eab4c6 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVBasicMacros.h @@ -0,0 +1,229 @@ + +// macros for checking to see if something is nil, and if it's not releasing and setting it to nil +#define VVRELEASE(item) {if (item != nil) { \ + [item release]; \ + item = nil; \ +}} +#define VVAUTORELEASE(item) {if (item != nil) { \ + [item autorelease]; \ + item = nil; \ +}} + + + +// macros for making a CGRect from an NSRect +#define NSMAKECGRECT(n) CGRectMake(n.origin.x, n.origin.y, n.size.width, n.size.height) +#define NSMAKECGPOINT(n) CGPointMake(n.x, n.y) +#define NSMAKECGSIZE(n) CGSizeMake(n.width, n.height) +// macros for making an NSRect from a CGRect +#define CGMAKENSRECT(n) NSMakeRect(n.origin.x, n.origin.y, n.size.width, n.size.height) +#define CGMAKENSSIZE(n) NSMakeSize(n.width,n.height) + +// macro for quickly printing out the dimensions of a rect (and a name/id so you can distinguish between them) +#define NSRectLog(n,r) NSLog(@"%@, (%f,%f) : %fx%f",n,r.origin.x,r.origin.y,r.size.width,r.size.height) +#define NSPointLog(n,r) NSLog(@"%@, (%f,%f)",n,r.x,r.y) +#define NSSizeLog(n,s) NSLog(@"%@, %fx%f",n,s.width,s.height) + +// macros for quickly making numbers and values +#define NUMINT(i) [NSNumber numberWithInt:i] +#define NUMFLOAT(f) [NSNumber numberWithFloat:f] +#define NUMBOOL(b) [NSNumber numberWithBool:b] +#define NUMDOUBLE(d) [NSNumber numberWithDouble:d] +#define VALSIZE(s) [NSValue valueWithSize:s] +#define VALRECT(r) [NSValue valueWithRect:r] + +// macro for quickly archiving and object +#define ARCHIVE(a) [NSKeyedArchiver archivedDataWithRootObject:a] +#define UNARCHIVE(a) [NSKeyedUnarchiver unarchiveObjectWithData:a] + +// macro for quickly making colors +#define VVDEVCOLOR(r,g,b,a) [NSColor colorWithDeviceRed:r green:g blue:b alpha:a] +#define VVCALCOLOR(r,g,b,a) [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a] + +// nice little macro for strings +#define VVSTRING(n) ((NSString *)[NSString stringWithString:n]) +#define VVFMTSTRING(f, ...) ((NSString *)[NSString stringWithFormat:f, ##__VA_ARGS__]) +#define VVDATASTRING(n) ((NSData *)[[NSString stringWithString:n] dataUsingEncoding:NSUTF8StringEncoding]) +#define VVDATAFMTSTRING(f, ...) ((NSData *)[[NSString stringWithFormat:f, ##__VA_ARGS__] dataUsingEncoding:NSUTF8StringEncoding]) + +// macros for quickly making arrays because.....well, it's the wiimote, and i'm fucking tired of typing. so there. +#define OBJARRAY(f) [NSArray arrayWithObject:f] +#define OBJSARRAY(f, ...) [NSArray arrayWithObjects:f, ##__VA_ARGS__, nil] +#define MUTARRAY [NSMutableArray arrayWithCapacity:0] + +// macros for quickly making dicts +#define OBJDICT(o,k) [NSDictionary dictionaryWithObject:o forKey:k] +#define OBJSDICT(o, ...) [NSDictionary dictionaryWithObjectsAndKeys:o,#__VA_ARGS__, nil] +#define MUTDICT [NSMutableDictionary dictionaryWithCapacity:0] + +// calculating the distance between two NSPoints or similar structs +#define POINTDISTANCE(a,b) fabs(sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y))) + + +// this is a macro for drawing an NSRect in opengl +#define GLDRAWRECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_QUADS,0,4); \ +} + + + +// this is a macro for stroking an NSRect in opengl +#define GLSTROKERECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x-0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y-0.5, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,8); \ +} +/* +#define GLSTROKERECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,8); \ +} +*/ + + +// this is a macro for drawing a line connecting two points +#define GLDRAWLINE(p,q) \ +{ \ + GLfloat vvMacroVertices[]={ \ + p.x, p.y, 0.0, \ + q.x, q.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,2); \ +} + + + +// this is a macro for drawing a diamond specified by a point and radius in opengl +#define GLDRAWDIAMOND(p,r) \ +{ \ + GLfloat vvMacroVertices[] = { \ + p.x-r, p.y, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x, p.y-r, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_QUADS,0,4); \ +} + + + +// this is a macro for stroking an diamond around a point in opengl +#define GLSTROKEDIAMOND(p,r) \ +{ \ + GLfloat vvMacroVertices[] = { \ + p.x-r, p.y, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x, p.y-r, 0.0, \ + p.x, p.y-r, 0.0, \ + p.x-r, p.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINE_LOOP,0,8); \ +} + + +// this is a macro for drawing a texture of a specified size in a rect +#define GLDRAWTEXSIZEDINRECT(t,s,r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0,s.height, \ + s.width,s.height, \ + s.width,0.0, \ + 0.0,0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWFLIPPEDTEXSIZEDINRECT(t,s,r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0, 0.0, \ + s.width, 0.0, \ + s.width, s.height, \ + 0.0, s.height}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWTEXSIZEDINRECTATZ(t,s,r,z) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, z, \ + r.origin.x, r.origin.y+r.size.height, z}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0,s.height, \ + s.width,s.height, \ + s.width,0.0, \ + 0.0,0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWFLIPPEDTEXSIZEDINRECTATZ(t,s,r,z) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, z, \ + r.origin.x, r.origin.y+r.size.height, z}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0, 0.0, \ + s.width, 0.0, \ + s.width, s.height, \ + 0.0, s.height}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVBasics.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVBasics.h new file mode 100644 index 0000000..b36c65a --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVBasics.h @@ -0,0 +1,55 @@ + +#import "VVBasicMacros.h" + +#import "VVThreadLoop.h" +#import "VVAssertionHandler.h" +#import "VVStopwatch.h" +#import "ObjectHolder.h" +#import "MutLockArray.h" +#import "MutLockDict.h" +#import "MutNRLockArray.h" +#import "MutNRLockDict.h" +#import "NamedMutLockArray.h" + +#if !IPHONE + #import "VVCURLDL.h" + #import "VVSprite.h" + #import "VVSpriteManager.h" + #import "VVSpriteView.h" + #import "VVSpriteControl.h" + #import "VVSpriteControlCell.h" + #import "VVSpriteGLView.h" + #import "VVCrashReporter.h" + //#import "NSHostAdditions.h" +#endif + +/* + the following stuff is for doxygen +*/ + +/*! +\mainpage + +\htmlonly + + + +Introduction +

+VVBasics is an Objective-c framework with a number of classes which perform functions that i need regularly- but, for whatever reason, aren't provided by the stock frameworks. Expect pretty much everything to link against this framework for one reason or another- macros, useful classes, etc- and expect this framework to continuously grow as I start to open-source more and more of my bag of tricks. +

+ +\endhtmlonly +*/ diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCURLDL.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCURLDL.h new file mode 100644 index 0000000..39d4c9b --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCURLDL.h @@ -0,0 +1,72 @@ + +/* + this class offers a very limited, very simple cocoa interface to libcurl for doing extremely + basic http transfer ops + + basically, this class exists because at this time NSURLConnection is problematic and + top-heavy, and i wanted an easy, effective, and reliable interface for handling the extremely + limited set of http data transfer operations required by my frameworks/apps. + + this class was meant to be used as a one-shot throwaway; that is, you're meant to create an + instance of this class which will be auto-released as soon as the autorelease pool is + popped. the instance you create is meant to be used once, and then thrown away- THIS WILL + PROBABLY BREAK IF YOU TRY TO USE THE SAME INSTANCE TO PERFORM MORE THAN ONE TRANSFER. +*/ + + +#import +#import + + + + +@protocol VVCURLDLDelegate +- (void) dlFinished:(id)h; +@end + + + + +@interface VVCURLDL : NSObject { + NSString *urlString; + CURL *curlHandle; + + NSMutableData *responseData; + + struct curl_slist *headerList; // nil by default- if non-nil, supplied to the handle as CURLOPT_HTTPHEADER + NSMutableData *postData; // if non-nil, simply posted as CURLOPT_POSTFIELDS + struct curl_httppost *firstFormPtr; // if postData was nil but this isn't, posted as CURLOPT_HTTPPOST + struct curl_httppost *lastFormPtr; + + BOOL returnOnMain; + BOOL performing; + CURLcode err; +} + ++ (id) createWithAddress:(NSString *)a; +- (id) initWithAddress:(NSString *)a; + +- (void) perform; +- (void) performAsync:(BOOL)as withDelegate:(id )d; +- (void) _performAsyncWithDelegate:(id )d; +- (void) _performWithDelegate:(id )d; + +//- (struct curl_slist *) headerList; +//- (struct curl_httppost *) firstFormPtr; +//- (struct curl_httppost *) lastFormPtr; +- (void) appendDataToPOST:(NSData *)d; +- (void) appendStringToPOST:(NSString *)s; + +- (void) writePtr:(void *)ptr size:(size_t)s; + +@property (assign,readwrite) struct curl_slist *headerList; +@property (assign,readwrite) struct curl_httppost *firstFormPtr; +@property (assign,readwrite) struct curl_httppost *lastFormPtr; +@property (assign,readwrite) BOOL returnOnMain; +@property (readonly) NSMutableData *responseData; +@property (readonly) NSString *responseString; +@property (readonly) CURLcode err; + +@end + +size_t vvcurlWriteFunction(void *ptr, size_t size, size_t nmemb, void *stream); diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporter.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporter.h new file mode 100644 index 0000000..0dc9c90 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporter.h @@ -0,0 +1,101 @@ + +#import +#import +#include "AvailabilityMacros.h" +#import +#import +#import "VVCURLDL.h" +#import "MutLockArray.h" + + + + +/// The crash reporter's delegate must adhere to this protocol +/*! + This protocol exists largely because it's conceivable that objects will want to know when the crash reporter- which uploads asynchronously- has finished sending its data to the remote server. +*/ +@protocol OldVVCrashReporterDelegate +- (void) crashReporterCheckDone; +@end + +@protocol VVCrashReporterDelegate +- (void) crashReporterCheckDone:(BOOL)foundLogs; // "new"- 'f' designates whether crash reports were found or not +@end + + + +/// Simple class which automatically uploads crash logs and other relevant diagnostic information automatically made available by os x to a remote server. +/*! +it's been my experience that most apps crash much more frequently on end-users than the app's developers would guess. the simplest and easiest way to improve the end-user's experience is to have the application check their machine for crash logs- which are generated automatically by os x whenever an application crashes- and send them to the developer. + +this class exists so i have a really easy way to make my apps send their crash logs to me; the goal here is to make it as easy as possible to get all the information i need to troubleshoot a problem with as little work on the user's part as possible. it also sends a basic system profile, anything the app- and ONLY the app, not other apps- recently printed to the console log, and optional description/email fields to facilitate communication directly with the user. this data is then uploaded to a given URL using an HTTP POST. + +on the server side, i use a PHP page which sanitizes the POST data (i can't stress how important this step is) and works with it. i've included a sample PHP page that simply dumps the received data to a file on disk (and optionally emails someone) with this project. + +HOW TO USE THIS CLASS: + + 1)- create an instance of this class + + 2)- set the instance's delegate, uploadURL, and developerEmail. these are necessary! + + 3)- call "check" on the instance. when it's done, it calls "crashReporterCheckDone" on the + delegate. that's it- you're done. +*/ + +@interface VVCrashReporter : NSObject { + NSString *uploadURL; // does NOT includes http:// + NSString *developerEmail; + id delegate; // must respond to VVCrashReporterDelegate protocol + MutLockArray *crashLogArray; + NSMutableDictionary *systemProfilerDict; + NSString *consoleLog; + int jobSize; // used to update progress indicator/label + int jobCurrentIndex; // used to update progress indicator/label + int currentCrashLogTimeout; // countdown for timeout of sending/receiving data for a specific crash log + NSTimer *currentCrashLogTimer; + + IBOutlet NSWindow *window; + IBOutlet NSButton *replyButton; + IBOutlet NSView *emailFieldHolder; + IBOutlet NSTextField *emailField; + IBOutlet NSTextView *descriptionField; + IBOutlet NSTextField *submittingLabel; // non-editable. 'submitting', 'getting machine profile', etc. + IBOutlet NSProgressIndicator *progressIndicator; // indicates progress through all crash logs to be submitted + IBOutlet NSTextField *countdownLabel; // non-editable; countdown so user knows app hasn't hung + + NSNib *theNib; + NSArray *nibTopLevelObjects; +} + ++ (NSString *) _stringForSystemProfilerDataType:(NSString *)t; + +/// This is the main method- when you call 'check', the crash reporter looks for crash logs, gets a basic system profile, and collects anything your applications has dumped to the console log. +- (void) check; +- (void) openCrashReporter; +- (IBAction) replyButtonClicked:(id)sender; +- (IBAction) doneClicked:(id)sender; +- (void) sendACrashLog; +- (void) closeCrashReporter; + +- (NSString *) _nibName; +- (BOOL) _assembleCrashLogs; // assembles the array of crash logs, returns a YES if logs were found and have to be sent in +- (NSString *) _consoleLogString; +- (NSMutableDictionary *) _systemProfilerDict; + +- (void) updateCrashLogTimeout:(NSTimer *)t; + +// VVCURLDLDelegate method- this class will be the delegate of multiple VVCURLDL instances +- (void) dlFinished:(id)h; + +/// Sets the developer email address; this is displayed if the user has a problem connecting to the internet/the server the crash reporter is supposed to be connecting to +- (void) setDeveloperEmail:(NSString *)n; +- (NSString *) developerEmail; +/// This is the URL of the php/cgi/etc. page which the crash data will be POSTed to +- (void) setUploadURL:(NSString *)n; +- (NSString *) uploadURL; + +/// The crash reporter's delegate is notified when the check has completed +@property (assign,readwrite) id delegate; +@property (readonly) NSButton *replyButton; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporterDescriptionField.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporterDescriptionField.h new file mode 100644 index 0000000..f39f0f5 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporterDescriptionField.h @@ -0,0 +1,15 @@ +#import + + +/* + this class exists solely to prevent users from pasting or dragging huge amounts of text (like + crash/console logs!) into the description field of the crash reporter. sounds weird, but trust + me- it's necessary. +*/ + + +@interface VVCrashReporterDescriptionField : NSTextView { + +} + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporterEmailField.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporterEmailField.h new file mode 100644 index 0000000..fb883f8 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVCrashReporterEmailField.h @@ -0,0 +1,14 @@ +#import +#import + + +/* + this class exists solely to prevent users from pasting huge amounts of text into the email field +*/ + + +@interface VVCrashReporterEmailField : NSTextField { + +} + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSprite.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSprite.h new file mode 100644 index 0000000..34246be --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSprite.h @@ -0,0 +1,104 @@ + +/* Always with the sprites... + + sprite |sprÄ«t| + noun + 1 an elf or fairy. + 2 a computer graphic that may be moved on-screen and otherwise manipulated as a single entity. + 3 a faint flash, typically red, sometimes emitted in the upper atmosphere over a thunderstorm owing to the collision of high-energy electrons with air molecules. + ORIGIN Middle English : alteration of sprit, a contraction of spirit . */ + +#import +#include + + + + +typedef enum _VVSpriteEventType { + VVSpriteEventNULL = 0, + VVSpriteEventDown = 1, + VVSpriteEventDrag = 2, + VVSpriteEventUp = 3, + VVSpriteEventDouble = 4, + VVSpriteEventRightDown = 5, + VVSpriteEventRightUp = 6 +} VVSpriteEventType; + + + + +@interface VVSprite : NSObject { + BOOL deleted; + BOOL locked; // whether or not i should respond to mouse input. DOESN'T AFFECT ANYTHING IN THIS CLASS! variable exists for the user's convenience, and is otherwise superfluous! + BOOL hidden; // whether or not the sprite should draw. DOESN'T AFFECT ANYTHING IN THIS CLASS! variable exists for the user's convenience, and is otherwise superfluous! + BOOL dropFromMultiSpriteActions; // only valid if sprite manager's allowMultiSpriteInteraction' is YES. NO by default. if YES, then if you mousedown on this and any other sprite, this sprite gets dropped from the mousedown. used for allowing multi-sprite interaction to prevent clicks from hitting "background" sprites (which have this set to YES) + long spriteIndex; + id manager; // the VVSpriteManager i exist within- NOT retained! + id delegate; // NOT retained! + SEL drawCallback; // delegate method; passed a ptr to this sprite! + SEL actionCallback; // delegate method; passed a ptr to this sprite! + + NSRect rect; // the sprite i'm tracking + NSBezierPath *bezierPath; // retained. nil by default, set to nil if you call setRect: on this instance. if non-nil, this path is used instead of "rect" for determining mouse action and drawing intersection! + OSSpinLock pathLock; + + int lastActionType; // updated whenever an action is received + NSPoint lastActionCoords; // coords at which last action took place + BOOL lastActionInBounds; // whether or not the last action was within my bounds + BOOL trackingFlag; // whether or not i'm tracking stuff + NSPoint mouseDownCoords; // absolute coords of mousedown + NSPoint lastActionDelta; // change between most-recently-received action coords and last received coords + NSPoint mouseDownDelta; // change between mousedown loc and most-recently received coords + long mouseDownModifierFlags; + + id userInfo; // RETAINED! for storing a random thing... + id NRUserInfo; // NOT RETAINED! for storing something that *shouldn't* be retained... + id safeString; // nil on init- many sprites need formatted text, this is a convenience variable... +} + ++ (id) createWithRect:(NSRect)r inManager:(id)m; +- (id) initWithRect:(NSRect)r inManager:(id)m; + +- (void) prepareToBeDeleted; + +- (BOOL) checkPoint:(NSPoint)p; +- (BOOL) checkRect:(NSRect)r; + +- (void) receivedEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m; +- (void) mouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) rightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) rightMouseUp:(NSPoint)p; +- (void) mouseDragged:(NSPoint)p; +- (void) mouseUp:(NSPoint)p; +- (void) draw; + +- (void) bringToFront; +- (void) sendToBack; + +@property (assign, readwrite) BOOL locked; +@property (assign, readwrite) BOOL hidden; +@property (assign, readwrite) BOOL dropFromMultiSpriteActions; +@property (readonly) long spriteIndex; +@property (readonly) id manager; +@property (assign, readwrite) id delegate; +@property (assign, readwrite) SEL drawCallback; +@property (assign, readwrite) SEL actionCallback; + +@property (assign, readwrite) NSRect rect; +//@property (retain,readwrite) NSBezierPath *path; +- (void) setBezierPath:(NSBezierPath *)n; +- (NSBezierPath *) safelyGetBezierPath; +- (NSRect) spriteBounds; // special method- either returns "rect" or (if path is non-nil) the bounds of the bezier path! +@property (readonly) VVSpriteEventType lastActionType; +@property (readonly) NSPoint lastActionCoords; +@property (readonly) BOOL lastActionInBounds; +@property (readonly) BOOL trackingFlag; +@property (readonly) NSPoint mouseDownCoords; +@property (readonly) NSPoint lastActionDelta; +@property (readonly) NSPoint mouseDownDelta; +@property (readonly) long mouseDownModifierFlags; +@property (assign,readwrite) id userInfo; +@property (assign,readwrite) id NRUserInfo; +@property (assign,readwrite) id safeString; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteControl.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteControl.h new file mode 100644 index 0000000..2ed78b7 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteControl.h @@ -0,0 +1,49 @@ + +#import +#import "VVSpriteManager.h" +#include + + + + +extern int _maxSpriteControlCount; +extern int _spriteControlCount; + + + + +@interface VVSpriteControl : NSControl { + BOOL deleted; + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + + OSSpinLock propertyLock; + NSEvent *lastMouseEvent; + NSColor *clearColor; + BOOL drawBorder; + NSColor *borderColor; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED +} + +- (void) generalInit; + +- (void) prepareToBeDeleted; + +- (void) finishedDrawing; + +- (void) updateSprites; + +@property (readonly) BOOL deleted; +@property (readonly) VVSpriteManager *spriteManager; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) BOOL mouseIsDown; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteControlCell.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteControlCell.h new file mode 100644 index 0000000..fc8e151 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteControlCell.h @@ -0,0 +1,11 @@ + +#import + + + + +@interface VVSpriteControlCell : NSActionCell { + +} + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteGLView.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteGLView.h new file mode 100644 index 0000000..a47b6a2 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteGLView.h @@ -0,0 +1,82 @@ + +#import +#import "VVSpriteManager.h" +#import +#import +#import + + + + +typedef enum { + VVFenceModeEveryRefresh = 0, // every time a display callback runs, drawing commands are sent to the GPU. + VVFenceModeDBSkip = 1, // the apple gl fence extension is used to make sure that drawing commands for the back buffer have finished before more drawing commands are sent to the back buffer (the front buffer can receive commands, though) + VVFenceModeSBSkip = 2, // the apple gl fence extension is used to make sure that drawing commands for the single buffer have finished before more drawing commands are sent to it + VVFenceModeFinish = 3 // glFinish is used instead of glFlush +} VVFenceMode; + +typedef enum { + VVFlushModeGL = 0, // glFlush() + VVFlushModeCGL = 1, // CGLFlushDrawable() + VVFlushModeNS = 2, // [context flushBuffer] + VVFlushModeApple = 3, // glFlushRenderAPPLE() + VVFlushModeFinish = 4 // glFinish() +} VVFlushMode; + + + + +@interface VVSpriteGLView : NSOpenGLView { + BOOL deleted; + + BOOL initialized; + //BOOL needsReshape; + pthread_mutex_t glLock; + + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + NSEvent *lastMouseEvent; + GLfloat clearColor[4]; + BOOL drawBorder; + GLfloat borderColor[4]; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED + + VVFlushMode flushMode; + + VVFenceMode fenceMode; + GLuint fenceA; + GLuint fenceB; + BOOL waitingForFenceA; + BOOL fenceADeployed; + BOOL fenceBDeployed; + OSSpinLock fenceLock; +} + +- (void) generalInit; +- (void) prepareToBeDeleted; + +- (void) initializeGL; +- (void) finishedDrawing; +//- (void) reshapeGL; +- (void) updateSprites; + +- (void) _lock; +- (void) _unlock; +//- (void) lockSetOpenGLContext:(NSOpenGLContext *)n; + +@property (readonly) BOOL deleted; +@property (assign,readwrite) BOOL initialized; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) VVSpriteManager *spriteManager; +@property (readonly) BOOL mouseIsDown; +@property (assign, readwrite) VVFlushMode flushMode; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteManager.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteManager.h new file mode 100644 index 0000000..b8f0dc4 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteManager.h @@ -0,0 +1,57 @@ + +#import +#import "VVSprite.h" +#import "MutLockArray.h" + + + + +@interface VVSpriteManager : NSObject { + BOOL deleted; + BOOL allowMultiSpriteInteraction; // NO by default- if YES, clicking/dragging/etc works with multiple sprites! + BOOL multiSpriteExecutesOnMultipleSprites; // only relevant if multi-sprite interaction is YES. this is NO by default- if it's YES all sprites in "spritesInUse" will receive an action callback when any of them get an action method. if this is NO then only the sprite that "caught" the interaction will receive an action callback! + MutLockArray *spriteArray; // searched from beginning to end, so order is like z-index! + VVSprite *spriteInUse; // array of VVSprite objects currently tracking drag info + MutLockArray *spritesInUse; // ONLY VALID IF MULTI SPRITE INTERACTION IS YES! array of VVSprite o + long spriteIndexCount; +} + +- (void) prepareToBeDeleted; + +// return YES if the mousedown occurred on one or more sprites +- (BOOL) receivedMouseDownEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m visibleOnly:(BOOL)v; +- (void) receivedOtherEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m; +- (BOOL) localMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localVisibleMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localRightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localVisibleRightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) localRightMouseUp:(NSPoint)p; +- (void) localMouseDragged:(NSPoint)p; +- (void) localMouseUp:(NSPoint)p; +- (void) terminatePresentMouseSession; // call this and sprites will stop responding to the mouse until it is clicked again + +- (id) newSpriteAtBottomForRect:(NSRect)r; +- (id) newSpriteAtTopForRect:(NSRect)r; +- (long) getUniqueSpriteIndex; + +- (VVSprite *) spriteAtPoint:(NSPoint)p; +- (VVSprite *) visibleSpriteAtPoint:(NSPoint)p; +- (VVSprite *) spriteForIndex:(long)i; +- (void) removeSpriteForIndex:(long)i; +- (void) removeSprite:(id)z; +- (void) removeSpritesFromArray:(NSArray *)array; +- (void) removeAllSprites; +//- (void) moveSpriteToFront:(VVSprite *)z; + +- (void) draw; +- (void) drawRect:(NSRect)r; + +- (VVSprite *) spriteInUse; +- (void) setSpriteInUse:(VVSprite *)z; + +@property (assign,readwrite) BOOL allowMultiSpriteInteraction; +@property (assign,readwrite) BOOL multiSpriteExecutesOnMultipleSprites; +@property (readonly) MutLockArray *spriteArray; +@property (readonly) MutLockArray *spritesInUse; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteView.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteView.h new file mode 100644 index 0000000..a8d17a0 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVSpriteView.h @@ -0,0 +1,48 @@ + +#import +#import "VVSpriteManager.h" +#include + + + + +extern int _spriteViewCount; + + + + +@interface VVSpriteView : NSView { + BOOL deleted; + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + + OSSpinLock propertyLock; + NSEvent *lastMouseEvent; + NSColor *clearColor; + BOOL drawBorder; + NSColor *borderColor; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED +} + +- (void) generalInit; + +- (void) prepareToBeDeleted; + +- (void) finishedDrawing; + +- (void) updateSprites; + +@property (readonly) BOOL deleted; +@property (readonly) VVSpriteManager *spriteManager; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) BOOL mouseIsDown; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVStopwatch.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVStopwatch.h new file mode 100644 index 0000000..a1f9c35 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVStopwatch.h @@ -0,0 +1,35 @@ + +#if IPHONE +#import +#else +#import +#endif +#include +#import + + + +/// This class is used to measure how long it takes to do things; much easier to work with than NSDate. + +@interface VVStopwatch : NSObject { + struct timeval startTime; + OSSpinLock timeLock; +} + +/// Returns an auto-released instance of VVStopwatch; the stopwatch is started on creation. ++ (id) create; + +/// Starts the stopwatch over again +- (void) start; +/// Returns a float representing the time (in seconds) since the stopwatch was started +- (double) timeSinceStart; +/// Sets the stopwatch's starting time as an offset to the current time +- (void) startInTimeInterval:(NSTimeInterval)t; +/// Populates the passed timeval struct with the current timeval +- (void) copyStartTimeToTimevalStruct:(struct timeval *)dst; +/// Populates the starting time with the passed timeval struct +- (void) setStartTimeStruct:(struct timeval *)src; + +@end + +void populateTimevalWithFloat(struct timeval *tval, double secVal); diff --git a/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVThreadLoop.h b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVThreadLoop.h new file mode 100644 index 0000000..0a6342f --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVBasics.framework/headers/VVThreadLoop.h @@ -0,0 +1,63 @@ + +#if IPHONE +#import +#else +#import +#endif +#include +#import +#include + + + + +/// Simple class for spawning a thread which executes at a specified interval- simpler and easier to work with than NSThread/NSTimer in multi-threaded programming environments. +/*! +When started, an instance of this class will spawn a thread and repeatedly execute a method on that thread. If it was passed a target and selector on creation, the selector will be called on the target every time the thread executes. If it's more convenient to subclass VVThreadLoop and work with your custom subclass, leave the target/selector nil and VVThreadLoop will call "threadProc" on itself- just override this method (it's empty anyway) in your subclass and do whatever you want in there. + +You can change the execution interval, and VVThreadLoop also examines how long it takes to execute your code and adjusts in an attempt to ensure that the interval is accurate (sleep-time is interval-duration minus proc-execution-duration) +*/ + + + + +@interface VVThreadLoop : NSObject { + double interval; + double maxInterval; + BOOL running; + BOOL bail; + BOOL paused; + BOOL executingCallback; + + OSSpinLock valLock; // ONLY used for quickly accessing 'running', 'bail', 'paused', and 'executingCallback' in a threadsafe fashion + + id targetObj; //! + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers deleted file mode 120000 index a177d2a..0000000 --- a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/Headers \ No newline at end of file diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCAddressSpace.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCAddressSpace.h new file mode 100644 index 0000000..966aa33 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCAddressSpace.h @@ -0,0 +1,77 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "OSCNode.h" + + + + +// OSCAddressSpace delegate protocol +@protocol OSCAddressSpaceDelegateProtocol +- (void) nodeRenamed:(OSCNode *)n; +- (void) dispatchReplyOrError:(OSCMessage *)m; // this method is called by nodes in the address space. the passed message is a reply or error in response to a query which should be sent out an output. +@end + + + + +// this is the main instance of OSCAddressSpace. it is auto-created when this class is initialized +extern id _mainAddressSpace; + + + + +/// OSCAddressSpace is a representation of the OSC address space described in the OSC spec. It is a subclass of OSCNode. This class is optional- it's not needed for basic OSC message sending/receiving. +/*! +There should only ever be one instance of OSCAddressSpace, and you shouldn't explicitly create it. Just call [OSCAddressSpace class] (or any other OSCAddressSpace method) and it will be automatically created. This main instance may be retrieved by the class method +[OSCAddressSpace mainAddressSpace] or by the class variable _mainAddressSpace. + +OSCAddressSpace is your application's main way of dealing with the OSC address space- if you need to dispatch a message, set, rename, or delete a node, you should do via the main instance of this class. +*/ +@interface OSCAddressSpace : OSCNode { + id delegate; +} + +/// Returns the main instance of the OSC address space (and creates it if necessary) ++ (id) mainAddressSpace; ++ (void) refreshMenu; +#if !IPHONE ++ (NSMenu *) makeMenuForNode:(OSCNode *)n withTarget:(id)t action:(SEL)a; ++ (NSMenu *) makeMenuForNode:(OSCNode *)n ofType:(NSIndexSet *)ts withTarget:(id)t action:(SEL)a; +#endif + +/// Renames 'before' to 'after'. Sub-nodes stay with their owners! Can also be though of as a "move". +- (void) renameAddress:(NSString *)before to:(NSString *)after; +- (void) renameAddressArray:(NSArray *)before toArray:(NSArray *)after; + +/// If 'n' is nil, the node at the passed address will be deleted (as will any of its sub-nodes) +- (void) setNode:(OSCNode *)n forAddress:(NSString *)a; +- (void) setNode:(OSCNode *)n forAddress:(NSString *)a createIfMissing:(BOOL)c; +- (void) setNode:(OSCNode *)n forAddressArray:(NSArray *)a; +- (void) setNode:(OSCNode *)n forAddressArray:(NSArray *)a createIfMissing:(BOOL)c; + +// this method is called whenever a node is added to another node +- (void) nodeRenamed:(OSCNode *)n; + +/// Unlike a normal OSCNode, this method finds the destination node and then dispatches the msg. If the destination is itself, it just calls the super. +- (void) dispatchMessage:(OSCMessage *)m; +// This method gets called by an OSCNode inside me (or by me), and you probably won't need to ever call this method. The passed message is a reply or error that needs to be sent back in response to a query. The passed OSCMessage contains the IP address and port of the destination. This method just passes the data on to the addres space's delegate- it does NOT actually send anything out, this is something you'll have to implement in the delegate. +- (void) _dispatchReplyOrError:(OSCMessage *)m; + +- (void) addDelegate:(id)d forPath:(NSString *)p; +- (void) removeDelegate:(id)d forPath:(NSString *)p; +/* +- (void) addQueryDelegate:(id)d forPath:(NSString *)p; +- (void) removeQueryDelegate:(id)d forPath:(NSString *)p; +*/ +@property (assign, readwrite) id delegate; + + +@end + + + + + diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCBundle.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCBundle.h new file mode 100644 index 0000000..857d688 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCBundle.h @@ -0,0 +1,46 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import "OSCMessage.h" + + + + +/// An OSCBundle is a "container" for multiple OSC messages or bundles (bundles may also be nested) +/*! +According to the OSC spec, an OSC bundle is basically a wrapper for multiple OSC messages (or other bundles). Instead of sending a bunch of individual messages, you can wrap them all into a bundle, and send the bundle (messages will still be sent to their individual address paths). OSCBundleÕs interface is correspondingly simple: you can create a bundle from some elements, or you can create a bundle and then add some elements (OSCMessages or OSCBundles) to it. + +OSC bundles also have a time stamp- by default, this will be set to immediate execution (0s except for a single 1 in the LSB). while timetag execution isn't widely supported, you may specify non-immediate time tags in the hopes that the software on the receiving end will execute the bundle in time. +*/ + + + + +@interface OSCBundle : NSObject { + NSMutableArray *elementArray; // array of messages or bundles + NSDate *timeTag; // nil by default, or the time at which the contents of this bundle should be dispatched +} + ++ (void) parseRawBuffer:(unsigned char *)b ofMaxLength:(int)l toInPort:(id)p inheritedTimeTag:(NSDate *)d fromAddr:(unsigned int)txAddr port:(unsigned short)txPort; +/// Creates and returns an auto-released bundle ++ (id) create; +/// Creates and returns an auto-released bundle with the single passed element ++ (id) createWithElement:(id)n; +/// Creates and returns an auto-released bundle with the array of passed elements ++ (id) createWithElementArray:(id)a; + +/// Adds the passed element to the bundle +- (void) addElement:(id)n; +/// Adds the array of passed elements to the bundle +- (void) addElementArray:(NSArray *)a; + +- (long) bufferLength; +- (void) writeToBuffer:(unsigned char *)b; + +@property (retain,readwrite) NSDate *timeTag; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCConstants.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCConstants.h new file mode 100644 index 0000000..7261ae2 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCConstants.h @@ -0,0 +1,131 @@ + +/*! +\file OSCConstants.h +\brief Constants and Macros used by one or more of the OSC classes in this framework +*/ + +/// OSCValueType +/*! +OSCValues have distinct types; these are used to describe the type of an OSCValue. +*/ +typedef enum { + OSCValInt = 1, //! +#else +#import +#endif + +#import +//#import +//#import +#import +#import +#import +#import "OSCPacket.h" +#import "OSCBundle.h" +#import "OSCMessage.h" +#import "OSCOutPort.h" + + + + +/// OSCInPort handles everything needed to receive OSC data on a given port +/*! +You should never create or destroy an instance of this class manually. OSCInPort instances should be created/destroyed by the OSCManager. + +Each OSCInPort is running in its own separate thread- so make sure anything called as a result of received OSC input is thread-safe! When OSCInPort receives data, it gets parsed and passed to the in port's delegate as a series of OSCMessages consisting of an address path and an OSCValue. By default, the inport's delegate is the manager which created it- and by default, managers pass this data on to *their* delegates (your objects/app). + +the documentation here only covers the basics, the header file for this class is small and heavily commented if you want to know more because you're heavily customizing OSCInPort. +*/ +@interface OSCInPort : NSObject { + BOOL deleted; // whether or not i'm deleted- ensures that socket gets closed + BOOL bound; // whether or not the socket is bound + OSSpinLock socketLock; + int sock; // socket file descriptor. remember, everything in unix is files! + struct sockaddr_in addr; // struct that describes *my* address (this is an in port) + unsigned short port; // the port number i'm receiving from + unsigned char buf[65506]; // the socket gets data and dumps it here immediately + + OSSpinLock scratchLock; + NSThread *thread; + //VVThreadLoop *threadLooper; + + NSString *portLabel; //! +#else +#import +#endif +#import "OSCAddressSpace.h" +#import "OSCZeroConfManager.h" +#import "OSCInPort.h" +#import "OSCOutPort.h" + + + + +/// Main VVOSC class- manages in & out port creation, zero configuration networking (bonjour/zeroconf) +/*! +The OSCManager will probably be the main class that you're working with: it creates/deletes inputs (which receive data) and outputs (which send data), passes any OSC data received to its delegate (your application), optionally handles distribution of all received OSC messages, and does other manager-ish things. You should only need one instance of OSCManager in your application. One of your objects should be OSCManager's delegate (see the "OSCDelegateProtocol" below) so you may receive OSC data. + +Incoming OSC data is initially received by an OSCInPort; fundamentally, in ports are running a loop which checks a socket for data received since the last loop. By default, the OSCInPort's delegate is the OSCManager which created it. Every time the loop runs, it passes the received data off to its delegate (the manager) as the raw address/value pairs in the order they're received. When the OSCManager receives data from its in port it immediately passes the received data to its delegate, which should respond to one of the following methods (referred to as the 'OSCDelegateProtocol'): + +\htmlonly +
+@protocol OSCDelegateProtocol
+- (void) receivedOSCMessage:(OSCMessage *)m;
+@end +
+\endhtmlonly + +...if you want to work with received OSC data, OSCManager's delegate must respond to this method! +*/ + + + + +@interface OSCManager : NSObject { + MutLockArray *inPortArray; // Array of OSCInPorts in a locking array for threadsafe access + MutLockArray *outPortArray; // Array of OSCOutPorts in a locking array for threadsafe access + + id delegate; //! +#else +#import +#endif +#import "OSCValue.h" +#import + + + + +/// Corresponds to an OSC message: contains zero or more values, and the address path the values have to get sent to. +/*! +According to the OSC spec, a message consists of an address path (where the message should be sent) and zero or more arguments. An OSCMessage must be created with an address path- once the OSCMessage exists, you may add as many arguments to it as you'd like. +*/ +@interface OSCMessage : NSObject { + NSString *address; //! 1 + + NSDate *timeTag; //! +#else +#import +#endif +#import "OSCMessage.h" +#import +#import +#import + + + + +@protocol OSCNodeDelegateProtocol +- (void) node:(id)n receivedOSCMessage:(id)msg; +- (void) nodeNameChanged:(id)node; +- (void) nodeDeleted:(id)node; +@end +/// An OSCNode's queryDelegate must respond to these methods, which are called when a query-type OSCMessage is dispatched to an OSCNode +@protocol OSCNodeQueryDelegateProtocol +- (NSMutableArray *) namespaceArrayForNode:(id)n; +- (NSString *) docStringForNode:(id)n; +- (NSString *) typeSignatureForNode:(id)n; +- (OSCValue *) currentValueForNode:(id)n; +- (NSString *) returnTypeStringForNode:(id)n; +@end + + + + +/// OSCNode describes a single destination for OSC addresses. The OSC address space is made up of many different nodes. This class is optional- it is not used for basic OSC message sending/receiving, and only gets used if you start working with OSCAddressSpace. +/*! +The OSC specification describes a slash-delineated address space- as messages are received, they are dispatched to the described address. An OSCNode represents a single unique destination in the OSC address space. OSCNodes may have subnodes and have a non-retaining reference to their parent node (unless they're top-level, in which case their parent node is nil). They retain a copy of the last message dispatched directly to this node for convenience. OSCNode instances have zero or more delegates- delegates are NOT retained, and are assumed to respond to all the methods in OSCNOdeDelegateProtocol. + +If you want to work with an instance of OSCNode, you need to acquire or work with it from the main OSCAddressSpace. Do not just start creating OSCNode instances willy-nilly; there's no point, they're only useful if they're part of an address space. + +Generally speaking, it's a good idea for each instance of OSCNode to have a discrete type, as this makes it easier to browse and filter the hierarchy of OSCNode instances that make up the OSC address space. Most of the documented methods here are simply for querying basic properties of the OSCNode instance or doing simple message dispatch. +*/ + + + + +@interface OSCNode : NSObject { + id addressSpace; // the class OSCAddressSpace is a subclass of OSCNode, and is essentially the "root" node. all OSCNodes have a pointer to the root node! + BOOL deleted; + + OSSpinLock nameLock; + NSString *nodeName; /// "local" name: name of the node at /a/b/c is "c" + NSString *fullName; /// "full" name: name of the node at /a/b/c is "/a/b/c" + MutLockArray *nodeContents; /// Contains OSCNode instances- this OSCNode's sub-nodes. type 'MutLockArray'- this should all be threadsafe... + OSCNode *parentNode; // my "parent" node (or nil). NOT retained! + OSCNodeType nodeType; /// What 'type' of node i am + BOOL hiddenInMenu; // NO by default. if YES, this node (and all its sub-nodes) will be omitted from menus! + + OSCMessage *lastReceivedMessage; /// The last message sent to this node is retained (the message is retained instead of the value because messages can have multiple values) + OSSpinLock lastReceivedMessageLock; + MutNRLockArray *delegateArray; // type 'MutNRLockArray'. contents are NOT retained! could be anything! + + BOOL autoQueryReply; // NO by default. if YES and the queryDelegate is nil or doesn't respond to one of the delegate methods or returns nil from one of the delegate methods, the OSCNode will try to automatically respond to the query + id queryDelegate; // nil by default, NOT retained; unlike "normal" delegates, an OSCNode has a single query delegate +} + +// only called by the address space to craft a formatted string for logging purposes +- (void) _logDescriptionToString:(NSMutableString *)s tabDepth:(int)d; + ++ (id) createWithName:(NSString *)n; +- (id) initWithName:(NSString *)n; +- (id) init; +- (void) prepareToBeDeleted; + +// convenience method so nodes may be sorted by name +- (NSComparisonResult) nodeNameCompare:(OSCNode *)comp; + +// "local" add/remove/find methods for working with my node contents +- (void) addLocalNode:(OSCNode *)n; +- (void) addLocalNodes:(NSArray *)n; +- (void) removeLocalNode:(OSCNode *)n; // this just removes the passed node from my 'nodeContents' array- doesn't assume that the passed node will be released! +- (void) deleteLocalNode:(OSCNode *)n; // calls 'prepareToBeDeleted' on the passed node- call this is if you want to make sure that the passed node will stop sending delegate messages/etc! +- (void) removeFromAddressSpace; // tries to remove me from the OSCAddressSpace singleton by setting my fullName to nil + +/// It's assumed that the passed name doesn't have any wildcards/regex. If the receiver contains a node with the identical name as the passed string, the node will be returned. This is not a "deep" search, it's restricted to the receiver's nodeContents array. +- (OSCNode *) findLocalNodeNamed:(NSString *)n; +/// Same as findLocalNodeNamed:, but if any of the interim nodes don't exist they will be created. +- (OSCNode *) findLocalNodeNamed:(NSString *)n createIfMissing:(BOOL)c; + +/// Compares the names of all the receiver's sub-nodes to the passed POSIX regex string, returns an array with all the nodes whose nodeNames match the regex. If there are no sub-nodes or none of the sub-nodes match the regex, returns nil. +- (NSMutableArray *) findLocalNodesMatchingPOSIXRegex:(NSString *)regex; +- (void) _addLocalNodesMatchingRegex:(NSString *)regex toMutArray:(NSMutableArray *)a; + + +/// Calls findNodeForAddress:createIfMissing:NO. +// these find methods do NOT work with regex! it is assumed that the passed string is NOT a regex algorithm! +- (OSCNode *) findNodeForAddress:(NSString *)p; +/// It's assumed that the passed address doesn't have any wildcards/regex (no checking is done). The receiver tries to locate the node at the passed address (relative to the receiver). If c is YES, any OSCNodes missing in the passed address are automatically created. If they have sub-nodes, the auto-created nodes' types are set to OSCNodeDirectory; if not, the auto-created nodes' types are OSCNodeTypeUnknown +- (OSCNode *) findNodeForAddress:(NSString *)p createIfMissing:(BOOL)c; +- (OSCNode *) findNodeForAddressArray:(NSArray *)a; +- (OSCNode *) findNodeForAddressArray:(NSArray *)a createIfMissing:(BOOL)c; +// these find methods work with regex! path components may be regex strings- this returns all the nodes that match every component in the passed address/address array! +- (NSMutableArray *) findNodesMatchingAddress:(NSString *)a; +- (NSMutableArray *) findNodesMatchingAddressArray:(NSArray *)a; + +// a node's delegate is informed of received osc messages or name changes (OSCNodeDelegateProtocol) +// NODE DELEGATES ARE __NOT__ RETAINED! +// NODE DELEGATES __MUST__ REMOVE THEMSELVES FROM THE DELEGATE ARRAY! +- (void) addDelegate:(id)d; +- (void) removeDelegate:(id)d; +- (void) informDelegatesOfNameChange; +- (void) addDelegatesFromNode:(OSCNode *)n; + +/// Sends the passed message to all of the node's delegates- it does NOT parse the address at all (it's assumed that the passed message's address points to this instance of OSCNode). If the passed message is a query, this tries to assemble a reply (either from the queryDelegate or automatically if autoQueryReply is enabled) which is sent to the main address space. +- (void) dispatchMessage:(OSCMessage *)m; + +@property (assign, readwrite) id addressSpace; +@property (assign, readwrite) NSString *nodeName; +- (void) _setNodeName:(NSString *)n; +@property (readonly) NSString *fullName; +@property (readonly) id nodeContents; +@property (assign, readwrite) OSCNode *parentNode; +@property (assign, readwrite) int nodeType; +@property (assign, readwrite) BOOL hiddenInMenu; +@property (readonly) OSCMessage *lastReceivedMessage; +@property (readonly) OSCValue *lastReceivedValue; +@property (readonly) id delegateArray; +//@property (readonly) id queryDelegateArray; +@property (assign,readwrite) BOOL autoQueryReply; +@property (assign,readwrite) id queryDelegate; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCOutPort.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCOutPort.h new file mode 100644 index 0000000..091b593 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCOutPort.h @@ -0,0 +1,71 @@ + +#if IPHONE +#import +#else +#import +#endif + + +#include + +#import "OSCPacket.h" +#import "OSCBundle.h" +#import "OSCMessage.h" + + + + +/// OSCOutPort handles everything needed to send OSC data to a given address +/*! +You should never create or destroy an instance of this class manually. OSCOutPort instances should be created/destroyed by the OSCManager. + +the documentation here only covers the basics, the header file for this class is small and heavily commented if you want to know more because you're heavily customizing OSCOutPort. +*/ +@interface OSCOutPort : NSObject { + BOOL deleted; + int sock; + struct sockaddr_in addr; + unsigned short port; //! +#else +#import +#endif + +#include +#import "OSCBundle.h" +#import "OSCMessage.h" + + + +/// Used to parse raw OSC data or to assemble raw OSC data from OSCMessages/OSCBundles +/*! +An OSC packet is the basic unit of transmitting OSC data- the OSCPacket class is mostly used internally to either parse received raw data or to assemble raw data from OSCMessages/OSCBundles for sending. +*/ + +@interface OSCPacket : NSObject { + long bufferLength; + unsigned char *payload; +} + ++ (void) parseRawBuffer:(unsigned char *)b ofMaxLength:(int)l toInPort:(id)p fromAddr:(unsigned int)txAddr port:(unsigned short)txPort; +/// Creates & returns an auto-released packet from either an OSCBundle or an OSCMessage ++ (id) createWithContent:(id)c; +- (id) initWithContent:(id)c; + +- (long) bufferLength; +- (unsigned char *) payload; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCStringAdditions.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCStringAdditions.h new file mode 100644 index 0000000..48146c2 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCStringAdditions.h @@ -0,0 +1,49 @@ + +#if IPHONE +#import +#else +#import +#endif +#import +#import + + + + +extern NSCharacterSet *_OSCStrAdditionsWildcardCharSet; +extern MutLockDict *_OSCStrPOSIXRegexDict; // key is the regex string, object is an OSCPOSIXRegExpHolder containing the compiled regex- which is threadsafe, and may be reused + + + + +@interface OSCPOSIXRegExpHolder : NSObject { + NSString *regexString; + regex_t *regex; +} + ++ (id) createWithString:(NSString *)n; +- (id) initWithString:(NSString *)n; +- (BOOL) evalAgainstString:(NSString *)n; +- (NSString *) regexString; + +@end + + + + +@interface NSString (OSCStringAdditions) + ++ (NSString *) stringWithBytes:(const void *)b length:(NSUInteger)l encoding:(NSStringEncoding)e; ++ (NSString *) stringFromRawIPAddress:(unsigned long)i; +- (NSString *) trimFirstAndLastSlashes; +- (NSString *) stringByDeletingFirstPathComponent; +- (NSString *) firstPathComponent; +- (NSString *) stringBySanitizingForOSCPath; +- (NSString *) stringByDeletingLastAndAddingFirstSlash; +- (BOOL) containsOSCWildCard; + +- (BOOL) predicateMatchAgainstRegex:(NSString *)r; +- (BOOL) posixMatchAgainstSlowRegex:(NSString *)r; +- (BOOL) posixMatchAgainstFastRegex:(NSString *)r; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCValue.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCValue.h new file mode 100644 index 0000000..fd0ea5e --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCValue.h @@ -0,0 +1,107 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "OSCConstants.h" + + + + +/// OSCValue encapsulates any value you can send or receive via OSC. It is NOT mutable at this time. +/*! +When you send or receive values via OSC, you'll be working with OSCValue objects in an OSCMessage. Internally, OSCValue isn't mutable, and it attempts to store its value in its native format (int for an int, float for a float) instead of relying on NSNumber. The exceptions to this are NSColor/UIColor and NSString. +*/ + + + + +@interface OSCValue : NSObject { + OSCValueType type; //! +#import +#else +#import +#endif +//#import +#import +#import +#import +#import +#include + + + +#if IPHONE +@interface OSCZeroConfDomain : NSObject { +#else +@interface OSCZeroConfDomain : NSObject { +#endif + NSString *domainString; + NSNetServiceBrowser *serviceBrowser; + + MutLockArray *servicesArray; + + id domainManager; +} + ++ (id) createWithDomain:(NSString *)d andDomainManager:(id)m; +- (id) initWithDomain:(NSString *)d andDomainManager:(id)m; + +// NSNetServiceBrowser delegate methods +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didFindService:(NSNetService *)x moreComing:(BOOL)m; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didNotSearch:(NSDictionary *)err; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didRemoveService:(NSNetService *)s moreComing:(BOOL)m; + +// NSNetService delegate methods +- (void)netService:(NSNetService *)n didNotResolve:(NSDictionary *)err; +- (void)netServiceDidResolveAddress:(NSNetService *)n; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCZeroConfManager.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCZeroConfManager.h new file mode 100644 index 0000000..c1795ab --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/OSCZeroConfManager.h @@ -0,0 +1,37 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import +#import "OSCZeroConfDomain.h" +#import + + + + +#if IPHONE +@interface OSCZeroConfManager : NSObject { +#else +@interface OSCZeroConfManager : NSObject { +#endif + NSNetServiceBrowser *domainBrowser; + + NSMutableDictionary *domainDict; + pthread_rwlock_t domainLock; + + id oscManager; +} + +- (id) initWithOSCManager:(id)m; + +- (void) serviceRemoved:(NSNetService *)s; +- (void) serviceResolved:(NSNetService *)s; + +// NSNetServiceBrowser delegate methods +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didFindDomain:(NSString *)d moreComing:(BOOL)m; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didNotSearch:(NSDictionary *)err; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/VVOSC.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/VVOSC.h new file mode 100644 index 0000000..47eeb3a --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/VVOSC.h @@ -0,0 +1,121 @@ + + +#import "OSCConstants.h" + +#import "OSCValue.h" +#import "OSCMessage.h" +#import "OSCBundle.h" +#import "OSCPacket.h" + +#import "OSCOutPort.h" +#import "OSCInPort.h" + +#import "OSCManager.h" +#import "OSCZeroConfManager.h" + +#import "OSCNode.h" +#import "OSCAddressSpace.h" + +#import "OSCStringAdditions.h" + + + + +/// Most common means of passing OSC data to your application. Delegates of OSCManager and OSCInPort should support this protocol. +/*! +When instances of OSCInPort and OSCManager receive OSC data, they pass it to their delegate by calling this method. If you want to receive OSC data, your OSCManager's delegate must respond to this method! +*/ +@protocol OSCDelegateProtocol +/// This method is called whenever your in port/manager receives an OSCMessage. +- (void) receivedOSCMessage:(OSCMessage *)m; +@end + + + + +/* + the following stuff is for doxygen +*/ + + +/*! +\mainpage + +\htmlonly + + + + +Introduction +

+VVOSC is an Objective-c framework for assembling, sending, and receiving OSC (Open Sound Control) messages on OS X. A simple sample application (gui) which sends and receives OSC messages is also included to aid in the debugging of your software. There's also an SDK which allows you to develop iPhone applications which use VVOSC. All the source code is available on the project homepage: http://code.google.com/p/vvopensource +

+ + +Features and Capabilities +

+

  • Includes a sample GUI app for debugging OSC applications and hardware that also demonstrates use of the framework
  • +
  • Packet parsing (client) + construction (server)
  • +
  • Creates bundles/nested bundles, safely parse bundles/nested bundles
  • +
  • Detects other OSC destinations via bonjour/zero-conf networking and automatically creates output ports so you can send data to them.
  • +
  • Input ports automagically advertise their presence via bonjour/zero-conf networking. This is as close to no-setup as it gets!
  • +
  • Supports the following data types: i (int32), f (float32), s/S (OSC-string), b (OSC blob), h (64-bit int), d (64-bit float/double), r (32-bit RGBA color), m (MIDI message), T (tru), F (false), N(nil), I (infinity), t (OSC-timetag)
  • +
  • Processing frequency defaults to 30hz, but may be adjusted dynamically well in excess of 100hz
  • +
  • Multithreaded- each input port runs on its own thread- and threadsafe.
  • +
  • Optional OSC address space classes (OSCNode & OSCAddressSpace) may be used to quickly create a simple OSC-based API for controlling software. Address space includes POSIX regex-based pattern matching engine for dispatching a single message to multiple nodes.
  • +
  • Built on a handful of small, easy-to-grok classes written specifically for OS X. Very easy to understand, modify, subclass, or extend.
  • +
  • Project includes targets that build and install an SDK for using VVOSC in iOS apps
  • +

    + +Breaks from the OSC specification +

    +
  • "char" data type not supported yet, you can use "string" in the meantime
  • +
  • It's possible to create an OSCValue from an NSString containing UTF8 characters, which VVOSC will try to send- and if the software receiving this data doesn't freak out, this allows you to UTF8 characters. In other words, VVOSC doesn't explicitly prevent the use of non-ASCII characters, so it's possible to use it to create incompatible OSC data!
  • +
  • The OSC specification describes a limited subset of regex to be used in wildcard/pattern matching for OSC dispatch. VVOSC's message dispatch is presently a POSIX regex engine simply because it was faster and easier to get going (it's built into the OS) than rolling my own. The specific engine used may change if message dispatch becomes a speed issue in the future; presumably, this ambiguity is why the OSC spec describes a specific and limited subset of regex!
  • +
  • The OSC spec describes the optional type characters [ and ] to delineate arrays and basic node-based structures for ad-hoc data types. Lacking any specific usage examples, this isn't supported yet- if someone wants to send me a specific example i can use to support this protocol properly, please let me know.
  • +
  • While VVOSC parses, stores, and allows you to set OSC time tags (and even create and pass time tags as values), it doesn't perform any delay or scheduling if it receives an OSC bundle with a time tag which is later than the current time. Parsed time tags are available to your applications as the 'timeTag' variable of a passed OSCMessage, which is stored as an NSDate (which, internally, is a double which basically represents 64-bit NTP time, as I understand it).
  • +

    + + +Sample code + +
    +// create an OSCManager- set myself up as its delegate
    +manager = [[OSCManager alloc] init];
    +[manager setDelegate:self];
    +
    +// create an input port for receiving OSC data
    +[manager createNewInputForPort:1234];
    +
    +// create an output so i can send OSC data to myself
    +outPort = [manager createNewOutputToAddress:@"127.0.0.1" atPort:1234];
    +
    +// make an OSC message
    +newMsg = [OSCMessage createWithAddress:@"/Address/Path/1"];
    +
    +// add a bunch arguments to the message
    +[newMsg addInt:12];
    +[newMsg addFloat:12.34];
    +[newMsg addColor:[NSColor colorWithDeviceRed:0.0 green:1.0 blue:0.0 alpha:1.0]];
    +[newMsg addBOOL:YES];
    +[newMsg addString:@"Hello World!"];
    +
    +// send the OSC message
    +[outPort sendThisMessage:newMsg];
    +
    + + +\endhtmlonly +*/ diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/lgpl-3.0.txt b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/lgpl-3.0.txt new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Headers/lgpl-3.0.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Resources b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Resources deleted file mode 120000 index 953ee36..0000000 --- a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Resources +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/Resources \ No newline at end of file diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Resources/Info.plist b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Resources/Info.plist new file mode 100644 index 0000000..ed0ff17 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Resources/Info.plist @@ -0,0 +1,38 @@ + + + + + BuildMachineOSBuild + 11E53 + CFBundleDevelopmentRegion + English + CFBundleExecutable + VVOSC + CFBundleGetInfoString + 156 + CFBundleIdentifier + com.vidvox.VVOSC + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 156 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E2002 + DTPlatformVersion + GM + DTSDKBuild + 11E53 + DTSDKName + + DTXcode + 0432 + DTXcodeBuild + 4E2002 + + diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/VVOSC b/atemOSC.app/Contents/Frameworks/VVOSC.framework/VVOSC deleted file mode 120000 index c6a43b0..0000000 --- a/atemOSC.app/Contents/Frameworks/VVOSC.framework/VVOSC +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/VVOSC \ No newline at end of file diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/VVOSC b/atemOSC.app/Contents/Frameworks/VVOSC.framework/VVOSC new file mode 100755 index 0000000..b74bb36 Binary files /dev/null and b/atemOSC.app/Contents/Frameworks/VVOSC.framework/VVOSC differ diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current deleted file mode 120000 index 8c7e5a6..0000000 --- a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current +++ /dev/null @@ -1 +0,0 @@ -A \ No newline at end of file diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCAddressSpace.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCAddressSpace.h new file mode 100644 index 0000000..966aa33 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCAddressSpace.h @@ -0,0 +1,77 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "OSCNode.h" + + + + +// OSCAddressSpace delegate protocol +@protocol OSCAddressSpaceDelegateProtocol +- (void) nodeRenamed:(OSCNode *)n; +- (void) dispatchReplyOrError:(OSCMessage *)m; // this method is called by nodes in the address space. the passed message is a reply or error in response to a query which should be sent out an output. +@end + + + + +// this is the main instance of OSCAddressSpace. it is auto-created when this class is initialized +extern id _mainAddressSpace; + + + + +/// OSCAddressSpace is a representation of the OSC address space described in the OSC spec. It is a subclass of OSCNode. This class is optional- it's not needed for basic OSC message sending/receiving. +/*! +There should only ever be one instance of OSCAddressSpace, and you shouldn't explicitly create it. Just call [OSCAddressSpace class] (or any other OSCAddressSpace method) and it will be automatically created. This main instance may be retrieved by the class method +[OSCAddressSpace mainAddressSpace] or by the class variable _mainAddressSpace. + +OSCAddressSpace is your application's main way of dealing with the OSC address space- if you need to dispatch a message, set, rename, or delete a node, you should do via the main instance of this class. +*/ +@interface OSCAddressSpace : OSCNode { + id delegate; +} + +/// Returns the main instance of the OSC address space (and creates it if necessary) ++ (id) mainAddressSpace; ++ (void) refreshMenu; +#if !IPHONE ++ (NSMenu *) makeMenuForNode:(OSCNode *)n withTarget:(id)t action:(SEL)a; ++ (NSMenu *) makeMenuForNode:(OSCNode *)n ofType:(NSIndexSet *)ts withTarget:(id)t action:(SEL)a; +#endif + +/// Renames 'before' to 'after'. Sub-nodes stay with their owners! Can also be though of as a "move". +- (void) renameAddress:(NSString *)before to:(NSString *)after; +- (void) renameAddressArray:(NSArray *)before toArray:(NSArray *)after; + +/// If 'n' is nil, the node at the passed address will be deleted (as will any of its sub-nodes) +- (void) setNode:(OSCNode *)n forAddress:(NSString *)a; +- (void) setNode:(OSCNode *)n forAddress:(NSString *)a createIfMissing:(BOOL)c; +- (void) setNode:(OSCNode *)n forAddressArray:(NSArray *)a; +- (void) setNode:(OSCNode *)n forAddressArray:(NSArray *)a createIfMissing:(BOOL)c; + +// this method is called whenever a node is added to another node +- (void) nodeRenamed:(OSCNode *)n; + +/// Unlike a normal OSCNode, this method finds the destination node and then dispatches the msg. If the destination is itself, it just calls the super. +- (void) dispatchMessage:(OSCMessage *)m; +// This method gets called by an OSCNode inside me (or by me), and you probably won't need to ever call this method. The passed message is a reply or error that needs to be sent back in response to a query. The passed OSCMessage contains the IP address and port of the destination. This method just passes the data on to the addres space's delegate- it does NOT actually send anything out, this is something you'll have to implement in the delegate. +- (void) _dispatchReplyOrError:(OSCMessage *)m; + +- (void) addDelegate:(id)d forPath:(NSString *)p; +- (void) removeDelegate:(id)d forPath:(NSString *)p; +/* +- (void) addQueryDelegate:(id)d forPath:(NSString *)p; +- (void) removeQueryDelegate:(id)d forPath:(NSString *)p; +*/ +@property (assign, readwrite) id delegate; + + +@end + + + + + diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCBundle.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCBundle.h new file mode 100644 index 0000000..857d688 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCBundle.h @@ -0,0 +1,46 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import "OSCMessage.h" + + + + +/// An OSCBundle is a "container" for multiple OSC messages or bundles (bundles may also be nested) +/*! +According to the OSC spec, an OSC bundle is basically a wrapper for multiple OSC messages (or other bundles). Instead of sending a bunch of individual messages, you can wrap them all into a bundle, and send the bundle (messages will still be sent to their individual address paths). OSCBundleÕs interface is correspondingly simple: you can create a bundle from some elements, or you can create a bundle and then add some elements (OSCMessages or OSCBundles) to it. + +OSC bundles also have a time stamp- by default, this will be set to immediate execution (0s except for a single 1 in the LSB). while timetag execution isn't widely supported, you may specify non-immediate time tags in the hopes that the software on the receiving end will execute the bundle in time. +*/ + + + + +@interface OSCBundle : NSObject { + NSMutableArray *elementArray; // array of messages or bundles + NSDate *timeTag; // nil by default, or the time at which the contents of this bundle should be dispatched +} + ++ (void) parseRawBuffer:(unsigned char *)b ofMaxLength:(int)l toInPort:(id)p inheritedTimeTag:(NSDate *)d fromAddr:(unsigned int)txAddr port:(unsigned short)txPort; +/// Creates and returns an auto-released bundle ++ (id) create; +/// Creates and returns an auto-released bundle with the single passed element ++ (id) createWithElement:(id)n; +/// Creates and returns an auto-released bundle with the array of passed elements ++ (id) createWithElementArray:(id)a; + +/// Adds the passed element to the bundle +- (void) addElement:(id)n; +/// Adds the array of passed elements to the bundle +- (void) addElementArray:(NSArray *)a; + +- (long) bufferLength; +- (void) writeToBuffer:(unsigned char *)b; + +@property (retain,readwrite) NSDate *timeTag; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCConstants.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCConstants.h new file mode 100644 index 0000000..7261ae2 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCConstants.h @@ -0,0 +1,131 @@ + +/*! +\file OSCConstants.h +\brief Constants and Macros used by one or more of the OSC classes in this framework +*/ + +/// OSCValueType +/*! +OSCValues have distinct types; these are used to describe the type of an OSCValue. +*/ +typedef enum { + OSCValInt = 1, //! +#else +#import +#endif + +#import +//#import +//#import +#import +#import +#import +#import "OSCPacket.h" +#import "OSCBundle.h" +#import "OSCMessage.h" +#import "OSCOutPort.h" + + + + +/// OSCInPort handles everything needed to receive OSC data on a given port +/*! +You should never create or destroy an instance of this class manually. OSCInPort instances should be created/destroyed by the OSCManager. + +Each OSCInPort is running in its own separate thread- so make sure anything called as a result of received OSC input is thread-safe! When OSCInPort receives data, it gets parsed and passed to the in port's delegate as a series of OSCMessages consisting of an address path and an OSCValue. By default, the inport's delegate is the manager which created it- and by default, managers pass this data on to *their* delegates (your objects/app). + +the documentation here only covers the basics, the header file for this class is small and heavily commented if you want to know more because you're heavily customizing OSCInPort. +*/ +@interface OSCInPort : NSObject { + BOOL deleted; // whether or not i'm deleted- ensures that socket gets closed + BOOL bound; // whether or not the socket is bound + OSSpinLock socketLock; + int sock; // socket file descriptor. remember, everything in unix is files! + struct sockaddr_in addr; // struct that describes *my* address (this is an in port) + unsigned short port; // the port number i'm receiving from + unsigned char buf[65506]; // the socket gets data and dumps it here immediately + + OSSpinLock scratchLock; + NSThread *thread; + //VVThreadLoop *threadLooper; + + NSString *portLabel; //! +#else +#import +#endif +#import "OSCAddressSpace.h" +#import "OSCZeroConfManager.h" +#import "OSCInPort.h" +#import "OSCOutPort.h" + + + + +/// Main VVOSC class- manages in & out port creation, zero configuration networking (bonjour/zeroconf) +/*! +The OSCManager will probably be the main class that you're working with: it creates/deletes inputs (which receive data) and outputs (which send data), passes any OSC data received to its delegate (your application), optionally handles distribution of all received OSC messages, and does other manager-ish things. You should only need one instance of OSCManager in your application. One of your objects should be OSCManager's delegate (see the "OSCDelegateProtocol" below) so you may receive OSC data. + +Incoming OSC data is initially received by an OSCInPort; fundamentally, in ports are running a loop which checks a socket for data received since the last loop. By default, the OSCInPort's delegate is the OSCManager which created it. Every time the loop runs, it passes the received data off to its delegate (the manager) as the raw address/value pairs in the order they're received. When the OSCManager receives data from its in port it immediately passes the received data to its delegate, which should respond to one of the following methods (referred to as the 'OSCDelegateProtocol'): + +\htmlonly +
    +@protocol OSCDelegateProtocol
    +- (void) receivedOSCMessage:(OSCMessage *)m;
    +@end +
    +\endhtmlonly + +...if you want to work with received OSC data, OSCManager's delegate must respond to this method! +*/ + + + + +@interface OSCManager : NSObject { + MutLockArray *inPortArray; // Array of OSCInPorts in a locking array for threadsafe access + MutLockArray *outPortArray; // Array of OSCOutPorts in a locking array for threadsafe access + + id delegate; //! +#else +#import +#endif +#import "OSCValue.h" +#import + + + + +/// Corresponds to an OSC message: contains zero or more values, and the address path the values have to get sent to. +/*! +According to the OSC spec, a message consists of an address path (where the message should be sent) and zero or more arguments. An OSCMessage must be created with an address path- once the OSCMessage exists, you may add as many arguments to it as you'd like. +*/ +@interface OSCMessage : NSObject { + NSString *address; //! 1 + + NSDate *timeTag; //! +#else +#import +#endif +#import "OSCMessage.h" +#import +#import +#import + + + + +@protocol OSCNodeDelegateProtocol +- (void) node:(id)n receivedOSCMessage:(id)msg; +- (void) nodeNameChanged:(id)node; +- (void) nodeDeleted:(id)node; +@end +/// An OSCNode's queryDelegate must respond to these methods, which are called when a query-type OSCMessage is dispatched to an OSCNode +@protocol OSCNodeQueryDelegateProtocol +- (NSMutableArray *) namespaceArrayForNode:(id)n; +- (NSString *) docStringForNode:(id)n; +- (NSString *) typeSignatureForNode:(id)n; +- (OSCValue *) currentValueForNode:(id)n; +- (NSString *) returnTypeStringForNode:(id)n; +@end + + + + +/// OSCNode describes a single destination for OSC addresses. The OSC address space is made up of many different nodes. This class is optional- it is not used for basic OSC message sending/receiving, and only gets used if you start working with OSCAddressSpace. +/*! +The OSC specification describes a slash-delineated address space- as messages are received, they are dispatched to the described address. An OSCNode represents a single unique destination in the OSC address space. OSCNodes may have subnodes and have a non-retaining reference to their parent node (unless they're top-level, in which case their parent node is nil). They retain a copy of the last message dispatched directly to this node for convenience. OSCNode instances have zero or more delegates- delegates are NOT retained, and are assumed to respond to all the methods in OSCNOdeDelegateProtocol. + +If you want to work with an instance of OSCNode, you need to acquire or work with it from the main OSCAddressSpace. Do not just start creating OSCNode instances willy-nilly; there's no point, they're only useful if they're part of an address space. + +Generally speaking, it's a good idea for each instance of OSCNode to have a discrete type, as this makes it easier to browse and filter the hierarchy of OSCNode instances that make up the OSC address space. Most of the documented methods here are simply for querying basic properties of the OSCNode instance or doing simple message dispatch. +*/ + + + + +@interface OSCNode : NSObject { + id addressSpace; // the class OSCAddressSpace is a subclass of OSCNode, and is essentially the "root" node. all OSCNodes have a pointer to the root node! + BOOL deleted; + + OSSpinLock nameLock; + NSString *nodeName; /// "local" name: name of the node at /a/b/c is "c" + NSString *fullName; /// "full" name: name of the node at /a/b/c is "/a/b/c" + MutLockArray *nodeContents; /// Contains OSCNode instances- this OSCNode's sub-nodes. type 'MutLockArray'- this should all be threadsafe... + OSCNode *parentNode; // my "parent" node (or nil). NOT retained! + OSCNodeType nodeType; /// What 'type' of node i am + BOOL hiddenInMenu; // NO by default. if YES, this node (and all its sub-nodes) will be omitted from menus! + + OSCMessage *lastReceivedMessage; /// The last message sent to this node is retained (the message is retained instead of the value because messages can have multiple values) + OSSpinLock lastReceivedMessageLock; + MutNRLockArray *delegateArray; // type 'MutNRLockArray'. contents are NOT retained! could be anything! + + BOOL autoQueryReply; // NO by default. if YES and the queryDelegate is nil or doesn't respond to one of the delegate methods or returns nil from one of the delegate methods, the OSCNode will try to automatically respond to the query + id queryDelegate; // nil by default, NOT retained; unlike "normal" delegates, an OSCNode has a single query delegate +} + +// only called by the address space to craft a formatted string for logging purposes +- (void) _logDescriptionToString:(NSMutableString *)s tabDepth:(int)d; + ++ (id) createWithName:(NSString *)n; +- (id) initWithName:(NSString *)n; +- (id) init; +- (void) prepareToBeDeleted; + +// convenience method so nodes may be sorted by name +- (NSComparisonResult) nodeNameCompare:(OSCNode *)comp; + +// "local" add/remove/find methods for working with my node contents +- (void) addLocalNode:(OSCNode *)n; +- (void) addLocalNodes:(NSArray *)n; +- (void) removeLocalNode:(OSCNode *)n; // this just removes the passed node from my 'nodeContents' array- doesn't assume that the passed node will be released! +- (void) deleteLocalNode:(OSCNode *)n; // calls 'prepareToBeDeleted' on the passed node- call this is if you want to make sure that the passed node will stop sending delegate messages/etc! +- (void) removeFromAddressSpace; // tries to remove me from the OSCAddressSpace singleton by setting my fullName to nil + +/// It's assumed that the passed name doesn't have any wildcards/regex. If the receiver contains a node with the identical name as the passed string, the node will be returned. This is not a "deep" search, it's restricted to the receiver's nodeContents array. +- (OSCNode *) findLocalNodeNamed:(NSString *)n; +/// Same as findLocalNodeNamed:, but if any of the interim nodes don't exist they will be created. +- (OSCNode *) findLocalNodeNamed:(NSString *)n createIfMissing:(BOOL)c; + +/// Compares the names of all the receiver's sub-nodes to the passed POSIX regex string, returns an array with all the nodes whose nodeNames match the regex. If there are no sub-nodes or none of the sub-nodes match the regex, returns nil. +- (NSMutableArray *) findLocalNodesMatchingPOSIXRegex:(NSString *)regex; +- (void) _addLocalNodesMatchingRegex:(NSString *)regex toMutArray:(NSMutableArray *)a; + + +/// Calls findNodeForAddress:createIfMissing:NO. +// these find methods do NOT work with regex! it is assumed that the passed string is NOT a regex algorithm! +- (OSCNode *) findNodeForAddress:(NSString *)p; +/// It's assumed that the passed address doesn't have any wildcards/regex (no checking is done). The receiver tries to locate the node at the passed address (relative to the receiver). If c is YES, any OSCNodes missing in the passed address are automatically created. If they have sub-nodes, the auto-created nodes' types are set to OSCNodeDirectory; if not, the auto-created nodes' types are OSCNodeTypeUnknown +- (OSCNode *) findNodeForAddress:(NSString *)p createIfMissing:(BOOL)c; +- (OSCNode *) findNodeForAddressArray:(NSArray *)a; +- (OSCNode *) findNodeForAddressArray:(NSArray *)a createIfMissing:(BOOL)c; +// these find methods work with regex! path components may be regex strings- this returns all the nodes that match every component in the passed address/address array! +- (NSMutableArray *) findNodesMatchingAddress:(NSString *)a; +- (NSMutableArray *) findNodesMatchingAddressArray:(NSArray *)a; + +// a node's delegate is informed of received osc messages or name changes (OSCNodeDelegateProtocol) +// NODE DELEGATES ARE __NOT__ RETAINED! +// NODE DELEGATES __MUST__ REMOVE THEMSELVES FROM THE DELEGATE ARRAY! +- (void) addDelegate:(id)d; +- (void) removeDelegate:(id)d; +- (void) informDelegatesOfNameChange; +- (void) addDelegatesFromNode:(OSCNode *)n; + +/// Sends the passed message to all of the node's delegates- it does NOT parse the address at all (it's assumed that the passed message's address points to this instance of OSCNode). If the passed message is a query, this tries to assemble a reply (either from the queryDelegate or automatically if autoQueryReply is enabled) which is sent to the main address space. +- (void) dispatchMessage:(OSCMessage *)m; + +@property (assign, readwrite) id addressSpace; +@property (assign, readwrite) NSString *nodeName; +- (void) _setNodeName:(NSString *)n; +@property (readonly) NSString *fullName; +@property (readonly) id nodeContents; +@property (assign, readwrite) OSCNode *parentNode; +@property (assign, readwrite) int nodeType; +@property (assign, readwrite) BOOL hiddenInMenu; +@property (readonly) OSCMessage *lastReceivedMessage; +@property (readonly) OSCValue *lastReceivedValue; +@property (readonly) id delegateArray; +//@property (readonly) id queryDelegateArray; +@property (assign,readwrite) BOOL autoQueryReply; +@property (assign,readwrite) id queryDelegate; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCOutPort.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCOutPort.h new file mode 100644 index 0000000..091b593 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCOutPort.h @@ -0,0 +1,71 @@ + +#if IPHONE +#import +#else +#import +#endif + + +#include + +#import "OSCPacket.h" +#import "OSCBundle.h" +#import "OSCMessage.h" + + + + +/// OSCOutPort handles everything needed to send OSC data to a given address +/*! +You should never create or destroy an instance of this class manually. OSCOutPort instances should be created/destroyed by the OSCManager. + +the documentation here only covers the basics, the header file for this class is small and heavily commented if you want to know more because you're heavily customizing OSCOutPort. +*/ +@interface OSCOutPort : NSObject { + BOOL deleted; + int sock; + struct sockaddr_in addr; + unsigned short port; //! +#else +#import +#endif + +#include +#import "OSCBundle.h" +#import "OSCMessage.h" + + + +/// Used to parse raw OSC data or to assemble raw OSC data from OSCMessages/OSCBundles +/*! +An OSC packet is the basic unit of transmitting OSC data- the OSCPacket class is mostly used internally to either parse received raw data or to assemble raw data from OSCMessages/OSCBundles for sending. +*/ + +@interface OSCPacket : NSObject { + long bufferLength; + unsigned char *payload; +} + ++ (void) parseRawBuffer:(unsigned char *)b ofMaxLength:(int)l toInPort:(id)p fromAddr:(unsigned int)txAddr port:(unsigned short)txPort; +/// Creates & returns an auto-released packet from either an OSCBundle or an OSCMessage ++ (id) createWithContent:(id)c; +- (id) initWithContent:(id)c; + +- (long) bufferLength; +- (unsigned char *) payload; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCStringAdditions.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCStringAdditions.h new file mode 100644 index 0000000..48146c2 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCStringAdditions.h @@ -0,0 +1,49 @@ + +#if IPHONE +#import +#else +#import +#endif +#import +#import + + + + +extern NSCharacterSet *_OSCStrAdditionsWildcardCharSet; +extern MutLockDict *_OSCStrPOSIXRegexDict; // key is the regex string, object is an OSCPOSIXRegExpHolder containing the compiled regex- which is threadsafe, and may be reused + + + + +@interface OSCPOSIXRegExpHolder : NSObject { + NSString *regexString; + regex_t *regex; +} + ++ (id) createWithString:(NSString *)n; +- (id) initWithString:(NSString *)n; +- (BOOL) evalAgainstString:(NSString *)n; +- (NSString *) regexString; + +@end + + + + +@interface NSString (OSCStringAdditions) + ++ (NSString *) stringWithBytes:(const void *)b length:(NSUInteger)l encoding:(NSStringEncoding)e; ++ (NSString *) stringFromRawIPAddress:(unsigned long)i; +- (NSString *) trimFirstAndLastSlashes; +- (NSString *) stringByDeletingFirstPathComponent; +- (NSString *) firstPathComponent; +- (NSString *) stringBySanitizingForOSCPath; +- (NSString *) stringByDeletingLastAndAddingFirstSlash; +- (BOOL) containsOSCWildCard; + +- (BOOL) predicateMatchAgainstRegex:(NSString *)r; +- (BOOL) posixMatchAgainstSlowRegex:(NSString *)r; +- (BOOL) posixMatchAgainstFastRegex:(NSString *)r; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCValue.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCValue.h new file mode 100644 index 0000000..fd0ea5e --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCValue.h @@ -0,0 +1,107 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "OSCConstants.h" + + + + +/// OSCValue encapsulates any value you can send or receive via OSC. It is NOT mutable at this time. +/*! +When you send or receive values via OSC, you'll be working with OSCValue objects in an OSCMessage. Internally, OSCValue isn't mutable, and it attempts to store its value in its native format (int for an int, float for a float) instead of relying on NSNumber. The exceptions to this are NSColor/UIColor and NSString. +*/ + + + + +@interface OSCValue : NSObject { + OSCValueType type; //! +#import +#else +#import +#endif +//#import +#import +#import +#import +#import +#include + + + +#if IPHONE +@interface OSCZeroConfDomain : NSObject { +#else +@interface OSCZeroConfDomain : NSObject { +#endif + NSString *domainString; + NSNetServiceBrowser *serviceBrowser; + + MutLockArray *servicesArray; + + id domainManager; +} + ++ (id) createWithDomain:(NSString *)d andDomainManager:(id)m; +- (id) initWithDomain:(NSString *)d andDomainManager:(id)m; + +// NSNetServiceBrowser delegate methods +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didFindService:(NSNetService *)x moreComing:(BOOL)m; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didNotSearch:(NSDictionary *)err; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didRemoveService:(NSNetService *)s moreComing:(BOOL)m; + +// NSNetService delegate methods +- (void)netService:(NSNetService *)n didNotResolve:(NSDictionary *)err; +- (void)netServiceDidResolveAddress:(NSNetService *)n; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCZeroConfManager.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCZeroConfManager.h new file mode 100644 index 0000000..c1795ab --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/OSCZeroConfManager.h @@ -0,0 +1,37 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import +#import "OSCZeroConfDomain.h" +#import + + + + +#if IPHONE +@interface OSCZeroConfManager : NSObject { +#else +@interface OSCZeroConfManager : NSObject { +#endif + NSNetServiceBrowser *domainBrowser; + + NSMutableDictionary *domainDict; + pthread_rwlock_t domainLock; + + id oscManager; +} + +- (id) initWithOSCManager:(id)m; + +- (void) serviceRemoved:(NSNetService *)s; +- (void) serviceResolved:(NSNetService *)s; + +// NSNetServiceBrowser delegate methods +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didFindDomain:(NSString *)d moreComing:(BOOL)m; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didNotSearch:(NSDictionary *)err; + +@end diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/VVOSC.h b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/VVOSC.h new file mode 100644 index 0000000..47eeb3a --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/VVOSC.h @@ -0,0 +1,121 @@ + + +#import "OSCConstants.h" + +#import "OSCValue.h" +#import "OSCMessage.h" +#import "OSCBundle.h" +#import "OSCPacket.h" + +#import "OSCOutPort.h" +#import "OSCInPort.h" + +#import "OSCManager.h" +#import "OSCZeroConfManager.h" + +#import "OSCNode.h" +#import "OSCAddressSpace.h" + +#import "OSCStringAdditions.h" + + + + +/// Most common means of passing OSC data to your application. Delegates of OSCManager and OSCInPort should support this protocol. +/*! +When instances of OSCInPort and OSCManager receive OSC data, they pass it to their delegate by calling this method. If you want to receive OSC data, your OSCManager's delegate must respond to this method! +*/ +@protocol OSCDelegateProtocol +/// This method is called whenever your in port/manager receives an OSCMessage. +- (void) receivedOSCMessage:(OSCMessage *)m; +@end + + + + +/* + the following stuff is for doxygen +*/ + + +/*! +\mainpage + +\htmlonly + + + + +Introduction +

    +VVOSC is an Objective-c framework for assembling, sending, and receiving OSC (Open Sound Control) messages on OS X. A simple sample application (gui) which sends and receives OSC messages is also included to aid in the debugging of your software. There's also an SDK which allows you to develop iPhone applications which use VVOSC. All the source code is available on the project homepage: http://code.google.com/p/vvopensource +

    + + +Features and Capabilities +

    +

  • Includes a sample GUI app for debugging OSC applications and hardware that also demonstrates use of the framework
  • +
  • Packet parsing (client) + construction (server)
  • +
  • Creates bundles/nested bundles, safely parse bundles/nested bundles
  • +
  • Detects other OSC destinations via bonjour/zero-conf networking and automatically creates output ports so you can send data to them.
  • +
  • Input ports automagically advertise their presence via bonjour/zero-conf networking. This is as close to no-setup as it gets!
  • +
  • Supports the following data types: i (int32), f (float32), s/S (OSC-string), b (OSC blob), h (64-bit int), d (64-bit float/double), r (32-bit RGBA color), m (MIDI message), T (tru), F (false), N(nil), I (infinity), t (OSC-timetag)
  • +
  • Processing frequency defaults to 30hz, but may be adjusted dynamically well in excess of 100hz
  • +
  • Multithreaded- each input port runs on its own thread- and threadsafe.
  • +
  • Optional OSC address space classes (OSCNode & OSCAddressSpace) may be used to quickly create a simple OSC-based API for controlling software. Address space includes POSIX regex-based pattern matching engine for dispatching a single message to multiple nodes.
  • +
  • Built on a handful of small, easy-to-grok classes written specifically for OS X. Very easy to understand, modify, subclass, or extend.
  • +
  • Project includes targets that build and install an SDK for using VVOSC in iOS apps
  • +

    + +Breaks from the OSC specification +

    +
  • "char" data type not supported yet, you can use "string" in the meantime
  • +
  • It's possible to create an OSCValue from an NSString containing UTF8 characters, which VVOSC will try to send- and if the software receiving this data doesn't freak out, this allows you to UTF8 characters. In other words, VVOSC doesn't explicitly prevent the use of non-ASCII characters, so it's possible to use it to create incompatible OSC data!
  • +
  • The OSC specification describes a limited subset of regex to be used in wildcard/pattern matching for OSC dispatch. VVOSC's message dispatch is presently a POSIX regex engine simply because it was faster and easier to get going (it's built into the OS) than rolling my own. The specific engine used may change if message dispatch becomes a speed issue in the future; presumably, this ambiguity is why the OSC spec describes a specific and limited subset of regex!
  • +
  • The OSC spec describes the optional type characters [ and ] to delineate arrays and basic node-based structures for ad-hoc data types. Lacking any specific usage examples, this isn't supported yet- if someone wants to send me a specific example i can use to support this protocol properly, please let me know.
  • +
  • While VVOSC parses, stores, and allows you to set OSC time tags (and even create and pass time tags as values), it doesn't perform any delay or scheduling if it receives an OSC bundle with a time tag which is later than the current time. Parsed time tags are available to your applications as the 'timeTag' variable of a passed OSCMessage, which is stored as an NSDate (which, internally, is a double which basically represents 64-bit NTP time, as I understand it).
  • +

    + + +Sample code + +
    +// create an OSCManager- set myself up as its delegate
    +manager = [[OSCManager alloc] init];
    +[manager setDelegate:self];
    +
    +// create an input port for receiving OSC data
    +[manager createNewInputForPort:1234];
    +
    +// create an output so i can send OSC data to myself
    +outPort = [manager createNewOutputToAddress:@"127.0.0.1" atPort:1234];
    +
    +// make an OSC message
    +newMsg = [OSCMessage createWithAddress:@"/Address/Path/1"];
    +
    +// add a bunch arguments to the message
    +[newMsg addInt:12];
    +[newMsg addFloat:12.34];
    +[newMsg addColor:[NSColor colorWithDeviceRed:0.0 green:1.0 blue:0.0 alpha:1.0]];
    +[newMsg addBOOL:YES];
    +[newMsg addString:@"Hello World!"];
    +
    +// send the OSC message
    +[outPort sendThisMessage:newMsg];
    +
    + + +\endhtmlonly +*/ diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/lgpl-3.0.txt b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/lgpl-3.0.txt new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Headers/lgpl-3.0.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Resources/Info.plist b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Resources/Info.plist new file mode 100644 index 0000000..ed0ff17 --- /dev/null +++ b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/Resources/Info.plist @@ -0,0 +1,38 @@ + + + + + BuildMachineOSBuild + 11E53 + CFBundleDevelopmentRegion + English + CFBundleExecutable + VVOSC + CFBundleGetInfoString + 156 + CFBundleIdentifier + com.vidvox.VVOSC + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 156 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E2002 + DTPlatformVersion + GM + DTSDKBuild + 11E53 + DTSDKName + + DTXcode + 0432 + DTXcodeBuild + 4E2002 + + diff --git a/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/VVOSC b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/VVOSC new file mode 100755 index 0000000..b74bb36 Binary files /dev/null and b/atemOSC.app/Contents/Frameworks/VVOSC.framework/Versions/Current/VVOSC differ diff --git a/atemOSC.app/Contents/Info.plist b/atemOSC.app/Contents/Info.plist index 74bcd1a..49633e8 100644 --- a/atemOSC.app/Contents/Info.plist +++ b/atemOSC.app/Contents/Info.plist @@ -3,7 +3,7 @@ BuildMachineOSBuild - 11E53 + 12C60 CFBundleDevelopmentRegion English CFBundleExecutable @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 2.0 CFBundleSignature ???? CFBundleVersion @@ -25,19 +25,19 @@ DTCompiler DTPlatformBuild - 4E2002 + 4G1004 DTPlatformVersion GM DTSDKBuild - 10K549 + 12C60 DTSDKName - macosx10.6 + DTXcode - 0432 + 0451 DTXcodeBuild - 4E2002 + 4G1004 LSMinimumSystemVersion - 10.6 + 10.8 NSMainNibFile MainMenu NSPrincipalClass diff --git a/atemOSC.app/Contents/MacOS/atemOSC b/atemOSC.app/Contents/MacOS/atemOSC index a2b4b61..854f085 100755 Binary files a/atemOSC.app/Contents/MacOS/atemOSC and b/atemOSC.app/Contents/MacOS/atemOSC differ diff --git a/atemOSC.app/Contents/Resources/English.lproj/MainMenu.nib b/atemOSC.app/Contents/Resources/English.lproj/MainMenu.nib index bf57757..6f8ca93 100644 Binary files a/atemOSC.app/Contents/Resources/English.lproj/MainMenu.nib and b/atemOSC.app/Contents/Resources/English.lproj/MainMenu.nib differ diff --git a/atemOSC.jpg b/atemOSC.jpg index 972483b..04deeb3 100644 Binary files a/atemOSC.jpg and b/atemOSC.jpg differ diff --git a/atemOSC/English.lproj/MainMenu.xib b/atemOSC/English.lproj/MainMenu.xib index 11634ec..294a5e7 100644 --- a/atemOSC/English.lproj/MainMenu.xib +++ b/atemOSC/English.lproj/MainMenu.xib @@ -1,26 +1,32 @@ - 1060 - 11E53 - 2182 - 1138.47 - 569.00 + 1080 + 12C60 + 2843 + 1187.34 + 625.00 com.apple.InterfaceBuilder.CocoaPlugin - 2182 + 2843 YES - NSTextField - NSView - NSWindowTemplate + NSBox + NSButton + NSButtonCell + NSCustomObject + NSLevelIndicator + NSLevelIndicatorCell NSMenu NSMenuItem + NSNumberFormatter + NSPopUpButton + NSPopUpButtonCell + NSTextField NSTextFieldCell - NSButtonCell - NSButton - NSCustomObject + NSView + NSWindowTemplate YES @@ -186,28 +192,29 @@ _NSMainMenu - 15 + 7 2 - {{335, 426}, {394, 177}} + {{335, 426}, {394, 284}} 1954021376 AtemOSC NSWindow - + 256 YES 268 - {{17, 140}, {130, 17}} + {{17, 247}, {130, 17}} + YES - 68288064 + 68157504 272630784 Switcher IP address: @@ -235,16 +242,18 @@ + NO 268 - {{152, 138}, {222, 22}} + {{152, 245}, {222, 22}} - + + YES - -1804468671 + -1804599231 272630784 @@ -266,37 +275,41 @@ + NO 268 - {{14, 7}, {366, 32}} + {{14, 114}, {366, 32}} - + + YES - 67239424 + 67108864 134217728 Connect - -2038284033 + -2038284288 129 200 25 + NO 268 - {{17, 110}, {102, 17}} + {{17, 217}, {102, 17}} + YES - 68288064 + 68157504 272630784 Switcher Name: @@ -304,16 +317,18 @@ + NO 268 - {{152, 108}, {222, 22}} + {{152, 215}, {198, 22}} - + + YES - -2072904127 + -2073034687 272630784 @@ -322,16 +337,18 @@ + NO 268 - {{17, 54}, {128, 17}} + {{17, 161}, {128, 17}} + YES - 68288064 + 68157504 272630784 OSC incoming port: @@ -339,16 +356,18 @@ + NO 268 - {{17, 82}, {103, 17}} + {{17, 189}, {103, 17}} + YES - 68288064 + 68157504 272630784 OSC IP address: @@ -356,34 +375,38 @@ + NO 268 - {{152, 52}, {64, 22}} + {{152, 159}, {64, 22}} + YES - -1804468671 + -1804599231 272630784 - + 3333 YES + NO 268 - {{152, 80}, {222, 22}} + {{152, 187}, {222, 22}} + YES - -1804468671 + -1804599231 272630784 @@ -392,33 +415,38 @@ + NO 268 - {{310, 51}, {64, 22}} + {{310, 158}, {64, 22}} + + YES - -1804468671 + -1804599231 272630784 - + 4444 YES + NO 268 - {{239, 54}, {66, 17}} + {{239, 161}, {66, 17}} + YES - 68288064 + 68157504 272630784 outgoing: @@ -426,9 +454,449 @@ + NO + + + + 12 + + YES + + + 274 + + YES + + + 268 + {{12, 61}, {248, 26}} + + + + _NS:9 + YES + + -2076180416 + 2048 + + _NS:9 + + 109199360 + 129 + + + 400 + 75 + + YES + + OtherViews + + YES + + + + -1 + 1 + YES + YES + 2 + + NO + + + + 268 + {{258, 57}, {94, 32}} + + + + _NS:9 + YES + + 67108864 + 134217728 + Connect + + _NS:9 + + -2038284288 + 129 + + + 200 + 25 + + NO + + + + 268 + {{12, 9}, {88, 26}} + + + + _NS:9 + YES + + -2076180416 + 2048 + + _NS:9 + + 109199360 + 129 + + + 400 + 75 + + YES + + OtherViews + + YES + + + + -1 + 1 + YES + YES + 2 + + NO + + + + 268 + {{103, 9}, {88, 26}} + + + + _NS:9 + 1 + YES + + -2076180416 + 2048 + + _NS:9 + + 109199360 + 129 + + + 400 + 75 + + YES + + OtherViews + + YES + + + + -1 + 1 + YES + YES + 2 + + NO + + + + 268 + {{194, 9}, {88, 26}} + + + + _NS:9 + 2 + YES + + -2076180416 + 2048 + + _NS:9 + + 109199360 + 129 + + + 400 + 75 + + YES + + OtherViews + + YES + + + + -1 + 1 + YES + YES + 2 + + NO + + + + 268 + {{285, 9}, {88, 26}} + + + + _NS:9 + 3 + YES + + -2076180416 + 2048 + + _NS:9 + + 109199360 + 129 + + + 400 + 75 + + YES + + OtherViews + + YES + + + + -1 + 1 + YES + YES + 2 + + NO + + + + 268 + {{15, 35}, {88, 17}} + + + + _NS:1535 + YES + + 68157504 + 138413056 + Tally A + + _NS:1535 + + + + 6 + System + disabledControlTextColor + + 3 + MC4zMzMzMzMzMzMzAA + + + + NO + + + + 268 + {{105, 35}, {88, 17}} + + + + _NS:1535 + YES + + 68157504 + 138413056 + Tally B + + _NS:1535 + + + + + NO + + + + 268 + {{195, 35}, {88, 17}} + + + + _NS:1535 + YES + + 68157504 + 138413056 + Tally C + + _NS:1535 + + + + + NO + + + + 268 + {{285, 35}, {88, 17}} + + + + _NS:1535 + YES + + 68157504 + 138413056 + Tally D + + _NS:1535 + + + + + NO + + + + 268 + {{352, 64}, {16, 18}} + + + + _NS:9 + YES + + 0 + 0 + _NS:9 + + 1 + 1 + 1 + 2 + + NO + + + + -2147483380 + {{352, 64}, {16, 18}} + + + + _NS:9 + YES + + 0 + 0 + _NS:9 + + 1 + 1 + 2 + + NO + + + {{1, 1}, {382, 95}} + + + + _NS:11 + + + {{5, 3}, {384, 111}} + + + + _NS:9 + {0, 0} + + 67108864 + 0 + Tally-Interface + + LucidaGrande + 11 + 3100 + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 2 + NO + + + + 268 + {{358, 216}, {16, 18}} + + + + _NS:9 + YES + + 0 + 0 + _NS:9 + + 1 + 1 + 1 + 2 + + NO + + + + -2147483380 + {{358, 216}, {16, 18}} + + + + _NS:9 + YES + + 0 + 0 + _NS:9 + + 1 + 1 + 2 + + NO - {394, 177} + {394, 284} + + {{0, 0}, {2560, 1418}} @@ -441,6 +909,70 @@ NSFontManager + + + YES + + YES + allowsFloats + formatterBehavior + lenient + locale + maximum + minimum + negativeInfinitySymbol + nilSymbol + numberStyle + positiveInfinitySymbol + + + YES + + + + + + + + + -∞ + + + +∞ + + + # + # + + + + + + + + NaN + + YES + + YES + + + + + + + + 3 + YES + YES + YES + + . + , + NO + NO + YES + @@ -549,37 +1081,173 @@ 622 + + + oscdevice + + + + 636 + + + + serialSelectMenu + + + + 643 + + + + connectButton + + + + 646 + - portChanged: + initPort - + + + 648 + + + + greenLight + + + + 735 + + + + redLight + + + + 736 + + + + tallyA + + + + 737 + + + + tallyB + + + + 738 + + + + tallyC + + + + 739 + + + + tallyD + + + + 740 + + + + tallyGreenLight + + + + 746 + + + + tallyRedLight + + - 629 + 747 - portChanged: + tallyChanged: - + - 630 + 764 - portChanged: + tallyChanged: - + - 635 + 765 - - oscdevice + + tallyChanged: - + - 636 + 766 + + + + tallyChanged: + + + + 767 + + + + formatter + + + + 755 + + + + delegate + + + + 759 + + + + formatter + + + + 756 + + + + delegate + + + + 760 + + + + delegate + + + + 761 @@ -587,9 +1255,7 @@ YES 0 - - YES - + @@ -737,6 +1403,9 @@ + + + @@ -904,6 +1573,287 @@ + + 725 + + + YES + + + + + + + + + + + + + + + + + 637 + + + YES + + + + + + 638 + + + YES + + + + + + 639 + + + YES + + + + + 644 + + + YES + + + + + + 645 + + + + + 657 + + + YES + + + + + + 658 + + + YES + + + + + + 659 + + + YES + + + + + 701 + + + YES + + + + + + 702 + + + YES + + + + + + 703 + + + YES + + + + + 707 + + + YES + + + + + + 708 + + + YES + + + + + + 709 + + + YES + + + + + 713 + + + YES + + + + + + 714 + + + YES + + + + + + 715 + + + YES + + + + + 649 + + + YES + + + + + + 650 + + + + + 719 + + + YES + + + + + + 720 + + + + + 721 + + + YES + + + + + + 722 + + + + + 723 + + + YES + + + + + + 724 + + + + + 731 + + + YES + + + + + + 732 + + + + + 733 + + + YES + + + + + + 734 + + + + + 741 + + + YES + + + + + + 742 + + + YES + + + + + + 743 + + + + + 744 + + + + + 754 + + + @@ -956,6 +1906,43 @@ 632.IBPluginDependency 633.IBPluginDependency 634.IBPluginDependency + 637.IBPluginDependency + 638.IBPluginDependency + 639.IBPluginDependency + 644.IBPluginDependency + 645.IBPluginDependency + 649.IBPluginDependency + 650.IBPluginDependency + 657.IBPluginDependency + 658.IBPluginDependency + 659.IBPluginDependency + 701.IBPluginDependency + 702.IBPluginDependency + 703.IBPluginDependency + 707.IBPluginDependency + 708.IBPluginDependency + 709.IBPluginDependency + 713.IBPluginDependency + 714.IBPluginDependency + 715.IBPluginDependency + 719.IBPluginDependency + 720.IBPluginDependency + 721.IBPluginDependency + 722.IBPluginDependency + 723.IBPluginDependency + 724.IBPluginDependency + 725.IBPluginDependency + 731.IBPluginDependency + 732.IBPluginDependency + 733.IBPluginDependency + 734.IBPluginDependency + 741.IBPluginDependency + 742.IBPluginDependency + 743.IBPluginDependency + 744.IBPluginDependency + 754.IBNumberFormatterBehaviorMetadataKey + 754.IBNumberFormatterLocalizesFormatMetadataKey + 754.IBPluginDependency YES @@ -1005,6 +1992,43 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + com.apple.InterfaceBuilder.CocoaPlugin @@ -1019,7 +2043,7 @@ - 636 + 767 @@ -1032,12 +2056,14 @@ YES connectButtonPressed: + initPort: portChanged: YES id id + id @@ -1045,6 +2071,7 @@ YES connectButtonPressed: + initPort: portChanged: @@ -1053,6 +2080,10 @@ connectButtonPressed: id + + initPort: + id + portChanged: id @@ -1063,22 +2094,42 @@ YES YES + connectButton + greenLight incoming mAddressTextField mConnectButton mSwitcherNameLabel oscdevice outgoing + redLight + serialSelectMenu + tallyA + tallyB + tallyC + tallyD + tallyGreenLight + tallyRedLight window YES + NSButton + NSLevelIndicator NSTextField NSTextField NSButton NSTextField NSTextField NSTextField + NSLevelIndicator + NSPopUpButton + NSPopUpButton + NSPopUpButton + NSPopUpButton + NSPopUpButton + NSLevelIndicator + NSLevelIndicator NSWindow @@ -1086,16 +2137,34 @@ YES YES + connectButton + greenLight incoming mAddressTextField mConnectButton mSwitcherNameLabel oscdevice outgoing + redLight + serialSelectMenu + tallyA + tallyB + tallyC + tallyD + tallyGreenLight + tallyRedLight window YES + + connectButton + NSButton + + + greenLight + NSLevelIndicator + incoming NSTextField @@ -1120,6 +2189,38 @@ outgoing NSTextField + + redLight + NSLevelIndicator + + + serialSelectMenu + NSPopUpButton + + + tallyA + NSPopUpButton + + + tallyB + NSPopUpButton + + + tallyC + NSPopUpButton + + + tallyD + NSPopUpButton + + + tallyGreenLight + NSLevelIndicator + + + tallyRedLight + NSLevelIndicator + window NSWindow @@ -1135,10 +2236,6 @@ 0 IBCocoaFramework - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 diff --git a/atemOSC/SwitcherPanelAppDelegate.h b/atemOSC/SwitcherPanelAppDelegate.h index 2e494ca..90878a3 100644 --- a/atemOSC/SwitcherPanelAppDelegate.h +++ b/atemOSC/SwitcherPanelAppDelegate.h @@ -29,14 +29,14 @@ #import #import -#import - +#import "VVOSC/VVOSC.h" +#import "AMSerialPort.h" class MixEffectBlockMonitor; class SwitcherMonitor; class InputMonitor; -@interface SwitcherPanelAppDelegate : NSObject +@interface SwitcherPanelAppDelegate : NSObject { NSWindow *window; @@ -59,8 +59,22 @@ class InputMonitor; IBOutlet NSTextField* incoming; IBOutlet NSTextField* outgoing; IBOutlet NSTextField* oscdevice; - - + + IBOutlet NSLevelIndicator *redLight; + IBOutlet NSLevelIndicator *greenLight; + + IBOutlet NSLevelIndicator *tallyRedLight; + IBOutlet NSLevelIndicator *tallyGreenLight; + + IBOutlet NSPopUpButton *tallyA; + IBOutlet NSPopUpButton *tallyB; + IBOutlet NSPopUpButton *tallyC; + IBOutlet NSPopUpButton *tallyD; + + + AMSerialPort *port; + IBOutlet NSPopUpButton *serialSelectMenu; + IBOutlet NSButton *connectButton; } @property (assign) IBOutlet NSWindow *window; @@ -80,4 +94,12 @@ class InputMonitor; - (void)updateFTBFramesTextField; - (void)mixEffectBlockBoxSetEnabled:(bool)enabled; + +// Serial Port Methods +- (AMSerialPort *)port; +- (void)setPort:(AMSerialPort *)newPort; +- (void)listDevices; + +- (IBAction)initPort:(id)sender; + @end diff --git a/atemOSC/SwitcherPanelAppDelegate.mm b/atemOSC/SwitcherPanelAppDelegate.mm index 1bda0f1..ab7f680 100644 --- a/atemOSC/SwitcherPanelAppDelegate.mm +++ b/atemOSC/SwitcherPanelAppDelegate.mm @@ -28,7 +28,8 @@ #import "SwitcherPanelAppDelegate.h" #include #include - +#import "AMSerialPortList.h" +#import "AMSerialPortAdditions.h" static inline bool operator== (const REFIID& iid1, const REFIID& iid2) { @@ -280,6 +281,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; mAddressTextField.stringValue = [prefs stringForKey:@"atem"]; + outgoing.intValue = [prefs integerForKey:@"outgoing"]; incoming.intValue = [prefs integerForKey:@"incoming"]; oscdevice.stringValue = [prefs objectForKey:@"oscdevice"]; @@ -290,6 +292,21 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification [self portChanged:self]; + + /// set up notifications + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didAddPorts:) name:AMSerialPortListDidAddPortsNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRemovePorts:) name:AMSerialPortListDidRemovePortsNotification object:nil]; + + /// initialize port list to arm notifications + [AMSerialPortList sharedPortList]; + [self listDevices]; + + +} + + +- (void)controlTextDidEndEditing:(NSNotification *)aNotification { + [self portChanged:self]; } - (void) receivedOSCMessage:(OSCMessage *)m { @@ -327,13 +344,15 @@ - (void) receivedOSCMessage:(OSCMessage *)m { - (void) activateChannel:(int)channel isProgram:(BOOL)program { NSString *strip; - + if (program) { strip = @"program"; + [self send:self Channel:channel]; } else { strip = @"preview"; } - + + for (int i = 0;i<=12;i++) { OSCMessage *newMsg = [OSCMessage createWithAddress:[NSString stringWithFormat:@"/atem/%@/%d",strip,i]]; if (channel==i) {[newMsg addFloat:1.0];} else {[newMsg addFloat:0.0];} @@ -359,13 +378,20 @@ - (IBAction)portChanged:(id)sender { [manager removeInput:inPort]; [manager removeOutput:outPort]; - outPort = [manager createNewOutputToAddress:[oscdevice stringValue] atPort:[outgoing intValue] withLabel:@"test app"]; - inPort = [manager createNewInputForPort:[incoming intValue] withLabel:@"test app"]; + + outPort = [manager createNewOutputToAddress:[oscdevice stringValue] atPort:[outgoing intValue] withLabel:@"atemOSC"]; + inPort = [manager createNewInputForPort:[incoming intValue] withLabel:@"atemOSC"]; [manager setDelegate:self]; } +- (IBAction)tallyChanged:(id)sender { + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + [prefs setObject:[NSString stringWithFormat:@"%d",[[sender selectedItem] tag]] forKey:[NSString stringWithFormat:@"tally%ld",[sender tag]] ]; +} + - (void)applicationWillTerminate:(NSNotification*)aNotification { mSwitcherMonitor->Release(); @@ -449,6 +475,8 @@ - (void)switcherConnected [outPort sendThisMessage:newMsg]; [mConnectButton setEnabled:NO]; // disable Connect button while connected + [greenLight setHidden:NO]; + [redLight setHidden:YES]; NSString* productName; if (FAILED(mSwitcher->GetString(bmdSwitcherPropertyIdProductName, (CFStringRef*)&productName))) @@ -519,7 +547,10 @@ - (void)switcherDisconnected [mConnectButton setEnabled:YES]; // enable connect button so user can re-connect [mSwitcherNameLabel setStringValue:@""]; + [greenLight setHidden:YES]; + [redLight setHidden:NO]; + [self mixEffectBlockBoxSetEnabled:NO]; // cleanup resources created when switcher was connected @@ -567,15 +598,38 @@ - (void)updatePopupButtonItems NSString* name; BMDSwitcherInputId id; + + input->GetInputId(&id); input->GetString(bmdSwitcherInputPropertyIdLongName, (CFStringRef*)&name); - + [tallyA addItemWithTitle:name]; + [[tallyA lastItem] setTag:id]; + + [tallyB addItemWithTitle:name]; + [[tallyB lastItem] setTag:id]; + + [tallyC addItemWithTitle:name]; + [[tallyC lastItem] setTag:id]; + + [tallyD addItemWithTitle:name]; + [[tallyD lastItem] setTag:id]; + input->Release(); [name release]; } inputIterator->Release(); + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + + [tallyA selectItemAtIndex:[[prefs objectForKey:@"tally0"] intValue]]; + [tallyB selectItemAtIndex:[[prefs objectForKey:@"tally1"] intValue]]; + [tallyC selectItemAtIndex:[[prefs objectForKey:@"tally2"] intValue]]; + [tallyD selectItemAtIndex:[[prefs objectForKey:@"tally3"] intValue]]; + + + [self updateProgramButtonSelection]; [self updatePreviewButtonSelection]; @@ -658,4 +712,151 @@ - (void)mixEffectBlockBoxSetEnabled:(bool)enabled } + + + + + + +# pragma mark Serial Port Stuff + +- (IBAction)initPort:(id)sender { + + + NSString *deviceName = [serialSelectMenu titleOfSelectedItem]; + + if (![deviceName isEqualToString:[port bsdPath]]) { + + + [port close]; + + [self setPort:[[[AMSerialPort alloc] init:deviceName withName:deviceName type:(NSString*)CFSTR(kIOSerialBSDModemType)] autorelease]]; + [port setDelegate:self]; + + if ([port open]) { + + NSLog(@"successfully connected"); + + [connectButton setEnabled:NO]; + [serialSelectMenu setEnabled:NO]; + [tallyGreenLight setHidden:NO]; + [tallyRedLight setHidden:YES]; + + [port setSpeed:B9600]; + + + // listen for data in a separate thread + [port readDataInBackground]; + + + } else { // an error occured while creating port + + NSLog(@"error connecting"); + //[serialScreenMessage setStringValue:@"Error Trying to Connect..."]; + [self setPort:nil]; + + } + } +} + + + + +- (void)serialPortReadData:(NSDictionary *)dataDictionary +{ + + AMSerialPort *sendPort = [dataDictionary objectForKey:@"serialPort"]; + NSData *data = [dataDictionary objectForKey:@"data"]; + + if ([data length] > 0) { + + NSString *receivedText = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; + NSLog(@"Serial Port Data Received: %@",receivedText); + + + //Typically, I arrange my serial messages coming from the Arduino in chunks, with the + //data being separated by a comma or semicolon. If you're doing something similar, a + //variant of the following command is invaluable. + + //NSArray *dataArray = [receivedText componentsSeparatedByString:@","]; + + + // continue listening + [sendPort readDataInBackground]; + + } else { + // port closed + NSLog(@"Port was closed on a readData operation...not good!"); + [connectButton setEnabled:YES]; + [serialSelectMenu setEnabled:YES]; + [tallyGreenLight setHidden:YES]; + [tallyRedLight setHidden:NO]; + } + +} + +- (void)listDevices +{ + //get an port enumerator + NSEnumerator *enumerator = [AMSerialPortList portEnumerator]; + AMSerialPort *aPort; + [serialSelectMenu removeAllItems]; + + while (aPort = [enumerator nextObject]) { + [serialSelectMenu addItemWithTitle:[aPort bsdPath]]; + } +} + +- (IBAction)send:(id)sender Channel:(int)channel { + + + if([port isOpen]) { + if (channel>0 && channel<7) { + + if (channel == [[tallyA selectedItem] tag]) {NSLog(@"A");[port writeString:@"A" usingEncoding:NSUTF8StringEncoding error:NULL];} + else if (channel == [[tallyB selectedItem] tag]) {NSLog(@"B");[port writeString:@"B" usingEncoding:NSUTF8StringEncoding error:NULL];} + else if (channel == [[tallyC selectedItem] tag]) {NSLog(@"C");[port writeString:@"C" usingEncoding:NSUTF8StringEncoding error:NULL];} + else if (channel == [[tallyD selectedItem] tag]) {NSLog(@"D");[port writeString:@"D" usingEncoding:NSUTF8StringEncoding error:NULL];} + else {[port writeString:@"0" usingEncoding:NSUTF8StringEncoding error:NULL];}; + + } else { + [port writeString:@"0" usingEncoding:NSUTF8StringEncoding error:NULL]; + } + } +} + +- (AMSerialPort *)port +{ + return port; +} + +- (void)setPort:(AMSerialPort *)newPort +{ + id old = nil; + + if (newPort != port) { + old = port; + port = [newPort retain]; + [old release]; + } +} + + +# pragma mark Notifications + +- (void)didAddPorts:(NSNotification *)theNotification +{ + NSLog(@"A port was added"); + [self listDevices]; +} + +- (void)didRemovePorts:(NSNotification *)theNotification +{ + NSLog(@"A port was removed"); + [self listDevices]; +} + + + + @end diff --git a/atemOSC/VVBasics.framework/Resources b/atemOSC/VVBasics.framework/Resources deleted file mode 120000 index 953ee36..0000000 --- a/atemOSC/VVBasics.framework/Resources +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/Resources \ No newline at end of file diff --git a/atemOSC/VVBasics.framework/Resources/Info.plist b/atemOSC/VVBasics.framework/Resources/Info.plist new file mode 100644 index 0000000..29822ba --- /dev/null +++ b/atemOSC/VVBasics.framework/Resources/Info.plist @@ -0,0 +1,38 @@ + + + + + BuildMachineOSBuild + 11E53 + CFBundleDevelopmentRegion + English + CFBundleExecutable + VVBasics + CFBundleGetInfoString + 156 + CFBundleIdentifier + com.vidvox.VVBasics + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 156 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E2002 + DTPlatformVersion + GM + DTSDKBuild + 10K549 + DTSDKName + macosx10.6 + DTXcode + 0432 + DTXcodeBuild + 4E2002 + + diff --git a/atemOSC/VVBasics.framework/Resources/VVCrashReporter.nib b/atemOSC/VVBasics.framework/Resources/VVCrashReporter.nib new file mode 100644 index 0000000..4c7b505 Binary files /dev/null and b/atemOSC/VVBasics.framework/Resources/VVCrashReporter.nib differ diff --git a/atemOSC/VVBasics.framework/VVBasics b/atemOSC/VVBasics.framework/VVBasics deleted file mode 120000 index b4f88c3..0000000 --- a/atemOSC/VVBasics.framework/VVBasics +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/VVBasics \ No newline at end of file diff --git a/atemOSC/VVBasics.framework/VVBasics b/atemOSC/VVBasics.framework/VVBasics new file mode 100755 index 0000000..e109f6a Binary files /dev/null and b/atemOSC/VVBasics.framework/VVBasics differ diff --git a/atemOSC/VVBasics.framework/Versions/Current b/atemOSC/VVBasics.framework/Versions/Current deleted file mode 120000 index 8c7e5a6..0000000 --- a/atemOSC/VVBasics.framework/Versions/Current +++ /dev/null @@ -1 +0,0 @@ -A \ No newline at end of file diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/MutLockArray.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/MutLockArray.h new file mode 100644 index 0000000..deaf284 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/MutLockArray.h @@ -0,0 +1,185 @@ + +#if IPHONE +#import +#else +#import +#endif +#import + + + +/// Similar to NSMutableArray, but thread-safe. Internally, uses an NSMutableArray and a rwlock. +/* +This class exists because NSMutableArray is not thread-safe by default: if you call methods on it from two different threads at the same time, it will try to execute both, often crashing in the process. I found myself writing a lot of lock/array pairs, so simplified everything by combining them into a single class. MutLockArray has methods which allow you to work with a mutable array in a transparent and thread-safe manner- it will automatically establish the read-/write-locks necessary to perform the relevant task. By avoiding the "lock" methods, you can also work with the array without performing any locking- so you can get a read-/write-lock, perform a number of actions, and then unlock. + +It is important to remember, when working with it, that MutLockArray is NOT a subclass of NSMutableArray; rather, it is a subclass of NSObject with an instance of an NSMutableArray and a rwlock for working with it safely. This means that you can't pass an instance of MutLockArray to anything which is expecting to be passed an NSMutableArray- internally, apple's frameworks will probably be doing some dark voodoo bullshit which will result in a spectacular failure. If you want to work with an actual NSMutableArray, check out the "array", "createArrayCopy", and "lockCreateArrayCopy" methods below. + +...and remember- when looking for stuff in an NSMutableArray, the array will use the "isEqualTo:" comparator method, which is slower than comparing the address of two pointers. if you know the pointer address hasn't changed (if you're *not* working with NSStrings), use the "indexOfIdenticalPtr", "removeIdenticalPtr", etc. methods to work with the array. +*/ + +@interface MutLockArray : NSObject { + NSMutableArray *array; + pthread_rwlock_t arrayLock; +} + +/// Creates and returns an auto-released MutLockArray with a given capacity. The capacity may be 0. ++ (id) arrayWithCapacity:(NSUInteger)c; +/// Inits and returns a MutLockArray with a given capacity; the capacity may be 0. +- (id) initWithCapacity:(NSUInteger)c; +- (id) init; + +/// Establishes a read-lock for the array; multiple read locks may exist simultaneously (if it's not changing, anything can look at the contents of the array). This method does not return until it has been able to get the lock. +- (void) rdlock; +- (BOOL) tryRdLock; // returns YES if i got a read-lock successfully! +/// Establishes a write-lock for the array. Only one write-lock may exist at any given time, and all read-locks must be relinquished before the write-lock may be established (if you're going to change the array, nothing else can be changing or observing it). +- (void) wrlock; +/// Unlocks the array. +- (void) unlock; + +/// Returns the NSMutableArray with everything in it. This returns the actual array, so be careful- it's possible to do something which ISN'T threadsafe with this... +- (NSMutableArray *) array; +/// Returns an NSMutableArray which was created by calling "mutableCopy" on my array. Again, it's possible to do something which ISN'T threadsafe by calling this... +- (NSMutableArray *) createArrayCopy; +/// Returns an NSMutableArray which was created while a read-lock was established; this is threadsafe. +- (NSMutableArray *) lockCreateArrayCopy; + +/// Calls "addObject" on my array; not threadsafe. +- (void) addObject:(id)o; +/// Establishes a write-lock, then calls "addObject" on self; threadsafe. +- (void) lockAddObject:(id)o; +/// Calls "addObjectsFromArray" on my array; not threadsafe. +- (void) addObjectsFromArray:(id)a; +/// Establishes a write-lock, then calls "addObjectsFromArray" on self; threadsafe. +- (void) lockAddObjectsFromArray:(id)a; +/// Calls "addObjectsFromArray" on my array; not threadsafe. +- (void) replaceWithObjectsFromArray:(id)a; +/// Establishes a write-lock, then calls "replaceWithObjectsFromArray" on self; threadsafe. +- (void) lockReplaceWithObjectsFromArray:(id)a; +/// Calls "insertObject:atIndex:" on my array; not threadsafe. +- (void) insertObject:(id)o atIndex:(NSUInteger)i; +/// Establishes a write-lock, then calls "insertObject:atIndex:" on self; threadsafe. +- (void) lockInsertObject:(id)o atIndex:(NSUInteger)i; +/// Calls "removeAllObjects" on my array; not threadsafe. +- (void) removeAllObjects; +/// Establishes a write-lock, then calls "removeAllObjects" on self; threadsafe. +- (void) lockRemoveAllObjects; +/// Calls "objectAtIndex:0" on my array; not threadsafe. +- (id) firstObject; +/// Establishes a read-lock, then calls "firstObject" on self; threadsafe +- (id) lockFirstObject; +/// Calls "removeObjectAtIndex:0" on my array; not threadsafe +- (void) removeFirstObject; +/// Establishes a write-lock, then calls "removeFirstObject" on self; threadsafe. +- (void) lockRemoveFirstObject; +/// Calls "lastObject" on my array; not threadsafe. +- (id) lastObject; +/// Establishes a read-lock, then calls "lastObject" on self; threadsafe. +- (id) lockLastObject; +/// Calls "removeLastObject" on my array; not threadsafe. +- (void) removeLastObject; +/// Establishes a write-lock, then calls "removeLastObject" on self; threadsafe. +- (void) lockRemoveLastObject; +/// Calls "removeObject:" on my array; not threadsafe. +- (void) removeObject:(id)o; +/// Establishes a write-lock, then calls "removeObject:" on self; threadsafe. +- (void) lockRemoveObject:(id)o; +/// Calls "removeObjectAtIndex:" on my array; not threadsafe. +- (void) removeObjectAtIndex:(NSUInteger)i; +/// Establishes a write-lock, then calls "removeObjectAtIndex:" on self; threadsafe. +- (void) lockRemoveObjectAtIndex:(NSUInteger)i; +/// Calls "removeObjectsAtIndexes:" on my array; not threadsafe. +- (void) removeObjectsAtIndexes:(NSIndexSet *)i; +/// Establishes a write-lock, then calls "removeObjectsAtIndexes:" on self; threadsafe. +- (void) lockRemoveObjectsAtIndexes:(NSIndexSet *)i; +/// Calls "removeObjectsInArray:" on my array; not threadsafe. +- (void) removeObjectsInArray:(NSArray *)otherArray; +/// Establishes a write-lock, then calls "removeObjectsInArray:" on self; threadsafe. +- (void) lockRemoveObjectsInArray:(NSArray *)otherArray; +/// Calls "removeIdenticalPtrsInArray:" on my array; not threadsafe +- (void) removeIdenticalPtrsInArray:(NSArray *)a; +/// Establishes a write-lock, then calls "removeIdenticalPtrsInArray:" on self; threadsafe. +- (void) lockRemoveIdenticalPtrsInArray:(NSArray *)a; + +/// Calls "replaceObjectsAtIndexes:withObjects" on my array; not threadsafe. +- (void) replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects; +// Establishes a write-lock, then calls "replaceObjectsAtIndexes:withObjects on self; threadsafe +- (void) lockReplaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects; + +/// Calls "valueForKey:" on my array; not threadsafe. +- (id) valueForKey:(NSString *)key; +/// Establishes a read-lock, then calls "valueForKey:" on self; threadsafe. +- (id) lockValueForKey:(NSString *)key; + + +/// Calls "containsObject:" on my array; not threadsafe. +- (BOOL) containsObject:(id)o; +/// Establishes a read-lock, then calls "containsObject:" on self; threadsafe. +- (BOOL) lockContainsObject:(id)o; +/// Calls "objectAtIndex:" on my array; not threadsafe. +- (id) objectAtIndex:(NSUInteger)i; +/// Establishes a read-lock, then calls "objectAtIndex:" on self; threadsafe. +- (id) lockObjectAtIndex:(NSUInteger)i; +/// Calls "objectsAtIndexes:" on my array; not threadsafe. +- (NSArray *) objectsAtIndexes:(NSIndexSet *)indexes; +/// Establishes a read-lock, then calls "objectsAtIndexes:" on self; threadsafe. +- (NSArray *) lockObjectsAtIndexes:(NSIndexSet *)indexes; +/// Calls "indexOfObject:" on my array; not threadsafe. +- (NSUInteger) indexOfObject:(id)o; +/// Establishes a read-lock, then calls "indexOfObject:" on self; threadsafe. +- (NSUInteger) lockIndexOfObject:(id)o; + + +/// Enumerates through my array- compares the address of each item in the array to the passed pointer. Unlike NSMutableArray, this method does NOT call isEqualTo:, it's just a simple == operator. +- (BOOL) containsIdenticalPtr:(id)o; +/// Establishes a read-lock, then calls "containsIdenticalPtr:" on self; threadsafe. +- (BOOL) lockContainsIdenticalPtr:(id)o; +/// Enumerates through my array- compares the address of each item in the array to the passed pointer. Unlike NSMutableArray, this method does NOT call isEqualTo:, it's just a simple == operator. +- (long) indexOfIdenticalPtr:(id)o; +/// Establishes a read-lock, then calls "indexOfIdenticalPtr:" on self; threadsafe. +- (long) lockIndexOfIdenticalPtr:(id)o; +/// Locates an item in my array by enumerating through it and comparing the address of each item in the array to the passed ptr, and then deletes the matching item from the array; not threadsafe. +- (void) removeIdenticalPtr:(id)o; +/// Establishes a write-lock, then calls "removeIdenticalPtr:" on self; threadsafe. +- (void) lockRemoveIdenticalPtr:(id)o; + +// Calls "filteredArrayUsingPredicate:" on my array; not threadsafe +- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate; +// Establishes a read-lock, then calls "filteredArrayUsingPredicate:" on self; threadsafe +- (NSArray *) lockFilteredArrayUsingPredicate:(NSPredicate *)predicate; + +/// Calls "makeObjectsPerformSelector:" on my array; not threadsafe. +- (void) makeObjectsPerformSelector:(SEL)s; +/// Establishes a read-lock, then calls "makeObjectsPerformSelector:" on self; threadsafe. +- (void) lockMakeObjectsPerformSelector:(SEL)s; +/// Calls "makeObjectsPerformSelector:withObject:" on my array; not threadsafe. +- (void) makeObjectsPerformSelector:(SEL)s withObject:(id)o; +/// Establishes a read-lock, then calls "makeObjectsPerformSelector:withObject:" on self; threadsafe. +- (void) lockMakeObjectsPerformSelector:(SEL)s withObject:(id)o; + + + +/* +- (void) makeCopyPerformSelector:(SEL)s; +- (void) lockMakeCopyPerformSelector:(SEL)s; +- (void) makeCopyPerformSelector:(SEL)s withObject:(id)o; +- (void) lockMakeCopyPerformSelector:(SEL)s withObject:(id)o; +*/ + + + +/// Calls "sortUsingSelector:" on my array; not threadsafe. +- (void) sortUsingSelector:(SEL)s; +/// Establishes a write-lock, then calls "sortUsingSelector:" on self; threadsafe. +- (void) lockSortUsingSelector:(SEL)s; + +/// Calls "sortUsingDescriptors:" on my array; not threadsafe. +- (void) sortUsingDescriptors:(NSArray *)descriptors; +/// Establishes a write-lock, then calls "sortUsingDescriptors:" on self; threadsafe. +- (void) lockSortUsingDescriptors:(NSArray *)descriptors; + +- (NSEnumerator *) objectEnumerator; +- (NSEnumerator *) reverseObjectEnumerator; +- (long) count; +- (long) lockCount; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/MutLockDict.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/MutLockDict.h new file mode 100644 index 0000000..e162293 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/MutLockDict.h @@ -0,0 +1,56 @@ + +#if IPHONE +#import +#else +#import +#endif +#import + + + +/// MutLockDict is a thread-safe version of NSMutableDictionary. +/*! +This class exists because NSMutableDictionary is not thread-safe by default: if you call methods on it from two different threads at the same time, it will try to execute both, often crashing in the process. This class has methods which allow you to work with a mutable dictionary in a transparent and thread-safe manner. +*/ + +@interface MutLockDict : NSObject { + NSMutableDictionary *dict; + pthread_rwlock_t dictLock; +} + ++ (id) dictionaryWithCapacity:(NSUInteger)c; ++ (id) dictionaryWithDict:(NSDictionary *)d; +- (id) initWithCapacity:(NSUInteger)c; + +- (void) rdlock; +- (void) wrlock; +- (void) unlock; + +- (NSMutableDictionary *) dict; +- (NSMutableDictionary *) createDictCopy; +- (NSMutableDictionary *) lockCreateDictCopy; + +- (void) setObject:(id)o forKey:(NSString *)s; +- (void) lockSetObject:(id)o forKey:(NSString *)s; +- (void) setValue:(id)v forKey:(NSString *)s; +- (void) lockSetValue:(id)v forKey:(NSString *)s; +- (void) removeAllObjects; +- (void) lockRemoveAllObjects; +- (id) objectForKey:(NSString *)k; +- (id) lockObjectForKey:(NSString *)k; +- (void) removeObjectForKey:(NSString *)k; +- (void) lockRemoveObjectForKey:(NSString *)k; +- (void) addEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (void) lockAddEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (NSArray *) allKeys; +- (NSArray *) lockAllKeys; +- (NSArray *) allValues; +- (NSArray *) lockAllValues; + +- (void) lockMakeObjectsPerformSelector:(SEL)s; +- (void) makeObjectsPerformSelector:(SEL)s; + +- (NSUInteger) count; +- (NSUInteger) lockCount; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/MutNRLockArray.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/MutNRLockArray.h new file mode 100644 index 0000000..9ad1138 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/MutNRLockArray.h @@ -0,0 +1,50 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import "MutLockArray.h" +#import "ObjectHolder.h" + + + +/// Subclass of MutLockArray; this class does NOT retain the objects in its array! +/* +this class exists because i frequently find myself in situations where i want to add an instance of an object to an array/dict/[any class which retains the passed instance], but i don't actually want the item to be retained. + +Instead of adding (and therefore retaining) objects to an array like my superclass, this class makes an ObjectHolder for objects which are added to it (so they don't get retained), and adds the ObjectHolder to me. when other classes ask me for the index of an object, or ask for the object at a particular index, i'll find the relevant ObjectHolder and then return the object it's storing. +*/ + +@interface MutNRLockArray : MutLockArray { + +} + ++ (id) arrayWithCapacity:(NSUInteger)c; + +- (NSMutableArray *) createArrayCopy; +- (NSMutableArray *) lockCreateArrayCopyFromObjects; +- (NSMutableArray *) createArrayCopyFromObjects; +- (void) addObject:(id)o; +- (void) addObjectsFromArray:(id)a; +- (void) replaceWithObjectsFromArray:(id)a; +- (void) insertObject:(id)o atIndex:(NSUInteger)i; +- (id) lastObject; +- (void) removeObject:(id)o; +- (BOOL) containsObject:(id)o; +- (id) objectAtIndex:(NSUInteger)i; +- (NSArray *) objectsAtIndexes:(NSIndexSet *)indexes; +- (NSUInteger) indexOfObject:(id)o; +- (BOOL) containsIdenticalPtr:(id)o; +- (long) indexOfIdenticalPtr:(id)o; +- (void) removeIdenticalPtr:(id)o; + +// these methods exist because the lookup cost for an ObjectHolder can be significant for high-performance applications- these methods get the object from the ObjectHolder and call the method directly on it! +- (void) bruteForceMakeObjectsPerformSelector:(SEL)s; +- (void) lockBruteForceMakeObjectsPerformSelector:(SEL)s; +- (void) bruteForceMakeObjectsPerformSelector:(SEL)s withObject:(id)o; +- (void) lockBruteForceMakeObjectsPerformSelector:(SEL)s withObject:(id)o; + + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/MutNRLockDict.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/MutNRLockDict.h new file mode 100644 index 0000000..f4f757f --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/MutNRLockDict.h @@ -0,0 +1,39 @@ +// +// MutNRLockDict.h +// VVOpenSource +// +// Created by David Lublin on 12/22/09. +// Copyright 2009 Vidvox. All rights reserved. +// + +#if IPHONE +#import +#else +#import +#endif + +#import "MutLockDict.h" +#import "ObjectHolder.h" + + + +/// Subclass of MutLockDict; this class does NOT retain the objects in its array! +/* +this class exists because i frequently find myself in situations where i want to add an instance of an object to an array/dict/[any class which retains the passed instance], but i don't actually want the item to be retained. + +Instead of adding (and therefore retaining) objects to an array like my superclass, this class makes an ObjectHolder for objects which are added to it (so they don't get retained), and adds the ObjectHolder to me. when other classes ask me for the index of an object, or ask for the object at a particular index, i'll find the relevant ObjectHolder and then return the object it's storing. +*/ + + +@interface MutNRLockDict : MutLockDict { + +} + + +- (void) setObject:(id)o forKey:(NSString *)s; +- (void) setValue:(id)v forKey:(NSString *)s; +- (id) objectForKey:(NSString *)k; +- (void) addEntriesFromDictionary:(id)otherDictionary; +- (NSArray *) allValues; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/NamedMutLockArray.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/NamedMutLockArray.h new file mode 100644 index 0000000..54e75d0 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/NamedMutLockArray.h @@ -0,0 +1,31 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "VVBasicMacros.h" +#import "MutLockArray.h" + + + + +/* + // only difference between this and MutLockArray is the "name" variable. +*/ + + + + +@interface NamedMutLockArray : MutLockArray { + NSString *name; +} + ++ (id) arrayWithCapacity:(int)c; ++ (id) create; + +- (NSComparisonResult) nameCompare:(NamedMutLockArray *)comp; + +@property (assign, readwrite) NSString *name; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/ObjectHolder.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/ObjectHolder.h new file mode 100644 index 0000000..64c397f --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/ObjectHolder.h @@ -0,0 +1,38 @@ + +#if IPHONE +#import +#else +#import +#endif + + + + +/* + created for working with the MutNRLockArray class. + + basically, you create an instance of this class and give it a reference to an + instance of an object. the instance is NOT retained- but you're now free to + pass ObjectHolder to stuff which will otherwise retain/release it without + worrying about whether the passed instance is retained/released. + + if you call a method on an instance of ObjectHolder and the ObjectHolder + class doesn't respond to that method, the instance will try to call the + method on its object. this means that working with ObjectHolder should- + theoretically, at any rate- be transparent... +*/ + + + + +@interface ObjectHolder : NSObject { + BOOL deleted; + id object; +} + ++ (id) createWithObject:(id)o; +- (id) initWithObject:(id)o; + +@property (assign,readwrite) id object; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVAssertionHandler.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVAssertionHandler.h new file mode 100644 index 0000000..47cdeef --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVAssertionHandler.h @@ -0,0 +1,31 @@ + +#if IPHONE +#import +#else +#import +#endif + + + + +#define USE_CUSTOM_ASSERTION_HANDLER \ +{ \ + NSThread *__currentThread = [NSThread currentThread]; \ + NSDictionary *__threadDict = (__currentThread==nil) ? nil : [__currentThread threadDictionary]; \ + if (__threadDict != nil) { \ + VVAssertionHandler *__newAH = [[VVAssertionHandler alloc] init]; \ + if (__newAH != nil) { \ + [__threadDict setValue:__newAH forKey:@"NSAssertionHandler"]; \ + [__newAH release]; \ + __newAH = nil; \ + } \ + } \ +} + + + +@interface VVAssertionHandler : NSAssertionHandler { + +} + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVBasicMacros.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVBasicMacros.h new file mode 100644 index 0000000..6eab4c6 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVBasicMacros.h @@ -0,0 +1,229 @@ + +// macros for checking to see if something is nil, and if it's not releasing and setting it to nil +#define VVRELEASE(item) {if (item != nil) { \ + [item release]; \ + item = nil; \ +}} +#define VVAUTORELEASE(item) {if (item != nil) { \ + [item autorelease]; \ + item = nil; \ +}} + + + +// macros for making a CGRect from an NSRect +#define NSMAKECGRECT(n) CGRectMake(n.origin.x, n.origin.y, n.size.width, n.size.height) +#define NSMAKECGPOINT(n) CGPointMake(n.x, n.y) +#define NSMAKECGSIZE(n) CGSizeMake(n.width, n.height) +// macros for making an NSRect from a CGRect +#define CGMAKENSRECT(n) NSMakeRect(n.origin.x, n.origin.y, n.size.width, n.size.height) +#define CGMAKENSSIZE(n) NSMakeSize(n.width,n.height) + +// macro for quickly printing out the dimensions of a rect (and a name/id so you can distinguish between them) +#define NSRectLog(n,r) NSLog(@"%@, (%f,%f) : %fx%f",n,r.origin.x,r.origin.y,r.size.width,r.size.height) +#define NSPointLog(n,r) NSLog(@"%@, (%f,%f)",n,r.x,r.y) +#define NSSizeLog(n,s) NSLog(@"%@, %fx%f",n,s.width,s.height) + +// macros for quickly making numbers and values +#define NUMINT(i) [NSNumber numberWithInt:i] +#define NUMFLOAT(f) [NSNumber numberWithFloat:f] +#define NUMBOOL(b) [NSNumber numberWithBool:b] +#define NUMDOUBLE(d) [NSNumber numberWithDouble:d] +#define VALSIZE(s) [NSValue valueWithSize:s] +#define VALRECT(r) [NSValue valueWithRect:r] + +// macro for quickly archiving and object +#define ARCHIVE(a) [NSKeyedArchiver archivedDataWithRootObject:a] +#define UNARCHIVE(a) [NSKeyedUnarchiver unarchiveObjectWithData:a] + +// macro for quickly making colors +#define VVDEVCOLOR(r,g,b,a) [NSColor colorWithDeviceRed:r green:g blue:b alpha:a] +#define VVCALCOLOR(r,g,b,a) [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a] + +// nice little macro for strings +#define VVSTRING(n) ((NSString *)[NSString stringWithString:n]) +#define VVFMTSTRING(f, ...) ((NSString *)[NSString stringWithFormat:f, ##__VA_ARGS__]) +#define VVDATASTRING(n) ((NSData *)[[NSString stringWithString:n] dataUsingEncoding:NSUTF8StringEncoding]) +#define VVDATAFMTSTRING(f, ...) ((NSData *)[[NSString stringWithFormat:f, ##__VA_ARGS__] dataUsingEncoding:NSUTF8StringEncoding]) + +// macros for quickly making arrays because.....well, it's the wiimote, and i'm fucking tired of typing. so there. +#define OBJARRAY(f) [NSArray arrayWithObject:f] +#define OBJSARRAY(f, ...) [NSArray arrayWithObjects:f, ##__VA_ARGS__, nil] +#define MUTARRAY [NSMutableArray arrayWithCapacity:0] + +// macros for quickly making dicts +#define OBJDICT(o,k) [NSDictionary dictionaryWithObject:o forKey:k] +#define OBJSDICT(o, ...) [NSDictionary dictionaryWithObjectsAndKeys:o,#__VA_ARGS__, nil] +#define MUTDICT [NSMutableDictionary dictionaryWithCapacity:0] + +// calculating the distance between two NSPoints or similar structs +#define POINTDISTANCE(a,b) fabs(sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y))) + + +// this is a macro for drawing an NSRect in opengl +#define GLDRAWRECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_QUADS,0,4); \ +} + + + +// this is a macro for stroking an NSRect in opengl +#define GLSTROKERECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x-0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y-0.5, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,8); \ +} +/* +#define GLSTROKERECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,8); \ +} +*/ + + +// this is a macro for drawing a line connecting two points +#define GLDRAWLINE(p,q) \ +{ \ + GLfloat vvMacroVertices[]={ \ + p.x, p.y, 0.0, \ + q.x, q.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,2); \ +} + + + +// this is a macro for drawing a diamond specified by a point and radius in opengl +#define GLDRAWDIAMOND(p,r) \ +{ \ + GLfloat vvMacroVertices[] = { \ + p.x-r, p.y, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x, p.y-r, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_QUADS,0,4); \ +} + + + +// this is a macro for stroking an diamond around a point in opengl +#define GLSTROKEDIAMOND(p,r) \ +{ \ + GLfloat vvMacroVertices[] = { \ + p.x-r, p.y, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x, p.y-r, 0.0, \ + p.x, p.y-r, 0.0, \ + p.x-r, p.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINE_LOOP,0,8); \ +} + + +// this is a macro for drawing a texture of a specified size in a rect +#define GLDRAWTEXSIZEDINRECT(t,s,r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0,s.height, \ + s.width,s.height, \ + s.width,0.0, \ + 0.0,0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWFLIPPEDTEXSIZEDINRECT(t,s,r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0, 0.0, \ + s.width, 0.0, \ + s.width, s.height, \ + 0.0, s.height}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWTEXSIZEDINRECTATZ(t,s,r,z) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, z, \ + r.origin.x, r.origin.y+r.size.height, z}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0,s.height, \ + s.width,s.height, \ + s.width,0.0, \ + 0.0,0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWFLIPPEDTEXSIZEDINRECTATZ(t,s,r,z) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, z, \ + r.origin.x, r.origin.y+r.size.height, z}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0, 0.0, \ + s.width, 0.0, \ + s.width, s.height, \ + 0.0, s.height}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVBasics.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVBasics.h new file mode 100644 index 0000000..b36c65a --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVBasics.h @@ -0,0 +1,55 @@ + +#import "VVBasicMacros.h" + +#import "VVThreadLoop.h" +#import "VVAssertionHandler.h" +#import "VVStopwatch.h" +#import "ObjectHolder.h" +#import "MutLockArray.h" +#import "MutLockDict.h" +#import "MutNRLockArray.h" +#import "MutNRLockDict.h" +#import "NamedMutLockArray.h" + +#if !IPHONE + #import "VVCURLDL.h" + #import "VVSprite.h" + #import "VVSpriteManager.h" + #import "VVSpriteView.h" + #import "VVSpriteControl.h" + #import "VVSpriteControlCell.h" + #import "VVSpriteGLView.h" + #import "VVCrashReporter.h" + //#import "NSHostAdditions.h" +#endif + +/* + the following stuff is for doxygen +*/ + +/*! +\mainpage + +\htmlonly + + + +Introduction +

    +VVBasics is an Objective-c framework with a number of classes which perform functions that i need regularly- but, for whatever reason, aren't provided by the stock frameworks. Expect pretty much everything to link against this framework for one reason or another- macros, useful classes, etc- and expect this framework to continuously grow as I start to open-source more and more of my bag of tricks. +

    + +\endhtmlonly +*/ diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCURLDL.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCURLDL.h new file mode 100644 index 0000000..39d4c9b --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCURLDL.h @@ -0,0 +1,72 @@ + +/* + this class offers a very limited, very simple cocoa interface to libcurl for doing extremely + basic http transfer ops + + basically, this class exists because at this time NSURLConnection is problematic and + top-heavy, and i wanted an easy, effective, and reliable interface for handling the extremely + limited set of http data transfer operations required by my frameworks/apps. + + this class was meant to be used as a one-shot throwaway; that is, you're meant to create an + instance of this class which will be auto-released as soon as the autorelease pool is + popped. the instance you create is meant to be used once, and then thrown away- THIS WILL + PROBABLY BREAK IF YOU TRY TO USE THE SAME INSTANCE TO PERFORM MORE THAN ONE TRANSFER. +*/ + + +#import +#import + + + + +@protocol VVCURLDLDelegate +- (void) dlFinished:(id)h; +@end + + + + +@interface VVCURLDL : NSObject { + NSString *urlString; + CURL *curlHandle; + + NSMutableData *responseData; + + struct curl_slist *headerList; // nil by default- if non-nil, supplied to the handle as CURLOPT_HTTPHEADER + NSMutableData *postData; // if non-nil, simply posted as CURLOPT_POSTFIELDS + struct curl_httppost *firstFormPtr; // if postData was nil but this isn't, posted as CURLOPT_HTTPPOST + struct curl_httppost *lastFormPtr; + + BOOL returnOnMain; + BOOL performing; + CURLcode err; +} + ++ (id) createWithAddress:(NSString *)a; +- (id) initWithAddress:(NSString *)a; + +- (void) perform; +- (void) performAsync:(BOOL)as withDelegate:(id )d; +- (void) _performAsyncWithDelegate:(id )d; +- (void) _performWithDelegate:(id )d; + +//- (struct curl_slist *) headerList; +//- (struct curl_httppost *) firstFormPtr; +//- (struct curl_httppost *) lastFormPtr; +- (void) appendDataToPOST:(NSData *)d; +- (void) appendStringToPOST:(NSString *)s; + +- (void) writePtr:(void *)ptr size:(size_t)s; + +@property (assign,readwrite) struct curl_slist *headerList; +@property (assign,readwrite) struct curl_httppost *firstFormPtr; +@property (assign,readwrite) struct curl_httppost *lastFormPtr; +@property (assign,readwrite) BOOL returnOnMain; +@property (readonly) NSMutableData *responseData; +@property (readonly) NSString *responseString; +@property (readonly) CURLcode err; + +@end + +size_t vvcurlWriteFunction(void *ptr, size_t size, size_t nmemb, void *stream); diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporter.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporter.h new file mode 100644 index 0000000..0dc9c90 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporter.h @@ -0,0 +1,101 @@ + +#import +#import +#include "AvailabilityMacros.h" +#import +#import +#import "VVCURLDL.h" +#import "MutLockArray.h" + + + + +/// The crash reporter's delegate must adhere to this protocol +/*! + This protocol exists largely because it's conceivable that objects will want to know when the crash reporter- which uploads asynchronously- has finished sending its data to the remote server. +*/ +@protocol OldVVCrashReporterDelegate +- (void) crashReporterCheckDone; +@end + +@protocol VVCrashReporterDelegate +- (void) crashReporterCheckDone:(BOOL)foundLogs; // "new"- 'f' designates whether crash reports were found or not +@end + + + +/// Simple class which automatically uploads crash logs and other relevant diagnostic information automatically made available by os x to a remote server. +/*! +it's been my experience that most apps crash much more frequently on end-users than the app's developers would guess. the simplest and easiest way to improve the end-user's experience is to have the application check their machine for crash logs- which are generated automatically by os x whenever an application crashes- and send them to the developer. + +this class exists so i have a really easy way to make my apps send their crash logs to me; the goal here is to make it as easy as possible to get all the information i need to troubleshoot a problem with as little work on the user's part as possible. it also sends a basic system profile, anything the app- and ONLY the app, not other apps- recently printed to the console log, and optional description/email fields to facilitate communication directly with the user. this data is then uploaded to a given URL using an HTTP POST. + +on the server side, i use a PHP page which sanitizes the POST data (i can't stress how important this step is) and works with it. i've included a sample PHP page that simply dumps the received data to a file on disk (and optionally emails someone) with this project. + +HOW TO USE THIS CLASS: + + 1)- create an instance of this class + + 2)- set the instance's delegate, uploadURL, and developerEmail. these are necessary! + + 3)- call "check" on the instance. when it's done, it calls "crashReporterCheckDone" on the + delegate. that's it- you're done. +*/ + +@interface VVCrashReporter : NSObject { + NSString *uploadURL; // does NOT includes http:// + NSString *developerEmail; + id delegate; // must respond to VVCrashReporterDelegate protocol + MutLockArray *crashLogArray; + NSMutableDictionary *systemProfilerDict; + NSString *consoleLog; + int jobSize; // used to update progress indicator/label + int jobCurrentIndex; // used to update progress indicator/label + int currentCrashLogTimeout; // countdown for timeout of sending/receiving data for a specific crash log + NSTimer *currentCrashLogTimer; + + IBOutlet NSWindow *window; + IBOutlet NSButton *replyButton; + IBOutlet NSView *emailFieldHolder; + IBOutlet NSTextField *emailField; + IBOutlet NSTextView *descriptionField; + IBOutlet NSTextField *submittingLabel; // non-editable. 'submitting', 'getting machine profile', etc. + IBOutlet NSProgressIndicator *progressIndicator; // indicates progress through all crash logs to be submitted + IBOutlet NSTextField *countdownLabel; // non-editable; countdown so user knows app hasn't hung + + NSNib *theNib; + NSArray *nibTopLevelObjects; +} + ++ (NSString *) _stringForSystemProfilerDataType:(NSString *)t; + +/// This is the main method- when you call 'check', the crash reporter looks for crash logs, gets a basic system profile, and collects anything your applications has dumped to the console log. +- (void) check; +- (void) openCrashReporter; +- (IBAction) replyButtonClicked:(id)sender; +- (IBAction) doneClicked:(id)sender; +- (void) sendACrashLog; +- (void) closeCrashReporter; + +- (NSString *) _nibName; +- (BOOL) _assembleCrashLogs; // assembles the array of crash logs, returns a YES if logs were found and have to be sent in +- (NSString *) _consoleLogString; +- (NSMutableDictionary *) _systemProfilerDict; + +- (void) updateCrashLogTimeout:(NSTimer *)t; + +// VVCURLDLDelegate method- this class will be the delegate of multiple VVCURLDL instances +- (void) dlFinished:(id)h; + +/// Sets the developer email address; this is displayed if the user has a problem connecting to the internet/the server the crash reporter is supposed to be connecting to +- (void) setDeveloperEmail:(NSString *)n; +- (NSString *) developerEmail; +/// This is the URL of the php/cgi/etc. page which the crash data will be POSTed to +- (void) setUploadURL:(NSString *)n; +- (NSString *) uploadURL; + +/// The crash reporter's delegate is notified when the check has completed +@property (assign,readwrite) id delegate; +@property (readonly) NSButton *replyButton; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporterDescriptionField.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporterDescriptionField.h new file mode 100644 index 0000000..f39f0f5 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporterDescriptionField.h @@ -0,0 +1,15 @@ +#import + + +/* + this class exists solely to prevent users from pasting or dragging huge amounts of text (like + crash/console logs!) into the description field of the crash reporter. sounds weird, but trust + me- it's necessary. +*/ + + +@interface VVCrashReporterDescriptionField : NSTextView { + +} + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporterEmailField.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporterEmailField.h new file mode 100644 index 0000000..fb883f8 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVCrashReporterEmailField.h @@ -0,0 +1,14 @@ +#import +#import + + +/* + this class exists solely to prevent users from pasting huge amounts of text into the email field +*/ + + +@interface VVCrashReporterEmailField : NSTextField { + +} + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSprite.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSprite.h new file mode 100644 index 0000000..34246be --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSprite.h @@ -0,0 +1,104 @@ + +/* Always with the sprites... + + sprite |sprīt| + noun + 1 an elf or fairy. + 2 a computer graphic that may be moved on-screen and otherwise manipulated as a single entity. + 3 a faint flash, typically red, sometimes emitted in the upper atmosphere over a thunderstorm owing to the collision of high-energy electrons with air molecules. + ORIGIN Middle English : alteration of sprit, a contraction of spirit . */ + +#import +#include + + + + +typedef enum _VVSpriteEventType { + VVSpriteEventNULL = 0, + VVSpriteEventDown = 1, + VVSpriteEventDrag = 2, + VVSpriteEventUp = 3, + VVSpriteEventDouble = 4, + VVSpriteEventRightDown = 5, + VVSpriteEventRightUp = 6 +} VVSpriteEventType; + + + + +@interface VVSprite : NSObject { + BOOL deleted; + BOOL locked; // whether or not i should respond to mouse input. DOESN'T AFFECT ANYTHING IN THIS CLASS! variable exists for the user's convenience, and is otherwise superfluous! + BOOL hidden; // whether or not the sprite should draw. DOESN'T AFFECT ANYTHING IN THIS CLASS! variable exists for the user's convenience, and is otherwise superfluous! + BOOL dropFromMultiSpriteActions; // only valid if sprite manager's allowMultiSpriteInteraction' is YES. NO by default. if YES, then if you mousedown on this and any other sprite, this sprite gets dropped from the mousedown. used for allowing multi-sprite interaction to prevent clicks from hitting "background" sprites (which have this set to YES) + long spriteIndex; + id manager; // the VVSpriteManager i exist within- NOT retained! + id delegate; // NOT retained! + SEL drawCallback; // delegate method; passed a ptr to this sprite! + SEL actionCallback; // delegate method; passed a ptr to this sprite! + + NSRect rect; // the sprite i'm tracking + NSBezierPath *bezierPath; // retained. nil by default, set to nil if you call setRect: on this instance. if non-nil, this path is used instead of "rect" for determining mouse action and drawing intersection! + OSSpinLock pathLock; + + int lastActionType; // updated whenever an action is received + NSPoint lastActionCoords; // coords at which last action took place + BOOL lastActionInBounds; // whether or not the last action was within my bounds + BOOL trackingFlag; // whether or not i'm tracking stuff + NSPoint mouseDownCoords; // absolute coords of mousedown + NSPoint lastActionDelta; // change between most-recently-received action coords and last received coords + NSPoint mouseDownDelta; // change between mousedown loc and most-recently received coords + long mouseDownModifierFlags; + + id userInfo; // RETAINED! for storing a random thing... + id NRUserInfo; // NOT RETAINED! for storing something that *shouldn't* be retained... + id safeString; // nil on init- many sprites need formatted text, this is a convenience variable... +} + ++ (id) createWithRect:(NSRect)r inManager:(id)m; +- (id) initWithRect:(NSRect)r inManager:(id)m; + +- (void) prepareToBeDeleted; + +- (BOOL) checkPoint:(NSPoint)p; +- (BOOL) checkRect:(NSRect)r; + +- (void) receivedEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m; +- (void) mouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) rightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) rightMouseUp:(NSPoint)p; +- (void) mouseDragged:(NSPoint)p; +- (void) mouseUp:(NSPoint)p; +- (void) draw; + +- (void) bringToFront; +- (void) sendToBack; + +@property (assign, readwrite) BOOL locked; +@property (assign, readwrite) BOOL hidden; +@property (assign, readwrite) BOOL dropFromMultiSpriteActions; +@property (readonly) long spriteIndex; +@property (readonly) id manager; +@property (assign, readwrite) id delegate; +@property (assign, readwrite) SEL drawCallback; +@property (assign, readwrite) SEL actionCallback; + +@property (assign, readwrite) NSRect rect; +//@property (retain,readwrite) NSBezierPath *path; +- (void) setBezierPath:(NSBezierPath *)n; +- (NSBezierPath *) safelyGetBezierPath; +- (NSRect) spriteBounds; // special method- either returns "rect" or (if path is non-nil) the bounds of the bezier path! +@property (readonly) VVSpriteEventType lastActionType; +@property (readonly) NSPoint lastActionCoords; +@property (readonly) BOOL lastActionInBounds; +@property (readonly) BOOL trackingFlag; +@property (readonly) NSPoint mouseDownCoords; +@property (readonly) NSPoint lastActionDelta; +@property (readonly) NSPoint mouseDownDelta; +@property (readonly) long mouseDownModifierFlags; +@property (assign,readwrite) id userInfo; +@property (assign,readwrite) id NRUserInfo; +@property (assign,readwrite) id safeString; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteControl.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteControl.h new file mode 100644 index 0000000..2ed78b7 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteControl.h @@ -0,0 +1,49 @@ + +#import +#import "VVSpriteManager.h" +#include + + + + +extern int _maxSpriteControlCount; +extern int _spriteControlCount; + + + + +@interface VVSpriteControl : NSControl { + BOOL deleted; + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + + OSSpinLock propertyLock; + NSEvent *lastMouseEvent; + NSColor *clearColor; + BOOL drawBorder; + NSColor *borderColor; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED +} + +- (void) generalInit; + +- (void) prepareToBeDeleted; + +- (void) finishedDrawing; + +- (void) updateSprites; + +@property (readonly) BOOL deleted; +@property (readonly) VVSpriteManager *spriteManager; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) BOOL mouseIsDown; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteControlCell.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteControlCell.h new file mode 100644 index 0000000..fc8e151 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteControlCell.h @@ -0,0 +1,11 @@ + +#import + + + + +@interface VVSpriteControlCell : NSActionCell { + +} + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteGLView.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteGLView.h new file mode 100644 index 0000000..a47b6a2 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteGLView.h @@ -0,0 +1,82 @@ + +#import +#import "VVSpriteManager.h" +#import +#import +#import + + + + +typedef enum { + VVFenceModeEveryRefresh = 0, // every time a display callback runs, drawing commands are sent to the GPU. + VVFenceModeDBSkip = 1, // the apple gl fence extension is used to make sure that drawing commands for the back buffer have finished before more drawing commands are sent to the back buffer (the front buffer can receive commands, though) + VVFenceModeSBSkip = 2, // the apple gl fence extension is used to make sure that drawing commands for the single buffer have finished before more drawing commands are sent to it + VVFenceModeFinish = 3 // glFinish is used instead of glFlush +} VVFenceMode; + +typedef enum { + VVFlushModeGL = 0, // glFlush() + VVFlushModeCGL = 1, // CGLFlushDrawable() + VVFlushModeNS = 2, // [context flushBuffer] + VVFlushModeApple = 3, // glFlushRenderAPPLE() + VVFlushModeFinish = 4 // glFinish() +} VVFlushMode; + + + + +@interface VVSpriteGLView : NSOpenGLView { + BOOL deleted; + + BOOL initialized; + //BOOL needsReshape; + pthread_mutex_t glLock; + + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + NSEvent *lastMouseEvent; + GLfloat clearColor[4]; + BOOL drawBorder; + GLfloat borderColor[4]; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED + + VVFlushMode flushMode; + + VVFenceMode fenceMode; + GLuint fenceA; + GLuint fenceB; + BOOL waitingForFenceA; + BOOL fenceADeployed; + BOOL fenceBDeployed; + OSSpinLock fenceLock; +} + +- (void) generalInit; +- (void) prepareToBeDeleted; + +- (void) initializeGL; +- (void) finishedDrawing; +//- (void) reshapeGL; +- (void) updateSprites; + +- (void) _lock; +- (void) _unlock; +//- (void) lockSetOpenGLContext:(NSOpenGLContext *)n; + +@property (readonly) BOOL deleted; +@property (assign,readwrite) BOOL initialized; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) VVSpriteManager *spriteManager; +@property (readonly) BOOL mouseIsDown; +@property (assign, readwrite) VVFlushMode flushMode; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteManager.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteManager.h new file mode 100644 index 0000000..b8f0dc4 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteManager.h @@ -0,0 +1,57 @@ + +#import +#import "VVSprite.h" +#import "MutLockArray.h" + + + + +@interface VVSpriteManager : NSObject { + BOOL deleted; + BOOL allowMultiSpriteInteraction; // NO by default- if YES, clicking/dragging/etc works with multiple sprites! + BOOL multiSpriteExecutesOnMultipleSprites; // only relevant if multi-sprite interaction is YES. this is NO by default- if it's YES all sprites in "spritesInUse" will receive an action callback when any of them get an action method. if this is NO then only the sprite that "caught" the interaction will receive an action callback! + MutLockArray *spriteArray; // searched from beginning to end, so order is like z-index! + VVSprite *spriteInUse; // array of VVSprite objects currently tracking drag info + MutLockArray *spritesInUse; // ONLY VALID IF MULTI SPRITE INTERACTION IS YES! array of VVSprite o + long spriteIndexCount; +} + +- (void) prepareToBeDeleted; + +// return YES if the mousedown occurred on one or more sprites +- (BOOL) receivedMouseDownEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m visibleOnly:(BOOL)v; +- (void) receivedOtherEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m; +- (BOOL) localMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localVisibleMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localRightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localVisibleRightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) localRightMouseUp:(NSPoint)p; +- (void) localMouseDragged:(NSPoint)p; +- (void) localMouseUp:(NSPoint)p; +- (void) terminatePresentMouseSession; // call this and sprites will stop responding to the mouse until it is clicked again + +- (id) newSpriteAtBottomForRect:(NSRect)r; +- (id) newSpriteAtTopForRect:(NSRect)r; +- (long) getUniqueSpriteIndex; + +- (VVSprite *) spriteAtPoint:(NSPoint)p; +- (VVSprite *) visibleSpriteAtPoint:(NSPoint)p; +- (VVSprite *) spriteForIndex:(long)i; +- (void) removeSpriteForIndex:(long)i; +- (void) removeSprite:(id)z; +- (void) removeSpritesFromArray:(NSArray *)array; +- (void) removeAllSprites; +//- (void) moveSpriteToFront:(VVSprite *)z; + +- (void) draw; +- (void) drawRect:(NSRect)r; + +- (VVSprite *) spriteInUse; +- (void) setSpriteInUse:(VVSprite *)z; + +@property (assign,readwrite) BOOL allowMultiSpriteInteraction; +@property (assign,readwrite) BOOL multiSpriteExecutesOnMultipleSprites; +@property (readonly) MutLockArray *spriteArray; +@property (readonly) MutLockArray *spritesInUse; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteView.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteView.h new file mode 100644 index 0000000..a8d17a0 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVSpriteView.h @@ -0,0 +1,48 @@ + +#import +#import "VVSpriteManager.h" +#include + + + + +extern int _spriteViewCount; + + + + +@interface VVSpriteView : NSView { + BOOL deleted; + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + + OSSpinLock propertyLock; + NSEvent *lastMouseEvent; + NSColor *clearColor; + BOOL drawBorder; + NSColor *borderColor; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED +} + +- (void) generalInit; + +- (void) prepareToBeDeleted; + +- (void) finishedDrawing; + +- (void) updateSprites; + +@property (readonly) BOOL deleted; +@property (readonly) VVSpriteManager *spriteManager; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) BOOL mouseIsDown; + +@end diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVStopwatch.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVStopwatch.h new file mode 100644 index 0000000..a1f9c35 --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVStopwatch.h @@ -0,0 +1,35 @@ + +#if IPHONE +#import +#else +#import +#endif +#include +#import + + + +/// This class is used to measure how long it takes to do things; much easier to work with than NSDate. + +@interface VVStopwatch : NSObject { + struct timeval startTime; + OSSpinLock timeLock; +} + +/// Returns an auto-released instance of VVStopwatch; the stopwatch is started on creation. ++ (id) create; + +/// Starts the stopwatch over again +- (void) start; +/// Returns a float representing the time (in seconds) since the stopwatch was started +- (double) timeSinceStart; +/// Sets the stopwatch's starting time as an offset to the current time +- (void) startInTimeInterval:(NSTimeInterval)t; +/// Populates the passed timeval struct with the current timeval +- (void) copyStartTimeToTimevalStruct:(struct timeval *)dst; +/// Populates the starting time with the passed timeval struct +- (void) setStartTimeStruct:(struct timeval *)src; + +@end + +void populateTimevalWithFloat(struct timeval *tval, double secVal); diff --git a/atemOSC/VVBasics.framework/Versions/Current/Headers/VVThreadLoop.h b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVThreadLoop.h new file mode 100644 index 0000000..0a6342f --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Headers/VVThreadLoop.h @@ -0,0 +1,63 @@ + +#if IPHONE +#import +#else +#import +#endif +#include +#import +#include + + + + +/// Simple class for spawning a thread which executes at a specified interval- simpler and easier to work with than NSThread/NSTimer in multi-threaded programming environments. +/*! +When started, an instance of this class will spawn a thread and repeatedly execute a method on that thread. If it was passed a target and selector on creation, the selector will be called on the target every time the thread executes. If it's more convenient to subclass VVThreadLoop and work with your custom subclass, leave the target/selector nil and VVThreadLoop will call "threadProc" on itself- just override this method (it's empty anyway) in your subclass and do whatever you want in there. + +You can change the execution interval, and VVThreadLoop also examines how long it takes to execute your code and adjusts in an attempt to ensure that the interval is accurate (sleep-time is interval-duration minus proc-execution-duration) +*/ + + + + +@interface VVThreadLoop : NSObject { + double interval; + double maxInterval; + BOOL running; + BOOL bail; + BOOL paused; + BOOL executingCallback; + + OSSpinLock valLock; // ONLY used for quickly accessing 'running', 'bail', 'paused', and 'executingCallback' in a threadsafe fashion + + id targetObj; //! + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/atemOSC/VVBasics.framework/Versions/Current/Resources/Info.plist b/atemOSC/VVBasics.framework/Versions/Current/Resources/Info.plist new file mode 100644 index 0000000..29822ba --- /dev/null +++ b/atemOSC/VVBasics.framework/Versions/Current/Resources/Info.plist @@ -0,0 +1,38 @@ + + + + + BuildMachineOSBuild + 11E53 + CFBundleDevelopmentRegion + English + CFBundleExecutable + VVBasics + CFBundleGetInfoString + 156 + CFBundleIdentifier + com.vidvox.VVBasics + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 156 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E2002 + DTPlatformVersion + GM + DTSDKBuild + 10K549 + DTSDKName + macosx10.6 + DTXcode + 0432 + DTXcodeBuild + 4E2002 + + diff --git a/atemOSC/VVBasics.framework/Versions/Current/Resources/VVCrashReporter.nib b/atemOSC/VVBasics.framework/Versions/Current/Resources/VVCrashReporter.nib new file mode 100644 index 0000000..4c7b505 Binary files /dev/null and b/atemOSC/VVBasics.framework/Versions/Current/Resources/VVCrashReporter.nib differ diff --git a/atemOSC/VVBasics.framework/Versions/Current/VVBasics b/atemOSC/VVBasics.framework/Versions/Current/VVBasics new file mode 100755 index 0000000..e109f6a Binary files /dev/null and b/atemOSC/VVBasics.framework/Versions/Current/VVBasics differ diff --git a/atemOSC/VVBasics.framework/headers/MutLockArray.h b/atemOSC/VVBasics.framework/headers/MutLockArray.h new file mode 100644 index 0000000..deaf284 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/MutLockArray.h @@ -0,0 +1,185 @@ + +#if IPHONE +#import +#else +#import +#endif +#import + + + +/// Similar to NSMutableArray, but thread-safe. Internally, uses an NSMutableArray and a rwlock. +/* +This class exists because NSMutableArray is not thread-safe by default: if you call methods on it from two different threads at the same time, it will try to execute both, often crashing in the process. I found myself writing a lot of lock/array pairs, so simplified everything by combining them into a single class. MutLockArray has methods which allow you to work with a mutable array in a transparent and thread-safe manner- it will automatically establish the read-/write-locks necessary to perform the relevant task. By avoiding the "lock" methods, you can also work with the array without performing any locking- so you can get a read-/write-lock, perform a number of actions, and then unlock. + +It is important to remember, when working with it, that MutLockArray is NOT a subclass of NSMutableArray; rather, it is a subclass of NSObject with an instance of an NSMutableArray and a rwlock for working with it safely. This means that you can't pass an instance of MutLockArray to anything which is expecting to be passed an NSMutableArray- internally, apple's frameworks will probably be doing some dark voodoo bullshit which will result in a spectacular failure. If you want to work with an actual NSMutableArray, check out the "array", "createArrayCopy", and "lockCreateArrayCopy" methods below. + +...and remember- when looking for stuff in an NSMutableArray, the array will use the "isEqualTo:" comparator method, which is slower than comparing the address of two pointers. if you know the pointer address hasn't changed (if you're *not* working with NSStrings), use the "indexOfIdenticalPtr", "removeIdenticalPtr", etc. methods to work with the array. +*/ + +@interface MutLockArray : NSObject { + NSMutableArray *array; + pthread_rwlock_t arrayLock; +} + +/// Creates and returns an auto-released MutLockArray with a given capacity. The capacity may be 0. ++ (id) arrayWithCapacity:(NSUInteger)c; +/// Inits and returns a MutLockArray with a given capacity; the capacity may be 0. +- (id) initWithCapacity:(NSUInteger)c; +- (id) init; + +/// Establishes a read-lock for the array; multiple read locks may exist simultaneously (if it's not changing, anything can look at the contents of the array). This method does not return until it has been able to get the lock. +- (void) rdlock; +- (BOOL) tryRdLock; // returns YES if i got a read-lock successfully! +/// Establishes a write-lock for the array. Only one write-lock may exist at any given time, and all read-locks must be relinquished before the write-lock may be established (if you're going to change the array, nothing else can be changing or observing it). +- (void) wrlock; +/// Unlocks the array. +- (void) unlock; + +/// Returns the NSMutableArray with everything in it. This returns the actual array, so be careful- it's possible to do something which ISN'T threadsafe with this... +- (NSMutableArray *) array; +/// Returns an NSMutableArray which was created by calling "mutableCopy" on my array. Again, it's possible to do something which ISN'T threadsafe by calling this... +- (NSMutableArray *) createArrayCopy; +/// Returns an NSMutableArray which was created while a read-lock was established; this is threadsafe. +- (NSMutableArray *) lockCreateArrayCopy; + +/// Calls "addObject" on my array; not threadsafe. +- (void) addObject:(id)o; +/// Establishes a write-lock, then calls "addObject" on self; threadsafe. +- (void) lockAddObject:(id)o; +/// Calls "addObjectsFromArray" on my array; not threadsafe. +- (void) addObjectsFromArray:(id)a; +/// Establishes a write-lock, then calls "addObjectsFromArray" on self; threadsafe. +- (void) lockAddObjectsFromArray:(id)a; +/// Calls "addObjectsFromArray" on my array; not threadsafe. +- (void) replaceWithObjectsFromArray:(id)a; +/// Establishes a write-lock, then calls "replaceWithObjectsFromArray" on self; threadsafe. +- (void) lockReplaceWithObjectsFromArray:(id)a; +/// Calls "insertObject:atIndex:" on my array; not threadsafe. +- (void) insertObject:(id)o atIndex:(NSUInteger)i; +/// Establishes a write-lock, then calls "insertObject:atIndex:" on self; threadsafe. +- (void) lockInsertObject:(id)o atIndex:(NSUInteger)i; +/// Calls "removeAllObjects" on my array; not threadsafe. +- (void) removeAllObjects; +/// Establishes a write-lock, then calls "removeAllObjects" on self; threadsafe. +- (void) lockRemoveAllObjects; +/// Calls "objectAtIndex:0" on my array; not threadsafe. +- (id) firstObject; +/// Establishes a read-lock, then calls "firstObject" on self; threadsafe +- (id) lockFirstObject; +/// Calls "removeObjectAtIndex:0" on my array; not threadsafe +- (void) removeFirstObject; +/// Establishes a write-lock, then calls "removeFirstObject" on self; threadsafe. +- (void) lockRemoveFirstObject; +/// Calls "lastObject" on my array; not threadsafe. +- (id) lastObject; +/// Establishes a read-lock, then calls "lastObject" on self; threadsafe. +- (id) lockLastObject; +/// Calls "removeLastObject" on my array; not threadsafe. +- (void) removeLastObject; +/// Establishes a write-lock, then calls "removeLastObject" on self; threadsafe. +- (void) lockRemoveLastObject; +/// Calls "removeObject:" on my array; not threadsafe. +- (void) removeObject:(id)o; +/// Establishes a write-lock, then calls "removeObject:" on self; threadsafe. +- (void) lockRemoveObject:(id)o; +/// Calls "removeObjectAtIndex:" on my array; not threadsafe. +- (void) removeObjectAtIndex:(NSUInteger)i; +/// Establishes a write-lock, then calls "removeObjectAtIndex:" on self; threadsafe. +- (void) lockRemoveObjectAtIndex:(NSUInteger)i; +/// Calls "removeObjectsAtIndexes:" on my array; not threadsafe. +- (void) removeObjectsAtIndexes:(NSIndexSet *)i; +/// Establishes a write-lock, then calls "removeObjectsAtIndexes:" on self; threadsafe. +- (void) lockRemoveObjectsAtIndexes:(NSIndexSet *)i; +/// Calls "removeObjectsInArray:" on my array; not threadsafe. +- (void) removeObjectsInArray:(NSArray *)otherArray; +/// Establishes a write-lock, then calls "removeObjectsInArray:" on self; threadsafe. +- (void) lockRemoveObjectsInArray:(NSArray *)otherArray; +/// Calls "removeIdenticalPtrsInArray:" on my array; not threadsafe +- (void) removeIdenticalPtrsInArray:(NSArray *)a; +/// Establishes a write-lock, then calls "removeIdenticalPtrsInArray:" on self; threadsafe. +- (void) lockRemoveIdenticalPtrsInArray:(NSArray *)a; + +/// Calls "replaceObjectsAtIndexes:withObjects" on my array; not threadsafe. +- (void) replaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects; +// Establishes a write-lock, then calls "replaceObjectsAtIndexes:withObjects on self; threadsafe +- (void) lockReplaceObjectsAtIndexes:(NSIndexSet *)indexes withObjects:(NSArray *)objects; + +/// Calls "valueForKey:" on my array; not threadsafe. +- (id) valueForKey:(NSString *)key; +/// Establishes a read-lock, then calls "valueForKey:" on self; threadsafe. +- (id) lockValueForKey:(NSString *)key; + + +/// Calls "containsObject:" on my array; not threadsafe. +- (BOOL) containsObject:(id)o; +/// Establishes a read-lock, then calls "containsObject:" on self; threadsafe. +- (BOOL) lockContainsObject:(id)o; +/// Calls "objectAtIndex:" on my array; not threadsafe. +- (id) objectAtIndex:(NSUInteger)i; +/// Establishes a read-lock, then calls "objectAtIndex:" on self; threadsafe. +- (id) lockObjectAtIndex:(NSUInteger)i; +/// Calls "objectsAtIndexes:" on my array; not threadsafe. +- (NSArray *) objectsAtIndexes:(NSIndexSet *)indexes; +/// Establishes a read-lock, then calls "objectsAtIndexes:" on self; threadsafe. +- (NSArray *) lockObjectsAtIndexes:(NSIndexSet *)indexes; +/// Calls "indexOfObject:" on my array; not threadsafe. +- (NSUInteger) indexOfObject:(id)o; +/// Establishes a read-lock, then calls "indexOfObject:" on self; threadsafe. +- (NSUInteger) lockIndexOfObject:(id)o; + + +/// Enumerates through my array- compares the address of each item in the array to the passed pointer. Unlike NSMutableArray, this method does NOT call isEqualTo:, it's just a simple == operator. +- (BOOL) containsIdenticalPtr:(id)o; +/// Establishes a read-lock, then calls "containsIdenticalPtr:" on self; threadsafe. +- (BOOL) lockContainsIdenticalPtr:(id)o; +/// Enumerates through my array- compares the address of each item in the array to the passed pointer. Unlike NSMutableArray, this method does NOT call isEqualTo:, it's just a simple == operator. +- (long) indexOfIdenticalPtr:(id)o; +/// Establishes a read-lock, then calls "indexOfIdenticalPtr:" on self; threadsafe. +- (long) lockIndexOfIdenticalPtr:(id)o; +/// Locates an item in my array by enumerating through it and comparing the address of each item in the array to the passed ptr, and then deletes the matching item from the array; not threadsafe. +- (void) removeIdenticalPtr:(id)o; +/// Establishes a write-lock, then calls "removeIdenticalPtr:" on self; threadsafe. +- (void) lockRemoveIdenticalPtr:(id)o; + +// Calls "filteredArrayUsingPredicate:" on my array; not threadsafe +- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate; +// Establishes a read-lock, then calls "filteredArrayUsingPredicate:" on self; threadsafe +- (NSArray *) lockFilteredArrayUsingPredicate:(NSPredicate *)predicate; + +/// Calls "makeObjectsPerformSelector:" on my array; not threadsafe. +- (void) makeObjectsPerformSelector:(SEL)s; +/// Establishes a read-lock, then calls "makeObjectsPerformSelector:" on self; threadsafe. +- (void) lockMakeObjectsPerformSelector:(SEL)s; +/// Calls "makeObjectsPerformSelector:withObject:" on my array; not threadsafe. +- (void) makeObjectsPerformSelector:(SEL)s withObject:(id)o; +/// Establishes a read-lock, then calls "makeObjectsPerformSelector:withObject:" on self; threadsafe. +- (void) lockMakeObjectsPerformSelector:(SEL)s withObject:(id)o; + + + +/* +- (void) makeCopyPerformSelector:(SEL)s; +- (void) lockMakeCopyPerformSelector:(SEL)s; +- (void) makeCopyPerformSelector:(SEL)s withObject:(id)o; +- (void) lockMakeCopyPerformSelector:(SEL)s withObject:(id)o; +*/ + + + +/// Calls "sortUsingSelector:" on my array; not threadsafe. +- (void) sortUsingSelector:(SEL)s; +/// Establishes a write-lock, then calls "sortUsingSelector:" on self; threadsafe. +- (void) lockSortUsingSelector:(SEL)s; + +/// Calls "sortUsingDescriptors:" on my array; not threadsafe. +- (void) sortUsingDescriptors:(NSArray *)descriptors; +/// Establishes a write-lock, then calls "sortUsingDescriptors:" on self; threadsafe. +- (void) lockSortUsingDescriptors:(NSArray *)descriptors; + +- (NSEnumerator *) objectEnumerator; +- (NSEnumerator *) reverseObjectEnumerator; +- (long) count; +- (long) lockCount; + +@end diff --git a/atemOSC/VVBasics.framework/headers/MutLockDict.h b/atemOSC/VVBasics.framework/headers/MutLockDict.h new file mode 100644 index 0000000..e162293 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/MutLockDict.h @@ -0,0 +1,56 @@ + +#if IPHONE +#import +#else +#import +#endif +#import + + + +/// MutLockDict is a thread-safe version of NSMutableDictionary. +/*! +This class exists because NSMutableDictionary is not thread-safe by default: if you call methods on it from two different threads at the same time, it will try to execute both, often crashing in the process. This class has methods which allow you to work with a mutable dictionary in a transparent and thread-safe manner. +*/ + +@interface MutLockDict : NSObject { + NSMutableDictionary *dict; + pthread_rwlock_t dictLock; +} + ++ (id) dictionaryWithCapacity:(NSUInteger)c; ++ (id) dictionaryWithDict:(NSDictionary *)d; +- (id) initWithCapacity:(NSUInteger)c; + +- (void) rdlock; +- (void) wrlock; +- (void) unlock; + +- (NSMutableDictionary *) dict; +- (NSMutableDictionary *) createDictCopy; +- (NSMutableDictionary *) lockCreateDictCopy; + +- (void) setObject:(id)o forKey:(NSString *)s; +- (void) lockSetObject:(id)o forKey:(NSString *)s; +- (void) setValue:(id)v forKey:(NSString *)s; +- (void) lockSetValue:(id)v forKey:(NSString *)s; +- (void) removeAllObjects; +- (void) lockRemoveAllObjects; +- (id) objectForKey:(NSString *)k; +- (id) lockObjectForKey:(NSString *)k; +- (void) removeObjectForKey:(NSString *)k; +- (void) lockRemoveObjectForKey:(NSString *)k; +- (void) addEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (void) lockAddEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (NSArray *) allKeys; +- (NSArray *) lockAllKeys; +- (NSArray *) allValues; +- (NSArray *) lockAllValues; + +- (void) lockMakeObjectsPerformSelector:(SEL)s; +- (void) makeObjectsPerformSelector:(SEL)s; + +- (NSUInteger) count; +- (NSUInteger) lockCount; + +@end diff --git a/atemOSC/VVBasics.framework/headers/MutNRLockArray.h b/atemOSC/VVBasics.framework/headers/MutNRLockArray.h new file mode 100644 index 0000000..9ad1138 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/MutNRLockArray.h @@ -0,0 +1,50 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import "MutLockArray.h" +#import "ObjectHolder.h" + + + +/// Subclass of MutLockArray; this class does NOT retain the objects in its array! +/* +this class exists because i frequently find myself in situations where i want to add an instance of an object to an array/dict/[any class which retains the passed instance], but i don't actually want the item to be retained. + +Instead of adding (and therefore retaining) objects to an array like my superclass, this class makes an ObjectHolder for objects which are added to it (so they don't get retained), and adds the ObjectHolder to me. when other classes ask me for the index of an object, or ask for the object at a particular index, i'll find the relevant ObjectHolder and then return the object it's storing. +*/ + +@interface MutNRLockArray : MutLockArray { + +} + ++ (id) arrayWithCapacity:(NSUInteger)c; + +- (NSMutableArray *) createArrayCopy; +- (NSMutableArray *) lockCreateArrayCopyFromObjects; +- (NSMutableArray *) createArrayCopyFromObjects; +- (void) addObject:(id)o; +- (void) addObjectsFromArray:(id)a; +- (void) replaceWithObjectsFromArray:(id)a; +- (void) insertObject:(id)o atIndex:(NSUInteger)i; +- (id) lastObject; +- (void) removeObject:(id)o; +- (BOOL) containsObject:(id)o; +- (id) objectAtIndex:(NSUInteger)i; +- (NSArray *) objectsAtIndexes:(NSIndexSet *)indexes; +- (NSUInteger) indexOfObject:(id)o; +- (BOOL) containsIdenticalPtr:(id)o; +- (long) indexOfIdenticalPtr:(id)o; +- (void) removeIdenticalPtr:(id)o; + +// these methods exist because the lookup cost for an ObjectHolder can be significant for high-performance applications- these methods get the object from the ObjectHolder and call the method directly on it! +- (void) bruteForceMakeObjectsPerformSelector:(SEL)s; +- (void) lockBruteForceMakeObjectsPerformSelector:(SEL)s; +- (void) bruteForceMakeObjectsPerformSelector:(SEL)s withObject:(id)o; +- (void) lockBruteForceMakeObjectsPerformSelector:(SEL)s withObject:(id)o; + + +@end diff --git a/atemOSC/VVBasics.framework/headers/MutNRLockDict.h b/atemOSC/VVBasics.framework/headers/MutNRLockDict.h new file mode 100644 index 0000000..f4f757f --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/MutNRLockDict.h @@ -0,0 +1,39 @@ +// +// MutNRLockDict.h +// VVOpenSource +// +// Created by David Lublin on 12/22/09. +// Copyright 2009 Vidvox. All rights reserved. +// + +#if IPHONE +#import +#else +#import +#endif + +#import "MutLockDict.h" +#import "ObjectHolder.h" + + + +/// Subclass of MutLockDict; this class does NOT retain the objects in its array! +/* +this class exists because i frequently find myself in situations where i want to add an instance of an object to an array/dict/[any class which retains the passed instance], but i don't actually want the item to be retained. + +Instead of adding (and therefore retaining) objects to an array like my superclass, this class makes an ObjectHolder for objects which are added to it (so they don't get retained), and adds the ObjectHolder to me. when other classes ask me for the index of an object, or ask for the object at a particular index, i'll find the relevant ObjectHolder and then return the object it's storing. +*/ + + +@interface MutNRLockDict : MutLockDict { + +} + + +- (void) setObject:(id)o forKey:(NSString *)s; +- (void) setValue:(id)v forKey:(NSString *)s; +- (id) objectForKey:(NSString *)k; +- (void) addEntriesFromDictionary:(id)otherDictionary; +- (NSArray *) allValues; + +@end diff --git a/atemOSC/VVBasics.framework/headers/NamedMutLockArray.h b/atemOSC/VVBasics.framework/headers/NamedMutLockArray.h new file mode 100644 index 0000000..54e75d0 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/NamedMutLockArray.h @@ -0,0 +1,31 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "VVBasicMacros.h" +#import "MutLockArray.h" + + + + +/* + // only difference between this and MutLockArray is the "name" variable. +*/ + + + + +@interface NamedMutLockArray : MutLockArray { + NSString *name; +} + ++ (id) arrayWithCapacity:(int)c; ++ (id) create; + +- (NSComparisonResult) nameCompare:(NamedMutLockArray *)comp; + +@property (assign, readwrite) NSString *name; + +@end diff --git a/atemOSC/VVBasics.framework/headers/ObjectHolder.h b/atemOSC/VVBasics.framework/headers/ObjectHolder.h new file mode 100644 index 0000000..64c397f --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/ObjectHolder.h @@ -0,0 +1,38 @@ + +#if IPHONE +#import +#else +#import +#endif + + + + +/* + created for working with the MutNRLockArray class. + + basically, you create an instance of this class and give it a reference to an + instance of an object. the instance is NOT retained- but you're now free to + pass ObjectHolder to stuff which will otherwise retain/release it without + worrying about whether the passed instance is retained/released. + + if you call a method on an instance of ObjectHolder and the ObjectHolder + class doesn't respond to that method, the instance will try to call the + method on its object. this means that working with ObjectHolder should- + theoretically, at any rate- be transparent... +*/ + + + + +@interface ObjectHolder : NSObject { + BOOL deleted; + id object; +} + ++ (id) createWithObject:(id)o; +- (id) initWithObject:(id)o; + +@property (assign,readwrite) id object; + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVAssertionHandler.h b/atemOSC/VVBasics.framework/headers/VVAssertionHandler.h new file mode 100644 index 0000000..47cdeef --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVAssertionHandler.h @@ -0,0 +1,31 @@ + +#if IPHONE +#import +#else +#import +#endif + + + + +#define USE_CUSTOM_ASSERTION_HANDLER \ +{ \ + NSThread *__currentThread = [NSThread currentThread]; \ + NSDictionary *__threadDict = (__currentThread==nil) ? nil : [__currentThread threadDictionary]; \ + if (__threadDict != nil) { \ + VVAssertionHandler *__newAH = [[VVAssertionHandler alloc] init]; \ + if (__newAH != nil) { \ + [__threadDict setValue:__newAH forKey:@"NSAssertionHandler"]; \ + [__newAH release]; \ + __newAH = nil; \ + } \ + } \ +} + + + +@interface VVAssertionHandler : NSAssertionHandler { + +} + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVBasicMacros.h b/atemOSC/VVBasics.framework/headers/VVBasicMacros.h new file mode 100644 index 0000000..6eab4c6 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVBasicMacros.h @@ -0,0 +1,229 @@ + +// macros for checking to see if something is nil, and if it's not releasing and setting it to nil +#define VVRELEASE(item) {if (item != nil) { \ + [item release]; \ + item = nil; \ +}} +#define VVAUTORELEASE(item) {if (item != nil) { \ + [item autorelease]; \ + item = nil; \ +}} + + + +// macros for making a CGRect from an NSRect +#define NSMAKECGRECT(n) CGRectMake(n.origin.x, n.origin.y, n.size.width, n.size.height) +#define NSMAKECGPOINT(n) CGPointMake(n.x, n.y) +#define NSMAKECGSIZE(n) CGSizeMake(n.width, n.height) +// macros for making an NSRect from a CGRect +#define CGMAKENSRECT(n) NSMakeRect(n.origin.x, n.origin.y, n.size.width, n.size.height) +#define CGMAKENSSIZE(n) NSMakeSize(n.width,n.height) + +// macro for quickly printing out the dimensions of a rect (and a name/id so you can distinguish between them) +#define NSRectLog(n,r) NSLog(@"%@, (%f,%f) : %fx%f",n,r.origin.x,r.origin.y,r.size.width,r.size.height) +#define NSPointLog(n,r) NSLog(@"%@, (%f,%f)",n,r.x,r.y) +#define NSSizeLog(n,s) NSLog(@"%@, %fx%f",n,s.width,s.height) + +// macros for quickly making numbers and values +#define NUMINT(i) [NSNumber numberWithInt:i] +#define NUMFLOAT(f) [NSNumber numberWithFloat:f] +#define NUMBOOL(b) [NSNumber numberWithBool:b] +#define NUMDOUBLE(d) [NSNumber numberWithDouble:d] +#define VALSIZE(s) [NSValue valueWithSize:s] +#define VALRECT(r) [NSValue valueWithRect:r] + +// macro for quickly archiving and object +#define ARCHIVE(a) [NSKeyedArchiver archivedDataWithRootObject:a] +#define UNARCHIVE(a) [NSKeyedUnarchiver unarchiveObjectWithData:a] + +// macro for quickly making colors +#define VVDEVCOLOR(r,g,b,a) [NSColor colorWithDeviceRed:r green:g blue:b alpha:a] +#define VVCALCOLOR(r,g,b,a) [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a] + +// nice little macro for strings +#define VVSTRING(n) ((NSString *)[NSString stringWithString:n]) +#define VVFMTSTRING(f, ...) ((NSString *)[NSString stringWithFormat:f, ##__VA_ARGS__]) +#define VVDATASTRING(n) ((NSData *)[[NSString stringWithString:n] dataUsingEncoding:NSUTF8StringEncoding]) +#define VVDATAFMTSTRING(f, ...) ((NSData *)[[NSString stringWithFormat:f, ##__VA_ARGS__] dataUsingEncoding:NSUTF8StringEncoding]) + +// macros for quickly making arrays because.....well, it's the wiimote, and i'm fucking tired of typing. so there. +#define OBJARRAY(f) [NSArray arrayWithObject:f] +#define OBJSARRAY(f, ...) [NSArray arrayWithObjects:f, ##__VA_ARGS__, nil] +#define MUTARRAY [NSMutableArray arrayWithCapacity:0] + +// macros for quickly making dicts +#define OBJDICT(o,k) [NSDictionary dictionaryWithObject:o forKey:k] +#define OBJSDICT(o, ...) [NSDictionary dictionaryWithObjectsAndKeys:o,#__VA_ARGS__, nil] +#define MUTDICT [NSMutableDictionary dictionaryWithCapacity:0] + +// calculating the distance between two NSPoints or similar structs +#define POINTDISTANCE(a,b) fabs(sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y))) + + +// this is a macro for drawing an NSRect in opengl +#define GLDRAWRECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_QUADS,0,4); \ +} + + + +// this is a macro for stroking an NSRect in opengl +#define GLSTROKERECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x-0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x+r.size.width+0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y+r.size.height-0.5, 0.0, \ + r.origin.x-0.5, r.origin.y-0.5, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,8); \ +} +/* +#define GLSTROKERECT(r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,8); \ +} +*/ + + +// this is a macro for drawing a line connecting two points +#define GLDRAWLINE(p,q) \ +{ \ + GLfloat vvMacroVertices[]={ \ + p.x, p.y, 0.0, \ + q.x, q.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINES,0,2); \ +} + + + +// this is a macro for drawing a diamond specified by a point and radius in opengl +#define GLDRAWDIAMOND(p,r) \ +{ \ + GLfloat vvMacroVertices[] = { \ + p.x-r, p.y, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x, p.y-r, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_QUADS,0,4); \ +} + + + +// this is a macro for stroking an diamond around a point in opengl +#define GLSTROKEDIAMOND(p,r) \ +{ \ + GLfloat vvMacroVertices[] = { \ + p.x-r, p.y, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x, p.y+r, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x+r, p.y, 0.0, \ + p.x, p.y-r, 0.0, \ + p.x, p.y-r, 0.0, \ + p.x-r, p.y, 0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glDrawArrays(GL_LINE_LOOP,0,8); \ +} + + +// this is a macro for drawing a texture of a specified size in a rect +#define GLDRAWTEXSIZEDINRECT(t,s,r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0,s.height, \ + s.width,s.height, \ + s.width,0.0, \ + 0.0,0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWFLIPPEDTEXSIZEDINRECT(t,s,r) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y, 0.0, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, 0.0, \ + r.origin.x, r.origin.y+r.size.height, 0.0}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0, 0.0, \ + s.width, 0.0, \ + s.width, s.height, \ + 0.0, s.height}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWTEXSIZEDINRECTATZ(t,s,r,z) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, z, \ + r.origin.x, r.origin.y+r.size.height, z}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0,s.height, \ + s.width,s.height, \ + s.width,0.0, \ + 0.0,0.0}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + +#define GLDRAWFLIPPEDTEXSIZEDINRECTATZ(t,s,r,z) \ +{ \ + GLfloat vvMacroVertices[]={ \ + r.origin.x, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y, z, \ + r.origin.x+r.size.width, r.origin.y+r.size.height, z, \ + r.origin.x, r.origin.y+r.size.height, z}; \ + GLfloat vvMacroTexCoords[]={ \ + 0.0, 0.0, \ + s.width, 0.0, \ + s.width, s.height, \ + 0.0, s.height}; \ + glVertexPointer(3,GL_FLOAT,0,vvMacroVertices); \ + glTexCoordPointer(2,GL_FLOAT,0,vvMacroTexCoords); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,t); \ + glDrawArrays(GL_QUADS,0,4); \ + glBindTexture(GL_TEXTURE_RECTANGLE_EXT,0); \ +} + diff --git a/atemOSC/VVBasics.framework/headers/VVBasics.h b/atemOSC/VVBasics.framework/headers/VVBasics.h new file mode 100644 index 0000000..b36c65a --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVBasics.h @@ -0,0 +1,55 @@ + +#import "VVBasicMacros.h" + +#import "VVThreadLoop.h" +#import "VVAssertionHandler.h" +#import "VVStopwatch.h" +#import "ObjectHolder.h" +#import "MutLockArray.h" +#import "MutLockDict.h" +#import "MutNRLockArray.h" +#import "MutNRLockDict.h" +#import "NamedMutLockArray.h" + +#if !IPHONE + #import "VVCURLDL.h" + #import "VVSprite.h" + #import "VVSpriteManager.h" + #import "VVSpriteView.h" + #import "VVSpriteControl.h" + #import "VVSpriteControlCell.h" + #import "VVSpriteGLView.h" + #import "VVCrashReporter.h" + //#import "NSHostAdditions.h" +#endif + +/* + the following stuff is for doxygen +*/ + +/*! +\mainpage + +\htmlonly + + + +Introduction +

    +VVBasics is an Objective-c framework with a number of classes which perform functions that i need regularly- but, for whatever reason, aren't provided by the stock frameworks. Expect pretty much everything to link against this framework for one reason or another- macros, useful classes, etc- and expect this framework to continuously grow as I start to open-source more and more of my bag of tricks. +

    + +\endhtmlonly +*/ diff --git a/atemOSC/VVBasics.framework/headers/VVCURLDL.h b/atemOSC/VVBasics.framework/headers/VVCURLDL.h new file mode 100644 index 0000000..39d4c9b --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVCURLDL.h @@ -0,0 +1,72 @@ + +/* + this class offers a very limited, very simple cocoa interface to libcurl for doing extremely + basic http transfer ops + + basically, this class exists because at this time NSURLConnection is problematic and + top-heavy, and i wanted an easy, effective, and reliable interface for handling the extremely + limited set of http data transfer operations required by my frameworks/apps. + + this class was meant to be used as a one-shot throwaway; that is, you're meant to create an + instance of this class which will be auto-released as soon as the autorelease pool is + popped. the instance you create is meant to be used once, and then thrown away- THIS WILL + PROBABLY BREAK IF YOU TRY TO USE THE SAME INSTANCE TO PERFORM MORE THAN ONE TRANSFER. +*/ + + +#import +#import + + + + +@protocol VVCURLDLDelegate +- (void) dlFinished:(id)h; +@end + + + + +@interface VVCURLDL : NSObject { + NSString *urlString; + CURL *curlHandle; + + NSMutableData *responseData; + + struct curl_slist *headerList; // nil by default- if non-nil, supplied to the handle as CURLOPT_HTTPHEADER + NSMutableData *postData; // if non-nil, simply posted as CURLOPT_POSTFIELDS + struct curl_httppost *firstFormPtr; // if postData was nil but this isn't, posted as CURLOPT_HTTPPOST + struct curl_httppost *lastFormPtr; + + BOOL returnOnMain; + BOOL performing; + CURLcode err; +} + ++ (id) createWithAddress:(NSString *)a; +- (id) initWithAddress:(NSString *)a; + +- (void) perform; +- (void) performAsync:(BOOL)as withDelegate:(id )d; +- (void) _performAsyncWithDelegate:(id )d; +- (void) _performWithDelegate:(id )d; + +//- (struct curl_slist *) headerList; +//- (struct curl_httppost *) firstFormPtr; +//- (struct curl_httppost *) lastFormPtr; +- (void) appendDataToPOST:(NSData *)d; +- (void) appendStringToPOST:(NSString *)s; + +- (void) writePtr:(void *)ptr size:(size_t)s; + +@property (assign,readwrite) struct curl_slist *headerList; +@property (assign,readwrite) struct curl_httppost *firstFormPtr; +@property (assign,readwrite) struct curl_httppost *lastFormPtr; +@property (assign,readwrite) BOOL returnOnMain; +@property (readonly) NSMutableData *responseData; +@property (readonly) NSString *responseString; +@property (readonly) CURLcode err; + +@end + +size_t vvcurlWriteFunction(void *ptr, size_t size, size_t nmemb, void *stream); diff --git a/atemOSC/VVBasics.framework/headers/VVCrashReporter.h b/atemOSC/VVBasics.framework/headers/VVCrashReporter.h new file mode 100644 index 0000000..0dc9c90 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVCrashReporter.h @@ -0,0 +1,101 @@ + +#import +#import +#include "AvailabilityMacros.h" +#import +#import +#import "VVCURLDL.h" +#import "MutLockArray.h" + + + + +/// The crash reporter's delegate must adhere to this protocol +/*! + This protocol exists largely because it's conceivable that objects will want to know when the crash reporter- which uploads asynchronously- has finished sending its data to the remote server. +*/ +@protocol OldVVCrashReporterDelegate +- (void) crashReporterCheckDone; +@end + +@protocol VVCrashReporterDelegate +- (void) crashReporterCheckDone:(BOOL)foundLogs; // "new"- 'f' designates whether crash reports were found or not +@end + + + +/// Simple class which automatically uploads crash logs and other relevant diagnostic information automatically made available by os x to a remote server. +/*! +it's been my experience that most apps crash much more frequently on end-users than the app's developers would guess. the simplest and easiest way to improve the end-user's experience is to have the application check their machine for crash logs- which are generated automatically by os x whenever an application crashes- and send them to the developer. + +this class exists so i have a really easy way to make my apps send their crash logs to me; the goal here is to make it as easy as possible to get all the information i need to troubleshoot a problem with as little work on the user's part as possible. it also sends a basic system profile, anything the app- and ONLY the app, not other apps- recently printed to the console log, and optional description/email fields to facilitate communication directly with the user. this data is then uploaded to a given URL using an HTTP POST. + +on the server side, i use a PHP page which sanitizes the POST data (i can't stress how important this step is) and works with it. i've included a sample PHP page that simply dumps the received data to a file on disk (and optionally emails someone) with this project. + +HOW TO USE THIS CLASS: + + 1)- create an instance of this class + + 2)- set the instance's delegate, uploadURL, and developerEmail. these are necessary! + + 3)- call "check" on the instance. when it's done, it calls "crashReporterCheckDone" on the + delegate. that's it- you're done. +*/ + +@interface VVCrashReporter : NSObject { + NSString *uploadURL; // does NOT includes http:// + NSString *developerEmail; + id delegate; // must respond to VVCrashReporterDelegate protocol + MutLockArray *crashLogArray; + NSMutableDictionary *systemProfilerDict; + NSString *consoleLog; + int jobSize; // used to update progress indicator/label + int jobCurrentIndex; // used to update progress indicator/label + int currentCrashLogTimeout; // countdown for timeout of sending/receiving data for a specific crash log + NSTimer *currentCrashLogTimer; + + IBOutlet NSWindow *window; + IBOutlet NSButton *replyButton; + IBOutlet NSView *emailFieldHolder; + IBOutlet NSTextField *emailField; + IBOutlet NSTextView *descriptionField; + IBOutlet NSTextField *submittingLabel; // non-editable. 'submitting', 'getting machine profile', etc. + IBOutlet NSProgressIndicator *progressIndicator; // indicates progress through all crash logs to be submitted + IBOutlet NSTextField *countdownLabel; // non-editable; countdown so user knows app hasn't hung + + NSNib *theNib; + NSArray *nibTopLevelObjects; +} + ++ (NSString *) _stringForSystemProfilerDataType:(NSString *)t; + +/// This is the main method- when you call 'check', the crash reporter looks for crash logs, gets a basic system profile, and collects anything your applications has dumped to the console log. +- (void) check; +- (void) openCrashReporter; +- (IBAction) replyButtonClicked:(id)sender; +- (IBAction) doneClicked:(id)sender; +- (void) sendACrashLog; +- (void) closeCrashReporter; + +- (NSString *) _nibName; +- (BOOL) _assembleCrashLogs; // assembles the array of crash logs, returns a YES if logs were found and have to be sent in +- (NSString *) _consoleLogString; +- (NSMutableDictionary *) _systemProfilerDict; + +- (void) updateCrashLogTimeout:(NSTimer *)t; + +// VVCURLDLDelegate method- this class will be the delegate of multiple VVCURLDL instances +- (void) dlFinished:(id)h; + +/// Sets the developer email address; this is displayed if the user has a problem connecting to the internet/the server the crash reporter is supposed to be connecting to +- (void) setDeveloperEmail:(NSString *)n; +- (NSString *) developerEmail; +/// This is the URL of the php/cgi/etc. page which the crash data will be POSTed to +- (void) setUploadURL:(NSString *)n; +- (NSString *) uploadURL; + +/// The crash reporter's delegate is notified when the check has completed +@property (assign,readwrite) id delegate; +@property (readonly) NSButton *replyButton; + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVCrashReporterDescriptionField.h b/atemOSC/VVBasics.framework/headers/VVCrashReporterDescriptionField.h new file mode 100644 index 0000000..f39f0f5 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVCrashReporterDescriptionField.h @@ -0,0 +1,15 @@ +#import + + +/* + this class exists solely to prevent users from pasting or dragging huge amounts of text (like + crash/console logs!) into the description field of the crash reporter. sounds weird, but trust + me- it's necessary. +*/ + + +@interface VVCrashReporterDescriptionField : NSTextView { + +} + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVCrashReporterEmailField.h b/atemOSC/VVBasics.framework/headers/VVCrashReporterEmailField.h new file mode 100644 index 0000000..fb883f8 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVCrashReporterEmailField.h @@ -0,0 +1,14 @@ +#import +#import + + +/* + this class exists solely to prevent users from pasting huge amounts of text into the email field +*/ + + +@interface VVCrashReporterEmailField : NSTextField { + +} + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVSprite.h b/atemOSC/VVBasics.framework/headers/VVSprite.h new file mode 100644 index 0000000..34246be --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVSprite.h @@ -0,0 +1,104 @@ + +/* Always with the sprites... + + sprite |sprÄ«t| + noun + 1 an elf or fairy. + 2 a computer graphic that may be moved on-screen and otherwise manipulated as a single entity. + 3 a faint flash, typically red, sometimes emitted in the upper atmosphere over a thunderstorm owing to the collision of high-energy electrons with air molecules. + ORIGIN Middle English : alteration of sprit, a contraction of spirit . */ + +#import +#include + + + + +typedef enum _VVSpriteEventType { + VVSpriteEventNULL = 0, + VVSpriteEventDown = 1, + VVSpriteEventDrag = 2, + VVSpriteEventUp = 3, + VVSpriteEventDouble = 4, + VVSpriteEventRightDown = 5, + VVSpriteEventRightUp = 6 +} VVSpriteEventType; + + + + +@interface VVSprite : NSObject { + BOOL deleted; + BOOL locked; // whether or not i should respond to mouse input. DOESN'T AFFECT ANYTHING IN THIS CLASS! variable exists for the user's convenience, and is otherwise superfluous! + BOOL hidden; // whether or not the sprite should draw. DOESN'T AFFECT ANYTHING IN THIS CLASS! variable exists for the user's convenience, and is otherwise superfluous! + BOOL dropFromMultiSpriteActions; // only valid if sprite manager's allowMultiSpriteInteraction' is YES. NO by default. if YES, then if you mousedown on this and any other sprite, this sprite gets dropped from the mousedown. used for allowing multi-sprite interaction to prevent clicks from hitting "background" sprites (which have this set to YES) + long spriteIndex; + id manager; // the VVSpriteManager i exist within- NOT retained! + id delegate; // NOT retained! + SEL drawCallback; // delegate method; passed a ptr to this sprite! + SEL actionCallback; // delegate method; passed a ptr to this sprite! + + NSRect rect; // the sprite i'm tracking + NSBezierPath *bezierPath; // retained. nil by default, set to nil if you call setRect: on this instance. if non-nil, this path is used instead of "rect" for determining mouse action and drawing intersection! + OSSpinLock pathLock; + + int lastActionType; // updated whenever an action is received + NSPoint lastActionCoords; // coords at which last action took place + BOOL lastActionInBounds; // whether or not the last action was within my bounds + BOOL trackingFlag; // whether or not i'm tracking stuff + NSPoint mouseDownCoords; // absolute coords of mousedown + NSPoint lastActionDelta; // change between most-recently-received action coords and last received coords + NSPoint mouseDownDelta; // change between mousedown loc and most-recently received coords + long mouseDownModifierFlags; + + id userInfo; // RETAINED! for storing a random thing... + id NRUserInfo; // NOT RETAINED! for storing something that *shouldn't* be retained... + id safeString; // nil on init- many sprites need formatted text, this is a convenience variable... +} + ++ (id) createWithRect:(NSRect)r inManager:(id)m; +- (id) initWithRect:(NSRect)r inManager:(id)m; + +- (void) prepareToBeDeleted; + +- (BOOL) checkPoint:(NSPoint)p; +- (BOOL) checkRect:(NSRect)r; + +- (void) receivedEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m; +- (void) mouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) rightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) rightMouseUp:(NSPoint)p; +- (void) mouseDragged:(NSPoint)p; +- (void) mouseUp:(NSPoint)p; +- (void) draw; + +- (void) bringToFront; +- (void) sendToBack; + +@property (assign, readwrite) BOOL locked; +@property (assign, readwrite) BOOL hidden; +@property (assign, readwrite) BOOL dropFromMultiSpriteActions; +@property (readonly) long spriteIndex; +@property (readonly) id manager; +@property (assign, readwrite) id delegate; +@property (assign, readwrite) SEL drawCallback; +@property (assign, readwrite) SEL actionCallback; + +@property (assign, readwrite) NSRect rect; +//@property (retain,readwrite) NSBezierPath *path; +- (void) setBezierPath:(NSBezierPath *)n; +- (NSBezierPath *) safelyGetBezierPath; +- (NSRect) spriteBounds; // special method- either returns "rect" or (if path is non-nil) the bounds of the bezier path! +@property (readonly) VVSpriteEventType lastActionType; +@property (readonly) NSPoint lastActionCoords; +@property (readonly) BOOL lastActionInBounds; +@property (readonly) BOOL trackingFlag; +@property (readonly) NSPoint mouseDownCoords; +@property (readonly) NSPoint lastActionDelta; +@property (readonly) NSPoint mouseDownDelta; +@property (readonly) long mouseDownModifierFlags; +@property (assign,readwrite) id userInfo; +@property (assign,readwrite) id NRUserInfo; +@property (assign,readwrite) id safeString; + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVSpriteControl.h b/atemOSC/VVBasics.framework/headers/VVSpriteControl.h new file mode 100644 index 0000000..2ed78b7 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVSpriteControl.h @@ -0,0 +1,49 @@ + +#import +#import "VVSpriteManager.h" +#include + + + + +extern int _maxSpriteControlCount; +extern int _spriteControlCount; + + + + +@interface VVSpriteControl : NSControl { + BOOL deleted; + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + + OSSpinLock propertyLock; + NSEvent *lastMouseEvent; + NSColor *clearColor; + BOOL drawBorder; + NSColor *borderColor; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED +} + +- (void) generalInit; + +- (void) prepareToBeDeleted; + +- (void) finishedDrawing; + +- (void) updateSprites; + +@property (readonly) BOOL deleted; +@property (readonly) VVSpriteManager *spriteManager; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) BOOL mouseIsDown; + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVSpriteControlCell.h b/atemOSC/VVBasics.framework/headers/VVSpriteControlCell.h new file mode 100644 index 0000000..fc8e151 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVSpriteControlCell.h @@ -0,0 +1,11 @@ + +#import + + + + +@interface VVSpriteControlCell : NSActionCell { + +} + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVSpriteGLView.h b/atemOSC/VVBasics.framework/headers/VVSpriteGLView.h new file mode 100644 index 0000000..a47b6a2 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVSpriteGLView.h @@ -0,0 +1,82 @@ + +#import +#import "VVSpriteManager.h" +#import +#import +#import + + + + +typedef enum { + VVFenceModeEveryRefresh = 0, // every time a display callback runs, drawing commands are sent to the GPU. + VVFenceModeDBSkip = 1, // the apple gl fence extension is used to make sure that drawing commands for the back buffer have finished before more drawing commands are sent to the back buffer (the front buffer can receive commands, though) + VVFenceModeSBSkip = 2, // the apple gl fence extension is used to make sure that drawing commands for the single buffer have finished before more drawing commands are sent to it + VVFenceModeFinish = 3 // glFinish is used instead of glFlush +} VVFenceMode; + +typedef enum { + VVFlushModeGL = 0, // glFlush() + VVFlushModeCGL = 1, // CGLFlushDrawable() + VVFlushModeNS = 2, // [context flushBuffer] + VVFlushModeApple = 3, // glFlushRenderAPPLE() + VVFlushModeFinish = 4 // glFinish() +} VVFlushMode; + + + + +@interface VVSpriteGLView : NSOpenGLView { + BOOL deleted; + + BOOL initialized; + //BOOL needsReshape; + pthread_mutex_t glLock; + + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + NSEvent *lastMouseEvent; + GLfloat clearColor[4]; + BOOL drawBorder; + GLfloat borderColor[4]; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED + + VVFlushMode flushMode; + + VVFenceMode fenceMode; + GLuint fenceA; + GLuint fenceB; + BOOL waitingForFenceA; + BOOL fenceADeployed; + BOOL fenceBDeployed; + OSSpinLock fenceLock; +} + +- (void) generalInit; +- (void) prepareToBeDeleted; + +- (void) initializeGL; +- (void) finishedDrawing; +//- (void) reshapeGL; +- (void) updateSprites; + +- (void) _lock; +- (void) _unlock; +//- (void) lockSetOpenGLContext:(NSOpenGLContext *)n; + +@property (readonly) BOOL deleted; +@property (assign,readwrite) BOOL initialized; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) VVSpriteManager *spriteManager; +@property (readonly) BOOL mouseIsDown; +@property (assign, readwrite) VVFlushMode flushMode; + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVSpriteManager.h b/atemOSC/VVBasics.framework/headers/VVSpriteManager.h new file mode 100644 index 0000000..b8f0dc4 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVSpriteManager.h @@ -0,0 +1,57 @@ + +#import +#import "VVSprite.h" +#import "MutLockArray.h" + + + + +@interface VVSpriteManager : NSObject { + BOOL deleted; + BOOL allowMultiSpriteInteraction; // NO by default- if YES, clicking/dragging/etc works with multiple sprites! + BOOL multiSpriteExecutesOnMultipleSprites; // only relevant if multi-sprite interaction is YES. this is NO by default- if it's YES all sprites in "spritesInUse" will receive an action callback when any of them get an action method. if this is NO then only the sprite that "caught" the interaction will receive an action callback! + MutLockArray *spriteArray; // searched from beginning to end, so order is like z-index! + VVSprite *spriteInUse; // array of VVSprite objects currently tracking drag info + MutLockArray *spritesInUse; // ONLY VALID IF MULTI SPRITE INTERACTION IS YES! array of VVSprite o + long spriteIndexCount; +} + +- (void) prepareToBeDeleted; + +// return YES if the mousedown occurred on one or more sprites +- (BOOL) receivedMouseDownEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m visibleOnly:(BOOL)v; +- (void) receivedOtherEvent:(VVSpriteEventType)e atPoint:(NSPoint)p withModifierFlag:(long)m; +- (BOOL) localMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localVisibleMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localRightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (BOOL) localVisibleRightMouseDown:(NSPoint)p modifierFlag:(long)m; +- (void) localRightMouseUp:(NSPoint)p; +- (void) localMouseDragged:(NSPoint)p; +- (void) localMouseUp:(NSPoint)p; +- (void) terminatePresentMouseSession; // call this and sprites will stop responding to the mouse until it is clicked again + +- (id) newSpriteAtBottomForRect:(NSRect)r; +- (id) newSpriteAtTopForRect:(NSRect)r; +- (long) getUniqueSpriteIndex; + +- (VVSprite *) spriteAtPoint:(NSPoint)p; +- (VVSprite *) visibleSpriteAtPoint:(NSPoint)p; +- (VVSprite *) spriteForIndex:(long)i; +- (void) removeSpriteForIndex:(long)i; +- (void) removeSprite:(id)z; +- (void) removeSpritesFromArray:(NSArray *)array; +- (void) removeAllSprites; +//- (void) moveSpriteToFront:(VVSprite *)z; + +- (void) draw; +- (void) drawRect:(NSRect)r; + +- (VVSprite *) spriteInUse; +- (void) setSpriteInUse:(VVSprite *)z; + +@property (assign,readwrite) BOOL allowMultiSpriteInteraction; +@property (assign,readwrite) BOOL multiSpriteExecutesOnMultipleSprites; +@property (readonly) MutLockArray *spriteArray; +@property (readonly) MutLockArray *spritesInUse; + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVSpriteView.h b/atemOSC/VVBasics.framework/headers/VVSpriteView.h new file mode 100644 index 0000000..a8d17a0 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVSpriteView.h @@ -0,0 +1,48 @@ + +#import +#import "VVSpriteManager.h" +#include + + + + +extern int _spriteViewCount; + + + + +@interface VVSpriteView : NSView { + BOOL deleted; + VVSpriteManager *spriteManager; + BOOL spritesNeedUpdate; + + OSSpinLock propertyLock; + NSEvent *lastMouseEvent; + NSColor *clearColor; + BOOL drawBorder; + NSColor *borderColor; + + long mouseDownModifierFlags; + BOOL mouseIsDown; + NSView *clickedSubview; // NOT RETAINED +} + +- (void) generalInit; + +- (void) prepareToBeDeleted; + +- (void) finishedDrawing; + +- (void) updateSprites; + +@property (readonly) BOOL deleted; +@property (readonly) VVSpriteManager *spriteManager; +@property (assign, readwrite) BOOL spritesNeedUpdate; +- (void) setSpritesNeedUpdate; +@property (readonly) NSEvent *lastMouseEvent; +@property (retain,readwrite) NSColor *clearColor; +@property (assign,readwrite) BOOL drawBorder; +@property (retain,readwrite) NSColor *borderColor; +@property (readonly) BOOL mouseIsDown; + +@end diff --git a/atemOSC/VVBasics.framework/headers/VVStopwatch.h b/atemOSC/VVBasics.framework/headers/VVStopwatch.h new file mode 100644 index 0000000..a1f9c35 --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVStopwatch.h @@ -0,0 +1,35 @@ + +#if IPHONE +#import +#else +#import +#endif +#include +#import + + + +/// This class is used to measure how long it takes to do things; much easier to work with than NSDate. + +@interface VVStopwatch : NSObject { + struct timeval startTime; + OSSpinLock timeLock; +} + +/// Returns an auto-released instance of VVStopwatch; the stopwatch is started on creation. ++ (id) create; + +/// Starts the stopwatch over again +- (void) start; +/// Returns a float representing the time (in seconds) since the stopwatch was started +- (double) timeSinceStart; +/// Sets the stopwatch's starting time as an offset to the current time +- (void) startInTimeInterval:(NSTimeInterval)t; +/// Populates the passed timeval struct with the current timeval +- (void) copyStartTimeToTimevalStruct:(struct timeval *)dst; +/// Populates the starting time with the passed timeval struct +- (void) setStartTimeStruct:(struct timeval *)src; + +@end + +void populateTimevalWithFloat(struct timeval *tval, double secVal); diff --git a/atemOSC/VVBasics.framework/headers/VVThreadLoop.h b/atemOSC/VVBasics.framework/headers/VVThreadLoop.h new file mode 100644 index 0000000..0a6342f --- /dev/null +++ b/atemOSC/VVBasics.framework/headers/VVThreadLoop.h @@ -0,0 +1,63 @@ + +#if IPHONE +#import +#else +#import +#endif +#include +#import +#include + + + + +/// Simple class for spawning a thread which executes at a specified interval- simpler and easier to work with than NSThread/NSTimer in multi-threaded programming environments. +/*! +When started, an instance of this class will spawn a thread and repeatedly execute a method on that thread. If it was passed a target and selector on creation, the selector will be called on the target every time the thread executes. If it's more convenient to subclass VVThreadLoop and work with your custom subclass, leave the target/selector nil and VVThreadLoop will call "threadProc" on itself- just override this method (it's empty anyway) in your subclass and do whatever you want in there. + +You can change the execution interval, and VVThreadLoop also examines how long it takes to execute your code and adjusts in an attempt to ensure that the interval is accurate (sleep-time is interval-duration minus proc-execution-duration) +*/ + + + + +@interface VVThreadLoop : NSObject { + double interval; + double maxInterval; + BOOL running; + BOOL bail; + BOOL paused; + BOOL executingCallback; + + OSSpinLock valLock; // ONLY used for quickly accessing 'running', 'bail', 'paused', and 'executingCallback' in a threadsafe fashion + + id targetObj; //! + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/atemOSC/VVOSC.framework/Headers b/atemOSC/VVOSC.framework/Headers deleted file mode 120000 index a177d2a..0000000 --- a/atemOSC/VVOSC.framework/Headers +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/Headers \ No newline at end of file diff --git a/atemOSC/VVOSC.framework/Headers/OSCAddressSpace.h b/atemOSC/VVOSC.framework/Headers/OSCAddressSpace.h new file mode 100644 index 0000000..966aa33 --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/OSCAddressSpace.h @@ -0,0 +1,77 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "OSCNode.h" + + + + +// OSCAddressSpace delegate protocol +@protocol OSCAddressSpaceDelegateProtocol +- (void) nodeRenamed:(OSCNode *)n; +- (void) dispatchReplyOrError:(OSCMessage *)m; // this method is called by nodes in the address space. the passed message is a reply or error in response to a query which should be sent out an output. +@end + + + + +// this is the main instance of OSCAddressSpace. it is auto-created when this class is initialized +extern id _mainAddressSpace; + + + + +/// OSCAddressSpace is a representation of the OSC address space described in the OSC spec. It is a subclass of OSCNode. This class is optional- it's not needed for basic OSC message sending/receiving. +/*! +There should only ever be one instance of OSCAddressSpace, and you shouldn't explicitly create it. Just call [OSCAddressSpace class] (or any other OSCAddressSpace method) and it will be automatically created. This main instance may be retrieved by the class method +[OSCAddressSpace mainAddressSpace] or by the class variable _mainAddressSpace. + +OSCAddressSpace is your application's main way of dealing with the OSC address space- if you need to dispatch a message, set, rename, or delete a node, you should do via the main instance of this class. +*/ +@interface OSCAddressSpace : OSCNode { + id delegate; +} + +/// Returns the main instance of the OSC address space (and creates it if necessary) ++ (id) mainAddressSpace; ++ (void) refreshMenu; +#if !IPHONE ++ (NSMenu *) makeMenuForNode:(OSCNode *)n withTarget:(id)t action:(SEL)a; ++ (NSMenu *) makeMenuForNode:(OSCNode *)n ofType:(NSIndexSet *)ts withTarget:(id)t action:(SEL)a; +#endif + +/// Renames 'before' to 'after'. Sub-nodes stay with their owners! Can also be though of as a "move". +- (void) renameAddress:(NSString *)before to:(NSString *)after; +- (void) renameAddressArray:(NSArray *)before toArray:(NSArray *)after; + +/// If 'n' is nil, the node at the passed address will be deleted (as will any of its sub-nodes) +- (void) setNode:(OSCNode *)n forAddress:(NSString *)a; +- (void) setNode:(OSCNode *)n forAddress:(NSString *)a createIfMissing:(BOOL)c; +- (void) setNode:(OSCNode *)n forAddressArray:(NSArray *)a; +- (void) setNode:(OSCNode *)n forAddressArray:(NSArray *)a createIfMissing:(BOOL)c; + +// this method is called whenever a node is added to another node +- (void) nodeRenamed:(OSCNode *)n; + +/// Unlike a normal OSCNode, this method finds the destination node and then dispatches the msg. If the destination is itself, it just calls the super. +- (void) dispatchMessage:(OSCMessage *)m; +// This method gets called by an OSCNode inside me (or by me), and you probably won't need to ever call this method. The passed message is a reply or error that needs to be sent back in response to a query. The passed OSCMessage contains the IP address and port of the destination. This method just passes the data on to the addres space's delegate- it does NOT actually send anything out, this is something you'll have to implement in the delegate. +- (void) _dispatchReplyOrError:(OSCMessage *)m; + +- (void) addDelegate:(id)d forPath:(NSString *)p; +- (void) removeDelegate:(id)d forPath:(NSString *)p; +/* +- (void) addQueryDelegate:(id)d forPath:(NSString *)p; +- (void) removeQueryDelegate:(id)d forPath:(NSString *)p; +*/ +@property (assign, readwrite) id delegate; + + +@end + + + + + diff --git a/atemOSC/VVOSC.framework/Headers/OSCBundle.h b/atemOSC/VVOSC.framework/Headers/OSCBundle.h new file mode 100644 index 0000000..857d688 --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/OSCBundle.h @@ -0,0 +1,46 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import "OSCMessage.h" + + + + +/// An OSCBundle is a "container" for multiple OSC messages or bundles (bundles may also be nested) +/*! +According to the OSC spec, an OSC bundle is basically a wrapper for multiple OSC messages (or other bundles). Instead of sending a bunch of individual messages, you can wrap them all into a bundle, and send the bundle (messages will still be sent to their individual address paths). OSCBundleÕs interface is correspondingly simple: you can create a bundle from some elements, or you can create a bundle and then add some elements (OSCMessages or OSCBundles) to it. + +OSC bundles also have a time stamp- by default, this will be set to immediate execution (0s except for a single 1 in the LSB). while timetag execution isn't widely supported, you may specify non-immediate time tags in the hopes that the software on the receiving end will execute the bundle in time. +*/ + + + + +@interface OSCBundle : NSObject { + NSMutableArray *elementArray; // array of messages or bundles + NSDate *timeTag; // nil by default, or the time at which the contents of this bundle should be dispatched +} + ++ (void) parseRawBuffer:(unsigned char *)b ofMaxLength:(int)l toInPort:(id)p inheritedTimeTag:(NSDate *)d fromAddr:(unsigned int)txAddr port:(unsigned short)txPort; +/// Creates and returns an auto-released bundle ++ (id) create; +/// Creates and returns an auto-released bundle with the single passed element ++ (id) createWithElement:(id)n; +/// Creates and returns an auto-released bundle with the array of passed elements ++ (id) createWithElementArray:(id)a; + +/// Adds the passed element to the bundle +- (void) addElement:(id)n; +/// Adds the array of passed elements to the bundle +- (void) addElementArray:(NSArray *)a; + +- (long) bufferLength; +- (void) writeToBuffer:(unsigned char *)b; + +@property (retain,readwrite) NSDate *timeTag; + +@end diff --git a/atemOSC/VVOSC.framework/Headers/OSCConstants.h b/atemOSC/VVOSC.framework/Headers/OSCConstants.h new file mode 100644 index 0000000..7261ae2 --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/OSCConstants.h @@ -0,0 +1,131 @@ + +/*! +\file OSCConstants.h +\brief Constants and Macros used by one or more of the OSC classes in this framework +*/ + +/// OSCValueType +/*! +OSCValues have distinct types; these are used to describe the type of an OSCValue. +*/ +typedef enum { + OSCValInt = 1, //! +#else +#import +#endif + +#import +//#import +//#import +#import +#import +#import +#import "OSCPacket.h" +#import "OSCBundle.h" +#import "OSCMessage.h" +#import "OSCOutPort.h" + + + + +/// OSCInPort handles everything needed to receive OSC data on a given port +/*! +You should never create or destroy an instance of this class manually. OSCInPort instances should be created/destroyed by the OSCManager. + +Each OSCInPort is running in its own separate thread- so make sure anything called as a result of received OSC input is thread-safe! When OSCInPort receives data, it gets parsed and passed to the in port's delegate as a series of OSCMessages consisting of an address path and an OSCValue. By default, the inport's delegate is the manager which created it- and by default, managers pass this data on to *their* delegates (your objects/app). + +the documentation here only covers the basics, the header file for this class is small and heavily commented if you want to know more because you're heavily customizing OSCInPort. +*/ +@interface OSCInPort : NSObject { + BOOL deleted; // whether or not i'm deleted- ensures that socket gets closed + BOOL bound; // whether or not the socket is bound + OSSpinLock socketLock; + int sock; // socket file descriptor. remember, everything in unix is files! + struct sockaddr_in addr; // struct that describes *my* address (this is an in port) + unsigned short port; // the port number i'm receiving from + unsigned char buf[65506]; // the socket gets data and dumps it here immediately + + OSSpinLock scratchLock; + NSThread *thread; + //VVThreadLoop *threadLooper; + + NSString *portLabel; //! +#else +#import +#endif +#import "OSCAddressSpace.h" +#import "OSCZeroConfManager.h" +#import "OSCInPort.h" +#import "OSCOutPort.h" + + + + +/// Main VVOSC class- manages in & out port creation, zero configuration networking (bonjour/zeroconf) +/*! +The OSCManager will probably be the main class that you're working with: it creates/deletes inputs (which receive data) and outputs (which send data), passes any OSC data received to its delegate (your application), optionally handles distribution of all received OSC messages, and does other manager-ish things. You should only need one instance of OSCManager in your application. One of your objects should be OSCManager's delegate (see the "OSCDelegateProtocol" below) so you may receive OSC data. + +Incoming OSC data is initially received by an OSCInPort; fundamentally, in ports are running a loop which checks a socket for data received since the last loop. By default, the OSCInPort's delegate is the OSCManager which created it. Every time the loop runs, it passes the received data off to its delegate (the manager) as the raw address/value pairs in the order they're received. When the OSCManager receives data from its in port it immediately passes the received data to its delegate, which should respond to one of the following methods (referred to as the 'OSCDelegateProtocol'): + +\htmlonly +
    +@protocol OSCDelegateProtocol
    +- (void) receivedOSCMessage:(OSCMessage *)m;
    +@end +
    +\endhtmlonly + +...if you want to work with received OSC data, OSCManager's delegate must respond to this method! +*/ + + + + +@interface OSCManager : NSObject { + MutLockArray *inPortArray; // Array of OSCInPorts in a locking array for threadsafe access + MutLockArray *outPortArray; // Array of OSCOutPorts in a locking array for threadsafe access + + id delegate; //! +#else +#import +#endif +#import "OSCValue.h" +#import + + + + +/// Corresponds to an OSC message: contains zero or more values, and the address path the values have to get sent to. +/*! +According to the OSC spec, a message consists of an address path (where the message should be sent) and zero or more arguments. An OSCMessage must be created with an address path- once the OSCMessage exists, you may add as many arguments to it as you'd like. +*/ +@interface OSCMessage : NSObject { + NSString *address; //! 1 + + NSDate *timeTag; //! +#else +#import +#endif +#import "OSCMessage.h" +#import +#import +#import + + + + +@protocol OSCNodeDelegateProtocol +- (void) node:(id)n receivedOSCMessage:(id)msg; +- (void) nodeNameChanged:(id)node; +- (void) nodeDeleted:(id)node; +@end +/// An OSCNode's queryDelegate must respond to these methods, which are called when a query-type OSCMessage is dispatched to an OSCNode +@protocol OSCNodeQueryDelegateProtocol +- (NSMutableArray *) namespaceArrayForNode:(id)n; +- (NSString *) docStringForNode:(id)n; +- (NSString *) typeSignatureForNode:(id)n; +- (OSCValue *) currentValueForNode:(id)n; +- (NSString *) returnTypeStringForNode:(id)n; +@end + + + + +/// OSCNode describes a single destination for OSC addresses. The OSC address space is made up of many different nodes. This class is optional- it is not used for basic OSC message sending/receiving, and only gets used if you start working with OSCAddressSpace. +/*! +The OSC specification describes a slash-delineated address space- as messages are received, they are dispatched to the described address. An OSCNode represents a single unique destination in the OSC address space. OSCNodes may have subnodes and have a non-retaining reference to their parent node (unless they're top-level, in which case their parent node is nil). They retain a copy of the last message dispatched directly to this node for convenience. OSCNode instances have zero or more delegates- delegates are NOT retained, and are assumed to respond to all the methods in OSCNOdeDelegateProtocol. + +If you want to work with an instance of OSCNode, you need to acquire or work with it from the main OSCAddressSpace. Do not just start creating OSCNode instances willy-nilly; there's no point, they're only useful if they're part of an address space. + +Generally speaking, it's a good idea for each instance of OSCNode to have a discrete type, as this makes it easier to browse and filter the hierarchy of OSCNode instances that make up the OSC address space. Most of the documented methods here are simply for querying basic properties of the OSCNode instance or doing simple message dispatch. +*/ + + + + +@interface OSCNode : NSObject { + id addressSpace; // the class OSCAddressSpace is a subclass of OSCNode, and is essentially the "root" node. all OSCNodes have a pointer to the root node! + BOOL deleted; + + OSSpinLock nameLock; + NSString *nodeName; /// "local" name: name of the node at /a/b/c is "c" + NSString *fullName; /// "full" name: name of the node at /a/b/c is "/a/b/c" + MutLockArray *nodeContents; /// Contains OSCNode instances- this OSCNode's sub-nodes. type 'MutLockArray'- this should all be threadsafe... + OSCNode *parentNode; // my "parent" node (or nil). NOT retained! + OSCNodeType nodeType; /// What 'type' of node i am + BOOL hiddenInMenu; // NO by default. if YES, this node (and all its sub-nodes) will be omitted from menus! + + OSCMessage *lastReceivedMessage; /// The last message sent to this node is retained (the message is retained instead of the value because messages can have multiple values) + OSSpinLock lastReceivedMessageLock; + MutNRLockArray *delegateArray; // type 'MutNRLockArray'. contents are NOT retained! could be anything! + + BOOL autoQueryReply; // NO by default. if YES and the queryDelegate is nil or doesn't respond to one of the delegate methods or returns nil from one of the delegate methods, the OSCNode will try to automatically respond to the query + id queryDelegate; // nil by default, NOT retained; unlike "normal" delegates, an OSCNode has a single query delegate +} + +// only called by the address space to craft a formatted string for logging purposes +- (void) _logDescriptionToString:(NSMutableString *)s tabDepth:(int)d; + ++ (id) createWithName:(NSString *)n; +- (id) initWithName:(NSString *)n; +- (id) init; +- (void) prepareToBeDeleted; + +// convenience method so nodes may be sorted by name +- (NSComparisonResult) nodeNameCompare:(OSCNode *)comp; + +// "local" add/remove/find methods for working with my node contents +- (void) addLocalNode:(OSCNode *)n; +- (void) addLocalNodes:(NSArray *)n; +- (void) removeLocalNode:(OSCNode *)n; // this just removes the passed node from my 'nodeContents' array- doesn't assume that the passed node will be released! +- (void) deleteLocalNode:(OSCNode *)n; // calls 'prepareToBeDeleted' on the passed node- call this is if you want to make sure that the passed node will stop sending delegate messages/etc! +- (void) removeFromAddressSpace; // tries to remove me from the OSCAddressSpace singleton by setting my fullName to nil + +/// It's assumed that the passed name doesn't have any wildcards/regex. If the receiver contains a node with the identical name as the passed string, the node will be returned. This is not a "deep" search, it's restricted to the receiver's nodeContents array. +- (OSCNode *) findLocalNodeNamed:(NSString *)n; +/// Same as findLocalNodeNamed:, but if any of the interim nodes don't exist they will be created. +- (OSCNode *) findLocalNodeNamed:(NSString *)n createIfMissing:(BOOL)c; + +/// Compares the names of all the receiver's sub-nodes to the passed POSIX regex string, returns an array with all the nodes whose nodeNames match the regex. If there are no sub-nodes or none of the sub-nodes match the regex, returns nil. +- (NSMutableArray *) findLocalNodesMatchingPOSIXRegex:(NSString *)regex; +- (void) _addLocalNodesMatchingRegex:(NSString *)regex toMutArray:(NSMutableArray *)a; + + +/// Calls findNodeForAddress:createIfMissing:NO. +// these find methods do NOT work with regex! it is assumed that the passed string is NOT a regex algorithm! +- (OSCNode *) findNodeForAddress:(NSString *)p; +/// It's assumed that the passed address doesn't have any wildcards/regex (no checking is done). The receiver tries to locate the node at the passed address (relative to the receiver). If c is YES, any OSCNodes missing in the passed address are automatically created. If they have sub-nodes, the auto-created nodes' types are set to OSCNodeDirectory; if not, the auto-created nodes' types are OSCNodeTypeUnknown +- (OSCNode *) findNodeForAddress:(NSString *)p createIfMissing:(BOOL)c; +- (OSCNode *) findNodeForAddressArray:(NSArray *)a; +- (OSCNode *) findNodeForAddressArray:(NSArray *)a createIfMissing:(BOOL)c; +// these find methods work with regex! path components may be regex strings- this returns all the nodes that match every component in the passed address/address array! +- (NSMutableArray *) findNodesMatchingAddress:(NSString *)a; +- (NSMutableArray *) findNodesMatchingAddressArray:(NSArray *)a; + +// a node's delegate is informed of received osc messages or name changes (OSCNodeDelegateProtocol) +// NODE DELEGATES ARE __NOT__ RETAINED! +// NODE DELEGATES __MUST__ REMOVE THEMSELVES FROM THE DELEGATE ARRAY! +- (void) addDelegate:(id)d; +- (void) removeDelegate:(id)d; +- (void) informDelegatesOfNameChange; +- (void) addDelegatesFromNode:(OSCNode *)n; + +/// Sends the passed message to all of the node's delegates- it does NOT parse the address at all (it's assumed that the passed message's address points to this instance of OSCNode). If the passed message is a query, this tries to assemble a reply (either from the queryDelegate or automatically if autoQueryReply is enabled) which is sent to the main address space. +- (void) dispatchMessage:(OSCMessage *)m; + +@property (assign, readwrite) id addressSpace; +@property (assign, readwrite) NSString *nodeName; +- (void) _setNodeName:(NSString *)n; +@property (readonly) NSString *fullName; +@property (readonly) id nodeContents; +@property (assign, readwrite) OSCNode *parentNode; +@property (assign, readwrite) int nodeType; +@property (assign, readwrite) BOOL hiddenInMenu; +@property (readonly) OSCMessage *lastReceivedMessage; +@property (readonly) OSCValue *lastReceivedValue; +@property (readonly) id delegateArray; +//@property (readonly) id queryDelegateArray; +@property (assign,readwrite) BOOL autoQueryReply; +@property (assign,readwrite) id queryDelegate; + +@end diff --git a/atemOSC/VVOSC.framework/Headers/OSCOutPort.h b/atemOSC/VVOSC.framework/Headers/OSCOutPort.h new file mode 100644 index 0000000..091b593 --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/OSCOutPort.h @@ -0,0 +1,71 @@ + +#if IPHONE +#import +#else +#import +#endif + + +#include + +#import "OSCPacket.h" +#import "OSCBundle.h" +#import "OSCMessage.h" + + + + +/// OSCOutPort handles everything needed to send OSC data to a given address +/*! +You should never create or destroy an instance of this class manually. OSCOutPort instances should be created/destroyed by the OSCManager. + +the documentation here only covers the basics, the header file for this class is small and heavily commented if you want to know more because you're heavily customizing OSCOutPort. +*/ +@interface OSCOutPort : NSObject { + BOOL deleted; + int sock; + struct sockaddr_in addr; + unsigned short port; //! +#else +#import +#endif + +#include +#import "OSCBundle.h" +#import "OSCMessage.h" + + + +/// Used to parse raw OSC data or to assemble raw OSC data from OSCMessages/OSCBundles +/*! +An OSC packet is the basic unit of transmitting OSC data- the OSCPacket class is mostly used internally to either parse received raw data or to assemble raw data from OSCMessages/OSCBundles for sending. +*/ + +@interface OSCPacket : NSObject { + long bufferLength; + unsigned char *payload; +} + ++ (void) parseRawBuffer:(unsigned char *)b ofMaxLength:(int)l toInPort:(id)p fromAddr:(unsigned int)txAddr port:(unsigned short)txPort; +/// Creates & returns an auto-released packet from either an OSCBundle or an OSCMessage ++ (id) createWithContent:(id)c; +- (id) initWithContent:(id)c; + +- (long) bufferLength; +- (unsigned char *) payload; + +@end diff --git a/atemOSC/VVOSC.framework/Headers/OSCStringAdditions.h b/atemOSC/VVOSC.framework/Headers/OSCStringAdditions.h new file mode 100644 index 0000000..48146c2 --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/OSCStringAdditions.h @@ -0,0 +1,49 @@ + +#if IPHONE +#import +#else +#import +#endif +#import +#import + + + + +extern NSCharacterSet *_OSCStrAdditionsWildcardCharSet; +extern MutLockDict *_OSCStrPOSIXRegexDict; // key is the regex string, object is an OSCPOSIXRegExpHolder containing the compiled regex- which is threadsafe, and may be reused + + + + +@interface OSCPOSIXRegExpHolder : NSObject { + NSString *regexString; + regex_t *regex; +} + ++ (id) createWithString:(NSString *)n; +- (id) initWithString:(NSString *)n; +- (BOOL) evalAgainstString:(NSString *)n; +- (NSString *) regexString; + +@end + + + + +@interface NSString (OSCStringAdditions) + ++ (NSString *) stringWithBytes:(const void *)b length:(NSUInteger)l encoding:(NSStringEncoding)e; ++ (NSString *) stringFromRawIPAddress:(unsigned long)i; +- (NSString *) trimFirstAndLastSlashes; +- (NSString *) stringByDeletingFirstPathComponent; +- (NSString *) firstPathComponent; +- (NSString *) stringBySanitizingForOSCPath; +- (NSString *) stringByDeletingLastAndAddingFirstSlash; +- (BOOL) containsOSCWildCard; + +- (BOOL) predicateMatchAgainstRegex:(NSString *)r; +- (BOOL) posixMatchAgainstSlowRegex:(NSString *)r; +- (BOOL) posixMatchAgainstFastRegex:(NSString *)r; + +@end diff --git a/atemOSC/VVOSC.framework/Headers/OSCValue.h b/atemOSC/VVOSC.framework/Headers/OSCValue.h new file mode 100644 index 0000000..fd0ea5e --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/OSCValue.h @@ -0,0 +1,107 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "OSCConstants.h" + + + + +/// OSCValue encapsulates any value you can send or receive via OSC. It is NOT mutable at this time. +/*! +When you send or receive values via OSC, you'll be working with OSCValue objects in an OSCMessage. Internally, OSCValue isn't mutable, and it attempts to store its value in its native format (int for an int, float for a float) instead of relying on NSNumber. The exceptions to this are NSColor/UIColor and NSString. +*/ + + + + +@interface OSCValue : NSObject { + OSCValueType type; //! +#import +#else +#import +#endif +//#import +#import +#import +#import +#import +#include + + + +#if IPHONE +@interface OSCZeroConfDomain : NSObject { +#else +@interface OSCZeroConfDomain : NSObject { +#endif + NSString *domainString; + NSNetServiceBrowser *serviceBrowser; + + MutLockArray *servicesArray; + + id domainManager; +} + ++ (id) createWithDomain:(NSString *)d andDomainManager:(id)m; +- (id) initWithDomain:(NSString *)d andDomainManager:(id)m; + +// NSNetServiceBrowser delegate methods +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didFindService:(NSNetService *)x moreComing:(BOOL)m; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didNotSearch:(NSDictionary *)err; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didRemoveService:(NSNetService *)s moreComing:(BOOL)m; + +// NSNetService delegate methods +- (void)netService:(NSNetService *)n didNotResolve:(NSDictionary *)err; +- (void)netServiceDidResolveAddress:(NSNetService *)n; + +@end diff --git a/atemOSC/VVOSC.framework/Headers/OSCZeroConfManager.h b/atemOSC/VVOSC.framework/Headers/OSCZeroConfManager.h new file mode 100644 index 0000000..c1795ab --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/OSCZeroConfManager.h @@ -0,0 +1,37 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import +#import "OSCZeroConfDomain.h" +#import + + + + +#if IPHONE +@interface OSCZeroConfManager : NSObject { +#else +@interface OSCZeroConfManager : NSObject { +#endif + NSNetServiceBrowser *domainBrowser; + + NSMutableDictionary *domainDict; + pthread_rwlock_t domainLock; + + id oscManager; +} + +- (id) initWithOSCManager:(id)m; + +- (void) serviceRemoved:(NSNetService *)s; +- (void) serviceResolved:(NSNetService *)s; + +// NSNetServiceBrowser delegate methods +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didFindDomain:(NSString *)d moreComing:(BOOL)m; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didNotSearch:(NSDictionary *)err; + +@end diff --git a/atemOSC/VVOSC.framework/Headers/VVOSC.h b/atemOSC/VVOSC.framework/Headers/VVOSC.h new file mode 100644 index 0000000..47eeb3a --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/VVOSC.h @@ -0,0 +1,121 @@ + + +#import "OSCConstants.h" + +#import "OSCValue.h" +#import "OSCMessage.h" +#import "OSCBundle.h" +#import "OSCPacket.h" + +#import "OSCOutPort.h" +#import "OSCInPort.h" + +#import "OSCManager.h" +#import "OSCZeroConfManager.h" + +#import "OSCNode.h" +#import "OSCAddressSpace.h" + +#import "OSCStringAdditions.h" + + + + +/// Most common means of passing OSC data to your application. Delegates of OSCManager and OSCInPort should support this protocol. +/*! +When instances of OSCInPort and OSCManager receive OSC data, they pass it to their delegate by calling this method. If you want to receive OSC data, your OSCManager's delegate must respond to this method! +*/ +@protocol OSCDelegateProtocol +/// This method is called whenever your in port/manager receives an OSCMessage. +- (void) receivedOSCMessage:(OSCMessage *)m; +@end + + + + +/* + the following stuff is for doxygen +*/ + + +/*! +\mainpage + +\htmlonly + + + + +Introduction +

    +VVOSC is an Objective-c framework for assembling, sending, and receiving OSC (Open Sound Control) messages on OS X. A simple sample application (gui) which sends and receives OSC messages is also included to aid in the debugging of your software. There's also an SDK which allows you to develop iPhone applications which use VVOSC. All the source code is available on the project homepage: http://code.google.com/p/vvopensource +

    + + +Features and Capabilities +

    +

  • Includes a sample GUI app for debugging OSC applications and hardware that also demonstrates use of the framework
  • +
  • Packet parsing (client) + construction (server)
  • +
  • Creates bundles/nested bundles, safely parse bundles/nested bundles
  • +
  • Detects other OSC destinations via bonjour/zero-conf networking and automatically creates output ports so you can send data to them.
  • +
  • Input ports automagically advertise their presence via bonjour/zero-conf networking. This is as close to no-setup as it gets!
  • +
  • Supports the following data types: i (int32), f (float32), s/S (OSC-string), b (OSC blob), h (64-bit int), d (64-bit float/double), r (32-bit RGBA color), m (MIDI message), T (tru), F (false), N(nil), I (infinity), t (OSC-timetag)
  • +
  • Processing frequency defaults to 30hz, but may be adjusted dynamically well in excess of 100hz
  • +
  • Multithreaded- each input port runs on its own thread- and threadsafe.
  • +
  • Optional OSC address space classes (OSCNode & OSCAddressSpace) may be used to quickly create a simple OSC-based API for controlling software. Address space includes POSIX regex-based pattern matching engine for dispatching a single message to multiple nodes.
  • +
  • Built on a handful of small, easy-to-grok classes written specifically for OS X. Very easy to understand, modify, subclass, or extend.
  • +
  • Project includes targets that build and install an SDK for using VVOSC in iOS apps
  • +

    + +Breaks from the OSC specification +

    +
  • "char" data type not supported yet, you can use "string" in the meantime
  • +
  • It's possible to create an OSCValue from an NSString containing UTF8 characters, which VVOSC will try to send- and if the software receiving this data doesn't freak out, this allows you to UTF8 characters. In other words, VVOSC doesn't explicitly prevent the use of non-ASCII characters, so it's possible to use it to create incompatible OSC data!
  • +
  • The OSC specification describes a limited subset of regex to be used in wildcard/pattern matching for OSC dispatch. VVOSC's message dispatch is presently a POSIX regex engine simply because it was faster and easier to get going (it's built into the OS) than rolling my own. The specific engine used may change if message dispatch becomes a speed issue in the future; presumably, this ambiguity is why the OSC spec describes a specific and limited subset of regex!
  • +
  • The OSC spec describes the optional type characters [ and ] to delineate arrays and basic node-based structures for ad-hoc data types. Lacking any specific usage examples, this isn't supported yet- if someone wants to send me a specific example i can use to support this protocol properly, please let me know.
  • +
  • While VVOSC parses, stores, and allows you to set OSC time tags (and even create and pass time tags as values), it doesn't perform any delay or scheduling if it receives an OSC bundle with a time tag which is later than the current time. Parsed time tags are available to your applications as the 'timeTag' variable of a passed OSCMessage, which is stored as an NSDate (which, internally, is a double which basically represents 64-bit NTP time, as I understand it).
  • +

    + + +Sample code + +
    +// create an OSCManager- set myself up as its delegate
    +manager = [[OSCManager alloc] init];
    +[manager setDelegate:self];
    +
    +// create an input port for receiving OSC data
    +[manager createNewInputForPort:1234];
    +
    +// create an output so i can send OSC data to myself
    +outPort = [manager createNewOutputToAddress:@"127.0.0.1" atPort:1234];
    +
    +// make an OSC message
    +newMsg = [OSCMessage createWithAddress:@"/Address/Path/1"];
    +
    +// add a bunch arguments to the message
    +[newMsg addInt:12];
    +[newMsg addFloat:12.34];
    +[newMsg addColor:[NSColor colorWithDeviceRed:0.0 green:1.0 blue:0.0 alpha:1.0]];
    +[newMsg addBOOL:YES];
    +[newMsg addString:@"Hello World!"];
    +
    +// send the OSC message
    +[outPort sendThisMessage:newMsg];
    +
    + + +\endhtmlonly +*/ diff --git a/atemOSC/VVOSC.framework/Headers/lgpl-3.0.txt b/atemOSC/VVOSC.framework/Headers/lgpl-3.0.txt new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/atemOSC/VVOSC.framework/Headers/lgpl-3.0.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/atemOSC/VVOSC.framework/Resources b/atemOSC/VVOSC.framework/Resources deleted file mode 120000 index 953ee36..0000000 --- a/atemOSC/VVOSC.framework/Resources +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/Resources \ No newline at end of file diff --git a/atemOSC/VVOSC.framework/Resources/Info.plist b/atemOSC/VVOSC.framework/Resources/Info.plist new file mode 100644 index 0000000..ed0ff17 --- /dev/null +++ b/atemOSC/VVOSC.framework/Resources/Info.plist @@ -0,0 +1,38 @@ + + + + + BuildMachineOSBuild + 11E53 + CFBundleDevelopmentRegion + English + CFBundleExecutable + VVOSC + CFBundleGetInfoString + 156 + CFBundleIdentifier + com.vidvox.VVOSC + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 156 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E2002 + DTPlatformVersion + GM + DTSDKBuild + 11E53 + DTSDKName + + DTXcode + 0432 + DTXcodeBuild + 4E2002 + + diff --git a/atemOSC/VVOSC.framework/VVOSC b/atemOSC/VVOSC.framework/VVOSC deleted file mode 120000 index c6a43b0..0000000 --- a/atemOSC/VVOSC.framework/VVOSC +++ /dev/null @@ -1 +0,0 @@ -Versions/Current/VVOSC \ No newline at end of file diff --git a/atemOSC/VVOSC.framework/VVOSC b/atemOSC/VVOSC.framework/VVOSC new file mode 100755 index 0000000..3798306 Binary files /dev/null and b/atemOSC/VVOSC.framework/VVOSC differ diff --git a/atemOSC/VVOSC.framework/Versions/Current b/atemOSC/VVOSC.framework/Versions/Current deleted file mode 120000 index 8c7e5a6..0000000 --- a/atemOSC/VVOSC.framework/Versions/Current +++ /dev/null @@ -1 +0,0 @@ -A \ No newline at end of file diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCAddressSpace.h b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCAddressSpace.h new file mode 100644 index 0000000..966aa33 --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCAddressSpace.h @@ -0,0 +1,77 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "OSCNode.h" + + + + +// OSCAddressSpace delegate protocol +@protocol OSCAddressSpaceDelegateProtocol +- (void) nodeRenamed:(OSCNode *)n; +- (void) dispatchReplyOrError:(OSCMessage *)m; // this method is called by nodes in the address space. the passed message is a reply or error in response to a query which should be sent out an output. +@end + + + + +// this is the main instance of OSCAddressSpace. it is auto-created when this class is initialized +extern id _mainAddressSpace; + + + + +/// OSCAddressSpace is a representation of the OSC address space described in the OSC spec. It is a subclass of OSCNode. This class is optional- it's not needed for basic OSC message sending/receiving. +/*! +There should only ever be one instance of OSCAddressSpace, and you shouldn't explicitly create it. Just call [OSCAddressSpace class] (or any other OSCAddressSpace method) and it will be automatically created. This main instance may be retrieved by the class method +[OSCAddressSpace mainAddressSpace] or by the class variable _mainAddressSpace. + +OSCAddressSpace is your application's main way of dealing with the OSC address space- if you need to dispatch a message, set, rename, or delete a node, you should do via the main instance of this class. +*/ +@interface OSCAddressSpace : OSCNode { + id delegate; +} + +/// Returns the main instance of the OSC address space (and creates it if necessary) ++ (id) mainAddressSpace; ++ (void) refreshMenu; +#if !IPHONE ++ (NSMenu *) makeMenuForNode:(OSCNode *)n withTarget:(id)t action:(SEL)a; ++ (NSMenu *) makeMenuForNode:(OSCNode *)n ofType:(NSIndexSet *)ts withTarget:(id)t action:(SEL)a; +#endif + +/// Renames 'before' to 'after'. Sub-nodes stay with their owners! Can also be though of as a "move". +- (void) renameAddress:(NSString *)before to:(NSString *)after; +- (void) renameAddressArray:(NSArray *)before toArray:(NSArray *)after; + +/// If 'n' is nil, the node at the passed address will be deleted (as will any of its sub-nodes) +- (void) setNode:(OSCNode *)n forAddress:(NSString *)a; +- (void) setNode:(OSCNode *)n forAddress:(NSString *)a createIfMissing:(BOOL)c; +- (void) setNode:(OSCNode *)n forAddressArray:(NSArray *)a; +- (void) setNode:(OSCNode *)n forAddressArray:(NSArray *)a createIfMissing:(BOOL)c; + +// this method is called whenever a node is added to another node +- (void) nodeRenamed:(OSCNode *)n; + +/// Unlike a normal OSCNode, this method finds the destination node and then dispatches the msg. If the destination is itself, it just calls the super. +- (void) dispatchMessage:(OSCMessage *)m; +// This method gets called by an OSCNode inside me (or by me), and you probably won't need to ever call this method. The passed message is a reply or error that needs to be sent back in response to a query. The passed OSCMessage contains the IP address and port of the destination. This method just passes the data on to the addres space's delegate- it does NOT actually send anything out, this is something you'll have to implement in the delegate. +- (void) _dispatchReplyOrError:(OSCMessage *)m; + +- (void) addDelegate:(id)d forPath:(NSString *)p; +- (void) removeDelegate:(id)d forPath:(NSString *)p; +/* +- (void) addQueryDelegate:(id)d forPath:(NSString *)p; +- (void) removeQueryDelegate:(id)d forPath:(NSString *)p; +*/ +@property (assign, readwrite) id delegate; + + +@end + + + + + diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCBundle.h b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCBundle.h new file mode 100644 index 0000000..857d688 --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCBundle.h @@ -0,0 +1,46 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import "OSCMessage.h" + + + + +/// An OSCBundle is a "container" for multiple OSC messages or bundles (bundles may also be nested) +/*! +According to the OSC spec, an OSC bundle is basically a wrapper for multiple OSC messages (or other bundles). Instead of sending a bunch of individual messages, you can wrap them all into a bundle, and send the bundle (messages will still be sent to their individual address paths). OSCBundleÕs interface is correspondingly simple: you can create a bundle from some elements, or you can create a bundle and then add some elements (OSCMessages or OSCBundles) to it. + +OSC bundles also have a time stamp- by default, this will be set to immediate execution (0s except for a single 1 in the LSB). while timetag execution isn't widely supported, you may specify non-immediate time tags in the hopes that the software on the receiving end will execute the bundle in time. +*/ + + + + +@interface OSCBundle : NSObject { + NSMutableArray *elementArray; // array of messages or bundles + NSDate *timeTag; // nil by default, or the time at which the contents of this bundle should be dispatched +} + ++ (void) parseRawBuffer:(unsigned char *)b ofMaxLength:(int)l toInPort:(id)p inheritedTimeTag:(NSDate *)d fromAddr:(unsigned int)txAddr port:(unsigned short)txPort; +/// Creates and returns an auto-released bundle ++ (id) create; +/// Creates and returns an auto-released bundle with the single passed element ++ (id) createWithElement:(id)n; +/// Creates and returns an auto-released bundle with the array of passed elements ++ (id) createWithElementArray:(id)a; + +/// Adds the passed element to the bundle +- (void) addElement:(id)n; +/// Adds the array of passed elements to the bundle +- (void) addElementArray:(NSArray *)a; + +- (long) bufferLength; +- (void) writeToBuffer:(unsigned char *)b; + +@property (retain,readwrite) NSDate *timeTag; + +@end diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCConstants.h b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCConstants.h new file mode 100644 index 0000000..7261ae2 --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCConstants.h @@ -0,0 +1,131 @@ + +/*! +\file OSCConstants.h +\brief Constants and Macros used by one or more of the OSC classes in this framework +*/ + +/// OSCValueType +/*! +OSCValues have distinct types; these are used to describe the type of an OSCValue. +*/ +typedef enum { + OSCValInt = 1, //! +#else +#import +#endif + +#import +//#import +//#import +#import +#import +#import +#import "OSCPacket.h" +#import "OSCBundle.h" +#import "OSCMessage.h" +#import "OSCOutPort.h" + + + + +/// OSCInPort handles everything needed to receive OSC data on a given port +/*! +You should never create or destroy an instance of this class manually. OSCInPort instances should be created/destroyed by the OSCManager. + +Each OSCInPort is running in its own separate thread- so make sure anything called as a result of received OSC input is thread-safe! When OSCInPort receives data, it gets parsed and passed to the in port's delegate as a series of OSCMessages consisting of an address path and an OSCValue. By default, the inport's delegate is the manager which created it- and by default, managers pass this data on to *their* delegates (your objects/app). + +the documentation here only covers the basics, the header file for this class is small and heavily commented if you want to know more because you're heavily customizing OSCInPort. +*/ +@interface OSCInPort : NSObject { + BOOL deleted; // whether or not i'm deleted- ensures that socket gets closed + BOOL bound; // whether or not the socket is bound + OSSpinLock socketLock; + int sock; // socket file descriptor. remember, everything in unix is files! + struct sockaddr_in addr; // struct that describes *my* address (this is an in port) + unsigned short port; // the port number i'm receiving from + unsigned char buf[65506]; // the socket gets data and dumps it here immediately + + OSSpinLock scratchLock; + NSThread *thread; + //VVThreadLoop *threadLooper; + + NSString *portLabel; //! +#else +#import +#endif +#import "OSCAddressSpace.h" +#import "OSCZeroConfManager.h" +#import "OSCInPort.h" +#import "OSCOutPort.h" + + + + +/// Main VVOSC class- manages in & out port creation, zero configuration networking (bonjour/zeroconf) +/*! +The OSCManager will probably be the main class that you're working with: it creates/deletes inputs (which receive data) and outputs (which send data), passes any OSC data received to its delegate (your application), optionally handles distribution of all received OSC messages, and does other manager-ish things. You should only need one instance of OSCManager in your application. One of your objects should be OSCManager's delegate (see the "OSCDelegateProtocol" below) so you may receive OSC data. + +Incoming OSC data is initially received by an OSCInPort; fundamentally, in ports are running a loop which checks a socket for data received since the last loop. By default, the OSCInPort's delegate is the OSCManager which created it. Every time the loop runs, it passes the received data off to its delegate (the manager) as the raw address/value pairs in the order they're received. When the OSCManager receives data from its in port it immediately passes the received data to its delegate, which should respond to one of the following methods (referred to as the 'OSCDelegateProtocol'): + +\htmlonly +
    +@protocol OSCDelegateProtocol
    +- (void) receivedOSCMessage:(OSCMessage *)m;
    +@end +
    +\endhtmlonly + +...if you want to work with received OSC data, OSCManager's delegate must respond to this method! +*/ + + + + +@interface OSCManager : NSObject { + MutLockArray *inPortArray; // Array of OSCInPorts in a locking array for threadsafe access + MutLockArray *outPortArray; // Array of OSCOutPorts in a locking array for threadsafe access + + id delegate; //! +#else +#import +#endif +#import "OSCValue.h" +#import + + + + +/// Corresponds to an OSC message: contains zero or more values, and the address path the values have to get sent to. +/*! +According to the OSC spec, a message consists of an address path (where the message should be sent) and zero or more arguments. An OSCMessage must be created with an address path- once the OSCMessage exists, you may add as many arguments to it as you'd like. +*/ +@interface OSCMessage : NSObject { + NSString *address; //! 1 + + NSDate *timeTag; //! +#else +#import +#endif +#import "OSCMessage.h" +#import +#import +#import + + + + +@protocol OSCNodeDelegateProtocol +- (void) node:(id)n receivedOSCMessage:(id)msg; +- (void) nodeNameChanged:(id)node; +- (void) nodeDeleted:(id)node; +@end +/// An OSCNode's queryDelegate must respond to these methods, which are called when a query-type OSCMessage is dispatched to an OSCNode +@protocol OSCNodeQueryDelegateProtocol +- (NSMutableArray *) namespaceArrayForNode:(id)n; +- (NSString *) docStringForNode:(id)n; +- (NSString *) typeSignatureForNode:(id)n; +- (OSCValue *) currentValueForNode:(id)n; +- (NSString *) returnTypeStringForNode:(id)n; +@end + + + + +/// OSCNode describes a single destination for OSC addresses. The OSC address space is made up of many different nodes. This class is optional- it is not used for basic OSC message sending/receiving, and only gets used if you start working with OSCAddressSpace. +/*! +The OSC specification describes a slash-delineated address space- as messages are received, they are dispatched to the described address. An OSCNode represents a single unique destination in the OSC address space. OSCNodes may have subnodes and have a non-retaining reference to their parent node (unless they're top-level, in which case their parent node is nil). They retain a copy of the last message dispatched directly to this node for convenience. OSCNode instances have zero or more delegates- delegates are NOT retained, and are assumed to respond to all the methods in OSCNOdeDelegateProtocol. + +If you want to work with an instance of OSCNode, you need to acquire or work with it from the main OSCAddressSpace. Do not just start creating OSCNode instances willy-nilly; there's no point, they're only useful if they're part of an address space. + +Generally speaking, it's a good idea for each instance of OSCNode to have a discrete type, as this makes it easier to browse and filter the hierarchy of OSCNode instances that make up the OSC address space. Most of the documented methods here are simply for querying basic properties of the OSCNode instance or doing simple message dispatch. +*/ + + + + +@interface OSCNode : NSObject { + id addressSpace; // the class OSCAddressSpace is a subclass of OSCNode, and is essentially the "root" node. all OSCNodes have a pointer to the root node! + BOOL deleted; + + OSSpinLock nameLock; + NSString *nodeName; /// "local" name: name of the node at /a/b/c is "c" + NSString *fullName; /// "full" name: name of the node at /a/b/c is "/a/b/c" + MutLockArray *nodeContents; /// Contains OSCNode instances- this OSCNode's sub-nodes. type 'MutLockArray'- this should all be threadsafe... + OSCNode *parentNode; // my "parent" node (or nil). NOT retained! + OSCNodeType nodeType; /// What 'type' of node i am + BOOL hiddenInMenu; // NO by default. if YES, this node (and all its sub-nodes) will be omitted from menus! + + OSCMessage *lastReceivedMessage; /// The last message sent to this node is retained (the message is retained instead of the value because messages can have multiple values) + OSSpinLock lastReceivedMessageLock; + MutNRLockArray *delegateArray; // type 'MutNRLockArray'. contents are NOT retained! could be anything! + + BOOL autoQueryReply; // NO by default. if YES and the queryDelegate is nil or doesn't respond to one of the delegate methods or returns nil from one of the delegate methods, the OSCNode will try to automatically respond to the query + id queryDelegate; // nil by default, NOT retained; unlike "normal" delegates, an OSCNode has a single query delegate +} + +// only called by the address space to craft a formatted string for logging purposes +- (void) _logDescriptionToString:(NSMutableString *)s tabDepth:(int)d; + ++ (id) createWithName:(NSString *)n; +- (id) initWithName:(NSString *)n; +- (id) init; +- (void) prepareToBeDeleted; + +// convenience method so nodes may be sorted by name +- (NSComparisonResult) nodeNameCompare:(OSCNode *)comp; + +// "local" add/remove/find methods for working with my node contents +- (void) addLocalNode:(OSCNode *)n; +- (void) addLocalNodes:(NSArray *)n; +- (void) removeLocalNode:(OSCNode *)n; // this just removes the passed node from my 'nodeContents' array- doesn't assume that the passed node will be released! +- (void) deleteLocalNode:(OSCNode *)n; // calls 'prepareToBeDeleted' on the passed node- call this is if you want to make sure that the passed node will stop sending delegate messages/etc! +- (void) removeFromAddressSpace; // tries to remove me from the OSCAddressSpace singleton by setting my fullName to nil + +/// It's assumed that the passed name doesn't have any wildcards/regex. If the receiver contains a node with the identical name as the passed string, the node will be returned. This is not a "deep" search, it's restricted to the receiver's nodeContents array. +- (OSCNode *) findLocalNodeNamed:(NSString *)n; +/// Same as findLocalNodeNamed:, but if any of the interim nodes don't exist they will be created. +- (OSCNode *) findLocalNodeNamed:(NSString *)n createIfMissing:(BOOL)c; + +/// Compares the names of all the receiver's sub-nodes to the passed POSIX regex string, returns an array with all the nodes whose nodeNames match the regex. If there are no sub-nodes or none of the sub-nodes match the regex, returns nil. +- (NSMutableArray *) findLocalNodesMatchingPOSIXRegex:(NSString *)regex; +- (void) _addLocalNodesMatchingRegex:(NSString *)regex toMutArray:(NSMutableArray *)a; + + +/// Calls findNodeForAddress:createIfMissing:NO. +// these find methods do NOT work with regex! it is assumed that the passed string is NOT a regex algorithm! +- (OSCNode *) findNodeForAddress:(NSString *)p; +/// It's assumed that the passed address doesn't have any wildcards/regex (no checking is done). The receiver tries to locate the node at the passed address (relative to the receiver). If c is YES, any OSCNodes missing in the passed address are automatically created. If they have sub-nodes, the auto-created nodes' types are set to OSCNodeDirectory; if not, the auto-created nodes' types are OSCNodeTypeUnknown +- (OSCNode *) findNodeForAddress:(NSString *)p createIfMissing:(BOOL)c; +- (OSCNode *) findNodeForAddressArray:(NSArray *)a; +- (OSCNode *) findNodeForAddressArray:(NSArray *)a createIfMissing:(BOOL)c; +// these find methods work with regex! path components may be regex strings- this returns all the nodes that match every component in the passed address/address array! +- (NSMutableArray *) findNodesMatchingAddress:(NSString *)a; +- (NSMutableArray *) findNodesMatchingAddressArray:(NSArray *)a; + +// a node's delegate is informed of received osc messages or name changes (OSCNodeDelegateProtocol) +// NODE DELEGATES ARE __NOT__ RETAINED! +// NODE DELEGATES __MUST__ REMOVE THEMSELVES FROM THE DELEGATE ARRAY! +- (void) addDelegate:(id)d; +- (void) removeDelegate:(id)d; +- (void) informDelegatesOfNameChange; +- (void) addDelegatesFromNode:(OSCNode *)n; + +/// Sends the passed message to all of the node's delegates- it does NOT parse the address at all (it's assumed that the passed message's address points to this instance of OSCNode). If the passed message is a query, this tries to assemble a reply (either from the queryDelegate or automatically if autoQueryReply is enabled) which is sent to the main address space. +- (void) dispatchMessage:(OSCMessage *)m; + +@property (assign, readwrite) id addressSpace; +@property (assign, readwrite) NSString *nodeName; +- (void) _setNodeName:(NSString *)n; +@property (readonly) NSString *fullName; +@property (readonly) id nodeContents; +@property (assign, readwrite) OSCNode *parentNode; +@property (assign, readwrite) int nodeType; +@property (assign, readwrite) BOOL hiddenInMenu; +@property (readonly) OSCMessage *lastReceivedMessage; +@property (readonly) OSCValue *lastReceivedValue; +@property (readonly) id delegateArray; +//@property (readonly) id queryDelegateArray; +@property (assign,readwrite) BOOL autoQueryReply; +@property (assign,readwrite) id queryDelegate; + +@end diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCOutPort.h b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCOutPort.h new file mode 100644 index 0000000..091b593 --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCOutPort.h @@ -0,0 +1,71 @@ + +#if IPHONE +#import +#else +#import +#endif + + +#include + +#import "OSCPacket.h" +#import "OSCBundle.h" +#import "OSCMessage.h" + + + + +/// OSCOutPort handles everything needed to send OSC data to a given address +/*! +You should never create or destroy an instance of this class manually. OSCOutPort instances should be created/destroyed by the OSCManager. + +the documentation here only covers the basics, the header file for this class is small and heavily commented if you want to know more because you're heavily customizing OSCOutPort. +*/ +@interface OSCOutPort : NSObject { + BOOL deleted; + int sock; + struct sockaddr_in addr; + unsigned short port; //! +#else +#import +#endif + +#include +#import "OSCBundle.h" +#import "OSCMessage.h" + + + +/// Used to parse raw OSC data or to assemble raw OSC data from OSCMessages/OSCBundles +/*! +An OSC packet is the basic unit of transmitting OSC data- the OSCPacket class is mostly used internally to either parse received raw data or to assemble raw data from OSCMessages/OSCBundles for sending. +*/ + +@interface OSCPacket : NSObject { + long bufferLength; + unsigned char *payload; +} + ++ (void) parseRawBuffer:(unsigned char *)b ofMaxLength:(int)l toInPort:(id)p fromAddr:(unsigned int)txAddr port:(unsigned short)txPort; +/// Creates & returns an auto-released packet from either an OSCBundle or an OSCMessage ++ (id) createWithContent:(id)c; +- (id) initWithContent:(id)c; + +- (long) bufferLength; +- (unsigned char *) payload; + +@end diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCStringAdditions.h b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCStringAdditions.h new file mode 100644 index 0000000..48146c2 --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCStringAdditions.h @@ -0,0 +1,49 @@ + +#if IPHONE +#import +#else +#import +#endif +#import +#import + + + + +extern NSCharacterSet *_OSCStrAdditionsWildcardCharSet; +extern MutLockDict *_OSCStrPOSIXRegexDict; // key is the regex string, object is an OSCPOSIXRegExpHolder containing the compiled regex- which is threadsafe, and may be reused + + + + +@interface OSCPOSIXRegExpHolder : NSObject { + NSString *regexString; + regex_t *regex; +} + ++ (id) createWithString:(NSString *)n; +- (id) initWithString:(NSString *)n; +- (BOOL) evalAgainstString:(NSString *)n; +- (NSString *) regexString; + +@end + + + + +@interface NSString (OSCStringAdditions) + ++ (NSString *) stringWithBytes:(const void *)b length:(NSUInteger)l encoding:(NSStringEncoding)e; ++ (NSString *) stringFromRawIPAddress:(unsigned long)i; +- (NSString *) trimFirstAndLastSlashes; +- (NSString *) stringByDeletingFirstPathComponent; +- (NSString *) firstPathComponent; +- (NSString *) stringBySanitizingForOSCPath; +- (NSString *) stringByDeletingLastAndAddingFirstSlash; +- (BOOL) containsOSCWildCard; + +- (BOOL) predicateMatchAgainstRegex:(NSString *)r; +- (BOOL) posixMatchAgainstSlowRegex:(NSString *)r; +- (BOOL) posixMatchAgainstFastRegex:(NSString *)r; + +@end diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCValue.h b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCValue.h new file mode 100644 index 0000000..fd0ea5e --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCValue.h @@ -0,0 +1,107 @@ + +#if IPHONE +#import +#else +#import +#endif +#import "OSCConstants.h" + + + + +/// OSCValue encapsulates any value you can send or receive via OSC. It is NOT mutable at this time. +/*! +When you send or receive values via OSC, you'll be working with OSCValue objects in an OSCMessage. Internally, OSCValue isn't mutable, and it attempts to store its value in its native format (int for an int, float for a float) instead of relying on NSNumber. The exceptions to this are NSColor/UIColor and NSString. +*/ + + + + +@interface OSCValue : NSObject { + OSCValueType type; //! +#import +#else +#import +#endif +//#import +#import +#import +#import +#import +#include + + + +#if IPHONE +@interface OSCZeroConfDomain : NSObject { +#else +@interface OSCZeroConfDomain : NSObject { +#endif + NSString *domainString; + NSNetServiceBrowser *serviceBrowser; + + MutLockArray *servicesArray; + + id domainManager; +} + ++ (id) createWithDomain:(NSString *)d andDomainManager:(id)m; +- (id) initWithDomain:(NSString *)d andDomainManager:(id)m; + +// NSNetServiceBrowser delegate methods +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didFindService:(NSNetService *)x moreComing:(BOOL)m; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didNotSearch:(NSDictionary *)err; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didRemoveService:(NSNetService *)s moreComing:(BOOL)m; + +// NSNetService delegate methods +- (void)netService:(NSNetService *)n didNotResolve:(NSDictionary *)err; +- (void)netServiceDidResolveAddress:(NSNetService *)n; + +@end diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCZeroConfManager.h b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCZeroConfManager.h new file mode 100644 index 0000000..c1795ab --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/OSCZeroConfManager.h @@ -0,0 +1,37 @@ + +#if IPHONE +#import +#else +#import +#endif + +#import +#import "OSCZeroConfDomain.h" +#import + + + + +#if IPHONE +@interface OSCZeroConfManager : NSObject { +#else +@interface OSCZeroConfManager : NSObject { +#endif + NSNetServiceBrowser *domainBrowser; + + NSMutableDictionary *domainDict; + pthread_rwlock_t domainLock; + + id oscManager; +} + +- (id) initWithOSCManager:(id)m; + +- (void) serviceRemoved:(NSNetService *)s; +- (void) serviceResolved:(NSNetService *)s; + +// NSNetServiceBrowser delegate methods +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didFindDomain:(NSString *)d moreComing:(BOOL)m; +- (void)netServiceBrowser:(NSNetServiceBrowser *)n didNotSearch:(NSDictionary *)err; + +@end diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/VVOSC.h b/atemOSC/VVOSC.framework/Versions/Current/Headers/VVOSC.h new file mode 100644 index 0000000..47eeb3a --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/VVOSC.h @@ -0,0 +1,121 @@ + + +#import "OSCConstants.h" + +#import "OSCValue.h" +#import "OSCMessage.h" +#import "OSCBundle.h" +#import "OSCPacket.h" + +#import "OSCOutPort.h" +#import "OSCInPort.h" + +#import "OSCManager.h" +#import "OSCZeroConfManager.h" + +#import "OSCNode.h" +#import "OSCAddressSpace.h" + +#import "OSCStringAdditions.h" + + + + +/// Most common means of passing OSC data to your application. Delegates of OSCManager and OSCInPort should support this protocol. +/*! +When instances of OSCInPort and OSCManager receive OSC data, they pass it to their delegate by calling this method. If you want to receive OSC data, your OSCManager's delegate must respond to this method! +*/ +@protocol OSCDelegateProtocol +/// This method is called whenever your in port/manager receives an OSCMessage. +- (void) receivedOSCMessage:(OSCMessage *)m; +@end + + + + +/* + the following stuff is for doxygen +*/ + + +/*! +\mainpage + +\htmlonly + + + + +Introduction +

    +VVOSC is an Objective-c framework for assembling, sending, and receiving OSC (Open Sound Control) messages on OS X. A simple sample application (gui) which sends and receives OSC messages is also included to aid in the debugging of your software. There's also an SDK which allows you to develop iPhone applications which use VVOSC. All the source code is available on the project homepage: http://code.google.com/p/vvopensource +

    + + +Features and Capabilities +

    +

  • Includes a sample GUI app for debugging OSC applications and hardware that also demonstrates use of the framework
  • +
  • Packet parsing (client) + construction (server)
  • +
  • Creates bundles/nested bundles, safely parse bundles/nested bundles
  • +
  • Detects other OSC destinations via bonjour/zero-conf networking and automatically creates output ports so you can send data to them.
  • +
  • Input ports automagically advertise their presence via bonjour/zero-conf networking. This is as close to no-setup as it gets!
  • +
  • Supports the following data types: i (int32), f (float32), s/S (OSC-string), b (OSC blob), h (64-bit int), d (64-bit float/double), r (32-bit RGBA color), m (MIDI message), T (tru), F (false), N(nil), I (infinity), t (OSC-timetag)
  • +
  • Processing frequency defaults to 30hz, but may be adjusted dynamically well in excess of 100hz
  • +
  • Multithreaded- each input port runs on its own thread- and threadsafe.
  • +
  • Optional OSC address space classes (OSCNode & OSCAddressSpace) may be used to quickly create a simple OSC-based API for controlling software. Address space includes POSIX regex-based pattern matching engine for dispatching a single message to multiple nodes.
  • +
  • Built on a handful of small, easy-to-grok classes written specifically for OS X. Very easy to understand, modify, subclass, or extend.
  • +
  • Project includes targets that build and install an SDK for using VVOSC in iOS apps
  • +

    + +Breaks from the OSC specification +

    +
  • "char" data type not supported yet, you can use "string" in the meantime
  • +
  • It's possible to create an OSCValue from an NSString containing UTF8 characters, which VVOSC will try to send- and if the software receiving this data doesn't freak out, this allows you to UTF8 characters. In other words, VVOSC doesn't explicitly prevent the use of non-ASCII characters, so it's possible to use it to create incompatible OSC data!
  • +
  • The OSC specification describes a limited subset of regex to be used in wildcard/pattern matching for OSC dispatch. VVOSC's message dispatch is presently a POSIX regex engine simply because it was faster and easier to get going (it's built into the OS) than rolling my own. The specific engine used may change if message dispatch becomes a speed issue in the future; presumably, this ambiguity is why the OSC spec describes a specific and limited subset of regex!
  • +
  • The OSC spec describes the optional type characters [ and ] to delineate arrays and basic node-based structures for ad-hoc data types. Lacking any specific usage examples, this isn't supported yet- if someone wants to send me a specific example i can use to support this protocol properly, please let me know.
  • +
  • While VVOSC parses, stores, and allows you to set OSC time tags (and even create and pass time tags as values), it doesn't perform any delay or scheduling if it receives an OSC bundle with a time tag which is later than the current time. Parsed time tags are available to your applications as the 'timeTag' variable of a passed OSCMessage, which is stored as an NSDate (which, internally, is a double which basically represents 64-bit NTP time, as I understand it).
  • +

    + + +Sample code + +
    +// create an OSCManager- set myself up as its delegate
    +manager = [[OSCManager alloc] init];
    +[manager setDelegate:self];
    +
    +// create an input port for receiving OSC data
    +[manager createNewInputForPort:1234];
    +
    +// create an output so i can send OSC data to myself
    +outPort = [manager createNewOutputToAddress:@"127.0.0.1" atPort:1234];
    +
    +// make an OSC message
    +newMsg = [OSCMessage createWithAddress:@"/Address/Path/1"];
    +
    +// add a bunch arguments to the message
    +[newMsg addInt:12];
    +[newMsg addFloat:12.34];
    +[newMsg addColor:[NSColor colorWithDeviceRed:0.0 green:1.0 blue:0.0 alpha:1.0]];
    +[newMsg addBOOL:YES];
    +[newMsg addString:@"Hello World!"];
    +
    +// send the OSC message
    +[outPort sendThisMessage:newMsg];
    +
    + + +\endhtmlonly +*/ diff --git a/atemOSC/VVOSC.framework/Versions/Current/Headers/lgpl-3.0.txt b/atemOSC/VVOSC.framework/Versions/Current/Headers/lgpl-3.0.txt new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Headers/lgpl-3.0.txt @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/atemOSC/VVOSC.framework/Versions/Current/Resources/Info.plist b/atemOSC/VVOSC.framework/Versions/Current/Resources/Info.plist new file mode 100644 index 0000000..ed0ff17 --- /dev/null +++ b/atemOSC/VVOSC.framework/Versions/Current/Resources/Info.plist @@ -0,0 +1,38 @@ + + + + + BuildMachineOSBuild + 11E53 + CFBundleDevelopmentRegion + English + CFBundleExecutable + VVOSC + CFBundleGetInfoString + 156 + CFBundleIdentifier + com.vidvox.VVOSC + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleSignature + ???? + CFBundleVersion + 156 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4E2002 + DTPlatformVersion + GM + DTSDKBuild + 11E53 + DTSDKName + + DTXcode + 0432 + DTXcodeBuild + 4E2002 + + diff --git a/atemOSC/VVOSC.framework/Versions/Current/VVOSC b/atemOSC/VVOSC.framework/Versions/Current/VVOSC new file mode 100755 index 0000000..3798306 Binary files /dev/null and b/atemOSC/VVOSC.framework/Versions/Current/VVOSC differ diff --git a/atemOSC/arduino/AMSDKCompatibility.h b/atemOSC/arduino/AMSDKCompatibility.h new file mode 100644 index 0000000..efa0310 --- /dev/null +++ b/atemOSC/arduino/AMSDKCompatibility.h @@ -0,0 +1,37 @@ +// +// AMSDKCompatibility.h +// +// Created by Nick Zitzmann on 2007-10-22. +// + +// AMSerialPort uses types that were introduced with the 10.5 SDK. +// This allows older SDKs to be used. + +#import + +#ifndef NSINTEGER_DEFINED + #ifdef NS_BUILD_32_LIKE_64 + typedef long NSInteger; + typedef unsigned long NSUInteger; + #else + typedef int NSInteger; + typedef unsigned int NSUInteger; + #endif + #define NSIntegerMax LONG_MAX + #define NSIntegerMin LONG_MIN + #define NSUIntegerMax ULONG_MAX + #define NSINTEGER_DEFINED 1 +#endif + +#ifndef CGFLOAT_DEFINED + typedef float CGFloat; + #define CGFLOAT_MIN FLT_MIN + #define CGFLOAT_MAX FLT_MAX + #define CGFLOAT_IS_DOUBLE 0 + #define CGFLOAT_DEFINED 1 +#endif + +#ifndef _SUSECONDS_T +#define _SUSECONDS_T +typedef int suseconds_t; +#endif diff --git a/atemOSC/arduino/AMSerialErrors.h b/atemOSC/arduino/AMSerialErrors.h new file mode 100644 index 0000000..22fd3c9 --- /dev/null +++ b/atemOSC/arduino/AMSerialErrors.h @@ -0,0 +1,29 @@ +/* + * AMSerialErrors.h + * + * Created by Andreas on 27.07.06. + * Copyright 2006 Andreas Mayer. All rights reserved. + * + */ + + +enum { + kAMSerialErrorNone = 0, + kAMSerialErrorFatal = 99, + + // reading only + kAMSerialErrorTimeout = 100, + kAMSerialErrorInternalBufferFull = 101, + + // writing only + kAMSerialErrorNoDataToWrite = 200, + kAMSerialErrorOnlySomeDataWritten = 201, +}; + +enum { + // reading only + kAMSerialEndOfStream = 0, + kAMSerialStopCharReached = 1, + kAMSerialStopLengthReached = 2, + kAMSerialStopLengthExceeded = 3, +}; diff --git a/atemOSC/arduino/AMSerialPort.h b/atemOSC/arduino/AMSerialPort.h new file mode 100644 index 0000000..031e61c --- /dev/null +++ b/atemOSC/arduino/AMSerialPort.h @@ -0,0 +1,263 @@ +// +// AMSerialPort.h +// +// Created by Andreas on 2002-04-24. +// Copyright (c) 2001 Andreas Mayer. All rights reserved. +// +// +// +// 2002-09-18 Andreas Mayer +// - added available & owner +// 2002-10-17 Andreas Mayer +// - countWriteInBackgroundThreads and countWriteInBackgroundThreadsLock added +// 2002-10-25 Andreas Mayer +// - more additional instance variables for reading and writing in background +// 2004-02-10 Andreas Mayer +// - added delegate for background reading/writing +// 2005-04-04 Andreas Mayer +// - added setDTR and clearDTR +// 2006-07-28 Andreas Mayer +// - added -canonicalMode, -endOfLineCharacter and friends +// (code contributed by Randy Bradley) +// - cleaned up accessor methods; moved deprecated methods to "Deprecated" category +// - -setSpeed: does support arbitrary values on 10.4 and later; returns YES on success, NO otherwiese +// 2006-08-16 Andreas Mayer +// - cleaned up the code and removed some (presumably) unnecessary locks +// 2007-10-26 Sean McBride +// - made code 64 bit and garbage collection clean +// 2009-3-20 Pat O'Keefe +// - fixed setSpeed method + + +/* + * Standard speeds defined in termios.h + * +#define B0 0 +#define B50 50 +#define B75 75 +#define B110 110 +#define B134 134 +#define B150 150 +#define B200 200 +#define B300 300 +#define B600 600 +#define B1200 1200 +#define B1800 1800 +#define B2400 2400 +#define B4800 4800 +#define B7200 7200 +#define B9600 9600 +#define B14400 14400 +#define B19200 19200 +#define B28800 28800 +#define B38400 38400 +#define B57600 57600 +#define B76800 76800 +#define B115200 115200 +#define B230400 230400 + */ + +#import "AMSDKCompatibility.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#import + +#define AMSerialOptionServiceName @"AMSerialOptionServiceName" +#define AMSerialOptionSpeed @"AMSerialOptionSpeed" +#define AMSerialOptionDataBits @"AMSerialOptionDataBits" +#define AMSerialOptionParity @"AMSerialOptionParity" +#define AMSerialOptionStopBits @"AMSerialOptionStopBits" +#define AMSerialOptionInputFlowControl @"AMSerialOptionInputFlowControl" +#define AMSerialOptionOutputFlowControl @"AMSerialOptionOutputFlowControl" +#define AMSerialOptionEcho @"AMSerialOptionEcho" +#define AMSerialOptionCanonicalMode @"AMSerialOptionCanonicalMode" + +// By default, debug code is preprocessed out. If you would like to compile with debug code enabled, +// "#define AMSerialDebug" before including any AMSerialPort headers, as in your prefix header + +typedef enum { + kAMSerialParityNone = 0, + kAMSerialParityOdd = 1, + kAMSerialParityEven = 2 +} AMSerialParity; + +typedef enum { + kAMSerialStopBitsOne = 1, + kAMSerialStopBitsTwo = 2 +} AMSerialStopBits; + +// Private constant +#define AMSER_MAXBUFSIZE 512UL//4096UL + +extern NSString *const AMSerialErrorDomain; + +@interface NSObject (AMSerialDelegate) +- (void)serialPortReadData:(NSDictionary *)dataDictionary; +- (void)serialPortWriteProgress:(NSDictionary *)dataDictionary; +@end + +@interface AMSerialPort : NSObject +{ +@private + NSString *bsdPath; + NSString *serviceName; + NSString *serviceType; + int fileDescriptor; + struct termios * __strong options; + struct termios * __strong originalOptions; + NSMutableDictionary *optionsDictionary; + NSFileHandle *fileHandle; + BOOL gotError; + int lastError; + id owner; + // used by AMSerialPortAdditions only: + char * __strong buffer; + id am_readTarget; + SEL am_readSelector; + NSTimeInterval readTimeout; // for public blocking read methods and doRead + fd_set * __strong readfds; + id delegate; + BOOL delegateHandlesReadInBackground; + BOOL delegateHandlesWriteInBackground; + + NSLock *writeLock; + BOOL stopWriteInBackground; + int countWriteInBackgroundThreads; + NSLock *readLock; + BOOL stopReadInBackground; + int countReadInBackgroundThreads; + NSLock *closeLock; +} + +- (id)init:(NSString *)path withName:(NSString *)name type:(NSString *)serialType; +// initializes port +// path is a bsdPath +// name is an IOKit service name +// type is an IOKit service type + +- (NSString *)bsdPath; +// bsdPath (e.g. '/dev/cu.modem') + +- (NSString *)name; +// IOKit service name (e.g. 'modem') + +- (NSString *)type; +// IOKit service type (e.g. kIOSerialBSDRS232Type) + +- (NSDictionary *)properties; +// IORegistry entry properties - see IORegistryEntryCreateCFProperties() + + +- (BOOL)isOpen; +// YES if port is open + +- (AMSerialPort *)obtainBy:(id)sender; +// get this port exclusively; NULL if it's not free + +- (void)free; +// give it back (and close the port if still open) + +- (BOOL)available; +// check if port is free and can be obtained + +- (id)owner; +// who obtained the port? + + +- (NSFileHandle *)open; +// opens port for read and write operations +// to actually read or write data use the methods provided by NSFileHandle +// (alternatively you may use those from AMSerialPortAdditions) + +- (void)close; +// close port - no more read or write operations allowed + +- (BOOL)drainInput; +- (BOOL)flushInput:(BOOL)fIn Output:(BOOL)fOut; // (fIn or fOut) must be YES +- (BOOL)sendBreak; + +- (BOOL)setDTR; +// set DTR - not yet tested! + +- (BOOL)clearDTR; +// clear DTR - not yet tested! + +// read and write serial port settings through a dictionary + +- (NSDictionary *)options; +// will open the port to get options if neccessary + +- (void)setOptions:(NSDictionary *)options; +// AMSerialOptionServiceName HAS to match! You may NOT switch ports using this +// method. + +// reading and setting parameters is only useful if the serial port is already open +- (long)speed; +- (BOOL)setSpeed:(long)speed; + +- (unsigned long)dataBits; +- (void)setDataBits:(unsigned long)bits; // 5 to 8 (5 may not work) + +- (AMSerialParity)parity; +- (void)setParity:(AMSerialParity)newParity; + +- (AMSerialStopBits)stopBits; +- (void)setStopBits:(AMSerialStopBits)numBits; + +- (BOOL)echoEnabled; +- (void)setEchoEnabled:(BOOL)echo; + +- (BOOL)RTSInputFlowControl; +- (void)setRTSInputFlowControl:(BOOL)rts; + +- (BOOL)DTRInputFlowControl; +- (void)setDTRInputFlowControl:(BOOL)dtr; + +- (BOOL)CTSOutputFlowControl; +- (void)setCTSOutputFlowControl:(BOOL)cts; + +- (BOOL)DSROutputFlowControl; +- (void)setDSROutputFlowControl:(BOOL)dsr; + +- (BOOL)CAROutputFlowControl; +- (void)setCAROutputFlowControl:(BOOL)car; + +- (BOOL)hangupOnClose; +- (void)setHangupOnClose:(BOOL)hangup; + +- (BOOL)localMode; +- (void)setLocalMode:(BOOL)local; // YES = ignore modem status lines + +- (BOOL)canonicalMode; +- (void)setCanonicalMode:(BOOL)flag; + +- (char)endOfLineCharacter; +- (void)setEndOfLineCharacter:(char)eol; + +- (void)clearError; // call this before changing any settings +- (BOOL)commitChanges; // call this after using any of the above set... functions +- (int)errorCode; // if -commitChanges returns NO, look here for further info + +// setting the delegate (for background reading/writing) + +- (id)delegate; +- (void)setDelegate:(id)newDelegate; + +// time out for blocking reads in seconds +- (NSTimeInterval)readTimeout; +- (void)setReadTimeout:(NSTimeInterval)aReadTimeout; + +- (void)readTimeoutAsTimeval:(struct timeval*)timeout; + + +@end diff --git a/atemOSC/arduino/AMSerialPort.m b/atemOSC/arduino/AMSerialPort.m new file mode 100644 index 0000000..eefae20 --- /dev/null +++ b/atemOSC/arduino/AMSerialPort.m @@ -0,0 +1,784 @@ +// +// AMSerialPort.m +// +// Created by Andreas on 2002-04-24. +// Copyright (c) 2001 Andreas Mayer. All rights reserved. +// +// 2002-09-18 Andreas Mayer +// - added available & owner +// 2002-10-10 Andreas Mayer +// - some log messages changed +// 2002-10-25 Andreas Mayer +// - additional locks and other changes for reading and writing in background +// 2003-11-26 James Watson +// - in dealloc [self close] reordered to execute before releasing closeLock +// 2007-05-22 Nick Zitzmann +// - added -hash and -isEqual: methods +// 2007-07-18 Sean McBride +// - behaviour change: -open and -close must now always be matched, -dealloc checks this +// - added -debugDescription so gdb's 'po' command gives something useful +// 2007-07-25 Andreas Mayer +// - replaced -debugDescription by -description; works for both, gdb's 'po' and NSLog() +// 2007-10-26 Sean McBride +// - made code 64 bit and garbage collection clean +// 2009-3-20 Pat O'Keefe +// - fixed setSpeed method + + +#import "AMSDKCompatibility.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#import "AMSerialPort.h" +#import "AMSerialErrors.h" + +#import +#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) + #import +#endif + +NSString *const AMSerialErrorDomain = @"de.harmless.AMSerial.ErrorDomain"; + + +@implementation AMSerialPort + +- (id)init:(NSString *)path withName:(NSString *)name type:(NSString *)type + // path is a bsdPath + // name is an IOKit service name +{ + if ((self = [super init])) { + bsdPath = [path copy]; + serviceName = [name copy]; + serviceType = [type copy]; + optionsDictionary = [[NSMutableDictionary dictionaryWithCapacity:8] retain]; +#ifndef __OBJC_GC__ + options = (struct termios*)malloc(sizeof(*options)); + originalOptions = (struct termios*)malloc(sizeof(*originalOptions)); + buffer = (char*)malloc(AMSER_MAXBUFSIZE); + readfds = (fd_set*)malloc(sizeof(*readfds)); +#else + options = (struct termios*)NSAllocateCollectable(sizeof(*options), 0); + originalOptions = (struct termios*)NSAllocateCollectable(sizeof(*originalOptions), 0); + buffer = (char*)NSAllocateCollectable(AMSER_MAXBUFSIZE, 0); + readfds = (fd_set*)NSAllocateCollectable(sizeof(*readfds), 0); +#endif + fileDescriptor = -1; + + writeLock = [[NSLock alloc] init]; + readLock = [[NSLock alloc] init]; + closeLock = [[NSLock alloc] init]; + + // By default blocking read attempts will timeout after 1 second + [self setReadTimeout:1.0]; + } + return self; +} + +#ifndef __OBJC_GC__ + +- (void)dealloc +{ +#ifdef AMSerialDebug + if (fileDescriptor != -1) + NSLog(@"It is a programmer error to have not called -close on an AMSerialPort you have opened"); +#endif + + [readLock release]; + [writeLock release]; + [closeLock release]; + [am_readTarget release]; + + free(readfds); + free(buffer); + free(originalOptions); + free(options); + [optionsDictionary release]; + [serviceName release]; + [serviceType release]; + [bsdPath release]; + [super dealloc]; +} + +#else + +- (void)finalize +{ +#ifdef AMSerialDebug + if (fileDescriptor != -1) + NSLog(@"It is a programmer error to have not called -close on an AMSerialPort you have opened"); +#endif + assert (fileDescriptor == -1); + + [super finalize]; +} + +#endif + +// So NSLog and gdb's 'po' command give something useful +- (NSString *)description +{ + NSString *result= [NSString stringWithFormat:@"<%@: %lx = name: %@, path: %@, type: %@, fileHandle: %@, fileDescriptor: %d>", NSStringFromClass([self class]), (long unsigned)self, serviceName, bsdPath, serviceType, fileHandle, fileDescriptor]; + return result; +} + +- (NSUInteger)hash +{ + return [[self bsdPath] hash]; +} + +- (BOOL)isEqual:(id)otherObject +{ + if ([otherObject isKindOfClass:[AMSerialPort class]]) + return [[self bsdPath] isEqualToString:[otherObject bsdPath]]; + return NO; +} + + +- (id)delegate +{ + return delegate; +} + +- (void)setDelegate:(id)newDelegate +{ + id old = nil; + + if (newDelegate != delegate) { + old = delegate; + delegate = [newDelegate retain]; + [old release]; + delegateHandlesReadInBackground = [delegate respondsToSelector:@selector(serialPortReadData:)]; + delegateHandlesWriteInBackground = [delegate respondsToSelector:@selector(serialPortWriteProgress:)]; + } +} + + +- (NSString *)bsdPath +{ + return bsdPath; +} + +- (NSString *)name +{ + return serviceName; +} + +- (NSString *)type +{ + return serviceType; +} + +- (NSDictionary *)properties +{ + NSDictionary *result = nil; + kern_return_t kernResult; + CFMutableDictionaryRef matchingDictionary; + io_service_t serialService; + + matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue); + CFDictionarySetValue(matchingDictionary, CFSTR(kIOTTYDeviceKey), (CFStringRef)[self name]); + if (matchingDictionary != NULL) { + CFRetain(matchingDictionary); + // This function decrements the refcount of the dictionary passed it + serialService = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDictionary); + + if (serialService) { + NSMutableDictionary *propertiesDict; + kernResult = IORegistryEntryCreateCFProperties(serialService, (CFMutableDictionaryRef *)&propertiesDict, kCFAllocatorDefault, 0); + if (kernResult == KERN_SUCCESS) { + result = [propertiesDict autorelease]; + } + } else { +#ifdef AMSerialDebug + NSLog(@"properties: no matching service for %@", matchingDictionary); +#endif + } + CFRelease(matchingDictionary); + // We have sucked this service dry of information so release it now. + (void)IOObjectRelease(serialService); + } + return result; +} + + +- (BOOL)isOpen +{ + // YES if port is open + return (fileDescriptor >= 0); +} + +- (AMSerialPort *)obtainBy:(id)sender +{ + // get this port exclusively; NULL if it's not free + if (owner == nil) { + owner = sender; + return self; + } else + return nil; +} + +- (void)free +{ + // give it back + owner = nil; + [self close]; // you never know ... +} + +- (BOOL)available +{ + // check if port is free and can be obtained + return (owner == nil); +} + +- (id)owner +{ + // who obtained the port? + return owner; +} + + +- (NSFileHandle *)open // use returned file handle to read and write +{ + NSFileHandle *result = nil; + + const char *path = [bsdPath fileSystemRepresentation]; + fileDescriptor = open(path, O_RDWR | O_NOCTTY); // | O_NONBLOCK); + +#ifdef AMSerialDebug + NSLog(@"open %@ (%d)\n", bsdPath, fileDescriptor); +#endif + + if (fileDescriptor < 0) { +#ifdef AMSerialDebug + NSLog(@"Error opening serial port %@ - %s(%d).\n", bsdPath, strerror(errno), errno); +#endif + } else { + /* + if (fcntl(fileDescriptor, F_SETFL, fcntl(fileDescriptor, F_GETFL, 0) & !O_NONBLOCK) == -1) + { + NSLog(@"Error clearing O_NDELAY %@ - %s(%d).\n", bsdPath, strerror(errno), errno); + } // ... else + */ + // get the current options and save them for later reset + if (tcgetattr(fileDescriptor, originalOptions) == -1) { +#ifdef AMSerialDebug + NSLog(@"Error getting tty attributes %@ - %s(%d).\n", bsdPath, strerror(errno), errno); +#endif + } else { + // Make an exact copy of the options + *options = *originalOptions; + + // This object owns the fileDescriptor and must dispose it later + // In other words, you must balance calls to -open with -close + fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor]; + result = fileHandle; + } + } + if (!result) { // failure + if (fileDescriptor >= 0) { + close(fileDescriptor); + } + fileDescriptor = -1; + } + return result; +} + + +- (void)close +{ + // Traditionally it is good to reset a serial port back to + // the state in which you found it. Let's continue that tradition. + if (fileDescriptor >= 0) { + //NSLog(@"close - attempt closeLock"); + [closeLock lock]; + //NSLog(@"close - closeLock locked"); + + // kill pending read by setting O_NONBLOCK + if (fcntl(fileDescriptor, F_SETFL, fcntl(fileDescriptor, F_GETFL, 0) | O_NONBLOCK) == -1) { +#ifdef AMSerialDebug + NSLog(@"Error clearing O_NONBLOCK %@ - %s(%d).\n", bsdPath, strerror(errno), errno); +#endif + } + if (tcsetattr(fileDescriptor, TCSANOW, originalOptions) == -1) { +#ifdef AMSerialDebug + NSLog(@"Error resetting tty attributes - %s(%d).\n", strerror(errno), errno); +#endif + } + + // Disallows further access to the communications channel + [fileHandle closeFile]; + + // Release the fileHandle + [fileHandle release]; + fileHandle = nil; + +#ifdef AMSerialDebug + NSLog(@"close (%d)\n", fileDescriptor); +#endif + // Close the fileDescriptor, that is our responsibility since the fileHandle does not own it + close(fileDescriptor); + fileDescriptor = -1; + + [closeLock unlock]; + //NSLog(@"close - closeLock unlocked"); + } +} + +- (BOOL)drainInput +{ + BOOL result = (tcdrain(fileDescriptor) != -1); + return result; +} + +- (BOOL)flushInput:(BOOL)fIn Output:(BOOL)fOut // (fIn or fOut) must be YES +{ + int mode = 0; + if (fIn == YES) + mode = TCIFLUSH; + if (fOut == YES) + mode = TCOFLUSH; + if (fIn && fOut) + mode = TCIOFLUSH; + + BOOL result = (tcflush(fileDescriptor, mode) != -1); + return result; +} + +- (BOOL)sendBreak +{ + BOOL result = (tcsendbreak(fileDescriptor, 0) != -1); + return result; +} + +- (BOOL)setDTR +{ + BOOL result = (ioctl(fileDescriptor, TIOCSDTR) != -1); + return result; +} + +- (BOOL)clearDTR +{ + BOOL result = (ioctl(fileDescriptor, TIOCCDTR) != -1); + return result; +} + + +// read and write serial port settings through a dictionary + +- (void)buildOptionsDictionary +{ + [optionsDictionary removeAllObjects]; + [optionsDictionary setObject:[self name] forKey:AMSerialOptionServiceName]; + [optionsDictionary setObject:[NSString stringWithFormat:@"%ld", [self speed]] forKey:AMSerialOptionSpeed]; + [optionsDictionary setObject:[NSString stringWithFormat:@"%lul", [self dataBits]] forKey:AMSerialOptionDataBits]; + switch ([self parity]) { + case kAMSerialParityOdd: { + [optionsDictionary setObject:@"Odd" forKey:AMSerialOptionParity]; + break; + } + case kAMSerialParityEven: { + [optionsDictionary setObject:@"Even" forKey:AMSerialOptionParity]; + break; + } + default:; + } + + [optionsDictionary setObject:[NSString stringWithFormat:@"%d", [self stopBits]] forKey:AMSerialOptionStopBits]; + if ([self RTSInputFlowControl]) + [optionsDictionary setObject:@"RTS" forKey:AMSerialOptionInputFlowControl]; + if ([self DTRInputFlowControl]) + [optionsDictionary setObject:@"DTR" forKey:AMSerialOptionInputFlowControl]; + + if ([self CTSOutputFlowControl]) + [optionsDictionary setObject:@"CTS" forKey:AMSerialOptionOutputFlowControl]; + if ([self DSROutputFlowControl]) + [optionsDictionary setObject:@"DSR" forKey:AMSerialOptionOutputFlowControl]; + if ([self CAROutputFlowControl]) + [optionsDictionary setObject:@"CAR" forKey:AMSerialOptionOutputFlowControl]; + + if ([self echoEnabled]) + [optionsDictionary setObject:@"YES" forKey:AMSerialOptionEcho]; + + if ([self canonicalMode]) + [optionsDictionary setObject:@"YES" forKey:AMSerialOptionCanonicalMode]; + +} + + +- (NSDictionary *)options +{ + // will open the port to get options if neccessary + if ([optionsDictionary objectForKey:AMSerialOptionServiceName] == nil) { + if (fileDescriptor < 0) { + [self open]; + [self close]; + } + [self buildOptionsDictionary]; + } + return [NSMutableDictionary dictionaryWithDictionary:optionsDictionary]; +} + +- (void)setOptions:(NSDictionary *)newOptions +{ + // AMSerialOptionServiceName HAS to match! You may NOT switch ports using this + // method. + NSString *temp; + + if ([(NSString *)[newOptions objectForKey:AMSerialOptionServiceName] isEqualToString:[self name]]) { + [self clearError]; + [optionsDictionary addEntriesFromDictionary:newOptions]; + // parse dictionary + temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionSpeed]; + [self setSpeed:[temp intValue]]; + temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionDataBits]; + [self setDataBits:[temp intValue]]; + + temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionParity]; + if (temp == nil) + [self setParity:kAMSerialParityNone]; + else if ([temp isEqualToString:@"Odd"]) + [self setParity:kAMSerialParityOdd]; + else + [self setParity:kAMSerialParityEven]; + + temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionStopBits]; + int numStopBits = [temp intValue]; + [self setStopBits:(AMSerialStopBits)numStopBits]; + + temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionInputFlowControl]; + [self setRTSInputFlowControl:[temp isEqualToString:@"RTS"]]; + [self setDTRInputFlowControl:[temp isEqualToString:@"DTR"]]; + + temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionOutputFlowControl]; + [self setCTSOutputFlowControl:[temp isEqualToString:@"CTS"]]; + [self setDSROutputFlowControl:[temp isEqualToString:@"DSR"]]; + [self setCAROutputFlowControl:[temp isEqualToString:@"CAR"]]; + + temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionEcho]; + [self setEchoEnabled:(temp != nil)]; + + temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionCanonicalMode]; + [self setCanonicalMode:(temp != nil)]; + + [self commitChanges]; + } else { +#ifdef AMSerialDebug + NSLog(@"Error setting options for port %s (wrong port name: %s).\n", [self name], [newOptions objectForKey:AMSerialOptionServiceName]); +#endif + } +} + + +- (long)speed +{ + return cfgetospeed(options); // we should support cfgetispeed too +} + +- (BOOL)setSpeed:(long)speed +{ + BOOL result = YES; + int errorCode = 0; + + options->c_ospeed = speed; + options->c_ispeed = speed; + +#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) + // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates + // other than those specified by POSIX. The driver for the underlying serial hardware + // ultimately determines which baud rates can be used. This ioctl sets both the input + // and output speed. + + speed_t newSpeed = speed; + if (fileDescriptor >= 0) { + errorCode = ioctl(fileDescriptor, IOSSIOSPEED, &newSpeed); + } else { + result = NO; + gotError = YES; + lastError = EBADF; // Bad file descriptor + } +#else + // set both the input and output speed + errorCode = cfsetospeed(options, speed); + errorCode = cfsetispeed(options, speed); +#endif + if (errorCode == -1) { + result = NO; + gotError = YES; + lastError = errno; + } + return result; +} + + +- (unsigned long)dataBits +{ + return 5 + ((options->c_cflag & CSIZE) >> 8); + // man ... I *hate* C syntax ... +} + +- (void)setDataBits:(unsigned long)bits // 5 to 8 (5 is marked as "(pseudo)") +{ + // ?? options->c_oflag &= ~OPOST; + options->c_cflag &= ~CSIZE; + switch (bits) { + case 5: options->c_cflag |= CS5; // redundant since CS5 == 0 + break; + case 6: options->c_cflag |= CS6; + break; + case 7: options->c_cflag |= CS7; + break; + case 8: options->c_cflag |= CS8; + break; + } +} + + +- (AMSerialParity)parity +{ + AMSerialParity result; + if (options->c_cflag & PARENB) { + if (options->c_cflag & PARODD) { + result = kAMSerialParityOdd; + } else { + result = kAMSerialParityEven; + } + } else { + result = kAMSerialParityNone; + } + return result; +} + +- (void)setParity:(AMSerialParity)newParity +{ + switch (newParity) { + case kAMSerialParityNone: { + options->c_cflag &= ~PARENB; + break; + } + case kAMSerialParityOdd: { + options->c_cflag |= PARENB; + options->c_cflag |= PARODD; + break; + } + case kAMSerialParityEven: { + options->c_cflag |= PARENB; + options->c_cflag &= ~PARODD; + break; + } + } +} + + +- (AMSerialStopBits)stopBits +{ + if (options->c_cflag & CSTOPB) + return kAMSerialStopBitsTwo; + else + return kAMSerialStopBitsOne; +} + +- (void)setStopBits:(AMSerialStopBits)numBits +{ + if (numBits == kAMSerialStopBitsOne) + options->c_cflag &= ~CSTOPB; + else if (numBits == kAMSerialStopBitsTwo) + options->c_cflag |= CSTOPB; +} + + +- (BOOL)echoEnabled +{ + return (options->c_lflag & ECHO); +} + +- (void)setEchoEnabled:(BOOL)echo +{ + if (echo == YES) + options->c_lflag |= ECHO; + else + options->c_lflag &= ~ECHO; +} + + +- (BOOL)RTSInputFlowControl +{ + return (options->c_cflag & CRTS_IFLOW); +} + +- (void)setRTSInputFlowControl:(BOOL)rts +{ + if (rts == YES) + options->c_cflag |= CRTS_IFLOW; + else + options->c_cflag &= ~CRTS_IFLOW; +} + + +- (BOOL)DTRInputFlowControl +{ + return (options->c_cflag & CDTR_IFLOW); +} + +- (void)setDTRInputFlowControl:(BOOL)dtr +{ + if (dtr == YES) + options->c_cflag |= CDTR_IFLOW; + else + options->c_cflag &= ~CDTR_IFLOW; +} + + +- (BOOL)CTSOutputFlowControl +{ + return (options->c_cflag & CCTS_OFLOW); +} + +- (void)setCTSOutputFlowControl:(BOOL)cts +{ + if (cts == YES) + options->c_cflag |= CCTS_OFLOW; + else + options->c_cflag &= ~CCTS_OFLOW; +} + + +- (BOOL)DSROutputFlowControl +{ + return (options->c_cflag & CDSR_OFLOW); +} + +- (void)setDSROutputFlowControl:(BOOL)dsr +{ + if (dsr == YES) + options->c_cflag |= CDSR_OFLOW; + else + options->c_cflag &= ~CDSR_OFLOW; +} + + +- (BOOL)CAROutputFlowControl +{ + return (options->c_cflag & CCAR_OFLOW); +} + +- (void)setCAROutputFlowControl:(BOOL)car +{ + if (car == YES) + options->c_cflag |= CCAR_OFLOW; + else + options->c_cflag &= ~CCAR_OFLOW; +} + + +- (BOOL)hangupOnClose +{ + return (options->c_cflag & HUPCL); +} + +- (void)setHangupOnClose:(BOOL)hangup +{ + if (hangup == YES) + options->c_cflag |= HUPCL; + else + options->c_cflag &= ~HUPCL; +} + +- (BOOL)localMode +{ + return (options->c_cflag & CLOCAL); +} + +- (void)setLocalMode:(BOOL)local +{ + // YES = ignore modem status lines + if (local == YES) + options->c_cflag |= CLOCAL; + else + options->c_cflag &= ~CLOCAL; +} + +- (BOOL)canonicalMode +{ + return (options->c_lflag & ICANON); +} + +- (void)setCanonicalMode:(BOOL)flag +{ + if (flag == YES) + options->c_lflag |= ICANON; + else + options->c_lflag &= ~ICANON; +} + +- (char)endOfLineCharacter +{ + return options->c_cc[VEOL]; +} + +- (void)setEndOfLineCharacter:(char)eol +{ + options->c_cc[VEOL] = eol; +} + +- (void)clearError +{ + // call this before changing any settings + gotError = NO; +} + +- (BOOL)commitChanges +{ + // call this after using any of the setters above + if (gotError) + return NO; + + if (tcsetattr(fileDescriptor, TCSANOW, options) == -1) { + // something went wrong + gotError = YES; + lastError = errno; + return NO; + } else { + [self buildOptionsDictionary]; + return YES; + } +} + +- (int)errorCode +{ + // if -commitChanges returns NO, look here for further info + return lastError; +} + +- (NSTimeInterval)readTimeout +{ + return readTimeout; +} + +- (void)setReadTimeout:(NSTimeInterval)aReadTimeout +{ + readTimeout = aReadTimeout; +} + +// private methods + +- (void)readTimeoutAsTimeval:(struct timeval*)timeout +{ + NSTimeInterval timeoutInterval = [self readTimeout]; + double numSecs = trunc(timeoutInterval); + double numUSecs = (timeoutInterval-numSecs)*1000000.0; + timeout->tv_sec = (time_t)lrint(numSecs); + timeout->tv_usec = (suseconds_t)lrint(numUSecs); +} + + +@end diff --git a/atemOSC/arduino/AMSerialPortAdditions.h b/atemOSC/arduino/AMSerialPortAdditions.h new file mode 100644 index 0000000..280738e --- /dev/null +++ b/atemOSC/arduino/AMSerialPortAdditions.h @@ -0,0 +1,94 @@ +// +// AMSerialPortAdditions.h +// +// Created by Andreas on Thu May 02 2002. +// Copyright (c) 2001 Andreas Mayer. All rights reserved. +// +// 2002-10-04 Andreas Mayer +// - readDataInBackgroundWithTarget:selector: and writeDataInBackground: added +// 2002-10-10 Andreas Mayer +// - stopWriteInBackground added +// 2002-10-17 Andreas Mayer +// - numberOfWriteInBackgroundThreads added +// 2002-10-25 Andreas Mayer +// - readDataInBackground and stopReadInBackground added +// 2004-02-10 Andreas Mayer +// - replaced notifications for background reading/writing with direct messages to delegate +// see informal protocol +// 2004-08-18 Andreas Mayer +// - readStringOfLength: added (suggested by Michael Beck) +// 2006-08-16 Andreas Mayer / Sean McBride +// - changed interface for blocking read/write access significantly +// - fixed -checkRead and renamed it to -bytesAvailable +// - see AMSerialPort_Deprecated for old interfaces +// 2007-10-26 Sean McBride +// - made code 64 bit and garbage collection clean + +#import "AMSDKCompatibility.h" + +#import +#import "AMSerialPort.h" + + +@interface AMSerialPort (AMSerialPortAdditions) + +// returns the number of bytes available in the input buffer +// Be careful how you use this information, it may be out of date just after you get it +- (int)bytesAvailable; + +- (void)waitForInput:(id)target selector:(SEL)selector; + + +// all blocking reads returns after [self readTimout] seconds elapse, at the latest +- (NSData *)readAndReturnError:(NSError **)error; + +// returns after 'bytes' bytes are read +- (NSData *)readBytes:(NSUInteger)bytes error:(NSError **)error; + +// returns when 'stopChar' is encountered +- (NSData *)readUpToChar:(char)stopChar error:(NSError **)error; + +// returns after 'bytes' bytes are read or if 'stopChar' is encountered, whatever comes first +- (NSData *)readBytes:(NSUInteger)bytes upToChar:(char)stopChar error:(NSError **)error; + +// data read will be converted into an NSString, using the given encoding +// NOTE: encodings that take up more than one byte per character may fail if only a part of the final string was received +- (NSString *)readStringUsingEncoding:(NSStringEncoding)encoding error:(NSError **)error; + +- (NSString *)readBytes:(NSUInteger)bytes usingEncoding:(NSStringEncoding)encoding error:(NSError **)error; + +// NOTE: 'stopChar' has to be a byte value, using the given encoding; you can not wait for an arbitrary character from a multi-byte encoding +- (NSString *)readUpToChar:(char)stopChar usingEncoding:(NSStringEncoding)encoding error:(NSError **)error; + +- (NSString *)readBytes:(NSUInteger)bytes upToChar:(char)stopChar usingEncoding:(NSStringEncoding)encoding error:(NSError **)error; + +// write to the serial port; NO if an error occured +- (BOOL)writeData:(NSData *)data error:(NSError **)error; + +- (BOOL)writeString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(NSError **)error; + + +- (void)readDataInBackground; +// +// Will send serialPortReadData: to delegate +// the dataDictionary object will contain these entries: +// 1. "serialPort": the AMSerialPort object that sent the message +// 2. "data": (NSData *)data - received data + +- (void)stopReadInBackground; + +- (void)writeDataInBackground:(NSData *)data; +// +// Will send serialPortWriteProgress: to delegate if task lasts more than +// approximately three seconds. +// the dataDictionary object will contain these entries: +// 1. "serialPort": the AMSerialPort object that sent the message +// 2. "value": (NSNumber *)value - bytes sent +// 3. "total": (NSNumber *)total - bytes total + +- (void)stopWriteInBackground; + +- (int)numberOfWriteInBackgroundThreads; + + +@end diff --git a/atemOSC/arduino/AMSerialPortAdditions.m b/atemOSC/arduino/AMSerialPortAdditions.m new file mode 100755 index 0000000..0cc0d00 --- /dev/null +++ b/atemOSC/arduino/AMSerialPortAdditions.m @@ -0,0 +1,612 @@ +// +// AMSerialPortAdditions.m +// +// Created by Andreas on Thu May 02 2002. +// Copyright (c) 2001 Andreas Mayer. All rights reserved. +// +// 2002-07-02 Andreas Mayer +// - initialize buffer in readString +// 2002-10-04 Andreas Mayer +// - readDataInBackgroundWithTarget:selector: and writeDataInBackground: added +// 2002-10-10 Andreas Mayer +// - stopWriteInBackground added +// - send notifications about sent data through distributed notification center +// 2002-10-17 Andreas Mayer +// - numberOfWriteInBackgroundThreads added +// - if total write time will exceed 3 seconds, send +// CommXWriteInBackgroundProgressNotification without delay +// 2002-10-25 Andreas Mayer +// - readDataInBackground and stopReadInBackground added +// 2004-08-18 Andreas Mayer +// - readStringOfLength: added (suggested by Michael Beck) +// 2005-04-11 Andreas Mayer +// - attempt at a fix for readDataInBackgroundThread - fileDescriptor could already be closed +// (thanks to David Bainbridge for the bug report) does not work as of yet +// 2007-10-26 Sean McBride +// - made code 64 bit and garbage collection clean + + +#import "AMSDKCompatibility.h" + +#import +#import + +#import "AMSerialPortAdditions.h" +#import "AMSerialErrors.h" + + +@interface AMSerialPort (AMSerialPortAdditionsPrivate) +- (void)readDataInBackgroundThread; +- (void)writeDataInBackgroundThread:(NSData *)data; +- (id)am_readTarget; +- (void)am_setReadTarget:(id)newReadTarget; +- (NSData *)readAndStopAfterBytes:(BOOL)stopAfterBytes bytes:(NSUInteger)bytes stopAtChar:(BOOL)stopAtChar stopChar:(char)stopChar error:(NSError **)error; +- (void)reportProgress:(NSUInteger)progress dataLen:(NSUInteger)dataLen; +@end + + +@implementation AMSerialPort (AMSerialPortAdditions) + + +// ============================================================ +#pragma mark - +#pragma mark blocking IO +// ============================================================ + +- (void)doRead:(NSTimer *)timer +{ + (void)timer; + +#ifdef AMSerialDebug + NSLog(@"doRead"); +#endif + int res; + struct timeval timeout; + if (fileDescriptor >= 0) { + FD_ZERO(readfds); + FD_SET(fileDescriptor, readfds); + [self readTimeoutAsTimeval:&timeout]; + res = select(fileDescriptor+1, readfds, nil, nil, &timeout); + if (res >= 1) { + NSString *readStr = [self readStringUsingEncoding:NSUTF8StringEncoding error:NULL]; + [[self am_readTarget] performSelector:am_readSelector withObject:readStr]; + [self am_setReadTarget:nil]; + } else { + [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doRead:) userInfo:self repeats:NO]; + } + } else { + // file already closed + [self am_setReadTarget:nil]; + } +} + +// all blocking reads returns after [self readTimout] seconds elapse, at the latest +- (NSData *)readAndReturnError:(NSError **)error +{ + NSData *result = [self readAndStopAfterBytes:NO bytes:0 stopAtChar:NO stopChar:0 error:error]; + return result; +} + +// returns after 'bytes' bytes are read +- (NSData *)readBytes:(NSUInteger)bytes error:(NSError **)error +{ + NSData *result = [self readAndStopAfterBytes:YES bytes:bytes stopAtChar:NO stopChar:0 error:error]; + return result; +} + +// returns when 'stopChar' is encountered +- (NSData *)readUpToChar:(char)stopChar error:(NSError **)error +{ + NSData *result = [self readAndStopAfterBytes:NO bytes:0 stopAtChar:YES stopChar:stopChar error:error]; + return result; +} + +// returns after 'bytes' bytes are read or if 'stopChar' is encountered, whatever comes first +- (NSData *)readBytes:(NSUInteger)bytes upToChar:(char)stopChar error:(NSError **)error +{ + NSData *result = [self readAndStopAfterBytes:YES bytes:bytes stopAtChar:YES stopChar:stopChar error:error]; + return result; +} + +// data read will be converted into an NSString, using the given encoding +// NOTE: encodings that take up more than one byte per character may fail if only a part of the final string was received +- (NSString *)readStringUsingEncoding:(NSStringEncoding)encoding error:(NSError **)error +{ + NSString *result = nil; + NSData *data = [self readAndStopAfterBytes:NO bytes:0 stopAtChar:NO stopChar:0 error:error]; + if (data) { + result = [[[NSString alloc] initWithData:data encoding:encoding] autorelease]; + } + return result; +} + +- (NSString *)readBytes:(NSUInteger)bytes usingEncoding:(NSStringEncoding)encoding error:(NSError **)error +{ + NSString *result = nil; + NSData *data = [self readAndStopAfterBytes:YES bytes:bytes stopAtChar:NO stopChar:0 error:error]; + if (data) { + result = [[[NSString alloc] initWithData:data encoding:encoding] autorelease]; + } + return result; +} + +// NOTE: 'stopChar' has to be a byte value, using the given encoding; you can not wait for an arbitrary character from a multi-byte encoding +- (NSString *)readUpToChar:(char)stopChar usingEncoding:(NSStringEncoding)encoding error:(NSError **)error +{ + NSString *result = nil; + NSData *data = [self readAndStopAfterBytes:NO bytes:0 stopAtChar:YES stopChar:stopChar error:error]; + if (data) { + result = [[[NSString alloc] initWithData:data encoding:encoding] autorelease]; + } + return result; +} + +- (NSString *)readBytes:(NSUInteger)bytes upToChar:(char)stopChar usingEncoding:(NSStringEncoding)encoding error:(NSError **)error +{ + NSString *result = nil; + NSData *data = [self readAndStopAfterBytes:YES bytes:bytes stopAtChar:YES stopChar:stopChar error:error]; + if (data) { + result = [[[NSString alloc] initWithData:data encoding:encoding] autorelease]; + } + return result; +} + + +// write to the serial port; NO if an error occured +- (BOOL)writeData:(NSData *)data error:(NSError **)error +{ + BOOL result = NO; + + const char *dataBytes = (const char*)[data bytes]; + NSUInteger dataLen = [data length]; + ssize_t bytesWritten = 0; + int errorCode = kAMSerialErrorNone; + if (dataBytes && (dataLen > 0)) { + bytesWritten = write(fileDescriptor, dataBytes, dataLen); + if (bytesWritten < 0) { + errorCode = kAMSerialErrorFatal; + } else if ((NSUInteger)bytesWritten == dataLen) { + result = YES; + } else { + errorCode = kAMSerialErrorOnlySomeDataWritten; + } + } else { + errorCode = kAMSerialErrorNoDataToWrite; + } + if (error) { + NSDictionary *userInfo = nil; + if (bytesWritten > 0) { + NSNumber* bytesWrittenNum = [NSNumber numberWithUnsignedLongLong:bytesWritten]; + userInfo = [NSDictionary dictionaryWithObject:bytesWrittenNum forKey:@"bytesWritten"]; + } + *error = [NSError errorWithDomain:AMSerialErrorDomain code:errorCode userInfo:userInfo]; + } + + return result; +} + +- (BOOL)writeString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(NSError **)error +{ + NSData *data = [string dataUsingEncoding:encoding]; + return [self writeData:data error:error]; +} + +- (int)bytesAvailable +{ +#ifdef AMSerialDebug + NSLog(@"bytesAvailable"); +#endif + + // yes, that cast is correct. ioctl() is declared to take a char* but should be void* as really it + // depends on the 2nd parameter. Ahhh, I love crappy old UNIX APIs :) + int result = 0; + int err = ioctl(fileDescriptor, FIONREAD, (char *)&result); + if (err != 0) { + result = -1; + } + return result; +} + + +- (void)waitForInput:(id)target selector:(SEL)selector +{ +#ifdef AMSerialDebug + NSLog(@"waitForInput"); +#endif + [self am_setReadTarget:target]; + am_readSelector = selector; + [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doRead:) userInfo:self repeats:NO]; +} + +// ============================================================ +#pragma mark - +#pragma mark threaded IO +// ============================================================ + +- (void)readDataInBackground +{ +#ifdef AMSerialDebug + NSLog(@"readDataInBackground"); +#endif + if (delegateHandlesReadInBackground) { + countReadInBackgroundThreads++; + [NSThread detachNewThreadSelector:@selector(readDataInBackgroundThread) toTarget:self withObject:nil]; + } else { + // ... throw exception? + } +} + +- (void)stopReadInBackground +{ +#ifdef AMSerialDebug + NSLog(@"stopReadInBackground"); +#endif + stopReadInBackground = YES; +} + +- (void)writeDataInBackground:(NSData *)data +{ +#ifdef AMSerialDebug + NSLog(@"writeDataInBackground"); +#endif + if (delegateHandlesWriteInBackground) { + countWriteInBackgroundThreads++; + [NSThread detachNewThreadSelector:@selector(writeDataInBackgroundThread:) toTarget:self withObject:data]; + } else { + // ... throw exception? + } +} + +- (void)stopWriteInBackground +{ +#ifdef AMSerialDebug + NSLog(@"stopWriteInBackground"); +#endif + stopWriteInBackground = YES; +} + +- (int)numberOfWriteInBackgroundThreads +{ + return countWriteInBackgroundThreads; +} + + +@end + +#pragma mark - + +@implementation AMSerialPort (AMSerialPortAdditionsPrivate) + +// ============================================================ +#pragma mark - +#pragma mark threaded methods +// ============================================================ + +- (void)readDataInBackgroundThread +{ + NSData *data = nil; + void *localBuffer; + ssize_t bytesRead = 0; + fd_set *localReadFDs = NULL; + + [readLock lock]; // read in sequence + //NSLog(@"readDataInBackgroundThread - [readLock lock]"); + + localBuffer = malloc(AMSER_MAXBUFSIZE); + stopReadInBackground = NO; + NSAutoreleasePool *localAutoreleasePool = [[NSAutoreleasePool alloc] init]; + [closeLock lock]; + if ((fileDescriptor >= 0) && (!stopReadInBackground)) { + //NSLog(@"readDataInBackgroundThread - [closeLock lock]"); + localReadFDs = (fd_set*)malloc(sizeof(fd_set)); + FD_ZERO(localReadFDs); + FD_SET(fileDescriptor, localReadFDs); + [closeLock unlock]; + //NSLog(@"readDataInBackgroundThread - [closeLock unlock]"); + int res = select(fileDescriptor+1, localReadFDs, nil, nil, nil); // timeout); + if ((res >= 1) && (fileDescriptor >= 0)) { + //bytesRead = read(fileDescriptor, localBuffer, AMSER_MAXBUFSIZE); + } + //FIXME: This was modified on 3-20-09 by Pat O'Keefe for a particular application...swap comments for normal operation + //data = [NSData dataWithBytes:localBuffer length:bytesRead]; + data = [self readUpToChar:'\n' error:NULL]; + [delegate performSelectorOnMainThread:@selector(serialPortReadData:) withObject:[NSDictionary dictionaryWithObjectsAndKeys: self, @"serialPort", data, @"data", nil] waitUntilDone:YES];//was NO + } else { + [closeLock unlock]; + } + [localAutoreleasePool release]; + if (localReadFDs) + free(localReadFDs); + if (localBuffer) + free(localBuffer); + + countReadInBackgroundThreads--; + + [readLock unlock]; + //NSLog(@"readDataInBackgroundThread - [readLock unlock]"); + +} + +/* new version - does not work yet +- (void)readDataInBackgroundThread +{ + NSData *data = nil; + void *localBuffer; + int bytesRead = 0; + fd_set *localReadFDs; + +#ifdef AMSerialDebug + NSLog(@"readDataInBackgroundThread: %@", [NSThread currentThread]); +#endif + localBuffer = malloc(AMSER_MAXBUFSIZE); + [stopReadInBackgroundLock lock]; + stopReadInBackground = NO; + //NSLog(@"stopReadInBackground set to NO: %@", [NSThread currentThread]); + [stopReadInBackgroundLock unlock]; + //NSLog(@"attempt readLock: %@", [NSThread currentThread]); + [readLock lock]; // write in sequence + //NSLog(@"readLock locked: %@", [NSThread currentThread]); + //NSLog(@"attempt closeLock: %@", [NSThread currentThread]); + [closeLock lock]; + //NSLog(@"closeLock locked: %@", [NSThread currentThread]); + if (!stopReadInBackground && (fileDescriptor >= 0)) { + NSAutoreleasePool *localAutoreleasePool = [[NSAutoreleasePool alloc] init]; + localReadFDs = malloc(sizeof(*localReadFDs)); + FD_ZERO(localReadFDs); + FD_SET(fileDescriptor, localReadFDs); + int res = select(fileDescriptor+1, localReadFDs, nil, nil, nil); // timeout); + if (res >= 1) { +#ifdef AMSerialDebug + NSLog(@"attempt read: %@", [NSThread currentThread]); +#endif + bytesRead = read(fileDescriptor, localBuffer, AMSER_MAXBUFSIZE); + } +#ifdef AMSerialDebug + NSLog(@"data read: %@", [NSThread currentThread]); +#endif + data = [NSData dataWithBytes:localBuffer length:bytesRead]; +#ifdef AMSerialDebug + NSLog(@"send AMSerialReadInBackgroundDataMessage"); +#endif + [delegate performSelectorOnMainThread:@selector(serialPortReadData:) withObject:[NSDictionary dictionaryWithObjectsAndKeys: self, @"serialPort", data, @"data", nil] waitUntilDone:NO]; + free(localReadFDs); + [localAutoreleasePool release]; + } else { +#ifdef AMSerialDebug + NSLog(@"read stopped: %@", [NSThread currentThread]); +#endif + } + + [closeLock unlock]; + //NSLog(@"closeLock unlocked: %@", [NSThread currentThread]); + [readLock unlock]; + //NSLog(@"readLock unlocked: %@", [NSThread currentThread]); + [countReadInBackgroundThreadsLock lock]; + countReadInBackgroundThreads--; + [countReadInBackgroundThreadsLock unlock]; + + free(localBuffer); +} +*/ + +- (void)writeDataInBackgroundThread:(NSData *)data +{ + +#ifdef AMSerialDebug + NSLog(@"writeDataInBackgroundThread"); +#endif + void *localBuffer; + NSUInteger pos; + NSUInteger bufferLen; + NSUInteger dataLen; + ssize_t written; + NSDate *nextNotificationDate; + BOOL notificationSent = NO; + long speed; + long estimatedTime; + BOOL error = NO; + + NSAutoreleasePool *localAutoreleasePool = [[NSAutoreleasePool alloc] init]; + + [data retain]; + localBuffer = malloc(AMSER_MAXBUFSIZE); + stopWriteInBackground = NO; + [writeLock lock]; // write in sequence + pos = 0; + dataLen = [data length]; + speed = [self speed]; + estimatedTime = (dataLen*8)/speed; + if (estimatedTime > 3) { // will take more than 3 seconds + notificationSent = YES; + [self reportProgress:pos dataLen:dataLen]; + nextNotificationDate = [NSDate dateWithTimeIntervalSinceNow:1.0]; + } else { + nextNotificationDate = [NSDate dateWithTimeIntervalSinceNow:2.0]; + } + while (!stopWriteInBackground && (pos < dataLen) && !error) { + bufferLen = MIN(AMSER_MAXBUFSIZE, dataLen-pos); + + [data getBytes:localBuffer range:NSMakeRange(pos, bufferLen)]; + written = write(fileDescriptor, localBuffer, bufferLen); + error = (written == 0); // error condition + if (error) + break; + pos += written; + + if ([(NSDate *)[NSDate date] compare:nextNotificationDate] == NSOrderedDescending) { + if (notificationSent || (pos < dataLen)) { // not for last block only + notificationSent = YES; + [self reportProgress:pos dataLen:dataLen]; + nextNotificationDate = [NSDate dateWithTimeIntervalSinceNow:1.0]; + } + } + } + if (notificationSent) { + [self reportProgress:pos dataLen:dataLen]; + } + stopWriteInBackground = NO; + [writeLock unlock]; + countWriteInBackgroundThreads--; + + free(localBuffer); + [data release]; + [localAutoreleasePool release]; +} + +- (id)am_readTarget +{ + return am_readTarget; +} + +- (void)am_setReadTarget:(id)newReadTarget +{ + if (am_readTarget != newReadTarget) { + [newReadTarget retain]; + [am_readTarget release]; + am_readTarget = newReadTarget; + } +} + +// Low-level blocking read method. +// This method reads from the serial port and blocks as necessary, it returns when: +// - [self readTimeout] seconds has elapsed +// - if stopAfterBytes is YES, when 'bytesToRead' bytes have been read +// - if stopAtChar is YES, when 'stopChar' is found at the end of the read buffer +// - a fatal error occurs +// +// Upon return: as long as some data was actually read, and no serious error occured, an autoreleased NSData +// object with that data is created and returned, otherwise nil is. +- (NSData *)readAndStopAfterBytes:(BOOL)stopAfterBytes bytes:(NSUInteger)bytesToRead stopAtChar:(BOOL)stopAtChar stopChar:(char)stopChar error:(NSError **)error +{ + NSData *result = nil; + + struct timeval timeout; + NSUInteger bytesRead = 0; + BOOL stop = NO; + int errorCode = kAMSerialErrorNone; + int endCode = kAMSerialEndOfStream; + NSError *underlyingError = nil; + + // Note the time that we start + NSDate *startTime = [NSDate date]; + + // How long, in total, do we block before timing out? + NSTimeInterval totalTimeout = [self readTimeout]; + + // This value will be decreased each time through the loop + NSTimeInterval remainingTimeout = totalTimeout; + + while (!stop) { + if (remainingTimeout <= 0.0) { + stop = YES; + errorCode = kAMSerialErrorTimeout; + break; + } else { + // Convert from NSTimeInterval to struct timeval + double numSecs = trunc(remainingTimeout); + double numUSecs = (remainingTimeout-numSecs)*1000000.0; + timeout.tv_sec = (time_t)lrint(numSecs); + timeout.tv_usec = (suseconds_t)lrint(numUSecs); +#ifdef AMSerialDebug + NSLog(@"timeout: %fs = %ds and %dus", remainingTimeout, timeout.tv_sec, timeout.tv_usec); +#endif + + // If the remaining time is so small that it has rounded to zero, bump it up to 1 microsec. + // Why? Because passing a zeroed timeval to select() indicates that we want to poll, but we don't. + if ((timeout.tv_sec == 0) && (timeout.tv_usec == 0)) { + timeout.tv_usec = 1; + } + FD_ZERO(readfds); + FD_SET(fileDescriptor, readfds); + [self readTimeoutAsTimeval:&timeout]; + int selectResult = select(fileDescriptor+1, readfds, NULL, NULL, &timeout); + if (selectResult == -1) { + stop = YES; + errorCode = kAMSerialErrorFatal; + break; + } else if (selectResult == 0) { + stop = YES; + errorCode = kAMSerialErrorTimeout; + break; + } else { + size_t sizeToRead; + if (stopAfterBytes) { + sizeToRead = (MIN(bytesToRead, AMSER_MAXBUFSIZE))-bytesRead; + } else { + sizeToRead = AMSER_MAXBUFSIZE-bytesRead; + } + ssize_t readResult = read(fileDescriptor, buffer+bytesRead, sizeToRead); + if (readResult > 0) { + bytesRead += readResult; + if (stopAfterBytes) { + if (bytesRead == bytesToRead) { + stop = YES; + endCode = kAMSerialStopLengthReached; + break; + } else if (bytesRead > bytesToRead) { + stop = YES; + endCode = kAMSerialStopLengthExceeded; + break; + } + } + if (stopAtChar && (buffer[bytesRead-1] == stopChar)) { + stop = YES; + endCode = kAMSerialStopCharReached; + break; + } + if (bytesRead >= AMSER_MAXBUFSIZE) { + stop = YES; + errorCode = kAMSerialErrorInternalBufferFull; + break; + } + } else if (readResult == 0) { + // Should not be possible since select() has indicated data is available + stop = YES; + errorCode = kAMSerialErrorFatal; + break; + } else { + stop = YES; + // Make underlying error + underlyingError = [NSError errorWithDomain:NSPOSIXErrorDomain code:readResult userInfo:nil]; + errorCode = kAMSerialErrorFatal; + break; + } + } + + // Reduce the timeout value by the amount of time actually spent so far + remainingTimeout = totalTimeout - [[NSDate date] timeIntervalSinceDate:startTime]; + } + } + + if (error) { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + [userInfo setObject:[NSNumber numberWithUnsignedLongLong:bytesRead] forKey:@"bytesRead"]; + if (underlyingError) { + [userInfo setObject:underlyingError forKey:NSUnderlyingErrorKey]; + } + if (errorCode == kAMSerialErrorNone) { + [userInfo setObject:[NSNumber numberWithInt:endCode] forKey:@"endCode"]; + } + *error = [NSError errorWithDomain:AMSerialErrorDomain code:errorCode userInfo:userInfo]; + } + if ((bytesRead > 0) && (errorCode != kAMSerialErrorFatal)) { + result = [NSData dataWithBytes:buffer length:bytesRead]; + } + + return result; +} + +- (void)reportProgress:(NSUInteger)progress dataLen:(NSUInteger)dataLen +{ +#ifdef AMSerialDebug + NSLog(@"send AMSerialWriteInBackgroundProgressMessage"); +#endif + [delegate performSelectorOnMainThread:@selector(serialPortWriteProgress:) withObject: + [NSDictionary dictionaryWithObjectsAndKeys: + self, @"serialPort", + [NSNumber numberWithUnsignedLongLong:progress], @"value", + [NSNumber numberWithUnsignedLongLong:dataLen], @"total", nil] + waitUntilDone:NO]; +} + +@end diff --git a/atemOSC/arduino/AMSerialPortList.h b/atemOSC/arduino/AMSerialPortList.h new file mode 100644 index 0000000..64e3b28 --- /dev/null +++ b/atemOSC/arduino/AMSerialPortList.h @@ -0,0 +1,57 @@ +// +// AMSerialPortList.h +// +// Created by Andreas on 2002-04-24. +// Copyright (c) 2001 Andreas Mayer. All rights reserved. +// +// 2002-09-09 Andreas Mayer +// - reuse AMSerialPort objects when calling init on an existing AMSerialPortList +// 2002-09-30 Andreas Mayer +// - added +sharedPortList +// 2004-02-10 Andreas Mayer +// - added +portEnumerator +// 2006-08-16 Andreas Mayer +// - added methods dealing with ports of a certain serial type +// - renamed -getSerialPorts to -serialPorts - moved old declaration to Deprecated category +// 2007-05-22 Nick Zitzmann +// - added notifications for when serial ports are added/removed +// 2007-10-26 Sean McBride +// - made code 64 bit and garbage collection clean + +#import "AMSDKCompatibility.h" + +#import + +// For constants clients will want to pass to methods that want a 'serialTypeKey' +#import +// note: the constants are C strings, so use '@' or CFSTR to convert, for example: +// NSArray *ports = [[AMSerialPort sharedPortList] serialPortsOfType:@kIOSerialBSDModemType]; +// NSArray *ports = [[AMSerialPort sharedPortList] serialPortsOfType:(NSString*)CFSTR(kIOSerialBSDModemType)]; + +@class AMSerialPort; + +extern NSString * const AMSerialPortListDidAddPortsNotification; +extern NSString * const AMSerialPortListDidRemovePortsNotification; +extern NSString * const AMSerialPortListAddedPorts; +extern NSString * const AMSerialPortListRemovedPorts; + +@interface AMSerialPortList : NSObject +{ +@private + NSMutableArray *portList; +} + ++ (AMSerialPortList *)sharedPortList; + ++ (NSEnumerator *)portEnumerator; ++ (NSEnumerator *)portEnumeratorForSerialPortsOfType:(NSString *)serialTypeKey; + +- (NSUInteger)count; +- (AMSerialPort *)objectAtIndex:(NSUInteger)idx; +- (AMSerialPort *)objectWithName:(NSString *)name; + +- (NSArray *)serialPorts; +- (NSArray *)serialPortsOfType:(NSString *)serialTypeKey; + + +@end diff --git a/atemOSC/arduino/AMSerialPortList.m b/atemOSC/arduino/AMSerialPortList.m new file mode 100644 index 0000000..0332ff5 --- /dev/null +++ b/atemOSC/arduino/AMSerialPortList.m @@ -0,0 +1,350 @@ +// +// AMSerialPortList.m +// +// Created by Andreas on 2002-04-24. +// Copyright (c) 2001 Andreas Mayer. All rights reserved. +// +// 2002-09-09 Andreas Mayer +// - reuse AMSerialPort objects when calling init on an existing AMSerialPortList +// 2002-09-30 Andreas Mayer +// - added +sharedPortList +// 2004-07-05 Andreas Mayer +// - added some log statements +// 2007-05-22 Nick Zitzmann +// - added notifications for when serial ports are added/removed +// 2007-07-18 Sean McBride +// - minor improvements to the added/removed notification support +// - changed singleton creation technique, now matches Apple's sample code +// - removed oldPortList as it is no longer needed +// 2007-10-26 Sean McBride +// - made code 64 bit and garbage collection clean + + +#import "AMSDKCompatibility.h" + +#import "AMSerialPortList.h" +#import "AMSerialPort.h" +#import "AMStandardEnumerator.h" + +#include + +#include + +#include +#include +#include + +static AMSerialPortList *AMSerialPortListSingleton = nil; + +NSString *const AMSerialPortListDidAddPortsNotification = @"AMSerialPortListDidAddPortsNotification"; +NSString *const AMSerialPortListDidRemovePortsNotification = @"AMSerialPortListDidRemovePortsNotification"; +NSString *const AMSerialPortListAddedPorts = @"AMSerialPortListAddedPorts"; +NSString *const AMSerialPortListRemovedPorts = @"AMSerialPortListRemovedPorts"; + + +// Private prototypes +void AMSerialPortWasAddedNotification(void *refcon, io_iterator_t iterator); +void AMSerialPortWasRemovedNotification(void *refcon, io_iterator_t iterator); + + + +@implementation AMSerialPortList + ++ (AMSerialPortList *)sharedPortList +{ + @synchronized(self) { + if (AMSerialPortListSingleton == nil) { +#ifndef __OBJC_GC__ + [[self alloc] init]; // assignment not done here +#else + // Singleton creation is easy in the GC case, just create it if it hasn't been created yet, + // it won't get collected since globals are strongly referenced. + AMSerialPortListSingleton = [[self alloc] init]; +#endif + } + } + return AMSerialPortListSingleton; +} + +#ifndef __OBJC_GC__ + ++ (id)allocWithZone:(NSZone *)zone +{ + id result = nil; + @synchronized(self) { + if (AMSerialPortListSingleton == nil) { + AMSerialPortListSingleton = [super allocWithZone:zone]; + result = AMSerialPortListSingleton; // assignment and return on first allocation + //on subsequent allocation attempts return nil + } + } + return result; +} + +- (id)copyWithZone:(NSZone *)zone +{ + (void)zone; + return self; +} + +- (id)retain +{ + return self; +} + +- (NSUInteger)retainCount +{ + return NSUIntegerMax; //denotes an object that cannot be released +} + +- (oneway void)release +{ + //do nothing +} + +- (id)autorelease +{ + return self; +} + +- (void)dealloc +{ + [portList release]; + [super dealloc]; +} + +#endif + ++ (NSEnumerator *)portEnumerator +{ + return [[[AMStandardEnumerator alloc] initWithCollection:[AMSerialPortList sharedPortList] + countSelector:@selector(count) objectAtIndexSelector:@selector(objectAtIndex:)] autorelease]; +} + ++ (NSEnumerator *)portEnumeratorForSerialPortsOfType:(NSString *)serialTypeKey +{ + return [[[AMStandardEnumerator alloc] initWithCollection:[[AMSerialPortList sharedPortList] + serialPortsOfType:serialTypeKey] countSelector:@selector(count) objectAtIndexSelector:@selector(objectAtIndex:)] autorelease]; +} + +- (AMSerialPort *)portByPath:(NSString *)bsdPath +{ + AMSerialPort *result = nil; + AMSerialPort *port; + NSEnumerator *enumerator; + + enumerator = [portList objectEnumerator]; + while ((port = [enumerator nextObject]) != nil) { + if ([[port bsdPath] isEqualToString:bsdPath]) { + result = port; + break; + } + } + return result; +} + +- (AMSerialPort *)getNextSerialPort:(io_iterator_t)serialPortIterator +{ + AMSerialPort *serialPort = nil; + + io_object_t serialService = IOIteratorNext(serialPortIterator); + if (serialService != 0) { + CFStringRef modemName = (CFStringRef)IORegistryEntryCreateCFProperty(serialService, CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0); + CFStringRef bsdPath = (CFStringRef)IORegistryEntryCreateCFProperty(serialService, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0); + CFStringRef serviceType = (CFStringRef)IORegistryEntryCreateCFProperty(serialService, CFSTR(kIOSerialBSDTypeKey), kCFAllocatorDefault, 0); + if (modemName && bsdPath) { + // If the port already exists in the list of ports, we want that one. We only create a new one as a last resort. + serialPort = [self portByPath:(NSString*)bsdPath]; + if (serialPort == nil) { + serialPort = [[[AMSerialPort alloc] init:(NSString*)bsdPath withName:(NSString*)modemName type:(NSString*)serviceType] autorelease]; + } + } + CFRelease(modemName); + CFRelease(bsdPath); + CFRelease(serviceType); + + // We have sucked this service dry of information so release it now. + (void)IOObjectRelease(serialService); + } + + return serialPort; +} + +- (void)portsWereAdded:(io_iterator_t)iterator +{ + AMSerialPort *serialPort; + NSMutableArray *addedPorts = [NSMutableArray array]; + + while ((serialPort = [self getNextSerialPort:iterator]) != nil) { + [portList addObject:serialPort]; + [addedPorts addObject:serialPort]; + } + + NSNotificationCenter* notifCenter = [NSNotificationCenter defaultCenter]; + NSDictionary* userInfo = [NSDictionary dictionaryWithObject:addedPorts forKey:AMSerialPortListAddedPorts]; + [notifCenter postNotificationName:AMSerialPortListDidAddPortsNotification object:self userInfo:userInfo]; +} + +- (void)portsWereRemoved:(io_iterator_t)iterator +{ + AMSerialPort *serialPort; + NSMutableArray *removedPorts = [NSMutableArray array]; + + while ((serialPort = [self getNextSerialPort:iterator]) != nil) { + // Since the port was removed, one should obviously not attempt to use it anymore -- so 'close' it. + // -close does nothing if the port was never opened. + [serialPort close]; + + [portList removeObject:serialPort]; + [removedPorts addObject:serialPort]; + } + + NSNotificationCenter* notifCenter = [NSNotificationCenter defaultCenter]; + NSDictionary* userInfo = [NSDictionary dictionaryWithObject:removedPorts forKey:AMSerialPortListRemovedPorts]; + [notifCenter postNotificationName:AMSerialPortListDidRemovePortsNotification object:self userInfo:userInfo]; +} + +void AMSerialPortWasAddedNotification(void *refcon, io_iterator_t iterator) +{ + (void)refcon; + [[AMSerialPortList sharedPortList] portsWereAdded:iterator]; +} + +void AMSerialPortWasRemovedNotification(void *refcon, io_iterator_t iterator) +{ + (void)refcon; + [[AMSerialPortList sharedPortList] portsWereRemoved:iterator]; +} + +- (void)registerForSerialPortChangeNotifications +{ + kern_return_t kernResult; + io_iterator_t unused; + CFMutableDictionaryRef classesToMatch1, classesToMatch2; + + // Serial devices are instances of class IOSerialBSDClient + classesToMatch1 = IOServiceMatching(kIOSerialBSDServiceValue); + if (classesToMatch1 == NULL) { +#ifdef AMSerialDebug + NSLog(@"IOServiceMatching returned a NULL dictionary."); +#endif + } else { + CFDictionarySetValue(classesToMatch1, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + classesToMatch2 = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, classesToMatch1); + } + + if (classesToMatch1 != NULL) + { + IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault); + CFRunLoopSourceRef notificationSource = IONotificationPortGetRunLoopSource(notificationPort); + + CFRunLoopAddSource([[NSRunLoop currentRunLoop] getCFRunLoop], notificationSource, kCFRunLoopCommonModes); + + // Set up notifications; consumes a reference to classesToMatch1 + kernResult = IOServiceAddMatchingNotification(notificationPort, kIOPublishNotification, classesToMatch1, AMSerialPortWasAddedNotification, NULL, &unused); + if (kernResult != KERN_SUCCESS) { +#ifdef AMSerialDebug + NSLog(@"Error %d when setting up add notifications!", kernResult); +#endif + } else { + while (IOIteratorNext(unused)) {} // arm the notification + } + // consumes a reference to classesToMatch2 + kernResult = IOServiceAddMatchingNotification(notificationPort, kIOTerminatedNotification, classesToMatch2, AMSerialPortWasRemovedNotification, NULL, &unused); + if (kernResult != KERN_SUCCESS) { +#ifdef AMSerialDebug + NSLog(@"Error %d when setting up add notifications!", kernResult); +#endif + } else { + while (IOIteratorNext(unused)) {} // arm the notification + } + } +} + +- (void)addAllSerialPortsToArray:(NSMutableArray *)array +{ + kern_return_t kernResult; + CFMutableDictionaryRef classesToMatch; + io_iterator_t serialPortIterator; + AMSerialPort* serialPort; + + // Serial devices are instances of class IOSerialBSDClient + classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue); + if (classesToMatch != NULL) { + CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); + + // This function decrements the refcount of the dictionary passed it + kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, &serialPortIterator); + if (kernResult == KERN_SUCCESS) { + while ((serialPort = [self getNextSerialPort:serialPortIterator]) != nil) { + [array addObject:serialPort]; + } + (void)IOObjectRelease(serialPortIterator); + } else { +#ifdef AMSerialDebug + NSLog(@"IOServiceGetMatchingServices returned %d", kernResult); +#endif + } + } else { +#ifdef AMSerialDebug + NSLog(@"IOServiceMatching returned a NULL dictionary."); +#endif + } +} + +- (id)init +{ + if ((self = [super init])) { + portList = [[NSMutableArray array] retain]; + + [self addAllSerialPortsToArray:portList]; + [self registerForSerialPortChangeNotifications]; + } + + return self; +} + +- (NSUInteger)count +{ + return [portList count]; +} + +- (AMSerialPort *)objectAtIndex:(NSUInteger)idx +{ + return [portList objectAtIndex:idx]; +} + +- (AMSerialPort *)objectWithName:(NSString *)name +{ + AMSerialPort *result = nil; + NSEnumerator *enumerator = [portList objectEnumerator]; + AMSerialPort *port; + while ((port = [enumerator nextObject]) != nil) { + if ([[port name] isEqualToString:name]) { + result = port; + break; + } + } + return result; +} + +- (NSArray *)serialPorts +{ + return [[portList copy] autorelease]; +} + +- (NSArray *)serialPortsOfType:(NSString *)serialTypeKey +{ + NSMutableArray *result = [NSMutableArray array]; + NSEnumerator *enumerator = [portList objectEnumerator]; + AMSerialPort *port; + while ((port = [enumerator nextObject]) != nil) { + if ([[port type] isEqualToString:serialTypeKey]) { + [result addObject:port]; + } + } + return result; +} + + +@end diff --git a/atemOSC/arduino/AMSerialPortList_Deprecated.h b/atemOSC/arduino/AMSerialPortList_Deprecated.h new file mode 100644 index 0000000..f6f520b --- /dev/null +++ b/atemOSC/arduino/AMSerialPortList_Deprecated.h @@ -0,0 +1,19 @@ +// +// AMSerialPortList_Deprecated.h +// AMSerialTest +// +// Created by Andreas on 14.08.06. +// Copyright 2006 Andreas Mayer. All rights reserved. +// + +#import +#import "AMSerialPortList.h" + + +@interface AMSerialPortList (Deprecated) + +- (NSArray *)getPortList; +// replaced by -serialPorts; + + +@end diff --git a/atemOSC/arduino/AMSerialPortList_Deprecated.m b/atemOSC/arduino/AMSerialPortList_Deprecated.m new file mode 100644 index 0000000..4d7df9d --- /dev/null +++ b/atemOSC/arduino/AMSerialPortList_Deprecated.m @@ -0,0 +1,20 @@ +// +// AMSerialPortList_Deprecated.m +// AMSerialTest +// +// Created by Andreas on 14.08.06. +// Copyright 2006 Andreas Mayer. All rights reserved. +// + +#import "AMSerialPortList_Deprecated.h" + + +@implementation AMSerialPortList (Deprecated) + +- (NSArray *)getPortList +{ + return [self serialPorts]; +} + + +@end diff --git a/atemOSC/arduino/AMStandardEnumerator.h b/atemOSC/arduino/AMStandardEnumerator.h new file mode 100644 index 0000000..a276b73 --- /dev/null +++ b/atemOSC/arduino/AMStandardEnumerator.h @@ -0,0 +1,32 @@ +// +// AMStandardEnumerator.h +// +// Created by Andreas on Mon Aug 04 2003. +// Copyright (c) 2003 Andreas Mayer. All rights reserved. +// +// 2007-10-26 Sean McBride +// - made code 64 bit and garbage collection clean + +#import "AMSDKCompatibility.h" + +#import + +typedef NSUInteger (*CountMethod)(id, SEL); +typedef id (*NextObjectMethod)(id, SEL, NSUInteger); + +@interface AMStandardEnumerator : NSEnumerator +{ +@private + id collection; + SEL countSelector; + SEL nextObjectSelector; + CountMethod count; + NextObjectMethod nextObject; + NSUInteger position; +} + +// Designated initializer +- (id)initWithCollection:(id)theCollection countSelector:(SEL)theCountSelector objectAtIndexSelector:(SEL)theObjectSelector; + + +@end diff --git a/atemOSC/arduino/AMStandardEnumerator.m b/atemOSC/arduino/AMStandardEnumerator.m new file mode 100644 index 0000000..59ef8cf --- /dev/null +++ b/atemOSC/arduino/AMStandardEnumerator.m @@ -0,0 +1,59 @@ +// +// AMStandardEnumerator.m +// +// Created by Andreas on Mon Aug 04 2003. +// Copyright (c) 2003 Andreas Mayer. All rights reserved. +// +// 2007-10-26 Sean McBride +// - made code 64 bit and garbage collection clean + +#import "AMSDKCompatibility.h" + +#import "AMStandardEnumerator.h" + + +@implementation AMStandardEnumerator + +// Designated initializer +- (id)initWithCollection:(id)theCollection countSelector:(SEL)theCountSelector objectAtIndexSelector:(SEL)theObjectSelector +{ + self = [super init]; + if (self) { + collection = [theCollection retain]; + countSelector = theCountSelector; + count = (CountMethod)[collection methodForSelector:countSelector]; + nextObjectSelector = theObjectSelector; + nextObject = (NextObjectMethod)[collection methodForSelector:nextObjectSelector]; + position = 0; + } + return self; +} + +#ifndef __OBJC_GC__ + +- (void)dealloc +{ + [collection release]; + [super dealloc]; +} + +#endif + +- (id)nextObject +{ + if (position >= count(collection, countSelector)) + return nil; + + return (nextObject(collection, nextObjectSelector, position++)); +} + +- (NSArray *)allObjects +{ + NSMutableArray *result = [[[NSMutableArray alloc] init] autorelease]; + id object; + while ((object = [self nextObject]) != nil) + [result addObject:object]; + return result; +} + +@end diff --git a/atemOSC/arduino/ArduinoSerial_Prefix.pch b/atemOSC/arduino/ArduinoSerial_Prefix.pch new file mode 100644 index 0000000..60b13cd --- /dev/null +++ b/atemOSC/arduino/ArduinoSerial_Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'ArduinoSerial' target in the 'ArduinoSerial' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/atemOSC/atemOSC-Info.plist b/atemOSC/atemOSC-Info.plist index f421619..66ff72e 100644 --- a/atemOSC/atemOSC-Info.plist +++ b/atemOSC/atemOSC-Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.0 + 2.0 CFBundleSignature ???? CFBundleVersion diff --git a/atemOSC/atemOSC.xcodeproj/project.pbxproj b/atemOSC/atemOSC.xcodeproj/project.pbxproj index 4bc8e87..125e5cb 100644 --- a/atemOSC/atemOSC.xcodeproj/project.pbxproj +++ b/atemOSC/atemOSC.xcodeproj/project.pbxproj @@ -9,11 +9,17 @@ /* Begin PBXBuildFile section */ 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; }; 256AC3DA0F4B6AC300CF3369 /* SwitcherPanelAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* SwitcherPanelAppDelegate.mm */; }; + 333E3045161395CF0002287B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 333E3044161395CF0002287B /* IOKit.framework */; }; 335AB1BF15703EF4003EA2D2 /* VVOSC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 335AB1BB15703EF4003EA2D2 /* VVOSC.framework */; }; 335AB1C115703EF4003EA2D2 /* VVBasics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 335AB1BD15703EF4003EA2D2 /* VVBasics.framework */; }; 335AB1C315703EFA003EA2D2 /* VVOSC.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335AB1BB15703EF4003EA2D2 /* VVOSC.framework */; }; 335AB1C415703EFA003EA2D2 /* VVBasics.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 335AB1BD15703EF4003EA2D2 /* VVBasics.framework */; }; 335B268D1573A16300F72574 /* BMDSwitcherAPIDispatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 335B268C1573A16300F72574 /* BMDSwitcherAPIDispatch.cpp */; }; + 33F328ED1573A29900D4722A /* AMSerialPort.m in Sources */ = {isa = PBXBuildFile; fileRef = 33F328E31573A29900D4722A /* AMSerialPort.m */; }; + 33F328EE1573A29900D4722A /* AMSerialPortAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 33F328E51573A29900D4722A /* AMSerialPortAdditions.m */; }; + 33F328EF1573A29900D4722A /* AMSerialPortList.m in Sources */ = {isa = PBXBuildFile; fileRef = 33F328E71573A29900D4722A /* AMSerialPortList.m */; }; + 33F328F01573A29900D4722A /* AMSerialPortList_Deprecated.m in Sources */ = {isa = PBXBuildFile; fileRef = 33F328E91573A29900D4722A /* AMSerialPortList_Deprecated.m */; }; + 33F328F11573A29900D4722A /* AMStandardEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 33F328EB1573A29900D4722A /* AMStandardEnumerator.m */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; @@ -43,11 +49,24 @@ 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + 333E3044161395CF0002287B /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; 335AB1BB15703EF4003EA2D2 /* VVOSC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = VVOSC.framework; sourceTree = ""; }; 335AB1BD15703EF4003EA2D2 /* VVBasics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = VVBasics.framework; sourceTree = ""; }; 335B268B1573A16300F72574 /* BMDSwitcherAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BMDSwitcherAPI.h; sourceTree = ""; }; 335B268C1573A16300F72574 /* BMDSwitcherAPIDispatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BMDSwitcherAPIDispatch.cpp; sourceTree = ""; }; - 33C7E513156FDAE5008129CF /* SDKSettings.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = SDKSettings.plist; sourceTree = ""; }; + 33F328E01573A29900D4722A /* AMSDKCompatibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMSDKCompatibility.h; sourceTree = ""; }; + 33F328E11573A29900D4722A /* AMSerialErrors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMSerialErrors.h; sourceTree = ""; }; + 33F328E21573A29900D4722A /* AMSerialPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMSerialPort.h; sourceTree = ""; }; + 33F328E31573A29900D4722A /* AMSerialPort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMSerialPort.m; sourceTree = ""; }; + 33F328E41573A29900D4722A /* AMSerialPortAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMSerialPortAdditions.h; sourceTree = ""; }; + 33F328E51573A29900D4722A /* AMSerialPortAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMSerialPortAdditions.m; sourceTree = ""; }; + 33F328E61573A29900D4722A /* AMSerialPortList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMSerialPortList.h; sourceTree = ""; }; + 33F328E71573A29900D4722A /* AMSerialPortList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMSerialPortList.m; sourceTree = ""; }; + 33F328E81573A29900D4722A /* AMSerialPortList_Deprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMSerialPortList_Deprecated.h; sourceTree = ""; }; + 33F328E91573A29900D4722A /* AMSerialPortList_Deprecated.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMSerialPortList_Deprecated.m; sourceTree = ""; }; + 33F328EA1573A29900D4722A /* AMStandardEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMStandardEnumerator.h; sourceTree = ""; }; + 33F328EB1573A29900D4722A /* AMStandardEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMStandardEnumerator.m; sourceTree = ""; }; + 33F328EC1573A29900D4722A /* ArduinoSerial_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArduinoSerial_Prefix.pch; sourceTree = ""; }; 8D1107310486CEB800E47090 /* atemOSC-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "atemOSC-Info.plist"; sourceTree = ""; }; 8D1107320486CEB800E47090 /* atemOSC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = atemOSC.app; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -57,6 +76,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 333E3045161395CF0002287B /* IOKit.framework in Frameworks */, 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, 335AB1BF15703EF4003EA2D2 /* VVOSC.framework in Frameworks */, 335AB1C115703EF4003EA2D2 /* VVBasics.framework in Frameworks */, @@ -78,6 +98,7 @@ 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { isa = PBXGroup; children = ( + 333E3044161395CF0002287B /* IOKit.framework */, 335AB1BB15703EF4003EA2D2 /* VVOSC.framework */, 335AB1BD15703EF4003EA2D2 /* VVBasics.framework */, 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, @@ -106,7 +127,6 @@ 29B97314FDCFA39411CA2CEA /* SwitcherPanel */ = { isa = PBXGroup; children = ( - 33C7E512156FDAE5008129CF /* macosx.sdk */, 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, @@ -119,6 +139,7 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( + 33F328DF1573A29900D4722A /* arduino */, 335B268B1573A16300F72574 /* BMDSwitcherAPI.h */, 335B268C1573A16300F72574 /* BMDSwitcherAPIDispatch.cpp */, 29B97316FDCFA39411CA2CEA /* main.m */, @@ -145,13 +166,24 @@ name = Frameworks; sourceTree = ""; }; - 33C7E512156FDAE5008129CF /* macosx.sdk */ = { + 33F328DF1573A29900D4722A /* arduino */ = { isa = PBXGroup; children = ( - 33C7E513156FDAE5008129CF /* SDKSettings.plist */, + 33F328E01573A29900D4722A /* AMSDKCompatibility.h */, + 33F328E11573A29900D4722A /* AMSerialErrors.h */, + 33F328E21573A29900D4722A /* AMSerialPort.h */, + 33F328E31573A29900D4722A /* AMSerialPort.m */, + 33F328E41573A29900D4722A /* AMSerialPortAdditions.h */, + 33F328E51573A29900D4722A /* AMSerialPortAdditions.m */, + 33F328E61573A29900D4722A /* AMSerialPortList.h */, + 33F328E71573A29900D4722A /* AMSerialPortList.m */, + 33F328E81573A29900D4722A /* AMSerialPortList_Deprecated.h */, + 33F328E91573A29900D4722A /* AMSerialPortList_Deprecated.m */, + 33F328EA1573A29900D4722A /* AMStandardEnumerator.h */, + 33F328EB1573A29900D4722A /* AMStandardEnumerator.m */, + 33F328EC1573A29900D4722A /* ArduinoSerial_Prefix.pch */, ); - name = macosx.sdk; - path = "../../../../../../Volumes/User/Downloads/brennon-vvocs-frameworks-5791867/VVOSC/macosx.sdk"; + path = arduino; sourceTree = ""; }; /* End PBXGroup section */ @@ -182,7 +214,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0430; + LastUpgradeCheck = 0450; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "atemOSC" */; compatibilityVersion = "Xcode 3.2"; @@ -223,6 +255,11 @@ 8D11072D0486CEB800E47090 /* main.m in Sources */, 256AC3DA0F4B6AC300CF3369 /* SwitcherPanelAppDelegate.mm in Sources */, 335B268D1573A16300F72574 /* BMDSwitcherAPIDispatch.cpp in Sources */, + 33F328ED1573A29900D4722A /* AMSerialPort.m in Sources */, + 33F328EE1573A29900D4722A /* AMSerialPortAdditions.m in Sources */, + 33F328EF1573A29900D4722A /* AMSerialPortList.m in Sources */, + 33F328F01573A29900D4722A /* AMSerialPortList_Deprecated.m in Sources */, + 33F328F11573A29900D4722A /* AMStandardEnumerator.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -252,10 +289,12 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_APPS_DIR)/Blackmagic ATEM Switchers/Developer SDK/Mac/Samples/SwitcherPanel\"", + "\"$(SRCROOT)\"", ); GCC_DYNAMIC_NO_PIC = NO; GCC_MODEL_TUNING = G5; @@ -266,7 +305,9 @@ INSTALL_PATH = "$(HOME)/Applications"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks @executable_path/../Frameworks"; MACH_O_TYPE = mh_execute; + MACOSX_DEPLOYMENT_TARGET = 10.8; PRODUCT_NAME = atemOSC; + SDKROOT = ""; }; name = Debug; }; @@ -274,10 +315,12 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_APPS_DIR)/Blackmagic ATEM Switchers/Developer SDK/Mac/Samples/SwitcherPanel\"", + "\"$(SRCROOT)\"", ); GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; @@ -286,7 +329,9 @@ INSTALL_PATH = "$(HOME)/Applications"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks @executable_path/../Frameworks"; MACH_O_TYPE = mh_execute; + MACOSX_DEPLOYMENT_TARGET = 10.8; PRODUCT_NAME = atemOSC; + SDKROOT = ""; }; name = Release; }; @@ -300,7 +345,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks @executable_path/../Frameworks"; ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Debug; }; @@ -312,7 +357,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks @executable_path/../Frameworks"; - SDKROOT = macosx10.6; + SDKROOT = macosx; }; name = Release; }; diff --git a/atemOSC/atemOSC.xcodeproj/project.xcworkspace/xcuserdata/dani.xcuserdatad/UserInterfaceState.xcuserstate b/atemOSC/atemOSC.xcodeproj/project.xcworkspace/xcuserdata/dani.xcuserdatad/UserInterfaceState.xcuserstate index bb11e0a..269ac19 100644 Binary files a/atemOSC/atemOSC.xcodeproj/project.xcworkspace/xcuserdata/dani.xcuserdatad/UserInterfaceState.xcuserstate and b/atemOSC/atemOSC.xcodeproj/project.xcworkspace/xcuserdata/dani.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/atemOSC/atemOSC.xcodeproj/xcuserdata/dani.xcuserdatad/xcschemes/atemOSC.xcscheme b/atemOSC/atemOSC.xcodeproj/xcuserdata/dani.xcuserdatad/xcschemes/atemOSC.xcscheme index 0144129..39e8836 100644 --- a/atemOSC/atemOSC.xcodeproj/xcuserdata/dani.xcuserdatad/xcschemes/atemOSC.xcscheme +++ b/atemOSC/atemOSC.xcodeproj/xcuserdata/dani.xcuserdatad/xcschemes/atemOSC.xcscheme @@ -1,5 +1,6 @@