diff --git a/LiveOSCQueryHelper/Assets.xcassets/AppIcon.appiconset/Contents.json b/LiveOSCQueryHelper/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 2db2b1c..0000000 --- a/LiveOSCQueryHelper/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "images" : [ - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "16x16", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "32x32", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "128x128", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "256x256", - "scale" : "2x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "1x" - }, - { - "idiom" : "mac", - "size" : "512x512", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/LiveOSCQueryHelper/Base.lproj/MainMenu.xib b/LiveOSCQueryHelper/Base.lproj/MainMenu.xib deleted file mode 100644 index 3fcfe1f..0000000 --- a/LiveOSCQueryHelper/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,854 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - Default - - - - - - - Left to Right - - - - - - - Right to Left - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Live OSCQuery Helper ("LOQH" from now on) creates an OSC query server from an Ableton Live project file. This app also creates an OSC server ("Live OSCQuery Helper"), as well as a virtual MIDI device ("From Live OSCQuery Helper"). Clients can browse the query server's OSC address space, and send OSC messages to the OSC server- these OSC messages are transformed into the appropriate MIDI messages, and published on the virtual MIDI device where Ableton Live can receive them. This allows multiple clients to browse and interact with an Ableton Live project in realtime. - -HOW TO USE IT: -1)- Tell LOQH what Ableton Live project file to use- this file will be used to populate the OSC query server with the description of another application's OSC address space. LOQH will "watch" the file and if it is updated, the query server will automatically update itself, and then notify all connected clients that it has been updated. LOQH will only create/publish OSC nodes for controls in your project file that have been mapped to MIDI- if a control doesn't have a MIDI mapping, it won't appear on the server! -2)- Configure Ableton Live to receive MIDI data from the virtual device published by this app (named "From Live OSCQuery Helper")- this is how this app communicates with Ableton Live! - -If LOQH is running, the OSC query server is running- you can check it with any OSC query client, or a web browser. The query server will stop when the app quits- if there's a problem with the file you load (if it's missing or malformed or corrupt) the query server will keep running, but its address space will be empty. - - - - - - - - - - - - - - - - - diff --git a/LiveOSCQueryHelper/Info.plist b/LiveOSCQueryHelper/Info.plist deleted file mode 100644 index dafcdcf..0000000 --- a/LiveOSCQueryHelper/Info.plist +++ /dev/null @@ -1,61 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - als - - CFBundleTypeName - ALS - CFBundleTypeOSTypes - - **** - - CFBundleTypeRole - Viewer - - - CFBundleTypeName - Folder - CFBundleTypeRole - Viewer - LSItemContentTypes - - public.folder - - - - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 0.3.0.4 - CFBundleVersion - 0.3.0.4 - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - Copyright © 2018 Vidvox, LLC. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - SUFeedURL - https://www.vidvox.net/version/LiveOSCQueryHelper.xml - - diff --git a/LiveOSCQueryHelper/LOQHMIDIManager.h b/LiveOSCQueryHelper/LOQHMIDIManager.h deleted file mode 100644 index d5ae518..0000000 --- a/LiveOSCQueryHelper/LOQHMIDIManager.h +++ /dev/null @@ -1,24 +0,0 @@ -#import -#import - - - - -/* first of all, this class uses a particular MIDI framework (VVMIDI, a precompiled version of - which is included in the project file). neither the OSC query protocol in general nor - VVOSCQueryProtocol.frameowrk in particular require this framework- this is just the MIDI - framework i chose to use because i happen to be familiar with it. you could just as easily use - literally any other MIDI framework in its place. - - this is a subclass of VVMIDIManager. this subclass exists for a couple reasons: - - by default, midi managers create both source and destination virtual nodes. we only want to - create a destination (we only want this app to appears as a "device" to other apps, we don't - want other apps to send MIDI data to this) */ - - - - -@interface LOQHMIDIManager : VVMIDIManager { -} - -@end diff --git a/LiveOSCQueryHelper/LOQHMIDIManager.m b/LiveOSCQueryHelper/LOQHMIDIManager.m deleted file mode 100644 index aec7025..0000000 --- a/LiveOSCQueryHelper/LOQHMIDIManager.m +++ /dev/null @@ -1,36 +0,0 @@ -#import "LOQHMIDIManager.h" - -@implementation LOQHMIDIManager - -- (void) generalInit { - [super generalInit]; -} -- (void) createVirtualNodes { - //NSLog(@"%s",__func__); - - // we only want to create the "sender" virtual node (the one that pretends i'm a "MIDI device") - - /* - make the sender- this node "owns" the destination: it is responsible for telling - any endpoints connected to this destination that it has received midi data - */ - if (virtualDest != nil) { - virtualDest = nil; - } - virtualDest = [[[self sendingNodeClass] alloc] initSenderWithName:[self sendingNodeName]]; - if (virtualDest != nil) - [virtualDest setDelegate:self]; -} -- (void) sendMsg:(VVMIDIMessage *)m { - //NSLog(@"%s ... %@",__func__,m); - // we only want to send the message to my virtual destination, and to the destination specified - [virtualDest sendMsg:m]; -} -- (NSString *) receivingNodeName { - return @"To Live OSCQuery Helper"; -} -- (NSString *) sendingNodeName { - return @"From Live OSCQuery Helper"; -} - -@end diff --git a/LiveOSCQueryHelper/LOQHOSCManager.h b/LiveOSCQueryHelper/LOQHOSCManager.h deleted file mode 100644 index c9d426c..0000000 --- a/LiveOSCQueryHelper/LOQHOSCManager.h +++ /dev/null @@ -1,25 +0,0 @@ -#import -#import - - - - -// this is the name of the notification that is posted any time the host info is changed by the user -extern NSString * const TargetAppHostInfoChangedNotification; - - - - -@interface LOQHOSCManager : OSCManager { - IBOutlet NSTextField *portField; // this app will create an OSC input that listens on this port -} - -- (void) setPortInt:(int)inPortInt; - -- (NSDictionary *) oscQueryHostInfo; - -- (IBAction) textFieldUsed:(id)sender; - -- (OSCInPort *) inPort; - -@end diff --git a/LiveOSCQueryHelper/LOQHOSCManager.m b/LiveOSCQueryHelper/LOQHOSCManager.m deleted file mode 100644 index 5274f79..0000000 --- a/LiveOSCQueryHelper/LOQHOSCManager.m +++ /dev/null @@ -1,72 +0,0 @@ -#import "LOQHOSCManager.h" -#import - - - - -NSString * const TargetAppHostInfoChangedNotification = @"TargetAppHostInfoChangedNotification"; - - - - -@implementation LOQHOSCManager - - -- (void) _generalInit { - [super _generalInit]; - [self setInPortLabelBase:@"Live OSCQuery Helper"]; -} -- (void) awakeFromNib { - // if there's a saved default for the IP address/port, put 'em in the fields - NSUserDefaults *def = [NSUserDefaults standardUserDefaults]; - NSNumber *tmpNum = nil; - tmpNum = [def objectForKey:@"lastPort"]; - if (tmpNum == nil) - tmpNum = [NSNumber numberWithInteger:1250]; - [self setPortInt:[tmpNum intValue]]; -} -- (void) setPortInt:(int)inPortInt { - OSCInPort *tmpPort = [inPortArray lockObjectAtIndex:0]; - if (tmpPort != nil && [tmpPort port] != inPortInt) { - [self deleteAllInputs]; - tmpPort = nil; - } - if (tmpPort == nil) - tmpPort = [self createNewInputForPort:inPortInt]; - - //int newPortInt = [tmpPort port]; - NSString *newPortString = [NSString stringWithFormat:@"%d",[tmpPort port]]; - dispatch_async(dispatch_get_main_queue(), ^{ - if (![[self->portField stringValue] isEqualToString:newPortString]) - [self->portField setStringValue:newPortString]; - }); -} -- (NSDictionary *) oscQueryHostInfo { - NSMutableDictionary *returnMe = [[NSMutableDictionary alloc] init]; - OSCInPort *tmpPort = [self inPort]; - if (tmpPort != nil) { - [returnMe setObject:[NSNumber numberWithInteger:[tmpPort port]] forKey:kVVOSCQ_ReqAttr_HostInfo_OSCPort]; - } - return returnMe; -} -- (IBAction) textFieldUsed:(id)sender { - //NSLog(@"%s",__func__); - NSUInteger tmpInt = [portField intValue]; - - [self setPortInt:(int)tmpInt]; - - // post a notification that the HOST_INFO information has changed - [[NSNotificationCenter defaultCenter] postNotificationName:TargetAppHostInfoChangedNotification object:nil]; -} -- (void) receivedOSCMessage:(OSCMessage *)n { - //NSLog(@"%s ... %@",__func__,n); - OSCAddressSpace *as = [OSCAddressSpace mainAddressSpace]; - [as dispatchMessage:n]; -} -- (OSCInPort *) inPort { - OSCInPort *returnMe = [inPortArray lockObjectAtIndex:0]; - return returnMe; -} - - -@end diff --git a/LiveOSCQueryHelper/LiveOSCQueryHelper.entitlements b/LiveOSCQueryHelper/LiveOSCQueryHelper.entitlements deleted file mode 100644 index 0c67376..0000000 --- a/LiveOSCQueryHelper/LiveOSCQueryHelper.entitlements +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/LiveOSCQueryHelper/LiveOSCQueryHelperAppDelegate.h b/LiveOSCQueryHelper/LiveOSCQueryHelperAppDelegate.h deleted file mode 100644 index 032a079..0000000 --- a/LiveOSCQueryHelper/LiveOSCQueryHelperAppDelegate.h +++ /dev/null @@ -1,25 +0,0 @@ -#import -#import -#import "LOQHOSCManager.h" -#import "LOQHMIDIManager.h" -#import "VVKQueueCenter.h" - -@interface LiveOSCQueryHelperAppDelegate : NSObject { - IBOutlet LOQHOSCManager *oscm; - IBOutlet LOQHMIDIManager *midim; - - NSMutableArray *delegates; // array of QueryServerNodeDelegate instances - - NSString *loadedFilePath; - NSDictionary *fileHostInfoDict; // the HOST_INFO dict from the top-level object (if there is one) is stripped and retained here - IBOutlet NSTextField *fileStatusField; - - VVOSCQueryServer *server; - IBOutlet NSTextField *serverStatusField; - - IBOutlet NSWindow *helpWindow; -} - - -@end - diff --git a/LiveOSCQueryHelper/LiveOSCQueryHelperAppDelegate.m b/LiveOSCQueryHelper/LiveOSCQueryHelperAppDelegate.m deleted file mode 100644 index 56d8598..0000000 --- a/LiveOSCQueryHelper/LiveOSCQueryHelperAppDelegate.m +++ /dev/null @@ -1,562 +0,0 @@ -#import "LiveOSCQueryHelperAppDelegate.h" -#import "QueryServerNodeDelegate.h" -#import "OSCNodeAdditions.h" -#import "LiveToOSCQHelper.h" - - - - -@interface LiveOSCQueryHelperAppDelegate () { - NSTimer *fileChangeCoalesceTimer; -} -@property (weak) IBOutlet NSWindow *window; -@property (strong) id activity; -- (void) _loadLastFile; -- (void) _loadFile:(NSString *)fullPath; -- (void) _loadAbletonProjectFile:(NSString *)fullPath; -- (void) _updateUIItems; -@end - - - - -// this class addition returns an attributed string that renders the receiver- which is presumed to contain valid HTML code- in NSTextFields. this is what makes the link "clickable". -@implementation NSString (NSStringAdditions) -- (NSAttributedString *) renderedHTMLWithFont:(NSFont *)font { - if (!font) font = [NSFont systemFontOfSize:0.0]; // Default font - NSString *html = [NSString stringWithFormat:@"%@", [font fontName], (int)[font pointSize], self]; - NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding]; - NSAttributedString* string = [[NSAttributedString alloc] initWithHTML:data documentAttributes:nil]; - return string; -} -@end - - - - -@implementation LiveOSCQueryHelperAppDelegate - - -+ (void) initialize { - // make sure the kqueue stuff is up and running - [VVKQueueCenter class]; -} -- (id) init { - self = [super init]; - if (self != nil) { - // disable app nap - self.activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityUserInitiated reason:@"Live OSCQuery Helper"]; - - // register the OSC address space - OSCAddressSpace *as = [OSCAddressSpace mainAddressSpace]; - // by default, the address space registers for app terminate notifications so it can tear itself down. we want to prevent this so we don't send "node deleted" messages to clients on app quit. - [[NSNotificationCenter defaultCenter] removeObserver:as name:NSApplicationWillTerminateNotification object:nil]; - - delegates = [[NSMutableArray alloc] init]; - loadedFilePath = nil; - fileChangeCoalesceTimer = nil; - - // make an VVOSCQueryServer- we'll start it later, when the app finishes launching - server = [[VVOSCQueryServer alloc] init]; - [server setName:@"Live OSCQuery Helper"]; - [server setBonjourName:@"Live OSCQuery Helper"]; - [server setDelegate:self]; - - // this notification is posted by our OSC manager subclass when the host info changes as a result of user interaction - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(targetAppHostInfoChangedNotification:) - name:TargetAppHostInfoChangedNotification - object:nil]; - } - return self; -} -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - // load the last file- this will populate the OSC address space with the contents of the file... - [self _loadLastFile]; - - // start the VVOSCQueryServer! - [server start]; - - // update my UI - [self _updateUIItems]; -} - - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - // stop the VVOSCQueryServer! - [server stop]; - // clear the delegates - OSCAddressSpace *as = [OSCAddressSpace mainAddressSpace]; - for (QueryServerNodeDelegate *tmpDelegate in delegates) { - [as removeDelegate:tmpDelegate forPath:[tmpDelegate address]]; - } - [delegates removeAllObjects]; -} -- (BOOL)application:(NSApplication *)sender openFile:(NSString *)inPath { - //NSLog(@"%s ... %@",__func__,inPath); - NSFileManager *fm = [NSFileManager defaultManager]; - BOOL isDirectory = NO; - NSError *nsErr = nil; - if ([fm fileExistsAtPath:inPath isDirectory:&isDirectory]) { - if (!isDirectory) { - [self _loadFile:inPath]; - return YES; - } - else { - NSArray *filenames = [fm contentsOfDirectoryAtPath:inPath error:&nsErr]; - for (NSString *filename in filenames) { - if ([[filename pathExtension] caseInsensitiveCompare:@"als"]==NSOrderedSame) { - NSString *fullPath = [NSString stringWithFormat:@"%@/%@",inPath,filename]; - [self _loadFile:fullPath]; - return YES; - } - } - } - } - - return NO; -} - - -#pragma mark -------------------------- UI - - -- (IBAction) openDocument:(id)sender { - //NSLog(@"%s",__func__); - NSUserDefaults *def = [NSUserDefaults standardUserDefaults]; - NSString *importDir = [def objectForKey:@"lastOpenDocumentFolder"]; - if (importDir == nil) - importDir = [@"~/Desktop" stringByExpandingTildeInPath]; - NSString *importFile = [def objectForKey:@"lastOpenDocumentFile"]; - //NSOpenPanel *op = [[NSOpenPanel openPanel] retain]; - NSOpenPanel *op = [NSOpenPanel openPanel]; - [op setAllowsMultipleSelection:NO]; - [op setCanChooseDirectories:NO]; - [op setResolvesAliases:YES]; - [op setMessage:@"Select Ableton Live project file to open"]; - [op setTitle:@"Open file"]; - [op setAllowedFileTypes:@[ @"als" ]]; - //[op setDirectoryURL:[NSURL fileURLWithPath:importDir]]; - if (importFile != nil) - [op setDirectoryURL:[NSURL fileURLWithPath:importFile]]; - else - [op setDirectoryURL:[NSURL fileURLWithPath:importDir]]; - - [op - beginSheetModalForWindow:[self window] - completionHandler:^(NSInteger result) { - if (result == NSFileHandlingPanelOKButton) { - // get the inspected object - NSArray *fileURLs = [op URLs]; - NSURL *urlPtr = (fileURLs==nil) ? nil : [fileURLs objectAtIndex:0]; - NSString *urlPath = (urlPtr==nil) ? nil : [urlPtr path]; - if (urlPath != nil) { - [self _loadFile:urlPath]; - } - // update the defaults so i know where the law directory i browsed was - NSString *directoryString = (urlPath==nil) ? nil : [urlPath stringByDeletingLastPathComponent]; - if (directoryString != nil) - [[NSUserDefaults standardUserDefaults] setObject:directoryString forKey:@"lastOpenDocumentFolder"]; - [[NSUserDefaults standardUserDefaults] synchronize]; - } - }]; -} - -- (IBAction) showHelp:(id)sender { - //NSLog(@"%s",__func__); - if (![NSThread isMainThread]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self showHelp:sender]; - }); - return; - } - - [[self window] beginSheet:helpWindow completionHandler:^(NSModalResponse returnCode) { - }]; -} -- (IBAction) closeHelp:(id)sender { - //NSLog(@"%s",__func__); - if (![NSThread isMainThread]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self closeHelp:sender]; - }); - return; - } - - [[self window] endSheet:helpWindow returnCode:NSModalResponseStop]; -} - - -#pragma mark -------------------------- backend - - -- (void) _loadLastFile { - NSUserDefaults *def = [NSUserDefaults standardUserDefaults]; - NSString *tmpString = [def objectForKey:@"lastOpenDocumentFile"]; - if (tmpString == nil) - return; - [self _loadFile:tmpString]; -} -- (void) _loadFile:(NSString *)fullPath { - //NSLog(@"%s ... %@",__func__,fullPath); - NSString *ext = (fullPath==nil) ? nil : [fullPath pathExtension]; - if ([ext caseInsensitiveCompare:@"als"]==NSOrderedSame) { - [self _loadAbletonProjectFile:fullPath]; - } -} -- (void) _loadAbletonProjectFile:(NSString *)fullPath { - //NSLog(@"%s ... %@",__func__,fullPath); - if (fullPath == nil) - return; - // unserialize the file at the path into a series of JSON objects - //NSError *nsErr = nil; - NSDictionary *rawFileObj = [LiveToOSCQHelper OSCQueryJSONObjectForLiveProject:fullPath]; - if (rawFileObj==nil || ![rawFileObj isKindOfClass:[NSDictionary class]]) { - NSLog(@"\t\terr: raw object is nil or of wrong type for path %@",fullPath); - return; - } - NSMutableDictionary *fileObject = (rawFileObj==nil) ? nil : [rawFileObj mutableCopy]; - //NSLog(@"\t\tfileObject is %@",fileObject); - - // if this is a different file, stop the server - NSUserDefaults *def = [NSUserDefaults standardUserDefaults]; - BOOL reloadingTheFile = YES; - BOOL wasRunning = [server isRunning]; - if (loadedFilePath==nil || (loadedFilePath!=nil && ![loadedFilePath isEqualToString:fullPath])) - reloadingTheFile = NO; - if (!reloadingTheFile && wasRunning) - [server stop]; - - // rename the server! - NSString *fileName = [[fullPath lastPathComponent] stringByDeletingPathExtension]; - [server setName:fileName]; - NSString *bjName = [NSString stringWithFormat:@"%@ OSCQuery Helper",fileName]; - int nameLength = (int)[bjName length]; - if (nameLength > 63) { - bjName = [NSString stringWithFormat:@"%@...%@",[bjName substringWithRange:NSMakeRange(0,30)],[bjName substringWithRange:NSMakeRange(nameLength-30,30)]]; - } - [server setBonjourName:bjName]; - - // if i'm not reloading a file then i may want to stop observing the file - if (!reloadingTheFile) { - // if i've already got a file loaded i need to stop observing it - if (loadedFilePath!=nil) { - [VVKQueueCenter removeObserver:self forPath:loadedFilePath]; - } - } - // update my local var storing the file path - loadedFilePath = fullPath; - // if i'm not reloading the file, add myself as an observer so i'll know if the file changes - if (!reloadingTheFile) { - [VVKQueueCenter addObserver:self forPath:loadedFilePath]; - } - // make sure that the file object doesn't have a host info dict - [fileObject removeObjectForKey:kVVOSCQ_ReqAttr_HostInfo]; - // update my user defaults so i know what file i last loaded - [def setObject:fullPath forKey:@"lastOpenDocumentFile"]; - [def synchronize]; - - - // ...now i need to run through the objects from the file, and create OSCNodes from them in an address space - - - OSCAddressSpace *as = [OSCAddressSpace mainAddressSpace]; - // destroy all the delegates immediately- we don't want them sending any messages while we're clearing the address space - for (QueryServerNodeDelegate *tmpDelegate in delegates) { - [as removeDelegate:tmpDelegate forPath:[tmpDelegate address]]; - } - [delegates removeAllObjects]; - - // clear out the OSC address space - NSArray *baseNodes = [[as nodeContents] lockCreateArrayCopy]; - for (OSCNode *baseNode in baseNodes) { - [baseNode removeFromAddressSpace]; - } - - // now run through 'fileObject' recursively using this block, creating OSC nodes for all the objects - __block __weak void (^ParseJSONObj)(NSDictionary *); - ParseJSONObj = ^(NSDictionary * baseObj) { - NSString *objFullPath = [baseObj objectForKey:kVVOSCQ_ReqAttr_Path]; - //NSLog(@"ParseJSONObj() called on %@",objFullPath); - if (objFullPath == nil) { - NSLog(@"\t\terr: bailing, node missing full path, %s",__func__); - return; - } - - // parse the base object, looking for entries that describe the type of MIDI message to send - NSString *tmpString = [baseObj objectForKey:@"MIDI_TYPE"]; - VVMIDIMsgType objMIDIMsgType = VVMIDIMsgUnknown; - if (tmpString != nil) { - if ([tmpString caseInsensitiveCompare:@"NOTE"] == NSOrderedSame) { - objMIDIMsgType = VVMIDINoteOnVal; - } - else if ([tmpString caseInsensitiveCompare:@"AFTERTOUCH"] == NSOrderedSame) { - objMIDIMsgType = VVMIDIAfterTouchVal; - } - else if ([tmpString caseInsensitiveCompare:@"CC"] == NSOrderedSame) { - objMIDIMsgType = VVMIDIControlChangeVal; - } - else if ([tmpString caseInsensitiveCompare:@"PGM"] == NSOrderedSame) { - objMIDIMsgType = VVMIDIProgramChangeVal; - } - else if ([tmpString caseInsensitiveCompare:@"PITCH"] == NSOrderedSame) { - objMIDIMsgType = VVMIDIPitchWheelVal; - } - } - - BOOL setUpAsMIDINode = YES; - // if the message type is unrecognized or there's no channel, bail - NSNumber *objMIDIChannelNum = [baseObj objectForKey:@"MIDI_CHANNEL"]; - if (objMIDIMsgType==VVMIDIMsgUnknown || objMIDIChannelNum==nil) { - setUpAsMIDINode = NO; - //NSLog(@"\t\terr: bailing, node missing msg type or channel num, %s",__func__); - //return; - } - // if there's no midi voice and i'm not pitch bend, bail (everything but pitch bend has a voice, pitch bend is 14-bit) - NSNumber *objMIDIVoiceNum = [baseObj objectForKey:@"MIDI_VOICE"]; - if (objMIDIVoiceNum==nil && (objMIDIMsgType!=VVMIDIPitchWheelVal && objMIDIMsgType!=VVMIDIProgramChangeVal)) { - setUpAsMIDINode = NO; - //NSLog(@"\t\terr: bailing, node missing voice num, %s",__func__); - //return; - } - - // parse the base object, looking for entries that describe the kind of OSC node to publish - NSString *objTypeTagString = [baseObj objectForKey:kVVOSCQ_ReqAttr_Type]; - NSDictionary *objContents = [baseObj objectForKey:kVVOSCQ_ReqAttr_Contents]; - NSString *objDesc = [baseObj objectForKey:kVVOSCQ_ReqAttr_Desc]; - NSArray *objTags = [baseObj objectForKey:kVVOSCQ_OptAttr_Tags]; - NSArray *objExtType = [baseObj objectForKey:kVVOSCQ_OptAttr_Ext_Type]; // one for each type from the type tag string - //NSNumber *objAccess = [baseObj objectForKey:kVVOSCQ_OptAttr_Access]; - NSArray *objRange = [baseObj objectForKey:kVVOSCQ_OptAttr_Range]; // one for each type from the type tag string - NSArray *objUnits = [baseObj objectForKey:kVVOSCQ_OptAttr_Unit]; // one for each type from the type tag string - NSNumber *objCritical = [baseObj objectForKey:kVVOSCQ_OptAttr_Critical]; - NSArray *objOverloads = [baseObj objectForKey:kVVOSCQ_OptAttr_Overloads]; - - if (setUpAsMIDINode) { - OSCNode *newNode = [[OSCAddressSpace mainAddressSpace] findNodeForAddress:objFullPath createIfMissing:YES]; - if (objTypeTagString != nil) { - [newNode setTypeTagString:objTypeTagString]; - [newNode setNodeType:OSCNodeTypeNumber]; - } - else - [newNode setNodeType:OSCNodeDirectory]; - if (objDesc != nil && [objDesc isKindOfClass:[NSString class]]) - [newNode setOSCDescription:objDesc]; - if (objTags != nil && [objTags isKindOfClass:[NSArray class]]) - [newNode setTags:objTags]; - if (objExtType != nil && [objExtType isKindOfClass:[NSArray class]]) - [newNode setExtendedType:objExtType]; - //if (objAccess != nil && [objAccess isKindOfClass:[NSNumber class]]) { - //[newNode setAccess:[objAccess intValue]]; // don't do this, access is always write-only in this application (we can't read the remote app's OSC address space) - [newNode setAccess:2]; - //} - if (objRange != nil && [objRange isKindOfClass:[NSArray class]]) - [newNode setRange:objRange]; - if (objUnits != nil && [objUnits isKindOfClass:[NSArray class]]) - [newNode setUnits:objUnits]; - if (objCritical != nil && [objCritical isKindOfClass:[NSNumber class]]) - [newNode setCritical:[objCritical boolValue]]; - if (objOverloads != nil && [objOverloads isKindOfClass:[NSArray class]]) - [newNode setOverloads:objOverloads]; - - // make a delegate for the node, add it to the array - QueryServerNodeDelegate *tmpDelegate = [[QueryServerNodeDelegate alloc] initWithMIDIManager:self->midim forAddress:[newNode fullName]]; - [tmpDelegate setMIDIMsgType:objMIDIMsgType]; - [tmpDelegate setMIDIChannel:[objMIDIChannelNum intValue]]; - [tmpDelegate setMIDIVoice:[objMIDIVoiceNum intValue]]; - if (objRange != nil) { - NSDictionary *tmpRange = [objRange objectAtIndex:0]; - NSNumber *tmpMin = [tmpRange objectForKey:kVVOSCQ_OptAttr_Range_Min]; - if (tmpMin != nil) { - [tmpDelegate setHasMin:YES]; - [tmpDelegate setMinVal:[tmpMin doubleValue]]; - } - NSNumber *tmpMax = [tmpRange objectForKey:kVVOSCQ_OptAttr_Range_Max]; - if (tmpMax != nil) { - [tmpDelegate setHasMax:YES]; - [tmpDelegate setMaxVal:[tmpMax doubleValue]]; - } - } - [newNode addDelegate:tmpDelegate]; - [self->delegates addObject:tmpDelegate]; - } - - // run through the contents, calling this block recursively on each object - [objContents enumerateKeysAndObjectsUsingBlock:^(NSString * tmpName, NSDictionary * tmpContentsObj, BOOL *stop) { - if ([tmpContentsObj isKindOfClass:[NSDictionary class]]) { - ParseJSONObj(tmpContentsObj); - } - }]; - }; - ParseJSONObj(fileObject); - - // restart the server if appropriate - if (!reloadingTheFile && wasRunning) - [server start]; - - // tell the OSC query server to send a PATH_CHANGED message for the root node - if (reloadingTheFile) - [server sendPathChangedToClients:@"/"]; - - [self _updateUIItems]; -} -- (void) _updateUIItems { - // make sure this method is called on the main thread - if (![NSThread isMainThread]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self _updateUIItems]; - }); - return; - } - - if (loadedFilePath != nil) { - [fileStatusField setStringValue:[loadedFilePath lastPathComponent]]; - } - else { - [fileStatusField setStringValue:@"No file selected!"]; - } - - // update the server status field - if ([server isRunning]) { - NSString *fullAddressString = [NSString stringWithFormat:@"http://localhost:%d",[server webServerPort]]; - NSString *htmlString = [NSString stringWithFormat:@"%@",fullAddressString,fullAddressString]; - NSAttributedString *htmlAttrStr = [htmlString renderedHTMLWithFont:nil]; - [serverStatusField setAttributedStringValue:htmlAttrStr]; - } - else { - [serverStatusField setStringValue:@"Not running!"]; - } -} -- (void) targetAppHostInfoChangedNotification:(NSNotification *)note { - // make sure this method is called on the main thread - if (![NSThread isMainThread]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self targetAppHostInfoChangedNotification:note]; - }); - return; - } - - // if the target app's host info changed then we need to stop and then start the server again - [server stop]; - // wait a bit before restarting it... - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.25*NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [self->server start]; - // wait a bit more before updating the UI... - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.25*NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [self _updateUIItems]; - }); - }); -} - - -#pragma mark -------------------------- VVKQueueCenterDelegate - - -- (void) file:(NSString *)p changed:(u_int)fflag { - //NSLog(@"%s ... %@",__func__,p); - @synchronized (self) { - if (loadedFilePath!=nil && p!=nil && [loadedFilePath isEqualToString:p]) { - // reset the coalesce timer- the upshot is that there's a 0.5 sec delay between changes to a file and when the app reloads that file - if (fileChangeCoalesceTimer != nil) { - [fileChangeCoalesceTimer invalidate]; - fileChangeCoalesceTimer = nil; - } - fileChangeCoalesceTimer = [NSTimer - scheduledTimerWithTimeInterval:1./2. - target:self - selector:@selector(fileChangeCoalesceTimerCallback:) - userInfo:nil - repeats:NO]; - } - } -} -- (void) fileChangeCoalesceTimerCallback:(NSTimer *)t { - //NSLog(@"%s",__func__); - [self _loadFile:loadedFilePath]; -} - - -#pragma mark -------------------------- VVOSCQueryServerDelegate - - -- (VVOSCQueryReply *) hostInfoQueryFromServer:(VVOSCQueryServer *)s { - NSMutableDictionary *hostInfo = [[NSMutableDictionary alloc] init]; - - // supply a server name if there isn't already one - NSString *myName = [s name]; - if ([hostInfo objectForKey:kVVOSCQ_ReqAttr_HostInfo_Name]==nil && myName!=nil) - [hostInfo setObject:myName forKey:kVVOSCQ_ReqAttr_HostInfo_Name]; - // supply a transport mode if there isn't already one - if ([hostInfo objectForKey:kVVOSCQ_ReqAttr_HostInfo_OSCTransport] == nil) - [hostInfo setObject:kVVOSCQueryOSCTransportUDP forKey:kVVOSCQ_ReqAttr_HostInfo_OSCTransport]; - // supply an extensions array if there isn't already one - NSDictionary *extDict = @{ - kVVOSCQ_OptAttr_Tags : @YES, - //kVVOSCQ_ReqAttr_Type : @YES, - kVVOSCQ_OptAttr_Access : @YES, - kVVOSCQ_OptAttr_Value : @YES, - kVVOSCQ_OptAttr_Range : @YES, - kVVOSCQ_OptAttr_Clipmode : @NO, - kVVOSCQ_OptAttr_Unit : @NO, - kVVOSCQ_OptAttr_Critical : @NO, - kVVOSCQ_OptAttr_Overloads : @NO, - kVVOSCQ_OptAttr_HTML : @YES, - kVVOSCQ_WSAttr_Cmd_Listen : @NO, - kVVOSCQ_WSAttr_Cmd_Ignore : @NO, - kVVOSCQ_WSAttr_Cmd_PathChanged : @YES, - kVVOSCQ_WSAttr_Cmd_PathRenamed : @NO, - kVVOSCQ_WSAttr_Cmd_PathRemoved : @NO, - kVVOSCQ_WSAttr_Cmd_PathAdded : @NO, - }; - if ([hostInfo objectForKey:kVVOSCQ_ReqAttr_HostInfo_Exts] == nil) - [hostInfo setObject:extDict forKey:kVVOSCQ_ReqAttr_HostInfo_Exts]; - - // get the host info details from the osc manager - NSDictionary *connectionHostInfo = [oscm oscQueryHostInfo]; - if (connectionHostInfo != nil) - [hostInfo addEntriesFromDictionary:connectionHostInfo]; - - return [[VVOSCQueryReply alloc] initWithJSONObject:hostInfo]; -} -// this is the VVOSCQueryServerDelegate protocol method- requests received by the OSC query server are passed to this method -- (VVOSCQueryReply *) server:(VVOSCQueryServer *)s wantsReplyForQuery:(VVOSCQuery *)q { - //NSLog(@"%s ... %@",__func__,q); - if (q==nil) - return nil; - - NSString *path = [q path]; - // retrieve the OSCNode corresponding to the query's path. this part is specific to my OSC library. - OSCNode *queriedNode = (path==nil) ? nil : [[OSCAddressSpace mainAddressSpace] findNodeForAddress:path createIfMissing:NO]; - // generate a reply to the OSCQuery. this is a class addition that is part of this test server project, and is specific to my OSC library. - VVOSCQueryReply *returnMe = (queriedNode==nil) ? nil : [queriedNode getReplyForOSCQuery:q]; - // if something went wrong and i couldn't generate a valid reply, return a 404 error - if (returnMe == nil) - returnMe = [[VVOSCQueryReply alloc] initWithErrorCode:404]; - return returnMe; -} -- (void) server:(VVOSCQueryServer *)s websocketDeliveredJSONObject:(NSDictionary *)jsonObj { - //NSLog(@"%s ... %@",__func__,jsonObj); -} -- (void) server:(VVOSCQueryServer *)s receivedOSCPacket:(const void*)packet sized:(size_t)packetSize { - //NSLog(@"%s",__func__); - // parse the raw packet - [OSCPacket - parseRawBuffer:(unsigned char *)packet - ofMaxLength:(int)packetSize - toInPort:[oscm inPort] - fromAddr:0 - port:0]; -} -- (BOOL) server:(VVOSCQueryServer *)s wantsToListenTo:(NSString *)address { - //NSLog(@"%s ... %@, %@",__func__,s,address); - // intentionally blank- we can't stream values because we don't have direct access to the remote app's address space (or data model corresponding to an address space) - return NO; -} -- (void) server:(VVOSCQueryServer *)s wantsToIgnore:(NSString *)address { - //NSLog(@"%s ... %@, %@",__func__,s,address); - // intentionally blank, listening is disabled -} - - -@end diff --git a/LiveOSCQueryHelper/QueryServerNodeDelegate.h b/LiveOSCQueryHelper/QueryServerNodeDelegate.h deleted file mode 100644 index 3a210e5..0000000 --- a/LiveOSCQueryHelper/QueryServerNodeDelegate.h +++ /dev/null @@ -1,47 +0,0 @@ -#import -#import -#import -#import "VVOSCQueryServer.h" - - -/* this class exists to bridge an OSC library (VVOSC.framework) with an OSC query library - (VVOSCQueryProtocol.framework). instances of this class are created by software that wants to - connect the query server with an OSC address space- these instances are registered as delegates - of OSCNodes in the OSC address space. when the nodes receive messages, these instances pass - those messages to the query server that created them. */ - - -@interface QueryServerNodeDelegate : NSObject { - __weak VVMIDIManager *midiManager; - NSString *address; - - // we store the MIDI msg type, channel, and voice number here- these are used to create the MIDI message when appropriate - VVMIDIMsgType midiMsgType; - int midiChannel; - int midiVoice; - - // we need expedited access to some basic properties of the OSC node we are a delegate of, because we want to try to normalize the incoming values to convert them to MIDI (we need to know if there is a min/max and what these vals are to do so) - BOOL hasMin; - double minVal; - BOOL hasMax; - double maxVal; -} - -- (id) initWithMIDIManager:(VVMIDIManager *)n forAddress:(NSString *)a; - -// once we compose a VVMIDIMessage, pass it to this method to dispatch it to the appropriate MIDI devices -- (void) sendMsg:(VVMIDIMessage *)n; - -@property (weak,setter=setMIDIManager:) VVMIDIManager *midiManager; -@property (strong) NSString * address; - -@property (setter=setMIDIMsgType:) VVMIDIMsgType midiMsgType; -@property (setter=setMIDIChannel:) int midiChannel; -@property (setter=setMIDIVoice:) int midiVoice; - -@property BOOL hasMin; -@property double minVal; -@property BOOL hasMax; -@property double maxVal; - -@end diff --git a/LiveOSCQueryHelper/QueryServerNodeDelegate.m b/LiveOSCQueryHelper/QueryServerNodeDelegate.m deleted file mode 100644 index 1966733..0000000 --- a/LiveOSCQueryHelper/QueryServerNodeDelegate.m +++ /dev/null @@ -1,178 +0,0 @@ -#import "QueryServerNodeDelegate.h" - - - - -@implementation QueryServerNodeDelegate - - -- (id) initWithMIDIManager:(VVMIDIManager *)n forAddress:(NSString *)a { - //NSLog(@"%s ... %@, %@",__func__,n,a); - self = [super init]; - if (self != nil) { - midiManager = n; - address = a; - midiMsgType = VVMIDIMsgUnknown; - midiChannel = 0; - midiVoice = 0; - - hasMin = NO; - minVal = 0.; - hasMax = NO; - maxVal = 0.; - } - return self; -} -- (void) dealloc { - //NSLog(@"%s",__func__); - [self setMIDIManager:nil]; - [self setAddress:nil]; -} - - -- (void) sendMsg:(VVMIDIMessage *)n { - //NSLog(@"%s ... %@",__func__,n); - //NSLog(@"\t\tmidiManager is %@",midiManager); - [midiManager sendMsg:n]; -} - - -- (void) node:(id)n receivedOSCMessage:(OSCMessage *)msg { - //NSLog(@"%s ... %@, %@",__func__,n,msg); - if (midiMsgType == VVMIDIMsgUnknown) { - NSLog(@"\t\terr: bailing, msg type is unknown, %s",__func__); - return; - } - - OSCValue *oscVal = [msg value]; - if (oscVal == nil) - return; - - // we're going to want to create a new MIDI message to send. - VVMIDIMessage *newMsg = nil; - - // MIDI is based on unsigned integer values that can possibly go as high as 14-bits, so we need to convert whatever we got to the raw integer that we're going to send - uint32_t msgIntVal = 0; // try to assemble a raw int value we can use directly - double msgNormVal = 0.; // try to assemble a normalized double val we can use if we're 14-bit - switch ([oscVal type]) { - case OSCValMIDI: // MIDI-type OSC messages can be converted perfectly, do so now - newMsg = [[VVMIDIMessage alloc] initFromVals:[oscVal midiPort]:[oscVal midiStatus]:[oscVal midiData1]:[oscVal midiData2]]; - [self sendMsg:newMsg]; - return; // return, not break! - case OSCValFloat: - case OSCValDouble: - case OSCValInt: - case OSCVal64Int: - case OSCValChar: - if (hasMin && hasMax) { - msgNormVal = [oscVal calculateDoubleValue]; - msgNormVal = (msgNormVal-minVal)/(maxVal-minVal); - msgIntVal = msgNormVal * 127.0; - } - else { - msgNormVal = [oscVal calculateDoubleValue]; - msgIntVal = [oscVal calculateIntValue]; - } - break; - case OSCValBool: - if ([oscVal boolValue]) { - msgNormVal = 1.; - msgIntVal = 127; - } - else { - msgNormVal = 0.; - msgIntVal = 0; - } - break; - case OSCValInfinity: - msgNormVal = 1.; - msgIntVal = 127; - break; - case OSCValNil: - msgNormVal = 0.; - msgIntVal = 0; - break; - case OSCValString: - case OSCValColor: - case OSCValTimeTag: - case OSCValArray: - case OSCValBlob: - case OSCValSMPTE: - case OSCValUnknown: - break; - } - //NSLog(@"\t\tmsgIntVal is %ld, msgNormVal is %0.2f",msgIntVal,msgNormVal); - - // now that we have tried to assemble both a raw integer value and a normalized double, we can try to assemble a message - switch (midiMsgType) { - case VVMIDINoteOffVal: - case VVMIDINoteOnVal: - { - // note off if velocity is 0 - if (msgIntVal == 0) - newMsg = [[VVMIDIMessage alloc] initFromVals:VVMIDINoteOffVal:midiChannel:midiVoice:msgIntVal]; - else - newMsg = [[VVMIDIMessage alloc] initFromVals:VVMIDINoteOnVal:midiChannel:midiVoice:msgIntVal]; - } - break; - case VVMIDIAfterTouchVal: - case VVMIDIControlChangeVal: - newMsg = [[VVMIDIMessage alloc] initFromVals:midiMsgType:midiChannel:midiVoice:msgIntVal]; - break; - case VVMIDIProgramChangeVal: - case VVMIDIChannelPressureVal: - newMsg = [[VVMIDIMessage alloc] initFromVals:midiMsgType:midiChannel:msgIntVal:0]; - break; - case VVMIDIPitchWheelVal: - { - uint8_t msb = ((msgIntVal >> 7) & 0x7F); - uint8_t lsb = (msgIntVal & 0x7F); - newMsg = [[VVMIDIMessage alloc] initFromVals:midiMsgType:midiChannel:msb:lsb]; - } - break; - // these are included to cut down on compiler warnings (i didn't want to just add a 'default') - case VVMIDIBeginSysexDumpVal: - case VVMIDIMTCQuarterFrameVal: - case VVMIDISongPosPointerVal: - case VVMIDISongSelectVal: - case VVMIDIUndefinedCommon1Val: - case VVMIDIUndefinedCommon2Val: - case VVMIDITuneRequestVal: - case VVMIDIEndSysexDumpVal: - case VVMIDIClockVal: - case VVMIDITickVal: - case VVMIDIStartVal: - case VVMIDIContinueVal: - case VVMIDIStopVal: - case VVMIDIUndefinedRealtime1Val: - case VVMIDIActiveSenseVal: - case VVMIDIResetVal: - case VVMIDIMsgUnknown: - break; - } - - // send the msg... - [self sendMsg:newMsg]; - -} -- (void) nodeNameChanged:(id)node { - [self setAddress:[node fullName]]; -} -- (void) nodeDeleted:(id)node { - // do nothing, passing delete messages to the query server is oustide the scope of this class -} - - -@synthesize midiManager; -@synthesize address; -@synthesize midiMsgType; -@synthesize midiChannel; -@synthesize midiVoice; - -@synthesize hasMin; -@synthesize minVal; -@synthesize hasMax; -@synthesize maxVal; - - -@end diff --git a/LiveOSCQueryHelper/main.m b/LiveOSCQueryHelper/main.m deleted file mode 100644 index 3d19036..0000000 --- a/LiveOSCQueryHelper/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// LiveOSCQueryHelper -// -// Created by testAdmin on 2/11/18. -// Copyright © 2018 testAdmin. All rights reserved. -// - -#import - -int main(int argc, const char * argv[]) { - return NSApplicationMain(argc, argv); -} diff --git a/MIDIOSCQueryHelper/Base.lproj/MainMenu.xib b/MIDIOSCQueryHelper/Base.lproj/MainMenu.xib index ed18c8f..9a5eee1 100644 --- a/MIDIOSCQueryHelper/Base.lproj/MainMenu.xib +++ b/MIDIOSCQueryHelper/Base.lproj/MainMenu.xib @@ -695,15 +695,16 @@ - + - - + + + - - + + @@ -742,15 +743,15 @@ - - - + + + - + - - + + @@ -761,9 +762,9 @@ - - - + + + @@ -798,9 +799,9 @@ - - - + + + @@ -837,19 +838,19 @@ - + - + - + - - - - - - MIDI OSCQuery Helper ("MOQH" from now on) adds OSC and OSCQuery capabilities to other applications that only support MIDI. - -- This app uses JSON files loaded into it to create an OSC address space. -- This app runs an OSC query server- this query server publishes the details of the address space. -- This app runs an OSC server- this server listens on a dedicated port for OSC messages. Clients browsing the OSC query server send OSC messages to this OSC server. -- This app creates a virtual MIDI device ("From MIDI OSCQuery Helper"). This app also lets you optionally pick an existing MIDI device. The OSC messages received by this app's OSC server are converted into MIDI messages (using data from the JSON file you loaded), and these MIDI messages are sent out both the virtual MIDI device created by this app as well as the existing MIDI device you selected (if any). - -HOW TO USE IT: -1)- Tell MOQH what file to use- this file will be used to populate the OSC query server with the description of another application's OSC address space. MOQH will "watch" the file and if it is updated, the query server will automatically update itself, and then notify all connected clients that it has been updated. For more information about the supported file type(s), see "FILE TYPE". -2)- Select a MIDI destination you want this app to send MIDI data to. This step is optional- MOQH also creates a virtual MIDI device ("From MIDI OSCQuery Helper") which other applications can listen to. - -If MOQH is running, the OSC query server is running- you can check it with any OSC query client, or a web browser. The query server will stop when the app quits- if there's a problem with the file you load (if it's missing or malformed or corrupt) the query server will keep running, but its address space will be empty. - -FILE TYPE: - -- JSON files can be imported- a sample file demonstrating the various basic MIDI data types is already installed on your machine in "~/Documents/MIDI OSCQuery Helper/SampleDocument.json". The JSON files that you import should have a structure similar to the desired output of the OSC query server- for more information, consult the OSC query protocol, defined here (https://github.com/mrRay/OSCQueryProposal). There are, however, several additional keys/values which must be used to indicate what sort of MIDI value should be sent- the query server will not publish any OSC nodes that are missing the following keys: - - "MIDI_TYPE": The value stored at the key "MIDI_TYPE" must be one of the following strings: "NOTE", "AFTERTOUCH", "CC", "PGM", or "PITCH". This value indicates what kind of MIDI message should be sent when an OSC message is received by this node. - - "MIDI_CHANNEL": The value stored at the key "MIDI_CHANNEL" must be an integer. This value describes the channel on which the MIDI message will be sent. - - "MIDI_VOICE": The value stored at the key "MIDI_VOICE" must be an integer. This value describes which controller or note will be used to send the value from the OSC message. - - - - + + + + + + - This app loads a file- Ableton Live project files (*.als) and simple JSON text files (*.txt, *.json) are the recognized document formats. The file you load creates and populates an OSC address space (if you load an Ableton project file, the OSC address space will be populated with every MIDI mapping in the project file- for more information, see "FILE TYPES"). +- This app runs an OSC query server- this query server publishes the details of the address space using JSON and HTTP. More information about the OSC query server can be found here: https://github.com/mrRay/OSCQueryProposal +- This app runs an OSC server- this server listens on a dedicated port for OSC messages. Clients browsing the OSC query server send OSC messages to this OSC server. More information about OSC can be found here: http://www.opensoundcontrol.org +- This app creates a virtual MIDI device ("From MIDI OSCQuery Helper"). This app also lets you optionally pick an existing MIDI device. The OSC messages received by this app's OSC server are converted into MIDI messages (using data from the JSON or Ableton project file you loaded), and these MIDI messages are sent out both the virtual MIDI device created by this app as well as the existing MIDI device you selected (if any). + + + + + + + + + + 1)- Tell MOQH which file to use- this file will be used to populate the OSC query server with the description of another application's OSC address space. MOQH will "watch" the file, and if it is updated the query server will automatically update itself and then notify all connected clients that it has been updated. For more information about the supported file types, see "FILE TYPES". +2)- Select a MIDI destination you want this app to send MIDI data to. This step is optional- MOQH also creates a virtual MIDI device ("From MIDI OSCQuery Helper") which other applications can listen to (if you're working with an Ableton project file, Ableton needs to be configured to receive MIDI data from this virtual MIDI device). + +If MOQH is running, the OSC query server is running- you can check it with any OSC query client, or a web browser. The query server will stop when the app quits- if there's a problem with the file you load (if it's missing or malformed or corrupt) the query server will keep running, but its address space will be empty. + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Ableton Live project files can be imported (.als). No modifications are necessary for these files- the rest of this information is for people who want to load or create JSON files that describe the MIDI inputs of other applications. + +- JSON files can be imported- a sample file demonstrating the various basic MIDI data types is already installed on your machine in "~/Documents/MIDI OSCQuery Helper/SampleDocument.json", and will re-create itself if you delete it and relaunch this app. The JSON files that you import should have a structure nearly identical to the desired output of the OSC query server- for more information, consult the OSC query protocol, defined here (https://github.com/mrRay/OSCQueryProposal). + - As a matter of convenience, you can omit the FULL_PATH attribute- it can be derived from the structure of the JSON object you're writing, and leaving it out makes changing the structure and layout of your objects faster and easier. + - There are a couple additional keys/values which must be used to indicate what sort of MIDI value should be sent- the query server will not publish any OSC nodes that are missing the following two or three keys (depending on the MIDI output type): + - "MIDI_TYPE": The value stored at the key "MIDI_TYPE" must be one of the following strings: "NOTE", "AFTERTOUCH", "CC", "PGM", or "PITCH". This value indicates what kind of MIDI message should be sent when an OSC message is received by this node. + - "MIDI_VOICE": If the MIDI_TYPE is "NOTE", "AFTERTOUCH, or "CC", an integer value must be provided for the "MIDI_VOICE" key. This key/value is not required if the MIDI_TYPE is "PGM" or "PITCH". + - "MIDI_CHANNEL": The value stored at the key "MIDI_CHANNEL" must be an integer. This value describes the channel on which the MIDI message will be sent. + + + + + + + + + + + + + - + diff --git a/MIDIOSCQueryHelper/Info.plist b/MIDIOSCQueryHelper/Info.plist index f3b0952..56991e0 100644 --- a/MIDIOSCQueryHelper/Info.plist +++ b/MIDIOSCQueryHelper/Info.plist @@ -24,7 +24,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile - + MIDIOSCQueryHelperAppIcon CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion @@ -34,9 +34,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.3.0.4 + 0.4 CFBundleVersion - 0.3.0.4 + 0.4 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright diff --git a/LiveOSCQueryHelper/LiveToOSCQHelper.h b/MIDIOSCQueryHelper/LiveToOSCQHelper.h similarity index 100% rename from LiveOSCQueryHelper/LiveToOSCQHelper.h rename to MIDIOSCQueryHelper/LiveToOSCQHelper.h diff --git a/LiveOSCQueryHelper/LiveToOSCQHelper.m b/MIDIOSCQueryHelper/LiveToOSCQHelper.m similarity index 100% rename from LiveOSCQueryHelper/LiveToOSCQHelper.m rename to MIDIOSCQueryHelper/LiveToOSCQHelper.m diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppDelegate.m b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppDelegate.m index 299033c..c2a1055 100644 --- a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppDelegate.m +++ b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppDelegate.m @@ -1,6 +1,7 @@ #import "MIDIOSCQueryHelperAppDelegate.h" #import "QueryServerNodeDelegate.h" #import "OSCNodeAdditions.h" +#import "LiveToOSCQHelper.h" @@ -11,9 +12,11 @@ @interface MIDIOSCQueryHelperAppDelegate () { @property (weak) IBOutlet NSWindow *window; @property (strong) id activity; - (void) _loadLastFile; -- (void) _loadFile:(NSString *)fullPath; -- (void) _loadJSONFile:(NSString *)fullPath; +- (BOOL) _loadFile:(NSString *)fullPath; +- (BOOL) _loadAbletonProject:(NSString *)fullPath; +- (BOOL) _loadJSONFile:(NSString *)fullPath; - (void) _updateUIItems; +- (NSString *) _assembleHTMLString; @end @@ -60,6 +63,8 @@ - (id) init { [server setName:@"MIDI OSCQuery Helper"]; [server setBonjourName:@"MIDI OSCQuery Helper"]; [server setDelegate:self]; + //[server setHTMLDirectory:[[NSBundle mainBundle] resourcePath]]; + [server setHTMLDirectory:[[NSBundle bundleForClass:[VVOSCQueryServer class]] pathForResource:@"oscqueryhtml" ofType:nil]]; // this notification is posted by our OSC manager subclass when the host info changes as a result of user interaction [[NSNotificationCenter defaultCenter] @@ -135,9 +140,9 @@ - (IBAction) openDocument:(id)sender { [op setAllowsMultipleSelection:NO]; [op setCanChooseDirectories:NO]; [op setResolvesAliases:YES]; - [op setMessage:@"Select JSON file to open (see Help for more)"]; + [op setMessage:@"Select JSON file or Ableton project file (.als) to open (see Help for more)"]; [op setTitle:@"Open file"]; - [op setAllowedFileTypes:@[ @"json", @"txt" ]]; + [op setAllowedFileTypes:@[ @"json", @"txt", @"als" ]]; //[op setDirectoryURL:[NSURL fileURLWithPath:importDir]]; if (importFile != nil) [op setDirectoryURL:[NSURL fileURLWithPath:importFile]]; @@ -198,6 +203,7 @@ - (IBAction) showSampleDocInFinderClicked:(id)sender { - (void) _loadLastFile { + NSLog(@"%s",__func__); NSUserDefaults *def = [NSUserDefaults standardUserDefaults]; NSString *tmpString = [def objectForKey:@"lastOpenDocumentFile"]; // if there's no default, try to find the sample document we include and use that @@ -210,17 +216,243 @@ - (void) _loadLastFile { } [self _loadFile:tmpString]; } -- (void) _loadFile:(NSString *)fullPath { - //NSLog(@"%s ... %@",__func__,fullPath); +- (BOOL) _loadFile:(NSString *)fullPath { + NSLog(@"%s ... %@",__func__,fullPath); + if (fullPath == nil) + return NO; + + BOOL returnMe = NO; NSString *ext = (fullPath==nil) ? nil : [fullPath pathExtension]; + BOOL isJSONFile = NO; + BOOL isAbletonFile = NO; if ([ext caseInsensitiveCompare:@"json"]==NSOrderedSame || [ext caseInsensitiveCompare:@"txt"]==NSOrderedSame) { - [self _loadJSONFile:fullPath]; + isJSONFile = YES; } + else if ([ext caseInsensitiveCompare:@"als"] == NSOrderedSame) { + isAbletonFile = YES; + } + + + NSUserDefaults *def = [NSUserDefaults standardUserDefaults]; + BOOL reloadingTheFile = YES; + BOOL wasRunning = [server isRunning]; + if (isJSONFile || isAbletonFile) { + // if this is a different file, stop the server + if (loadedFilePath==nil || (loadedFilePath!=nil && ![loadedFilePath isEqualToString:fullPath])) + reloadingTheFile = NO; + if (!reloadingTheFile && wasRunning) + [server stop]; + + // rename the server! + NSString *fileName = [[fullPath lastPathComponent] stringByDeletingPathExtension]; + [server setName:fileName]; + NSString *bjName = [NSString stringWithFormat:@"%@ OSCQuery Helper",fileName]; + int nameLength = (int)[bjName length]; + if (nameLength > 63) { + bjName = [NSString stringWithFormat:@"%@...%@",[bjName substringWithRange:NSMakeRange(0,30)],[bjName substringWithRange:NSMakeRange(nameLength-30,30)]]; + } + [server setBonjourName:bjName]; + + // if i'm not reloading a file then i may want to stop observing the file + if (!reloadingTheFile) { + // if i've already got a file loaded i need to stop observing it + if (loadedFilePath!=nil) { + [VVKQueueCenter removeObserver:self forPath:loadedFilePath]; + } + } + // update my local var storing the file path + loadedFilePath = fullPath; + // if i'm not reloading the file, add myself as an observer so i'll know if the file changes + if (!reloadingTheFile) { + [VVKQueueCenter addObserver:self forPath:loadedFilePath]; + } + // update my user defaults so i know what file i last loaded + [def setObject:fullPath forKey:@"lastOpenDocumentFile"]; + [def synchronize]; + } + + + if (isJSONFile) { + returnMe = [self _loadJSONFile:fullPath]; + } + else if (isAbletonFile) { + returnMe = [self _loadAbletonProject:fullPath]; + } + + + + if (isJSONFile || isAbletonFile) { + // restart the server if appropriate + if (!reloadingTheFile && wasRunning) + [server start]; + + // tell the OSC query server to send a PATH_CHANGED message for the root node + if (reloadingTheFile) + [server sendPathChangedToClients:@"/"]; + + [self _updateUIItems]; + } + + return returnMe; } -- (void) _loadJSONFile:(NSString *)fullPath { +- (BOOL) _loadAbletonProject:(NSString *)fullPath { //NSLog(@"%s ... %@",__func__,fullPath); if (fullPath == nil) - return; + return NO; + // unserialize the file at the path into a series of JSON objects + //NSError *nsErr = nil; + NSDictionary *rawFileObj = [LiveToOSCQHelper OSCQueryJSONObjectForLiveProject:fullPath]; + if (rawFileObj==nil || ![rawFileObj isKindOfClass:[NSDictionary class]]) { + NSLog(@"\t\terr: raw object is nil or of wrong type for path %@",fullPath); + return NO; + } + NSMutableDictionary *fileObject = (rawFileObj==nil) ? nil : [rawFileObj mutableCopy]; + //NSLog(@"\t\tfileObject is %@",fileObject); + + + // make sure that the file object doesn't have a host info dict + [fileObject removeObjectForKey:kVVOSCQ_ReqAttr_HostInfo]; + + + // ...now i need to run through the objects from the file, and create OSCNodes from them in an address space + + + OSCAddressSpace *as = [OSCAddressSpace mainAddressSpace]; + // destroy all the delegates immediately- we don't want them sending any messages while we're clearing the address space + for (QueryServerNodeDelegate *tmpDelegate in delegates) { + [as removeDelegate:tmpDelegate forPath:[tmpDelegate address]]; + } + [delegates removeAllObjects]; + + // clear out the OSC address space + NSArray *baseNodes = [[as nodeContents] lockCreateArrayCopy]; + for (OSCNode *baseNode in baseNodes) { + [baseNode removeFromAddressSpace]; + } + + // now run through 'fileObject' recursively using this block, creating OSC nodes for all the objects + __block __weak void (^ParseJSONObj)(NSDictionary *); + ParseJSONObj = ^(NSDictionary * baseObj) { + NSString *objFullPath = [baseObj objectForKey:kVVOSCQ_ReqAttr_Path]; + //NSLog(@"ParseJSONObj() called on %@",objFullPath); + if (objFullPath == nil) { + NSLog(@"\t\terr: bailing, node missing full path, %s",__func__); + return; + } + + // parse the base object, looking for entries that describe the type of MIDI message to send + NSString *tmpString = [baseObj objectForKey:@"MIDI_TYPE"]; + VVMIDIMsgType objMIDIMsgType = VVMIDIMsgUnknown; + if (tmpString != nil) { + if ([tmpString caseInsensitiveCompare:@"NOTE"] == NSOrderedSame) { + objMIDIMsgType = VVMIDINoteOnVal; + } + else if ([tmpString caseInsensitiveCompare:@"AFTERTOUCH"] == NSOrderedSame) { + objMIDIMsgType = VVMIDIAfterTouchVal; + } + else if ([tmpString caseInsensitiveCompare:@"CC"] == NSOrderedSame) { + objMIDIMsgType = VVMIDIControlChangeVal; + } + else if ([tmpString caseInsensitiveCompare:@"PGM"] == NSOrderedSame) { + objMIDIMsgType = VVMIDIProgramChangeVal; + } + else if ([tmpString caseInsensitiveCompare:@"PITCH"] == NSOrderedSame) { + objMIDIMsgType = VVMIDIPitchWheelVal; + } + } + + BOOL setUpAsMIDINode = YES; + // if the message type is unrecognized or there's no channel, bail + NSNumber *objMIDIChannelNum = [baseObj objectForKey:@"MIDI_CHANNEL"]; + if (objMIDIMsgType==VVMIDIMsgUnknown || objMIDIChannelNum==nil) { + setUpAsMIDINode = NO; + //NSLog(@"\t\terr: bailing, node missing msg type or channel num, %s",__func__); + //return; + } + // if there's no midi voice and i'm not pitch bend, bail (everything but pitch bend has a voice, pitch bend is 14-bit) + NSNumber *objMIDIVoiceNum = [baseObj objectForKey:@"MIDI_VOICE"]; + if (objMIDIVoiceNum==nil && (objMIDIMsgType!=VVMIDIPitchWheelVal && objMIDIMsgType!=VVMIDIProgramChangeVal)) { + setUpAsMIDINode = NO; + //NSLog(@"\t\terr: bailing, node missing voice num, %s",__func__); + //return; + } + + // parse the base object, looking for entries that describe the kind of OSC node to publish + NSString *objTypeTagString = [baseObj objectForKey:kVVOSCQ_ReqAttr_Type]; + NSDictionary *objContents = [baseObj objectForKey:kVVOSCQ_ReqAttr_Contents]; + NSString *objDesc = [baseObj objectForKey:kVVOSCQ_ReqAttr_Desc]; + NSArray *objTags = [baseObj objectForKey:kVVOSCQ_OptAttr_Tags]; + NSArray *objExtType = [baseObj objectForKey:kVVOSCQ_OptAttr_Ext_Type]; // one for each type from the type tag string + //NSNumber *objAccess = [baseObj objectForKey:kVVOSCQ_OptAttr_Access]; + NSArray *objRange = [baseObj objectForKey:kVVOSCQ_OptAttr_Range]; // one for each type from the type tag string + NSArray *objUnits = [baseObj objectForKey:kVVOSCQ_OptAttr_Unit]; // one for each type from the type tag string + NSNumber *objCritical = [baseObj objectForKey:kVVOSCQ_OptAttr_Critical]; + NSArray *objOverloads = [baseObj objectForKey:kVVOSCQ_OptAttr_Overloads]; + + if (setUpAsMIDINode) { + OSCNode *newNode = [[OSCAddressSpace mainAddressSpace] findNodeForAddress:objFullPath createIfMissing:YES]; + if (objTypeTagString != nil) { + [newNode setTypeTagString:objTypeTagString]; + [newNode setNodeType:OSCNodeTypeNumber]; + } + else + [newNode setNodeType:OSCNodeDirectory]; + if (objDesc != nil && [objDesc isKindOfClass:[NSString class]]) + [newNode setOSCDescription:objDesc]; + if (objTags != nil && [objTags isKindOfClass:[NSArray class]]) + [newNode setTags:objTags]; + if (objExtType != nil && [objExtType isKindOfClass:[NSArray class]]) + [newNode setExtendedType:objExtType]; + //if (objAccess != nil && [objAccess isKindOfClass:[NSNumber class]]) { + //[newNode setAccess:[objAccess intValue]]; // don't do this, access is always write-only in this application (we can't read the remote app's OSC address space) + [newNode setAccess:2]; + //} + if (objRange != nil && [objRange isKindOfClass:[NSArray class]]) + [newNode setRange:objRange]; + if (objUnits != nil && [objUnits isKindOfClass:[NSArray class]]) + [newNode setUnits:objUnits]; + if (objCritical != nil && [objCritical isKindOfClass:[NSNumber class]]) + [newNode setCritical:[objCritical boolValue]]; + if (objOverloads != nil && [objOverloads isKindOfClass:[NSArray class]]) + [newNode setOverloads:objOverloads]; + + // make a delegate for the node, add it to the array + QueryServerNodeDelegate *tmpDelegate = [[QueryServerNodeDelegate alloc] initWithMIDIManager:self->midim forAddress:[newNode fullName]]; + [tmpDelegate setMIDIMsgType:objMIDIMsgType]; + [tmpDelegate setMIDIChannel:[objMIDIChannelNum intValue]]; + [tmpDelegate setMIDIVoice:[objMIDIVoiceNum intValue]]; + if (objRange != nil) { + NSDictionary *tmpRange = [objRange objectAtIndex:0]; + NSNumber *tmpMin = [tmpRange objectForKey:kVVOSCQ_OptAttr_Range_Min]; + if (tmpMin != nil) { + [tmpDelegate setHasMin:YES]; + [tmpDelegate setMinVal:[tmpMin doubleValue]]; + } + NSNumber *tmpMax = [tmpRange objectForKey:kVVOSCQ_OptAttr_Range_Max]; + if (tmpMax != nil) { + [tmpDelegate setHasMax:YES]; + [tmpDelegate setMaxVal:[tmpMax doubleValue]]; + } + } + [newNode addDelegate:tmpDelegate]; + [self->delegates addObject:tmpDelegate]; + } + + // run through the contents, calling this block recursively on each object + [objContents enumerateKeysAndObjectsUsingBlock:^(NSString * tmpName, NSDictionary * tmpContentsObj, BOOL *stop) { + if ([tmpContentsObj isKindOfClass:[NSDictionary class]]) { + ParseJSONObj(tmpContentsObj); + } + }]; + }; + ParseJSONObj(fileObject); + + return YES; +} +- (BOOL) _loadJSONFile:(NSString *)fullPath { + //NSLog(@"%s ... %@",__func__,fullPath); + if (fullPath == nil) + return NO; // unserialize the file at the path into a series of JSON objects NSError *nsErr = nil; NSData *fileData = [NSData dataWithContentsOfFile:fullPath]; @@ -243,48 +475,14 @@ - (void) _loadJSONFile:(NSString *)fullPath { nil); } }); - return; + return NO; } NSMutableDictionary *fileObject = (rawFileObj==nil) ? nil : [rawFileObj mutableCopy]; //NSLog(@"\t\tfileObject is %@",fileObject); - // if this is a different file, stop the server - NSUserDefaults *def = [NSUserDefaults standardUserDefaults]; - BOOL reloadingTheFile = YES; - BOOL wasRunning = [server isRunning]; - if (loadedFilePath==nil || (loadedFilePath!=nil && ![loadedFilePath isEqualToString:fullPath])) - reloadingTheFile = NO; - if (!reloadingTheFile && wasRunning) - [server stop]; - - // rename the server! - NSString *fileName = [[fullPath lastPathComponent] stringByDeletingPathExtension]; - [server setName:fileName]; - NSString *bjName = [NSString stringWithFormat:@"%@ OSCQuery Helper",fileName]; - int nameLength = (int)[bjName length]; - if (nameLength > 63) { - bjName = [NSString stringWithFormat:@"%@...%@",[bjName substringWithRange:NSMakeRange(0,30)],[bjName substringWithRange:NSMakeRange(nameLength-30,30)]]; - } - [server setBonjourName:bjName]; - // if i'm not reloading a file then i may want to stop observing the file - if (!reloadingTheFile) { - // if i've already got a file loaded i need to stop observing it - if (loadedFilePath!=nil) { - [VVKQueueCenter removeObserver:self forPath:loadedFilePath]; - } - } - // update my local var storing the file path - loadedFilePath = fullPath; - // if i'm not reloading the file, add myself as an observer so i'll know if the file changes - if (!reloadingTheFile) { - [VVKQueueCenter addObserver:self forPath:loadedFilePath]; - } // make sure that the file object doesn't have a host info dict [fileObject removeObjectForKey:kVVOSCQ_ReqAttr_HostInfo]; - // update my user defaults so i know what file i last loaded - [def setObject:fullPath forKey:@"lastOpenDocumentFile"]; - [def synchronize]; // ...now i need to run through the objects from the file, and create OSCNodes from them in an address space @@ -415,15 +613,7 @@ - (void) _loadJSONFile:(NSString *)fullPath { }; ParseJSONObj(fileObject, @""); - // restart the server if appropriate - if (!reloadingTheFile && wasRunning) - [server start]; - - // tell the OSC query server to send a PATH_CHANGED message for the root node - if (reloadingTheFile) - [server sendPathChangedToClients:@"/"]; - - [self _updateUIItems]; + return YES; } - (void) _updateUIItems { // make sure this method is called on the main thread @@ -442,15 +632,61 @@ - (void) _updateUIItems { // update the server status field if ([server isRunning]) { - NSString *fullAddressString = [NSString stringWithFormat:@"http://localhost:%d",[server webServerPort]]; - NSString *htmlString = [NSString stringWithFormat:@"%@",fullAddressString,fullAddressString]; + NSString *htmlString = [self _assembleHTMLString]; NSAttributedString *htmlAttrStr = [htmlString renderedHTMLWithFont:nil]; + //NSLog(@"\t\tsetting val to %@",htmlAttrStr); [serverStatusField setAttributedStringValue:htmlAttrStr]; } else { [serverStatusField setStringValue:@"Not running!"]; } } +- (NSString *) _assembleHTMLString { + NSArray *addrs = [VVOSCQueryRemoteServer hostIPv4Addresses]; + //NSLog(@"\t\taddrs are %@",addrs); + int tmpPort = [server webServerPort]; + NSMutableString *sectionHTMLString = nil; + NSString *fullHTMLString = nil; + + // run through and make a clickable URL for each NIC for the plain OSC query server (these will return JSON objects) + for (NSString *addr in addrs) { + NSString *tmpURLString = [NSString stringWithFormat:@"http://%@:%d",addr,tmpPort]; + NSString *tmpHTMLString = [NSString stringWithFormat:@"%@",tmpURLString,tmpURLString]; + if (sectionHTMLString == nil) { + sectionHTMLString = [[NSMutableString alloc] init]; + [sectionHTMLString appendString:tmpHTMLString]; + } + else + [sectionHTMLString appendFormat:@"
%@",tmpHTMLString]; + } + if (sectionHTMLString !=nil) { + fullHTMLString = [NSString stringWithString:sectionHTMLString]; + } + + // run through and make a clickable URL for each NIC for the fancy HTML controls + sectionHTMLString = nil; + for (NSString *addr in addrs) { + NSString *tmpURLString = [NSString stringWithFormat:@"http://%@:%d/index.html?HTML",addr,tmpPort]; + NSString *tmpHTMLString = [NSString stringWithFormat:@"%@",tmpURLString,tmpURLString]; + if (sectionHTMLString == nil) { + sectionHTMLString = [[NSMutableString alloc] init]; + [sectionHTMLString appendString:tmpHTMLString]; + } + else + [sectionHTMLString appendFormat:@"
%@",tmpHTMLString]; + } + if (fullHTMLString == nil) { + if (sectionHTMLString != nil) + fullHTMLString = [NSString stringWithString:sectionHTMLString]; + } + else { + if (sectionHTMLString != nil) { + fullHTMLString = [fullHTMLString stringByAppendingFormat:@"
%@",sectionHTMLString]; + } + } + + return fullHTMLString; +} - (void) targetAppHostInfoChangedNotification:(NSNotification *)note { // make sure this method is called on the main thread if (![NSThread isMainThread]) { diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_1024.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_1024.png new file mode 100644 index 0000000..2ec658f Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_1024.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_1024@2x.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_1024@2x.png new file mode 100644 index 0000000..1519c96 Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_1024@2x.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_128.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_128.png new file mode 100644 index 0000000..5786f21 Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_128.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_128@2x.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_128@2x.png new file mode 100644 index 0000000..ea77487 Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_128@2x.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_256.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_256.png new file mode 100644 index 0000000..d2366ec Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_256.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_256@2x.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_256@2x.png new file mode 100644 index 0000000..d4dfbb9 Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_256@2x.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_32.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_32.png new file mode 100644 index 0000000..c2d7c14 Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_32.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_32@2x.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_32@2x.png new file mode 100644 index 0000000..f66ea91 Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_32@2x.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_512.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_512.png new file mode 100644 index 0000000..78a3104 Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_512.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_512@2x.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_512@2x.png new file mode 100644 index 0000000..4ac89db Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_512@2x.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_64.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_64.png new file mode 100644 index 0000000..167a554 Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_64.png differ diff --git a/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_64@2x.png b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_64@2x.png new file mode 100644 index 0000000..e2bf4fc Binary files /dev/null and b/MIDIOSCQueryHelper/MIDIOSCQueryHelperAppIcon.iconset/icon_64@2x.png differ diff --git a/MIDIOSCQueryHelper/QueryServerNodeDelegate.m b/MIDIOSCQueryHelper/QueryServerNodeDelegate.m index 1966733..31e5195 100644 --- a/MIDIOSCQueryHelper/QueryServerNodeDelegate.m +++ b/MIDIOSCQueryHelper/QueryServerNodeDelegate.m @@ -59,11 +59,14 @@ - (void) node:(id)n receivedOSCMessage:(OSCMessage *)msg { newMsg = [[VVMIDIMessage alloc] initFromVals:[oscVal midiPort]:[oscVal midiStatus]:[oscVal midiData1]:[oscVal midiData2]]; [self sendMsg:newMsg]; return; // return, not break! - case OSCValFloat: - case OSCValDouble: case OSCValInt: case OSCVal64Int: case OSCValChar: + msgNormVal = 0.; + msgIntVal = [oscVal calculateIntValue]; + break; + case OSCValFloat: + case OSCValDouble: if (hasMin && hasMax) { msgNormVal = [oscVal calculateDoubleValue]; msgNormVal = (msgNormVal-minVal)/(maxVal-minVal); @@ -103,6 +106,7 @@ - (void) node:(id)n receivedOSCMessage:(OSCMessage *)msg { } //NSLog(@"\t\tmsgIntVal is %ld, msgNormVal is %0.2f",msgIntVal,msgNormVal); + // now that we have tried to assemble both a raw integer value and a normalized double, we can try to assemble a message switch (midiMsgType) { case VVMIDINoteOffVal: @@ -151,6 +155,7 @@ - (void) node:(id)n receivedOSCMessage:(OSCMessage *)msg { break; } + // send the msg... [self sendMsg:newMsg]; diff --git a/OSCQueryHelper/Base.lproj/MainMenu.xib b/OSCQueryHelper/Base.lproj/MainMenu.xib index 0c71ee8..9276a27 100644 --- a/OSCQueryHelper/Base.lproj/MainMenu.xib +++ b/OSCQueryHelper/Base.lproj/MainMenu.xib @@ -702,11 +702,11 @@ - + - - - + + + - + @@ -750,15 +750,15 @@ - - + + - + - - + + @@ -769,8 +769,8 @@ - - + + @@ -862,7 +862,7 @@ - + @@ -889,7 +889,7 @@ - OSC Query Helper ("OQH" from now on) creates an OSC query server for other applications that support OSC, but don't support the OSC query protocol. This allows clients that support the query protocol to browse and send data directly to the other app's OSC address space. + OSC Query Helper ("OQH" from now on) creates an OSC query server for other applications that support OSC (can receive OSC), but don't support the OSC query protocol. This allows clients that support the query protocol to browse and send data directly to the other app's OSC address space. HOW TO USE IT: 1)- Tell OQH what file to use- this file will be used to populate the OSC query server with the description of another application's OSC address space. OQH will "watch" the file and if it is updated, the query server will automatically update itself, and then notify all connected clients that it has been updated. For more information about the supported file type(s), see "FILE TYPE". @@ -899,7 +899,7 @@ If OQH is running, the OSC query server is running- you can check it with any OS FILE TYPE: -- JSON files can be imported- a sample file demonstrating a wide variety of OSC types is already installed on your machine in "~/Documents/OSCQuery Helper/SampleDocument.json". The JSON files that you import should have a structure similar to the desired output of the OSC query server- for more information, consult the OSC query protocol, defined here (https://github.com/mrRay/OSCQueryProposal). You can include an optional HOST_INFO object in the root level of the JSON file's object if you want to hard-code the connection details of the target app or device (port and, if desired, an IP address other than localhost) as detailed in the query protocol. If you don't include this information, you can just use the UI in the app to specify the target. +- JSON files can be imported- a sample file demonstrating a wide variety of OSC types is already installed on your machine in "~/Documents/OSCQuery Helper/SampleDocument.json". The JSON files that you import should have a structure similar to the desired output of the OSC query server- for more information, consult the OSC query protocol, defined here (https://github.com/mrRay/OSCQueryProposal). You can include an optional HOST_INFO object in the root level of the JSON file's object if you want to hard-code the connection details of the target app or device (port and, if desired, an IP address other than localhost) as detailed in the query protocol. If you don't include this information, you can just use the UI in the app to specify the target. diff --git a/OSCQueryHelper/Info.plist b/OSCQueryHelper/Info.plist index ebfd5c1..615b0af 100644 --- a/OSCQueryHelper/Info.plist +++ b/OSCQueryHelper/Info.plist @@ -26,7 +26,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile - + OSCQueryHelperAppIcon CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion @@ -36,9 +36,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.3.0.4 + 0.4 CFBundleVersion - 0.3.0.4 + 0.4 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright diff --git a/OSCQueryHelper/OSCQueryHelperAppDelegate.m b/OSCQueryHelper/OSCQueryHelperAppDelegate.m index 13ba04e..400887c 100644 --- a/OSCQueryHelper/OSCQueryHelperAppDelegate.m +++ b/OSCQueryHelper/OSCQueryHelperAppDelegate.m @@ -13,6 +13,7 @@ @interface OSCQueryHelperAppDelegate () { - (void) _loadLastFile; - (void) _loadFile:(NSString *)fullPath; - (void) _updateUIItems; +- (NSString *) _assembleHTMLString; @end @@ -61,7 +62,8 @@ - (id) init { [server setName:@"OSCQuery Helper"]; [server setBonjourName:@"OSCQuery Helper"]; [server setDelegate:self]; - [server setHTMLDirectory:[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent]]; + //[server setHTMLDirectory:[[NSBundle mainBundle] resourcePath]]; + [server setHTMLDirectory:[[NSBundle bundleForClass:[VVOSCQueryServer class]] pathForResource:@"oscqueryhtml" ofType:nil]]; // this notification is posted by our OSC manager subclass when the host info changes as a result of user interaction [[NSNotificationCenter defaultCenter] @@ -407,15 +409,61 @@ - (void) _updateUIItems { // update the server status field if ([server isRunning]) { - NSString *fullAddressString = [NSString stringWithFormat:@"http://localhost:%d",[server webServerPort]]; - NSString *htmlString = [NSString stringWithFormat:@"%@",fullAddressString,fullAddressString]; + NSString *htmlString = [self _assembleHTMLString]; NSAttributedString *htmlAttrStr = [htmlString renderedHTMLWithFont:nil]; + //NSLog(@"\t\tsetting val to %@",htmlAttrStr); [serverStatusField setAttributedStringValue:htmlAttrStr]; } else { [serverStatusField setStringValue:@"Not running!"]; } } +- (NSString *) _assembleHTMLString { + NSArray *addrs = [VVOSCQueryRemoteServer hostIPv4Addresses]; + //NSLog(@"\t\taddrs are %@",addrs); + int tmpPort = [server webServerPort]; + NSMutableString *sectionHTMLString = nil; + NSString *fullHTMLString = nil; + + // run through and make a clickable URL for each NIC for the plain OSC query server (these will return JSON objects) + for (NSString *addr in addrs) { + NSString *tmpURLString = [NSString stringWithFormat:@"http://%@:%d",addr,tmpPort]; + NSString *tmpHTMLString = [NSString stringWithFormat:@"%@",tmpURLString,tmpURLString]; + if (sectionHTMLString == nil) { + sectionHTMLString = [[NSMutableString alloc] init]; + [sectionHTMLString appendString:tmpHTMLString]; + } + else + [sectionHTMLString appendFormat:@"
%@",tmpHTMLString]; + } + if (sectionHTMLString !=nil) { + fullHTMLString = [NSString stringWithString:sectionHTMLString]; + } + + // run through and make a clickable URL for each NIC for the fancy HTML controls + sectionHTMLString = nil; + for (NSString *addr in addrs) { + NSString *tmpURLString = [NSString stringWithFormat:@"http://%@:%d/index.html?HTML",addr,tmpPort]; + NSString *tmpHTMLString = [NSString stringWithFormat:@"%@",tmpURLString,tmpURLString]; + if (sectionHTMLString == nil) { + sectionHTMLString = [[NSMutableString alloc] init]; + [sectionHTMLString appendString:tmpHTMLString]; + } + else + [sectionHTMLString appendFormat:@"
%@",tmpHTMLString]; + } + if (fullHTMLString == nil) { + if (sectionHTMLString != nil) + fullHTMLString = [NSString stringWithString:sectionHTMLString]; + } + else { + if (sectionHTMLString != nil) { + fullHTMLString = [fullHTMLString stringByAppendingFormat:@"
%@",sectionHTMLString]; + } + } + + return fullHTMLString; +} - (void) targetAppHostInfoChangedNotification:(NSNotification *)note { if (![NSThread isMainThread]) { dispatch_async(dispatch_get_main_queue(), ^{ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_1024.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_1024.png new file mode 100644 index 0000000..b29a9f4 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_1024.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_1024@2x.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_1024@2x.png new file mode 100644 index 0000000..369f3f3 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_1024@2x.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_128.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_128.png new file mode 100644 index 0000000..7e33db6 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_128.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_128@2x.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_128@2x.png new file mode 100644 index 0000000..e1590ef Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_128@2x.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_256.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_256.png new file mode 100644 index 0000000..a0e9742 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_256.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_256@2x.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_256@2x.png new file mode 100644 index 0000000..631c188 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_256@2x.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_32.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_32.png new file mode 100644 index 0000000..00decaf Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_32.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_32@2x.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_32@2x.png new file mode 100644 index 0000000..de6ccc8 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_32@2x.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_512.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_512.png new file mode 100644 index 0000000..29133f1 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_512.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_512@2x.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_512@2x.png new file mode 100644 index 0000000..9f78879 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_512@2x.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_64.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_64.png new file mode 100644 index 0000000..b50189e Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_64.png differ diff --git a/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_64@2x.png b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_64@2x.png new file mode 100644 index 0000000..e8d5a09 Binary files /dev/null and b/OSCQueryHelper/OSCQueryHelperAppIcon.iconset/icon_64@2x.png differ diff --git a/VVOSCQueryBrowser/Info.plist b/VVOSCQueryBrowser/Info.plist index 84e5644..55869c1 100644 --- a/VVOSCQueryBrowser/Info.plist +++ b/VVOSCQueryBrowser/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile - + OSCQueryBrowserAppIcon CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.3.0.4 + 0.4 CFBundleVersion - 0.3.0.4 + 0.4 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_1024.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_1024.png new file mode 100644 index 0000000..adca7ce Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_1024.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_1024@2x.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_1024@2x.png new file mode 100644 index 0000000..18a0128 Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_1024@2x.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_128.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_128.png new file mode 100644 index 0000000..6734dac Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_128.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_128@2x.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_128@2x.png new file mode 100644 index 0000000..8c486f7 Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_128@2x.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_256.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_256.png new file mode 100644 index 0000000..81775cb Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_256.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_256@2x.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_256@2x.png new file mode 100644 index 0000000..a434077 Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_256@2x.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_32.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_32.png new file mode 100644 index 0000000..cbc4329 Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_32.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_32@2x.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_32@2x.png new file mode 100644 index 0000000..edc5ddb Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_32@2x.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_512.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_512.png new file mode 100644 index 0000000..4602d37 Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_512.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_512@2x.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_512@2x.png new file mode 100644 index 0000000..35d32a8 Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_512@2x.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_64.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_64.png new file mode 100644 index 0000000..c227a96 Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_64.png differ diff --git a/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_64@2x.png b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_64@2x.png new file mode 100644 index 0000000..94a31e8 Binary files /dev/null and b/VVOSCQueryBrowser/OSCQueryBrowserAppIcon.iconset/icon_64@2x.png differ diff --git a/VVOSCQueryBrowser/OSCValueView.m b/VVOSCQueryBrowser/OSCValueView.m index 66b7153..a69f3d4 100644 --- a/VVOSCQueryBrowser/OSCValueView.m +++ b/VVOSCQueryBrowser/OSCValueView.m @@ -68,8 +68,10 @@ - (void) setType:(OSCValueType)t value:(OSCValue *)v hint:(OSCValueViewHint)h va // if the type of the passed value matches the type i was passed then use it- else if there's a mismatch, nil out my value if (v!=nil && [v type]==t) [self setValue:v]; - else - [self setValue:nil]; + else { + //[self setValue:nil]; + [self setValue:[v createValByConvertingToType:t]]; + } [self setHint:h]; // if there's an array of values, locate and populate the pop-up button if (vals != nil && [vals count]>0) { @@ -116,7 +118,7 @@ - (void) updateUIItems { // ...if i'm here, i know i'm not displaying a pop-up button. switch (type) { - // these will display either a text field or a slider if the view is wide enough + // these will display either a text field or a slider case OSCValFloat: case OSCValDouble: //[textField setHidden:YES]; diff --git a/VVOSCQueryBrowser/RemoteNode.m b/VVOSCQueryBrowser/RemoteNode.m index 76ab033..812cf68 100644 --- a/VVOSCQueryBrowser/RemoteNode.m +++ b/VVOSCQueryBrowser/RemoteNode.m @@ -184,6 +184,27 @@ - (id) initWithParent:(RemoteNode *)p dict:(NSDictionary *)d { break; case 'h': // 64 bit int // not supported yet- maybe base64 data encoding? + + newRemoteNodeControl = [[RemoteNodeControl alloc] initWithParent:self typeString:tmpTypeString]; + if (jsonObj!=nil && [jsonObj isKindOfClass:[NSNumber class]]) + newOSCVal = [OSCValue createWithLongLong:[jsonObj longLongValue]]; + + tmpObj = jsonRangeDict[kVVOSCQ_OptAttr_Range_Min]; + if (tmpObj!=nil && [tmpObj isKindOfClass:[NSNumber class]]) + newOSCMin = [OSCValue createWithDouble:[tmpObj longLongValue]]; + tmpObj = jsonRangeDict[kVVOSCQ_OptAttr_Range_Max]; + if (tmpObj!=nil && [tmpObj isKindOfClass:[NSNumber class]]) + newOSCMax = [OSCValue createWithDouble:[tmpObj longLongValue]]; + tmpObj = jsonRangeDict[kVVOSCQ_OptAttr_Range_Vals]; + if (tmpObj!=nil && [tmpObj isKindOfClass:[NSArray class]]) { + newOSCVals = [[NSMutableArray alloc] init]; + for (tmpObj in jsonRangeDict[kVVOSCQ_OptAttr_Range_Vals]) { + if ([tmpObj isKindOfClass:[NSNumber class]]) { + tmpOSCVal = [OSCValue createWithLongLong:[tmpObj longLongValue]]; + [newOSCVals addObject:tmpOSCVal]; + } + } + } break; case 't': // time tag // not supported yet- maybe base64 data encoding? @@ -536,6 +557,7 @@ - (void) sendMessage { case 'F': // false case 'N': // nil case 'I': // infinity + case 'h': // 64 bit int // ask the corresponding control to create a current OSC value- if it can't, bail because somethign went wrong oscValForThisChar = (arrayIndex>=[controls count]) ? nil : [[controls objectAtIndex:arrayIndex] createCurrentOSCValue]; if (oscValForThisChar == nil) { @@ -595,9 +617,6 @@ - (void) sendMessage { case 'b': // blob // not supported yet- maybe base64 data encoding? break; - case 'h': // 64 bit int - // not supported yet- maybe base64 data encoding? - break; case 't': // time tag // not supported yet- maybe base64 data encoding? break; diff --git a/VVOSCQueryProtocol.xcodeproj/project.pbxproj b/VVOSCQueryProtocol.xcodeproj/project.pbxproj index 0171bc9..5dc9fec 100644 --- a/VVOSCQueryProtocol.xcodeproj/project.pbxproj +++ b/VVOSCQueryProtocol.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ 1AE214A92034907E006FEC2B /* PBXTargetDependency */, 1AE214AB2034907E006FEC2B /* PBXTargetDependency */, 1AE214AD2034907E006FEC2B /* PBXTargetDependency */, - 1AE214AF2034907E006FEC2B /* PBXTargetDependency */, 1AE214B12034907E006FEC2B /* PBXTargetDependency */, ); name = "All Apps"; @@ -27,6 +26,9 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 1A04694C20EC24E8002E591D /* OSCQueryHelperAppIcon.iconset in Resources */ = {isa = PBXBuildFile; fileRef = 1A04694B20EC24E8002E591D /* OSCQueryHelperAppIcon.iconset */; }; + 1A04695020EC251C002E591D /* MIDIOSCQueryHelperAppIcon.iconset in Resources */ = {isa = PBXBuildFile; fileRef = 1A04694F20EC251C002E591D /* MIDIOSCQueryHelperAppIcon.iconset */; }; + 1A04696020ECF845002E591D /* oscqueryhtml in Resources */ = {isa = PBXBuildFile; fileRef = 1A04695F20ECF845002E591D /* oscqueryhtml */; }; 1A0B5F55203E0EC800948FDA /* ZWRObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A0B5F53203E0EC800948FDA /* ZWRObject.m */; }; 1A0B5F56203E0EC800948FDA /* ZWRObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A0B5F54203E0EC800948FDA /* ZWRObject.h */; }; 1A0E2F361FD6D3CB00F0855D /* VVOSCQueryBrowserAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A0E2F351FD6D3CB00F0855D /* VVOSCQueryBrowserAppDelegate.m */; }; @@ -46,11 +48,7 @@ 1A1A86792025103500D72817 /* VVOSCQueryProtocol.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1A336E4B1FC870E00007877C /* VVOSCQueryProtocol.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1A1A867A2025103B00D72817 /* VVBasics.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1ABC044F20233BC700539E55 /* VVBasics.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1A1A867B2025103B00D72817 /* VVOSC.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1ABC045020233BC700539E55 /* VVOSC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1A1D9F572034892400920D80 /* LOQHMIDIManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1D9F562034892400920D80 /* LOQHMIDIManager.m */; }; 1A1D9F5820348E2100920D80 /* VVOSCQueryProtocol.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1A336E4B1FC870E00007877C /* VVOSCQueryProtocol.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1A28F4CA2031D0F4004B60FD /* VVKQueueCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A28F4C92031D0F4004B60FD /* VVKQueueCenter.m */; }; - 1A28F4CD2031D12D004B60FD /* LiveOSCQueryHelperAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A28F4CC2031D12D004B60FD /* LiveOSCQueryHelperAppDelegate.m */; }; - 1A28F4D02031D134004B60FD /* QueryServerNodeDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A28F4CF2031D134004B60FD /* QueryServerNodeDelegate.m */; }; 1A336E501FC870E00007877C /* VVOSCQueryProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A336E4E1FC870E00007877C /* VVOSCQueryProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1A336E901FC871870007877C /* VVOSCQueryServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A336E8E1FC871870007877C /* VVOSCQueryServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1A336E911FC871870007877C /* VVOSCQueryServer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A336E8F1FC871870007877C /* VVOSCQueryServer.mm */; }; @@ -69,9 +67,6 @@ 1A336EC71FC88C770007877C /* VVOSCQueryProtocol.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1A336E4B1FC870E00007877C /* VVOSCQueryProtocol.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1A336EC91FC88C890007877C /* VVOSCQueryProtocol.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1A336E4B1FC870E00007877C /* VVOSCQueryProtocol.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1A36DC4A20271B5C00C060E1 /* OQHOSCManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A36DC4920271B5C00C060E1 /* OQHOSCManager.mm */; }; - 1A43EB31203474700099D467 /* LiveToOSCQHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A43EB2F203474700099D467 /* LiveToOSCQHelper.m */; }; - 1A43EB332034747B0099D467 /* ALSKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A43EB322034747B0099D467 /* ALSKit.framework */; }; - 1A43EB34203474830099D467 /* ALSKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1A43EB322034747B0099D467 /* ALSKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1A480FDD1FC89A9D00F86354 /* VVOSCQueryReply.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A480FDB1FC89A9D00F86354 /* VVOSCQueryReply.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1A480FDE1FC89A9D00F86354 /* VVOSCQueryReply.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A480FDC1FC89A9D00F86354 /* VVOSCQueryReply.m */; }; 1A480FE11FC8A0EC00F86354 /* VVOSCQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A480FDF1FC8A0EC00F86354 /* VVOSCQuery.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -81,15 +76,6 @@ 1A4D91B51FD41817007138A8 /* WSPPClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A4D91B31FD41817007138A8 /* WSPPClient.cpp */; }; 1A4D91B61FD41817007138A8 /* WSPPClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1A4D91B41FD41817007138A8 /* WSPPClient.hpp */; }; 1A4F158E2030F43800F4CF29 /* VVKQueueCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A4F158D2030F43800F4CF29 /* VVKQueueCenter.m */; }; - 1A4F15992030FBEE00F4CF29 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A4F15982030FBEE00F4CF29 /* Assets.xcassets */; }; - 1A4F159C2030FBEE00F4CF29 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1A4F159A2030FBEE00F4CF29 /* MainMenu.xib */; }; - 1A4F159F2030FBEE00F4CF29 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A4F159E2030FBEE00F4CF29 /* main.m */; }; - 1A4F15A62030FD8C00F4CF29 /* VVOSCQueryProtocol.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A336E4B1FC870E00007877C /* VVOSCQueryProtocol.framework */; }; - 1A4F15A82030FD9D00F4CF29 /* VVOSCQueryProtocol.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1A336E4B1FC870E00007877C /* VVOSCQueryProtocol.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1A4F15A92030FD9D00F4CF29 /* VVBasics.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1ABC044F20233BC700539E55 /* VVBasics.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1A4F15AA2030FD9D00F4CF29 /* VVOSC.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1ABC045020233BC700539E55 /* VVOSC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1A4F15AB2030FDA600F4CF29 /* VVBasics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1ABC044F20233BC700539E55 /* VVBasics.framework */; }; - 1A4F15AC2030FDA600F4CF29 /* VVOSC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1ABC045020233BC700539E55 /* VVOSC.framework */; }; 1A71ADAF1FD1F26300B01872 /* WSPPQueryReply.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1A71ADAE1FD1F26300B01872 /* WSPPQueryReply.hpp */; }; 1A71AE0C1FD2049200B01872 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A71ADDE1FD2048700B01872 /* SystemConfiguration.framework */; }; 1A7C48F61FD586DB00AE4287 /* VVOSCQueryStringUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7C48F41FD586DB00AE4287 /* VVOSCQueryStringUtilities.cpp */; }; @@ -120,20 +106,15 @@ 1AC7D60E20252F1800C718D0 /* OSCNodeAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8A970C1FCF4E5500FEB54A /* OSCNodeAdditions.m */; }; 1AC94ED220E52CCA0035DC6B /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */; }; 1AC94ED320E52CCA0035DC6B /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */; }; - 1AC94ED420E52CCA0035DC6B /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */; }; 1AC94ED520E52CCA0035DC6B /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */; }; 1AC94ED620E52CD50035DC6B /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1AC94ED720E52CDA0035DC6B /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1AC94ED820E52CDD0035DC6B /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1AC94ED920E52CE10035DC6B /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 1ACEFAEC20EC237200A4B81C /* OSCQueryBrowserAppIcon.iconset in Resources */ = {isa = PBXBuildFile; fileRef = 1ACEFAEB20EC237200A4B81C /* OSCQueryBrowserAppIcon.iconset */; }; 1AE214B320349AD6006FEC2B /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 1AE214B220349AD6006FEC2B /* LICENSE */; }; 1AE214BD20349C72006FEC2B /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 1AE214BC20349C72006FEC2B /* Credits.rtf */; }; 1AE214BF20349C7E006FEC2B /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 1AE214BE20349C7E006FEC2B /* Credits.rtf */; }; - 1AE214C120349C8E006FEC2B /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 1AE214C020349C8E006FEC2B /* Credits.rtf */; }; 1AE214C320349C96006FEC2B /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 1AE214C220349C96006FEC2B /* Credits.rtf */; }; - 1AE8FD0C20330972007A3398 /* VVMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AE8FD0B20330972007A3398 /* VVMIDI.framework */; }; - 1AE8FD0D2033097B007A3398 /* VVMIDI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1AE8FD0B20330972007A3398 /* VVMIDI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 1AE8FD1020330B7D007A3398 /* LOQHOSCManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AE8FD0F20330B7D007A3398 /* LOQHOSCManager.m */; }; 1AE8FD192033388F007A3398 /* MIDIOSCQueryHelperAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AE8FD182033388F007A3398 /* MIDIOSCQueryHelperAppDelegate.m */; }; 1AE8FD1B2033388F007A3398 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1AE8FD1A2033388F007A3398 /* Assets.xcassets */; }; 1AE8FD1E2033388F007A3398 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1AE8FD1C2033388F007A3398 /* MainMenu.xib */; }; @@ -149,7 +130,6 @@ 1AE8FD3520333993007A3398 /* QueryServerNodeDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AE8FD3420333993007A3398 /* QueryServerNodeDelegate.m */; }; 1AE8FD38203339A5007A3398 /* MOQHOSCManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AE8FD37203339A5007A3398 /* MOQHOSCManager.m */; }; 1AE8FD44203346D9007A3398 /* MOQHMIDIManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AE8FD43203346D9007A3398 /* MOQHMIDIManager.m */; }; - 1AE8FD4520339631007A3398 /* OSCNodeAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8A970C1FCF4E5500FEB54A /* OSCNodeAdditions.m */; }; 1AE8FD4620339632007A3398 /* OSCNodeAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A8A970C1FCF4E5500FEB54A /* OSCNodeAdditions.m */; }; 1AEB5C881FD6E71700FFCE49 /* ServerListController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AEB5C871FD6E71700FFCE49 /* ServerListController.m */; }; 1AEB5CB81FD6E74D00FFCE49 /* ServerUIController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AEB5CB71FD6E74D00FFCE49 /* ServerUIController.m */; }; @@ -167,6 +147,9 @@ 1AF1087A1FCDC509004566A8 /* NSStringAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AF108781FCDC509004566A8 /* NSStringAdditions.h */; }; 1AF1087B1FCDC509004566A8 /* NSStringAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AF108791FCDC509004566A8 /* NSStringAdditions.m */; }; 1AF75BCB1FE91B8700D59211 /* QueryServerNodeDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AF75BCA1FE91B8700D59211 /* QueryServerNodeDelegate.m */; }; + 1AFC99E120EF785100F6B90E /* LiveToOSCQHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AFC99E020EF785100F6B90E /* LiveToOSCQHelper.m */; }; + 1AFC99E220EF789400F6B90E /* ALSKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A43EB322034747B0099D467 /* ALSKit.framework */; }; + 1AFC99E320EF789E00F6B90E /* ALSKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1A43EB322034747B0099D467 /* ALSKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1AFCB16D202799F100B70A37 /* QueryServerNodeDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1AFCB16C202799F100B70A37 /* QueryServerNodeDelegate.m */; }; /* End PBXBuildFile section */ @@ -199,13 +182,6 @@ remoteGlobalIDString = 1A336E4A1FC870E00007877C; remoteInfo = OSCQueryProtocol; }; - 1A4F15A42030FD8600F4CF29 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1A336E421FC870E00007877C /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1A336E4A1FC870E00007877C; - remoteInfo = VVOSCQueryProtocol; - }; 1AE214A42034907E006FEC2B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1A336E421FC870E00007877C /* Project object */; @@ -241,13 +217,6 @@ remoteGlobalIDString = 1A1A866120250EE300D72817; remoteInfo = "OSCQuery Helper"; }; - 1AE214AE2034907E006FEC2B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1A336E421FC870E00007877C /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1A4F15922030FBED00F4CF29; - remoteInfo = "Live OSCQuery Helper"; - }; 1AE214B02034907E006FEC2B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1A336E421FC870E00007877C /* Project object */; @@ -329,22 +298,6 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; - 1A4F15A72030FD8F00F4CF29 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 1AC94ED820E52CDD0035DC6B /* Sparkle.framework in Embed Frameworks */, - 1A43EB34203474830099D467 /* ALSKit.framework in Embed Frameworks */, - 1AE8FD0D2033097B007A3398 /* VVMIDI.framework in Embed Frameworks */, - 1A4F15A82030FD9D00F4CF29 /* VVOSCQueryProtocol.framework in Embed Frameworks */, - 1A4F15A92030FD9D00F4CF29 /* VVBasics.framework in Embed Frameworks */, - 1A4F15AA2030FD9D00F4CF29 /* VVOSC.framework in Embed Frameworks */, - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; 1AE8FD2C20333931007A3398 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -356,6 +309,7 @@ 1AE8FD2D20333938007A3398 /* VVBasics.framework in Embed Frameworks */, 1AE8FD2E20333938007A3398 /* VVOSC.framework in Embed Frameworks */, 1AE8FD2F20333938007A3398 /* VVMIDI.framework in Embed Frameworks */, + 1AFC99E320EF789E00F6B90E /* ALSKit.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -363,6 +317,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1A04694B20EC24E8002E591D /* OSCQueryHelperAppIcon.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; path = OSCQueryHelperAppIcon.iconset; sourceTree = ""; }; + 1A04694F20EC251C002E591D /* MIDIOSCQueryHelperAppIcon.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; path = MIDIOSCQueryHelperAppIcon.iconset; sourceTree = ""; }; + 1A04695F20ECF845002E591D /* oscqueryhtml */ = {isa = PBXFileReference; lastKnownFileType = folder; name = oscqueryhtml; path = external_projects/oscqueryhtml; sourceTree = SOURCE_ROOT; }; 1A0B5F53203E0EC800948FDA /* ZWRObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZWRObject.m; sourceTree = ""; }; 1A0B5F54203E0EC800948FDA /* ZWRObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZWRObject.h; sourceTree = ""; }; 1A0E2F321FD6D3CB00F0855D /* OSCQuery Browser.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "OSCQuery Browser.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -383,14 +340,6 @@ 1A1A866C20250EE300D72817 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1A1A866D20250EE300D72817 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 1A1A866F20250EE300D72817 /* OSCQueryHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OSCQueryHelper.entitlements; sourceTree = ""; }; - 1A1D9F552034892400920D80 /* LOQHMIDIManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOQHMIDIManager.h; sourceTree = ""; }; - 1A1D9F562034892400920D80 /* LOQHMIDIManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOQHMIDIManager.m; sourceTree = ""; }; - 1A28F4C82031D0F4004B60FD /* VVKQueueCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VVKQueueCenter.h; path = common/VVKQueueCenter.h; sourceTree = SOURCE_ROOT; }; - 1A28F4C92031D0F4004B60FD /* VVKQueueCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VVKQueueCenter.m; path = common/VVKQueueCenter.m; sourceTree = SOURCE_ROOT; }; - 1A28F4CB2031D12D004B60FD /* LiveOSCQueryHelperAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiveOSCQueryHelperAppDelegate.h; sourceTree = ""; }; - 1A28F4CC2031D12D004B60FD /* LiveOSCQueryHelperAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiveOSCQueryHelperAppDelegate.m; sourceTree = ""; }; - 1A28F4CE2031D134004B60FD /* QueryServerNodeDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QueryServerNodeDelegate.h; sourceTree = ""; }; - 1A28F4CF2031D134004B60FD /* QueryServerNodeDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QueryServerNodeDelegate.m; sourceTree = ""; }; 1A336E4B1FC870E00007877C /* VVOSCQueryProtocol.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = VVOSCQueryProtocol.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1A336E4E1FC870E00007877C /* VVOSCQueryProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VVOSCQueryProtocol.h; sourceTree = ""; }; 1A336E4F1FC870E00007877C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -416,8 +365,6 @@ 1A336EBC1FC88C170007877C /* OSCQueryProtocolClient.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OSCQueryProtocolClient.entitlements; sourceTree = ""; }; 1A36DC4820271B5C00C060E1 /* OQHOSCManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OQHOSCManager.h; sourceTree = ""; }; 1A36DC4920271B5C00C060E1 /* OQHOSCManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OQHOSCManager.mm; sourceTree = ""; }; - 1A43EB2F203474700099D467 /* LiveToOSCQHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiveToOSCQHelper.m; sourceTree = ""; }; - 1A43EB30203474700099D467 /* LiveToOSCQHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiveToOSCQHelper.h; sourceTree = ""; }; 1A43EB322034747B0099D467 /* ALSKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ALSKit.framework; path = external_frameworks/ALSKit.framework; sourceTree = ""; }; 1A480FDB1FC89A9D00F86354 /* VVOSCQueryReply.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VVOSCQueryReply.h; sourceTree = ""; }; 1A480FDC1FC89A9D00F86354 /* VVOSCQueryReply.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VVOSCQueryReply.m; sourceTree = ""; }; @@ -429,12 +376,6 @@ 1A4D91B41FD41817007138A8 /* WSPPClient.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = WSPPClient.hpp; sourceTree = ""; }; 1A4F158C2030F43800F4CF29 /* VVKQueueCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VVKQueueCenter.h; path = common/VVKQueueCenter.h; sourceTree = SOURCE_ROOT; }; 1A4F158D2030F43800F4CF29 /* VVKQueueCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = VVKQueueCenter.m; path = common/VVKQueueCenter.m; sourceTree = SOURCE_ROOT; }; - 1A4F15932030FBED00F4CF29 /* Live OSCQuery Helper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Live OSCQuery Helper.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1A4F15982030FBEE00F4CF29 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 1A4F159B2030FBEE00F4CF29 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 1A4F159D2030FBEE00F4CF29 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1A4F159E2030FBEE00F4CF29 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 1A4F15A02030FBEE00F4CF29 /* LiveOSCQueryHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LiveOSCQueryHelper.entitlements; sourceTree = ""; }; 1A71ADAE1FD1F26300B01872 /* WSPPQueryReply.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = WSPPQueryReply.hpp; sourceTree = ""; }; 1A71ADDE1FD2048700B01872 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 1A7C48F41FD586DB00AE4287 /* VVOSCQueryStringUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = VVOSCQueryStringUtilities.cpp; sourceTree = ""; }; @@ -455,14 +396,12 @@ 1ABC044F20233BC700539E55 /* VVBasics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VVBasics.framework; path = external_frameworks/VVBasics.framework; sourceTree = ""; }; 1ABC045020233BC700539E55 /* VVOSC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VVOSC.framework; path = external_frameworks/VVOSC.framework; sourceTree = ""; }; 1AC94ED120E52CCA0035DC6B /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = external_frameworks/Sparkle.framework; sourceTree = ""; }; + 1ACEFAEB20EC237200A4B81C /* OSCQueryBrowserAppIcon.iconset */ = {isa = PBXFileReference; lastKnownFileType = folder.iconset; path = OSCQueryBrowserAppIcon.iconset; sourceTree = ""; }; 1AE214B220349AD6006FEC2B /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; 1AE214BC20349C72006FEC2B /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; name = Credits.rtf; path = common/Credits.rtf; sourceTree = SOURCE_ROOT; }; 1AE214BE20349C7E006FEC2B /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; name = Credits.rtf; path = common/Credits.rtf; sourceTree = SOURCE_ROOT; }; - 1AE214C020349C8E006FEC2B /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; name = Credits.rtf; path = common/Credits.rtf; sourceTree = SOURCE_ROOT; }; 1AE214C220349C96006FEC2B /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; name = Credits.rtf; path = common/Credits.rtf; sourceTree = SOURCE_ROOT; }; 1AE8FD0B20330972007A3398 /* VVMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VVMIDI.framework; path = external_frameworks/VVMIDI.framework; sourceTree = ""; }; - 1AE8FD0E20330B7D007A3398 /* LOQHOSCManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOQHOSCManager.h; sourceTree = ""; }; - 1AE8FD0F20330B7D007A3398 /* LOQHOSCManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOQHOSCManager.m; sourceTree = ""; }; 1AE8FD152033388F007A3398 /* MIDI OSCQuery Helper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "MIDI OSCQuery Helper.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 1AE8FD172033388F007A3398 /* MIDIOSCQueryHelperAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MIDIOSCQueryHelperAppDelegate.h; sourceTree = ""; }; 1AE8FD182033388F007A3398 /* MIDIOSCQueryHelperAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MIDIOSCQueryHelperAppDelegate.m; sourceTree = ""; }; @@ -501,6 +440,8 @@ 1AF108791FCDC509004566A8 /* NSStringAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSStringAdditions.m; sourceTree = ""; }; 1AF75BC91FE91B8700D59211 /* QueryServerNodeDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QueryServerNodeDelegate.h; sourceTree = ""; }; 1AF75BCA1FE91B8700D59211 /* QueryServerNodeDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QueryServerNodeDelegate.m; sourceTree = ""; }; + 1AFC99DF20EF785100F6B90E /* LiveToOSCQHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiveToOSCQHelper.h; sourceTree = ""; }; + 1AFC99E020EF785100F6B90E /* LiveToOSCQHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiveToOSCQHelper.m; sourceTree = ""; }; 1AFCB16B202799F100B70A37 /* QueryServerNodeDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QueryServerNodeDelegate.h; sourceTree = ""; }; 1AFCB16C202799F100B70A37 /* QueryServerNodeDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QueryServerNodeDelegate.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -557,23 +498,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1A4F15902030FBED00F4CF29 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1A43EB332034747B0099D467 /* ALSKit.framework in Frameworks */, - 1AC94ED420E52CCA0035DC6B /* Sparkle.framework in Frameworks */, - 1A4F15A62030FD8C00F4CF29 /* VVOSCQueryProtocol.framework in Frameworks */, - 1A4F15AB2030FDA600F4CF29 /* VVBasics.framework in Frameworks */, - 1A4F15AC2030FDA600F4CF29 /* VVOSC.framework in Frameworks */, - 1AE8FD0C20330972007A3398 /* VVMIDI.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 1AE8FD122033388F007A3398 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 1AFC99E220EF789400F6B90E /* ALSKit.framework in Frameworks */, 1AE8FD282033392A007A3398 /* VVOSCQueryProtocol.framework in Frameworks */, 1AE8FD292033392F007A3398 /* VVBasics.framework in Frameworks */, 1AC94ED520E52CCA0035DC6B /* Sparkle.framework in Frameworks */, @@ -588,6 +517,7 @@ 1A0E2F331FD6D3CB00F0855D /* VVOSCQueryBrowser */ = { isa = PBXGroup; children = ( + 1ACEFAEB20EC237200A4B81C /* OSCQueryBrowserAppIcon.iconset */, 1A0E2F341FD6D3CB00F0855D /* VVOSCQueryBrowserAppDelegate.h */, 1A0E2F351FD6D3CB00F0855D /* VVOSCQueryBrowserAppDelegate.m */, 1AE214BC20349C72006FEC2B /* Credits.rtf */, @@ -621,6 +551,7 @@ 1A1A866320250EE300D72817 /* OSCQueryHelper */ = { isa = PBXGroup; children = ( + 1A04694B20EC24E8002E591D /* OSCQueryHelperAppIcon.iconset */, 1A1A866420250EE300D72817 /* OSCQueryHelperAppDelegate.h */, 1A1A866520250EE300D72817 /* OSCQueryHelperAppDelegate.m */, 1A8FA951203C6AC400778651 /* SampleDocument.json */, @@ -659,7 +590,6 @@ 1A336EAF1FC88C170007877C /* VVOSCQueryClient.app */, 1A0E2F321FD6D3CB00F0855D /* OSCQuery Browser.app */, 1A1A866220250EE300D72817 /* OSCQuery Helper.app */, - 1A4F15932030FBED00F4CF29 /* Live OSCQuery Helper.app */, 1AE8FD152033388F007A3398 /* MIDI OSCQuery Helper.app */, ); name = Products; @@ -681,6 +611,7 @@ 1A480FDC1FC89A9D00F86354 /* VVOSCQueryReply.m */, 1A480FDF1FC8A0EC00F86354 /* VVOSCQuery.h */, 1A480FE01FC8A0EC00F86354 /* VVOSCQuery.m */, + 1A04695F20ECF845002E591D /* oscqueryhtml */, 1AF1087C1FCDD7F3004566A8 /* internal */, ); path = VVOSCQueryProtocol; @@ -732,37 +663,11 @@ path = VVOSCQueryClient; sourceTree = ""; }; - 1A4F15942030FBED00F4CF29 /* LiveOSCQueryHelper */ = { - isa = PBXGroup; - children = ( - 1A28F4CB2031D12D004B60FD /* LiveOSCQueryHelperAppDelegate.h */, - 1A28F4CC2031D12D004B60FD /* LiveOSCQueryHelperAppDelegate.m */, - 1AE214C020349C8E006FEC2B /* Credits.rtf */, - 1A4F15982030FBEE00F4CF29 /* Assets.xcassets */, - 1A4F159A2030FBEE00F4CF29 /* MainMenu.xib */, - 1A4F159D2030FBEE00F4CF29 /* Info.plist */, - 1A4F159E2030FBEE00F4CF29 /* main.m */, - 1A4F15A02030FBEE00F4CF29 /* LiveOSCQueryHelper.entitlements */, - 1A28F4C82031D0F4004B60FD /* VVKQueueCenter.h */, - 1A28F4C92031D0F4004B60FD /* VVKQueueCenter.m */, - 1A28F4CE2031D134004B60FD /* QueryServerNodeDelegate.h */, - 1A28F4CF2031D134004B60FD /* QueryServerNodeDelegate.m */, - 1AE8FD0E20330B7D007A3398 /* LOQHOSCManager.h */, - 1AE8FD0F20330B7D007A3398 /* LOQHOSCManager.m */, - 1A1D9F552034892400920D80 /* LOQHMIDIManager.h */, - 1A1D9F562034892400920D80 /* LOQHMIDIManager.m */, - 1A43EB30203474700099D467 /* LiveToOSCQHelper.h */, - 1A43EB2F203474700099D467 /* LiveToOSCQHelper.m */, - ); - path = LiveOSCQueryHelper; - sourceTree = ""; - }; 1AC94ECF20E52C240035DC6B /* OSCQuery Utilities for Users */ = { isa = PBXGroup; children = ( 1A0E2F331FD6D3CB00F0855D /* VVOSCQueryBrowser */, 1A1A866320250EE300D72817 /* OSCQueryHelper */, - 1A4F15942030FBED00F4CF29 /* LiveOSCQueryHelper */, 1AE8FD162033388F007A3398 /* MIDIOSCQueryHelper */, ); name = "OSCQuery Utilities for Users"; @@ -780,8 +685,11 @@ 1AE8FD162033388F007A3398 /* MIDIOSCQueryHelper */ = { isa = PBXGroup; children = ( + 1A04694F20EC251C002E591D /* MIDIOSCQueryHelperAppIcon.iconset */, 1AE8FD172033388F007A3398 /* MIDIOSCQueryHelperAppDelegate.h */, 1AE8FD182033388F007A3398 /* MIDIOSCQueryHelperAppDelegate.m */, + 1AFC99DF20EF785100F6B90E /* LiveToOSCQHelper.h */, + 1AFC99E020EF785100F6B90E /* LiveToOSCQHelper.m */, 1A8FA953203C6E7C00778651 /* SampleDocument.json */, 1AE214C220349C96006FEC2B /* Credits.rtf */, 1AE8FD1A2033388F007A3398 /* Assets.xcassets */, @@ -951,25 +859,6 @@ productReference = 1A336EAF1FC88C170007877C /* VVOSCQueryClient.app */; productType = "com.apple.product-type.application"; }; - 1A4F15922030FBED00F4CF29 /* Live OSCQuery Helper */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1A4F15A12030FBEE00F4CF29 /* Build configuration list for PBXNativeTarget "Live OSCQuery Helper" */; - buildPhases = ( - 1A4F158F2030FBED00F4CF29 /* Sources */, - 1A4F15902030FBED00F4CF29 /* Frameworks */, - 1A4F15912030FBED00F4CF29 /* Resources */, - 1A4F15A72030FD8F00F4CF29 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 1A4F15A52030FD8600F4CF29 /* PBXTargetDependency */, - ); - name = "Live OSCQuery Helper"; - productName = LiveOSCQueryHelper; - productReference = 1A4F15932030FBED00F4CF29 /* Live OSCQuery Helper.app */; - productType = "com.apple.product-type.application"; - }; 1AE8FD142033388F007A3398 /* MIDI OSCQuery Helper */ = { isa = PBXNativeTarget; buildConfigurationList = 1AE8FD232033388F007A3398 /* Build configuration list for PBXNativeTarget "MIDI OSCQuery Helper" */; @@ -1033,15 +922,6 @@ }; }; }; - 1A4F15922030FBED00F4CF29 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 0; - }; - }; - }; 1AE214A02034906D006FEC2B = { CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; @@ -1075,7 +955,6 @@ 1A336EAE1FC88C170007877C /* VVOSCQueryClient */, 1A0E2F311FD6D3CB00F0855D /* OSCQuery Browser */, 1A1A866120250EE300D72817 /* OSCQuery Helper */, - 1A4F15922030FBED00F4CF29 /* Live OSCQuery Helper */, 1AE8FD142033388F007A3398 /* MIDI OSCQuery Helper */, 1AE214A02034906D006FEC2B /* All Apps */, ); @@ -1089,6 +968,7 @@ files = ( 1A0E2F381FD6D3CB00F0855D /* Assets.xcassets in Resources */, 1AE214BD20349C72006FEC2B /* Credits.rtf in Resources */, + 1ACEFAEC20EC237200A4B81C /* OSCQueryBrowserAppIcon.iconset in Resources */, 1A0E2F3B1FD6D3CB00F0855D /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1101,6 +981,7 @@ 1A1A866820250EE300D72817 /* Assets.xcassets in Resources */, 1AE214BF20349C7E006FEC2B /* Credits.rtf in Resources */, 1A1A866B20250EE300D72817 /* MainMenu.xib in Resources */, + 1A04694C20EC24E8002E591D /* OSCQueryHelperAppIcon.iconset in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1108,6 +989,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 1A04696020ECF845002E591D /* oscqueryhtml in Resources */, 1AE214B320349AD6006FEC2B /* LICENSE in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1131,16 +1013,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1A4F15912030FBED00F4CF29 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1A4F15992030FBEE00F4CF29 /* Assets.xcassets in Resources */, - 1AE214C120349C8E006FEC2B /* Credits.rtf in Resources */, - 1A4F159C2030FBEE00F4CF29 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 1AE8FD132033388F007A3398 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1149,6 +1021,7 @@ 1AE8FD1B2033388F007A3398 /* Assets.xcassets in Resources */, 1AE214C320349C96006FEC2B /* Credits.rtf in Resources */, 1AE8FD1E2033388F007A3398 /* MainMenu.xib in Resources */, + 1A04695020EC251C002E591D /* MIDIOSCQueryHelperAppIcon.iconset in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1228,21 +1101,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1A4F158F2030FBED00F4CF29 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1AE8FD1020330B7D007A3398 /* LOQHOSCManager.m in Sources */, - 1AE8FD4520339631007A3398 /* OSCNodeAdditions.m in Sources */, - 1A28F4CA2031D0F4004B60FD /* VVKQueueCenter.m in Sources */, - 1A28F4CD2031D12D004B60FD /* LiveOSCQueryHelperAppDelegate.m in Sources */, - 1A28F4D02031D134004B60FD /* QueryServerNodeDelegate.m in Sources */, - 1A43EB31203474700099D467 /* LiveToOSCQHelper.m in Sources */, - 1A1D9F572034892400920D80 /* LOQHMIDIManager.m in Sources */, - 1A4F159F2030FBEE00F4CF29 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 1AE8FD112033388F007A3398 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1253,6 +1111,7 @@ 1AE8FD3520333993007A3398 /* QueryServerNodeDelegate.m in Sources */, 1AE8FD192033388F007A3398 /* MIDIOSCQueryHelperAppDelegate.m in Sources */, 1AE8FD44203346D9007A3398 /* MOQHMIDIManager.m in Sources */, + 1AFC99E120EF785100F6B90E /* LiveToOSCQHelper.m in Sources */, 1AE8FD4620339632007A3398 /* OSCNodeAdditions.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1280,11 +1139,6 @@ target = 1A336E4A1FC870E00007877C /* VVOSCQueryProtocol */; targetProxy = 1A336EC21FC88C5D0007877C /* PBXContainerItemProxy */; }; - 1A4F15A52030FD8600F4CF29 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1A336E4A1FC870E00007877C /* VVOSCQueryProtocol */; - targetProxy = 1A4F15A42030FD8600F4CF29 /* PBXContainerItemProxy */; - }; 1AE214A52034907E006FEC2B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1A336E4A1FC870E00007877C /* VVOSCQueryProtocol */; @@ -1310,11 +1164,6 @@ target = 1A1A866120250EE300D72817 /* OSCQuery Helper */; targetProxy = 1AE214AC2034907E006FEC2B /* PBXContainerItemProxy */; }; - 1AE214AF2034907E006FEC2B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1A4F15922030FBED00F4CF29 /* Live OSCQuery Helper */; - targetProxy = 1AE214AE2034907E006FEC2B /* PBXContainerItemProxy */; - }; 1AE214B12034907E006FEC2B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1AE8FD142033388F007A3398 /* MIDI OSCQuery Helper */; @@ -1360,14 +1209,6 @@ name = MainMenu.xib; sourceTree = ""; }; - 1A4F159A2030FBEE00F4CF29 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 1A4F159B2030FBEE00F4CF29 /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; 1AE8FD1C2033388F007A3398 /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( @@ -1688,40 +1529,6 @@ }; name = Release; }; - 1A4F15A22030FBEE00F4CF29 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; - FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/external_frameworks"; - INFOPLIST_FILE = LiveOSCQueryHelper/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.vidvox.LiveOSCQueryHelper; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - }; - name = Debug; - }; - 1A4F15A32030FBEE00F4CF29 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "Developer ID Application: Vidvox, LLC (KH97KZU7A7)"; - CODE_SIGN_STYLE = Manual; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; - FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/external_frameworks"; - INFOPLIST_FILE = LiveOSCQueryHelper/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.vidvox.LiveOSCQueryHelper; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - }; - name = Release; - }; 1AE214A22034906E006FEC2B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1829,15 +1636,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1A4F15A12030FBEE00F4CF29 /* Build configuration list for PBXNativeTarget "Live OSCQuery Helper" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1A4F15A22030FBEE00F4CF29 /* Debug */, - 1A4F15A32030FBEE00F4CF29 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 1AE214A12034906E006FEC2B /* Build configuration list for PBXAggregateTarget "All Apps" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/VVOSCQueryProtocol.xcodeproj/xcshareddata/xcschemes/Live OSCQuery Helper.xcscheme b/VVOSCQueryProtocol.xcodeproj/xcshareddata/xcschemes/Live OSCQuery Helper.xcscheme deleted file mode 100644 index 82bd2be..0000000 --- a/VVOSCQueryProtocol.xcodeproj/xcshareddata/xcschemes/Live OSCQuery Helper.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/VVOSCQueryProtocol/Info.plist b/VVOSCQueryProtocol/Info.plist index 1c4fd30..3738b25 100644 --- a/VVOSCQueryProtocol/Info.plist +++ b/VVOSCQueryProtocol/Info.plist @@ -15,9 +15,9 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.3.0.4 + 0.4 CFBundleVersion - 0.3.0.4 + 0.4 NSHumanReadableCopyright Copyright © 2017 Vidvox, LLC. All rights reserved. NSPrincipalClass diff --git a/VVOSCQueryServer/Info.plist b/VVOSCQueryServer/Info.plist index 68dd184..9730341 100644 --- a/VVOSCQueryServer/Info.plist +++ b/VVOSCQueryServer/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.3.0.6 + 0.3.0.7 CFBundleVersion 1 LSMinimumSystemVersion diff --git a/VVOSCQueryServer/OSCQueryProtocolServerAppDelegate.m b/VVOSCQueryServer/OSCQueryProtocolServerAppDelegate.m index 20b4b86..df114fb 100644 --- a/VVOSCQueryServer/OSCQueryProtocolServerAppDelegate.m +++ b/VVOSCQueryServer/OSCQueryProtocolServerAppDelegate.m @@ -14,6 +14,7 @@ @interface OSCQueryProtocolServerAppDelegate () { - (void) _loadLastFile; - (void) _loadFile:(NSString *)fullPath; - (void) _updateUIItems; +- (NSString *) _assembleHTMLString; - (void) populateOSCAddressSpace; - (void) populateStreamingDirectory; - (void) populateTestDirectory; @@ -56,6 +57,7 @@ - (id) init { [server setBonjourName:@"server bonjour name"]; [server setDelegate:self]; [server setHTMLDirectory:[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent]]; + //[server setHTMLDirectory:[[NSBundle bundleForClass:[VVOSCQueryServer class]] pathForResource:@"oscqueryhtml" ofType:nil]]; NSLog(@"\t\thtml directory is %@",[server htmlDirectory]); @@ -460,31 +462,7 @@ - (void) _updateUIItems { return; } if ([server isRunning]) { - NSArray *addrs = [VVOSCQueryRemoteServer hostIPv4Addresses]; - //NSLog(@"\t\taddrs are %@",addrs); - int tmpPort = [server webServerPort]; - NSMutableString *htmlString = nil; - for (NSString *addr in addrs) { - NSString *rawStr = [NSString stringWithFormat:@"http://%@:%d",addr,tmpPort]; - NSString *fancyStr = [NSString stringWithFormat:@"http://%@:%d/index.html?HTML",addr,tmpPort]; - NSString *tmpStr = [NSString stringWithFormat:@"%@ / %@",rawStr,rawStr,fancyStr,fancyStr]; - if (htmlString == nil) { - htmlString = [[NSMutableString alloc] init]; - [htmlString appendString:tmpStr]; - } - else - [htmlString appendFormat:@"
%@",tmpStr]; - } - - - - - - - - //NSString *fullAddressString = [NSString stringWithFormat:@"http://localhost:%d",[server webServerPort]]; - //NSString *htmlString = [NSString stringWithFormat:@"%@",fullAddressString,fullAddressString]; - + NSString *htmlString = [self _assembleHTMLString]; NSAttributedString *htmlAttrStr = [htmlString renderedHTMLWithFont:nil]; //NSLog(@"\t\tsetting val to %@",htmlAttrStr); [statusField setAttributedStringValue:htmlAttrStr]; @@ -502,6 +480,52 @@ - (void) _updateUIItems { [portField setStringValue:portString]; } } +- (NSString *) _assembleHTMLString { + NSArray *addrs = [VVOSCQueryRemoteServer hostIPv4Addresses]; + //NSLog(@"\t\taddrs are %@",addrs); + int tmpPort = [server webServerPort]; + NSMutableString *sectionHTMLString = nil; + NSString *fullHTMLString = nil; + + // run through and make a clickable URL for each NIC for the plain OSC query server (these will return JSON objects) + for (NSString *addr in addrs) { + NSString *tmpURLString = [NSString stringWithFormat:@"http://%@:%d",addr,tmpPort]; + NSString *tmpHTMLString = [NSString stringWithFormat:@"%@",tmpURLString,tmpURLString]; + if (sectionHTMLString == nil) { + sectionHTMLString = [[NSMutableString alloc] init]; + [sectionHTMLString appendString:tmpHTMLString]; + } + else + [sectionHTMLString appendFormat:@"
%@",tmpHTMLString]; + } + if (sectionHTMLString !=nil) { + fullHTMLString = [NSString stringWithString:sectionHTMLString]; + } + + // run through and make a clickable URL for each NIC for the fancy HTML controls + sectionHTMLString = nil; + for (NSString *addr in addrs) { + NSString *tmpURLString = [NSString stringWithFormat:@"http://%@:%d/index.html?HTML",addr,tmpPort]; + NSString *tmpHTMLString = [NSString stringWithFormat:@"%@",tmpURLString,tmpURLString]; + if (sectionHTMLString == nil) { + sectionHTMLString = [[NSMutableString alloc] init]; + [sectionHTMLString appendString:tmpHTMLString]; + } + else + [sectionHTMLString appendFormat:@"
%@",tmpHTMLString]; + } + if (fullHTMLString == nil) { + if (sectionHTMLString != nil) + fullHTMLString = [NSString stringWithString:sectionHTMLString]; + } + else { + if (sectionHTMLString != nil) { + fullHTMLString = [fullHTMLString stringByAppendingFormat:@"
%@",sectionHTMLString]; + } + } + + return fullHTMLString; +} #pragma mark -------------------------- VVKQueueCenterDelegate @@ -565,8 +589,8 @@ - (VVOSCQueryReply *) hostInfoQueryFromServer:(VVOSCQueryServer *)s { //kVVOSCQ_OptAttr_Critical : @NO, //kVVOSCQ_OptAttr_Overloads : @NO, kVVOSCQ_OptAttr_HTML : @YES, - //kVVOSCQ_WSAttr_Cmd_Listen : @NO, - //kVVOSCQ_WSAttr_Cmd_Ignore : @NO, + kVVOSCQ_WSAttr_Cmd_Listen : @YES, + kVVOSCQ_WSAttr_Cmd_Ignore : @YES, kVVOSCQ_WSAttr_Cmd_PathChanged : @YES, //kVVOSCQ_WSAttr_Cmd_PathRenamed : @NO, //kVVOSCQ_WSAttr_Cmd_PathRemoved : @NO, diff --git a/external_projects/oscqueryhtml/bundle.js b/external_projects/oscqueryhtml/bundle.js new file mode 100644 index 0000000..ad86b1d --- /dev/null +++ b/external_projects/oscqueryhtml/bundle.js @@ -0,0 +1,9 @@ +window.oscQuery=function(t){var e={};function r(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(n,i,function(e){return t[e]}.bind(null,i));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=21)}([function(t,e,r){(function(e,n){var i=i||{};!function(){"use strict";i.SECS_70YRS=2208988800,i.TWO_32=4294967296,i.defaults={metadata:!1,unpackSingleArgs:!0},i.isCommonJS=!(void 0===t||!t.exports),i.isNode=i.isCommonJS&&"undefined"==typeof window,i.isElectron=!(void 0===e||!e.versions||!e.versions.electron),i.isBufferEnv=i.isNode||i.isElectron,i.isArray=function(t){return t&&"[object Array]"===Object.prototype.toString.call(t)},i.isTypedArrayView=function(t){return t.buffer&&t.buffer instanceof ArrayBuffer},i.isBuffer=function(t){return i.isBufferEnv&&t instanceof n},i.Long="undefined"!=typeof Long?Long:i.isNode?r(13):void 0,i.dataView=function(t,e,r){return t.buffer?new DataView(t.buffer,e,r):t instanceof ArrayBuffer?new DataView(t,e,r):new DataView(new Uint8Array(t),e,r)},i.byteArray=function(t){if(t instanceof Uint8Array)return t;var e=t.buffer?t.buffer:t;if(!(e instanceof ArrayBuffer||void 0!==e.length&&"string"!=typeof e))throw new Error("Can't wrap a non-array-like object as Uint8Array. Object was: "+JSON.stringify(t,null,2));return new Uint8Array(e)},i.nativeBuffer=function(t){return i.isBufferEnv?i.isBuffer(t)?t:new n(t.buffer?t:new Uint8Array(t)):i.isTypedArrayView(t)?t:new Uint8Array(t)},i.copyByteArray=function(t,e,r){if(i.isTypedArrayView(t)&&i.isTypedArrayView(e))e.set(t,r);else for(var n=void 0===r?0:r,o=Math.min(e.length-r,t.length),s=0,a=n;s1){var u=Math.floor(a);s+=u,a=a-u}return{raw:[n+s+i.SECS_70YRS,Math.round(i.TWO_32*a)]}},i.ntpToJSTime=function(t,e){return 1e3*(t-i.SECS_70YRS+e/i.TWO_32)},i.jsToNTPTime=function(t){var e=t/1e3,r=Math.floor(e),n=e-r;return[r+i.SECS_70YRS,Math.round(i.TWO_32*n)]},i.readArguments=function(t,e,r){var n=i.readString(t,r);if(0!==n.indexOf(","))throw new Error("A malformed type tag string was found while reading the arguments of an OSC message. String was: "+n," at offset: "+r.idx);var o=n.substring(1).split(""),s=[];return i.readArgumentsIntoArray(s,o,n,t,e,r),s},i.readArgument=function(t,e,r,n,o){var s=i.argumentTypes[t];if(!s)throw new Error("'"+t+"' is not a valid OSC type tag. Type tag string was: "+e);var a=s.reader,u=i[a](r,o);return n.metadata&&(u={type:t,value:u}),u},i.readArgumentsIntoArray=function(t,e,r,n,o,s){for(var a=0;a-1};f.prototype.append=function(t,e){t=a(t),e=u(e);var r=this.map[t];this.map[t]=r?r+","+e:e},f.prototype.delete=function(t){delete this.map[a(t)]},f.prototype.get=function(t){return t=a(t),this.has(t)?this.map[t]:null},f.prototype.has=function(t){return this.map.hasOwnProperty(a(t))},f.prototype.set=function(t,e){this.map[a(t)]=u(e)},f.prototype.forEach=function(t,e){for(var r in this.map)this.map.hasOwnProperty(r)&&t.call(e,this.map[r],r,this)},f.prototype.keys=function(){var t=[];return this.forEach(function(e,r){t.push(r)}),l(t)},f.prototype.values=function(){var t=[];return this.forEach(function(e){t.push(e)}),l(t)},f.prototype.entries=function(){var t=[];return this.forEach(function(e,r){t.push([r,e])}),l(t)},e.iterable&&(f.prototype[Symbol.iterator]=f.prototype.entries);var o=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];y.prototype.clone=function(){return new y(this,{body:this._bodyInit})},g.call(y.prototype),g.call(m.prototype),m.prototype.clone=function(){return new m(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new f(this.headers),url:this.url})},m.error=function(){var t=new m(null,{status:0,statusText:""});return t.type="error",t};var s=[301,302,303,307,308];m.redirect=function(t,e){if(-1===s.indexOf(e))throw new RangeError("Invalid status code");return new m(null,{status:e,headers:{location:t}})},t.Headers=f,t.Request=y,t.Response=m,t.fetch=function(t,r){return new Promise(function(n,i){var o=new y(t,r),s=new XMLHttpRequest;s.onload=function(){var t,e,r={status:s.status,statusText:s.statusText,headers:(t=s.getAllResponseHeaders()||"",e=new f,t.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(t){var r=t.split(":"),n=r.shift().trim();if(n){var i=r.join(":").trim();e.append(n,i)}}),e)};r.url="responseURL"in s?s.responseURL:r.headers.get("X-Request-URL");var i="response"in s?s.response:s.responseText;n(new m(i,r))},s.onerror=function(){i(new TypeError("Network request failed"))},s.ontimeout=function(){i(new TypeError("Network request failed"))},s.open(o.method,o.url,!0),"include"===o.credentials?s.withCredentials=!0:"omit"===o.credentials&&(s.withCredentials=!1),"responseType"in s&&e.blob&&(s.responseType="blob"),o.headers.forEach(function(t,e){s.setRequestHeader(e,t)}),s.send(void 0===o._bodyInit?null:o._bodyInit)})},t.fetch.polyfill=!0}function a(t){if("string"!=typeof t&&(t=String(t)),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(t))throw new TypeError("Invalid character in header field name");return t.toLowerCase()}function u(t){return"string"!=typeof t&&(t=String(t)),t}function l(t){var r={next:function(){var e=t.shift();return{done:void 0===e,value:e}}};return e.iterable&&(r[Symbol.iterator]=function(){return r}),r}function f(t){this.map={},t instanceof f?t.forEach(function(t,e){this.append(e,t)},this):Array.isArray(t)?t.forEach(function(t){this.append(t[0],t[1])},this):t&&Object.getOwnPropertyNames(t).forEach(function(e){this.append(e,t[e])},this)}function h(t){if(t.bodyUsed)return Promise.reject(new TypeError("Already read"));t.bodyUsed=!0}function c(t){return new Promise(function(e,r){t.onload=function(){e(t.result)},t.onerror=function(){r(t.error)}})}function d(t){var e=new FileReader,r=c(e);return e.readAsArrayBuffer(t),r}function p(t){if(t.slice)return t.slice(0);var e=new Uint8Array(t.byteLength);return e.set(new Uint8Array(t)),e.buffer}function g(){return this.bodyUsed=!1,this._initBody=function(t){if(this._bodyInit=t,t)if("string"==typeof t)this._bodyText=t;else if(e.blob&&Blob.prototype.isPrototypeOf(t))this._bodyBlob=t;else if(e.formData&&FormData.prototype.isPrototypeOf(t))this._bodyFormData=t;else if(e.searchParams&&URLSearchParams.prototype.isPrototypeOf(t))this._bodyText=t.toString();else if(e.arrayBuffer&&e.blob&&n(t))this._bodyArrayBuffer=p(t.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer]);else{if(!e.arrayBuffer||!ArrayBuffer.prototype.isPrototypeOf(t)&&!i(t))throw new Error("unsupported BodyInit type");this._bodyArrayBuffer=p(t)}else this._bodyText="";this.headers.get("content-type")||("string"==typeof t?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):e.searchParams&&URLSearchParams.prototype.isPrototypeOf(t)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},e.blob&&(this.blob=function(){var t=h(this);if(t)return t;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?h(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(d)}),this.text=function(){var t,e,r,n=h(this);if(n)return n;if(this._bodyBlob)return t=this._bodyBlob,e=new FileReader,r=c(e),e.readAsText(t),r;if(this._bodyArrayBuffer)return Promise.resolve(function(t){for(var e=new Uint8Array(t),r=new Array(e.length),n=0;n-1?n:r),this.mode=e.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&i)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(i)}function v(t){var e=new FormData;return t.trim().split("&").forEach(function(t){if(t){var r=t.split("="),n=r.shift().replace(/\+/g," "),i=r.join("=").replace(/\+/g," ");e.append(decodeURIComponent(n),decodeURIComponent(i))}}),e}function m(t,e){e||(e={}),this.type="default",this.status=void 0===e.status?200:e.status,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in e?e.statusText:"OK",this.headers=new f(e.headers),this.url=e.url||"",this._initBody(t)}}("undefined"!=typeof self?self:this)},function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABmJLR0QAdQDFAOofyosNAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gYYFxou+CfYGAAAAIVJREFUOMtj/P///38GCgELAwMDQ9mx12Qb0GUlCjGEgYGBIUGVi2QDFtz+hnAJDGiJchNtwLXXX+FsJkIKy469RtGADTAxUAFQxRAWfH7FJY4ediy4QhyfWBchQ9CjesHtbwSjH8MQZKfi88IQiR10r3URkYpZiIleog3BFrXEAkZqlCcA438w9u93ZL8AAAAASUVORK5CYII="},function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABmJLR0QAdQDFAOofyosNAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gYYFxokGPIxBgAAAGxJREFUOMtj/P///38GCgELAwMDQ9mx12Qb0GUlCjGEgYGBIUGVi2QDFtz+hnAJDGiJchNtwLXXX+FsJgYqgMFjCAs+v+IC6GHHgivE8UYrIUPIiWoWQk4dWrFD/SgmJnrxGkJM1OICjNQoTwCnQx1GpOWUrwAAAABJRU5ErkJggg=="},function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4gQaFwc6zVj7kgAAAzdJREFUSMellW9O6kwUxn8ttTSUPwLxT0QtsYoxEDWasAsX0C34zZW4DBbgJ5agxhBj0CAq1sQIgRSRIFigfT/cSASp9773Pskk7ZyZ55lz5pw5guu6Ll8gCAL/ggk6hK8CR0dH2Lb9TwKyLGMYBtlsFgDJi/zg4GBsY7vdptPpIAgCoVCIQCAwZj85OQHAtm1yuRwA2Wz2lwdfySeJLcvi7u4O13URRRFBEBgOhwiCgKZpLCwsTBWSZZnj42MkQRA4PDyc6m61WsU0TaLRKKlUisFggOM4yLLM8/MzpmnSaDTY2tpCFMWxvbZtIwgCY7OTp396emJlZYVUKkWhUODi4oJCocD5+TmyLLO3t0e326VUKnlyiF6GSqWCKIosLS1xenpKv99H13X29/eJxWI8PDzQaDTIZDK8vb3Rbreniohe2dBsNonH4xSLxVFMJUlCkiR0XWdxcRHTNFEUhUAggGmaU3nEaacHGA6HqKpKt9tlY2MDTdO4v7+n2+0CoGkagiBQq9VIJBKj+UkvPD2QJGl0cYFAgFAohK7r3NzcjNb4/X5s20ZRFM+6kLwMyWQSWZZxHIfr62tc1yUcDqPr+ljVyrJMq9XC5/N5h2gaotEoqqoiiiLpdBpd17Esi06nM5aK8XicarVKOBz+fwKf2N7exu/3Mzs7SzAYxLIsAMrlMoqi4DgOtm2TTCb/TkCW5dH3+/s7c3NzNJtNWq0WmUyGYrFINBpFkqS/EwBwHIerqytkWSYej1OpVMhkMtTrdQaDAevr6557/0ig1Wph2zY7OzsUi0VWV1fp9/s8Pj6iadq3Z+KPsugrarUam5ubAKytrTEzM8Pl5SWJRIL5+fkf94q/C43jOCSTSYLBIACqqlIul4lEIiwvL//2cD8KWJZFvV4fK6TBYECv1/PMmqkCsVjM8z1yHOebV6IoembNJz45Rdd1Rx1oWogme+zHxwc+n+/HiwXI5XK/mhSAYRjk8/lviyKRCC8vL/R6vVEd3N7eEg6HfxTI5/MYhjHe9M/OzsjlchiGMapWgFKpxOvr6+g/GAySTqc9w/LJ8dn0cScAfBuqqrq7u7uuoihT7V/HJP4DeEGMITyqe3YAAAAASUVORK5CYII="},function(t,e){t.exports="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4gQaFwgIghe23QAAA2BJREFUSMe1Vl1LMl0UXZP2MaVCEzGVECES1J0iCYEEUSgUdFVQP6Er5x/4C5yLqOuIQEi6EG+SwKsKRvImKKIPsMYGtEAHbNR03O9F6Gv50dPz8i4YmDnsvdY5Z5+z1zBERGgCwzD4L/hGh57mD0EQIEkSiKjlyefzSKVSeH5+RqFQaBsjSRIEQUAikfh3wvUVCIIAURRbZpTNZnF0dIRcLgee59Hf349MJgOTyYTV1VVMTk625AiCgM3NTczNzQFERH6/n9ohlUpRMBgkSZKIiKhSqVC5XCYiovv7e9rZ2aF4PE61Wq0lt87JACBJkj7VvmFvbw8+nw82mw3hcBhPT0/QdR0cx2FlZQU8z+Pg4AB2ux0ej+dLbiKRgNvtrtelFVdXV7S/v09ERKIo0u7uLimKQpVKhZLJJAUCAUqlUqRpGgUCAVJVtYUDAPV0Og03NzdwOp2Ix+NQVRXj4+Po6+uD0WiE0+nE+vo6wuEwWJaF2+2GJElteToKqKoKjuMgyzK2t7fh8XgQi8WgaRoAYHZ2FkNDQ5BlGQ6HA7Is/06A4zgYDAbUajWYzWYMDw/D6/UiGo02YqxWKzRNg8lkgq7rbXmMnQQWFhbAsiwKhQIikQh0Xcf09DSWlpa+XCqWZfH6+gqz2fy7FYyOjsJkMsFisWBtbQ1er7dRjzpkWYbVakUymYTdbv+dQB1bW1sYGBjAyMgIXC4XHh8fAQCXl5ew2WyoVqu4vb2Fw+H4O4He3t7G+8PDA2ZmZvD29obr62v4fD5Eo1EsLy/DYDD8nUB9r09OTsDzPMbGxhCPx7GxsQFFUZDP5+FyuX7K745sNkuHh4dERBSJREhRFMrn8ySKIsmy3DEPAP2RwNnZWeOm5nI50jSNgsEg3d3ddc0D8NmLvvfw7729VCqBZdnGWCwWg8Viwfz8fNetYRimew0ymQxeXl4a5ADw8fGBdDrd8dT8qsiyLKNarX4Zq9VqGBwchNFo/HOBZgdqRrVabbHAYrEIlmV/FKhz9hARQqFQ26CJiQmcn5+jVCoBAN7f33F8fIypqakfvTsUCoGIPi0zkUggFAq1tcyLiwucnp6CZVkUi0V4PB4sLi52JW+xTCIiSZLI7/c37LEZ5XKZ0uk0VSqVrseyHQfzf/+2/AMfsexPXpTdDAAAAABJRU5ErkJggg=="},function(t,e){!function(t,e,r){var n,i,o=t.SVGAngle||e.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")?"SVG":"VML",s=15,a="http://www.w3.org/2000/svg",u=['
','
','
',"
",'
','
','
',"
"].join("");function l(e){if(t.event&&t.event.contentOverflow!==r)return{x:t.event.offsetX,y:t.event.offsetY};if(e.offsetX!==r&&e.offsetY!==r)return{x:e.offsetX,y:e.offsetY};var n=e.target.parentNode.parentNode;return{x:e.layerX-n.offsetLeft,y:e.layerY-n.offsetTop}}function f(t,r,n){for(var i in t=e.createElementNS(a,t),r)t.setAttribute(i,r[i]);"[object Array]"!=Object.prototype.toString.call(n)&&(n=[n]);for(var o=0,s=n[0]&&n.length||0;o1||t.g>1||t.b>1)&&(n/=255,i/=255,o/=255),{h:(0==(r=(e=Math.max(n,i,o))-Math.min(n,i,o))?null:e==n?(i-o)/r+(i','','',"",""].join(""),n=['
','','',"",'','',"","
"].join(""),e.namespaces.v||e.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML"));var g=0;function y(t,e,r){if(!(this instanceof y))return new y(t,e,r);if(this.h=0,this.s=1,this.v=1,r)this.callback=r,this.pickerElement=e,this.slideElement=t;else{var s=t;s.innerHTML=u,this.slideElement=s.getElementsByClassName("slide")[0],this.pickerElement=s.getElementsByClassName("picker")[0];var a=s.getElementsByClassName("slide-indicator")[0],l=s.getElementsByClassName("picker-indicator")[0];y.fixIndicators(a,l),this.callback=function(t,r,n,i,o){y.positionIndicators(a,l,o,i),e(t,r,n)}}if("SVG"==o){var f=i.cloneNode(!0),h=n.cloneNode(!0),c=f.getElementsByTagName("linearGradient")[0],w=f.getElementsByTagName("rect")[0];c.id="gradient-hsv-"+g,w.setAttribute("fill","url(#"+c.id+")");var A=[h.getElementsByTagName("linearGradient")[0],h.getElementsByTagName("linearGradient")[1]],b=h.getElementsByTagName("rect");A[0].id="gradient-black-"+g,A[1].id="gradient-white-"+g,b[0].setAttribute("fill","url(#"+A[1].id+")"),b[1].setAttribute("fill","url(#"+A[0].id+")"),this.slideElement.appendChild(f),this.pickerElement.appendChild(h),g++}else this.slideElement.innerHTML=i,this.pickerElement.innerHTML=n;v(this.slideElement,"click",d(this,this.slideElement,this.pickerElement)),v(this.pickerElement,"click",p(this,this.pickerElement)),m(this,this.slideElement,d(this,this.slideElement,this.pickerElement)),m(this,this.pickerElement,p(this,this.pickerElement))}function v(t,e,r){t.attachEvent?t.attachEvent("on"+e,r):t.addEventListener&&t.addEventListener(e,r,!1)}function m(t,e,r){var n=!1;v(e,"mousedown",function(t){n=!0}),v(e,"mouseup",function(t){n=!1}),v(e,"mouseout",function(t){n=!1}),v(e,"mousemove",function(t){n&&r(t)})}function w(t,e,r,n){t.h=e.h%360,t.s=e.s,t.v=e.v;var i=h(t),o={y:t.h*t.slideElement.offsetHeight/360,x:0},s=t.pickerElement.offsetHeight,a={x:t.s*t.pickerElement.offsetWidth,y:s-t.v*s};return t.pickerElement.style.backgroundColor=h({h:t.h,s:1,v:1}).hex,t.callback&&t.callback(n||i.hex,{h:t.h,s:t.s,v:t.v},r||{r:i.r,g:i.g,b:i.b},a,o),t}y.hsv2rgb=function(t){var e=h(t);return delete e.hex,e},y.hsv2hex=function(t){return h(t).hex},y.rgb2hsv=c,y.rgb2hex=function(t){return h(c(t)).hex},y.hex2hsv=function(t){return c(y.hex2rgb(t))},y.hex2rgb=function(t){return{r:parseInt(t.substr(1,2),16),g:parseInt(t.substr(3,2),16),b:parseInt(t.substr(5,2),16)}},y.prototype.setHsv=function(t){return w(this,t)},y.prototype.setRgb=function(t){return w(this,c(t),t)},y.prototype.setHex=function(t){return w(this,y.hex2hsv(t),r,t)},y.positionIndicators=function(t,e,r,n){r&&(t.style.top=r.y-t.offsetHeight/2+"px"),n&&(e.style.top=n.y-e.offsetHeight/2+"px",e.style.left=n.x-e.offsetWidth/2+"px")},y.fixIndicators=function(t,e){e.style.pointerEvents="none",t.style.pointerEvents="none"},t.ColorPicker=y}(window,window.document)},function(t,e,r){"use strict";r.r(e),r.d(e,"retrieveJson",function(){return i}),r.d(e,"retrieveHostInfo",function(){return n});r(1);function n(t,e){fetch(t+"/?HOST_INFO").then(function(t){return t.json()}).then(function(t){e(t)}).catch(function(t){console.log('No HOST_INFO "'+t+'"')})}function i(t,e){fetch(t).then(function(t){return t.json()}).then(function(t){e(t)}).catch(function(t){throw document.write("Failed to retrieve JSON, check console for error details"),t})}},function(t,e){t.exports=window.ws},function(t,e,r){var n=n||r(0);!function(){"use strict";n.WebSocket="undefined"!=typeof WebSocket?WebSocket:r(8),n.WebSocketPort=function(t){n.Port.call(this,t),this.on("open",this.listen.bind(this)),this.socket=t.socket,this.socket&&(1===this.socket.readyState?(n.WebSocketPort.setupSocketForBinary(this.socket),this.emit("open",this.socket)):this.open())};var t=n.WebSocketPort.prototype=Object.create(n.Port.prototype);t.constructor=n.WebSocketPort,t.open=function(){(!this.socket||this.socket.readyState>1)&&(this.socket=new n.WebSocket(this.options.url)),n.WebSocketPort.setupSocketForBinary(this.socket);var t=this;this.socket.onopen=function(){t.emit("open",t.socket)}},t.listen=function(){var t=this;this.socket.onmessage=function(e){t.emit("data",e.data,e)},this.socket.onerror=function(e){t.emit("error",e)},this.socket.onclose=function(e){t.emit("close",e)},t.emit("ready")},t.sendRaw=function(t){this.socket&&1===this.socket.readyState?this.socket.send(t):n.fireClosedPortSendError(this)},t.close=function(t,e){this.socket.close(t,e)},n.WebSocketPort.setupSocketForBinary=function(t){t.binaryType=n.isNode?"nodebuffer":"arraybuffer"}}()},function(t,e){function r(){this._events=this._events||{},this._maxListeners=this._maxListeners||void 0}function n(t){return"function"==typeof t}function i(t){return"object"==typeof t&&null!==t}function o(t){return void 0===t}t.exports=r,r.EventEmitter=r,r.prototype._events=void 0,r.prototype._maxListeners=void 0,r.defaultMaxListeners=10,r.prototype.setMaxListeners=function(t){if("number"!=typeof t||t<0||isNaN(t))throw TypeError("n must be a positive number");return this._maxListeners=t,this},r.prototype.emit=function(t){var e,r,s,a,u,l;if(this._events||(this._events={}),"error"===t&&(!this._events.error||i(this._events.error)&&!this._events.error.length)){if((e=arguments[1])instanceof Error)throw e;var f=new Error('Uncaught, unspecified "error" event. ('+e+")");throw f.context=e,f}if(o(r=this._events[t]))return!1;if(n(r))switch(arguments.length){case 1:r.call(this);break;case 2:r.call(this,arguments[1]);break;case 3:r.call(this,arguments[1],arguments[2]);break;default:a=Array.prototype.slice.call(arguments,1),r.apply(this,a)}else if(i(r))for(a=Array.prototype.slice.call(arguments,1),s=(l=r.slice()).length,u=0;u0&&this._events[t].length>s&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),"function"==typeof console.trace&&console.trace()),this},r.prototype.on=r.prototype.addListener,r.prototype.once=function(t,e){if(!n(e))throw TypeError("listener must be a function");var r=!1;function i(){this.removeListener(t,i),r||(r=!0,e.apply(this,arguments))}return i.listener=e,this.on(t,i),this},r.prototype.removeListener=function(t,e){var r,o,s,a;if(!n(e))throw TypeError("listener must be a function");if(!this._events||!this._events[t])return this;if(s=(r=this._events[t]).length,o=-1,r===e||n(r.listener)&&r.listener===e)delete this._events[t],this._events.removeListener&&this.emit("removeListener",t,e);else if(i(r)){for(a=s;a-- >0;)if(r[a]===e||r[a].listener&&r[a].listener===e){o=a;break}if(o<0)return this;1===r.length?(r.length=0,delete this._events[t]):r.splice(o,1),this._events.removeListener&&this.emit("removeListener",t,e)}return this},r.prototype.removeAllListeners=function(t){var e,r;if(!this._events)return this;if(!this._events.removeListener)return 0===arguments.length?this._events={}:this._events[t]&&delete this._events[t],this;if(0===arguments.length){for(e in this._events)"removeListener"!==e&&this.removeAllListeners(e);return this.removeAllListeners("removeListener"),this._events={},this}if(n(r=this._events[t]))this.removeListener(t,r);else if(r)for(;r.length;)this.removeListener(t,r[r.length-1]);return delete this._events[t],this},r.prototype.listeners=function(t){return this._events&&this._events[t]?n(this._events[t])?[this._events[t]]:this._events[t].slice():[]},r.prototype.listenerCount=function(t){if(this._events){var e=this._events[t];if(n(e))return 1;if(e)return e.length}return 0},r.listenerCount=function(t,e){return t.listenerCount(e)}},function(t,e,r){!function(t,r){"use strict";t.slip=e,function(t){var e=t;e.END=192,e.ESC=219,e.ESC_END=220,e.ESC_ESC=221,e.byteArray=function(t,e,r){return t instanceof ArrayBuffer?new Uint8Array(t,e,r):t},e.expandByteArray=function(t){var e=new Uint8Array(2*t.length);return e.set(t),e},e.sliceByteArray=function(t,e,r){var n=t.buffer.slice?t.buffer.slice(e,r):t.subarray(e,r);return new Uint8Array(n)},e.encode=function(t,r){(r=r||{}).bufferPadding=r.bufferPadding||4;var n=(t=e.byteArray(t,r.offset,r.byteLength)).length+r.bufferPadding+3&-4,i=new Uint8Array(n),o=1;i[0]=e.END;for(var s=0;si.length-3&&(i=e.expandByteArray(i));var a=t[s];a===e.END?(i[o++]=e.ESC,a=e.ESC_END):a===e.ESC&&(i[o++]=e.ESC,a=e.ESC_ESC),i[o++]=a}return i[o]=e.END,e.sliceByteArray(i,0,o+1)},e.Decoder=function(t){t="function"!=typeof t?t||{}:{onMessage:t},this.maxMessageSize=t.maxMessageSize||10485760,this.bufferSize=t.bufferSize||1024,this.msgBuffer=new Uint8Array(this.bufferSize),this.msgBufferIdx=0,this.onMessage=t.onMessage,this.onError=t.onError,this.escape=!1};var r=e.Decoder.prototype;r.decode=function(t){var r;t=e.byteArray(t);for(var n=0;nthis.msgBuffer.length-1&&(this.msgBuffer=e.expandByteArray(this.msgBuffer)),this.msgBuffer[this.msgBufferIdx++]=t,this.escape=!1,this.msgBuffer.length>>=0)&&t<256)&&(n=s[t])?n:(r=l(t,(0|t)<0?-1:0,!0),i&&(s[t]=r),r):(i=-128<=(t|=0)&&t<128)&&(n=o[t])?n:(r=l(t,t<0?-1:0,!1),i&&(o[t]=r),r)}function u(t,e){if(isNaN(t))return e?m:v;if(e){if(t<0)return m;if(t>=p)return S}else{if(t<=-g)return T;if(t+1>=g)return E}return t<0?u(-t,e).neg():l(t%d|0,t/d|0,e)}function l(t,e,r){return new n(t,e,r)}n.fromInt=a,n.fromNumber=u,n.fromBits=l;var f=Math.pow;function h(t,e,r){if(0===t.length)throw Error("empty string");if("NaN"===t||"Infinity"===t||"+Infinity"===t||"-Infinity"===t)return v;if("number"==typeof e?(r=e,e=!1):e=!!e,(r=r||10)<2||360)throw Error("interior hyphen");if(0===n)return h(t.substring(1),e,r).neg();for(var i=u(f(r,8)),o=v,s=0;s>>0:this.low},B.toNumber=function(){return this.unsigned?(this.high>>>0)*d+(this.low>>>0):this.high*d+(this.low>>>0)},B.toString=function(t){if((t=t||10)<2||36>>0).toString(t);if((o=a).isZero())return l+s;for(;l.length<6;)l="0"+l;s=""+l+s}},B.getHighBits=function(){return this.high},B.getHighBitsUnsigned=function(){return this.high>>>0},B.getLowBits=function(){return this.low},B.getLowBitsUnsigned=function(){return this.low>>>0},B.getNumBitsAbs=function(){if(this.isNegative())return this.eq(T)?64:this.neg().getNumBitsAbs();for(var t=0!=this.high?this.high:this.low,e=31;e>0&&0==(t&1<=0},B.isOdd=function(){return 1==(1&this.low)},B.isEven=function(){return 0==(1&this.low)},B.equals=function(t){return i(t)||(t=c(t)),(this.unsigned===t.unsigned||this.high>>>31!=1||t.high>>>31!=1)&&(this.high===t.high&&this.low===t.low)},B.eq=B.equals,B.notEquals=function(t){return!this.eq(t)},B.neq=B.notEquals,B.ne=B.notEquals,B.lessThan=function(t){return this.comp(t)<0},B.lt=B.lessThan,B.lessThanOrEqual=function(t){return this.comp(t)<=0},B.lte=B.lessThanOrEqual,B.le=B.lessThanOrEqual,B.greaterThan=function(t){return this.comp(t)>0},B.gt=B.greaterThan,B.greaterThanOrEqual=function(t){return this.comp(t)>=0},B.gte=B.greaterThanOrEqual,B.ge=B.greaterThanOrEqual,B.compare=function(t){if(i(t)||(t=c(t)),this.eq(t))return 0;var e=this.isNegative(),r=t.isNegative();return e&&!r?-1:!e&&r?1:this.unsigned?t.high>>>0>this.high>>>0||t.high===this.high&&t.low>>>0>this.low>>>0?-1:1:this.sub(t).isNegative()?-1:1},B.comp=B.compare,B.negate=function(){return!this.unsigned&&this.eq(T)?T:this.not().add(w)},B.neg=B.negate,B.add=function(t){i(t)||(t=c(t));var e=this.high>>>16,r=65535&this.high,n=this.low>>>16,o=65535&this.low,s=t.high>>>16,a=65535&t.high,u=t.low>>>16,f=0,h=0,d=0,p=0;return d+=(p+=o+(65535&t.low))>>>16,h+=(d+=n+u)>>>16,f+=(h+=r+a)>>>16,f+=e+s,l((d&=65535)<<16|(p&=65535),(f&=65535)<<16|(h&=65535),this.unsigned)},B.subtract=function(t){return i(t)||(t=c(t)),this.add(t.neg())},B.sub=B.subtract,B.multiply=function(t){if(this.isZero())return v;if(i(t)||(t=c(t)),r)return l(r.mul(this.low,this.high,t.low,t.high),r.get_high(),this.unsigned);if(t.isZero())return v;if(this.eq(T))return t.isOdd()?T:v;if(t.eq(T))return this.isOdd()?T:v;if(this.isNegative())return t.isNegative()?this.neg().mul(t.neg()):this.neg().mul(t).neg();if(t.isNegative())return this.mul(t.neg()).neg();if(this.lt(y)&&t.lt(y))return u(this.toNumber()*t.toNumber(),this.unsigned);var e=this.high>>>16,n=65535&this.high,o=this.low>>>16,s=65535&this.low,a=t.high>>>16,f=65535&t.high,h=t.low>>>16,d=65535&t.low,p=0,g=0,m=0,w=0;return m+=(w+=s*d)>>>16,g+=(m+=o*d)>>>16,m&=65535,g+=(m+=s*h)>>>16,p+=(g+=n*d)>>>16,g&=65535,p+=(g+=o*h)>>>16,g&=65535,p+=(g+=s*f)>>>16,p+=e*d+n*h+o*f+s*a,l((m&=65535)<<16|(w&=65535),(p&=65535)<<16|(g&=65535),this.unsigned)},B.mul=B.multiply,B.divide=function(t){if(i(t)||(t=c(t)),t.isZero())throw Error("division by zero");var e,n,o;if(r)return this.unsigned||-2147483648!==this.high||-1!==t.low||-1!==t.high?l((this.unsigned?r.div_u:r.div_s)(this.low,this.high,t.low,t.high),r.get_high(),this.unsigned):this;if(this.isZero())return this.unsigned?m:v;if(this.unsigned){if(t.unsigned||(t=t.toUnsigned()),t.gt(this))return m;if(t.gt(this.shru(1)))return A;o=m}else{if(this.eq(T))return t.eq(w)||t.eq(b)?T:t.eq(T)?w:(e=this.shr(1).div(t).shl(1)).eq(v)?t.isNegative()?w:b:(n=this.sub(t.mul(e)),o=e.add(n.div(t)));else if(t.eq(T))return this.unsigned?m:v;if(this.isNegative())return t.isNegative()?this.neg().div(t.neg()):this.neg().div(t).neg();if(t.isNegative())return this.div(t.neg()).neg();o=v}for(n=this;n.gte(t);){e=Math.max(1,Math.floor(n.toNumber()/t.toNumber()));for(var s=Math.ceil(Math.log(e)/Math.LN2),a=s<=48?1:f(2,s-48),h=u(e),d=h.mul(t);d.isNegative()||d.gt(n);)d=(h=u(e-=a,this.unsigned)).mul(t);h.isZero()&&(h=w),o=o.add(h),n=n.sub(d)}return o},B.div=B.divide,B.modulo=function(t){return i(t)||(t=c(t)),r?l((this.unsigned?r.rem_u:r.rem_s)(this.low,this.high,t.low,t.high),r.get_high(),this.unsigned):this.sub(this.div(t).mul(t))},B.mod=B.modulo,B.rem=B.modulo,B.not=function(){return l(~this.low,~this.high,this.unsigned)},B.and=function(t){return i(t)||(t=c(t)),l(this.low&t.low,this.high&t.high,this.unsigned)},B.or=function(t){return i(t)||(t=c(t)),l(this.low|t.low,this.high|t.high,this.unsigned)},B.xor=function(t){return i(t)||(t=c(t)),l(this.low^t.low,this.high^t.high,this.unsigned)},B.shiftLeft=function(t){return i(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?l(this.low<>>32-t,this.unsigned):l(0,this.low<>>t|this.high<<32-t,this.high>>t,this.unsigned):l(this.high>>t-32,this.high>=0?0:-1,this.unsigned)},B.shr=B.shiftRight,B.shiftRightUnsigned=function(t){if(i(t)&&(t=t.toInt()),0===(t&=63))return this;var e=this.high;return t<32?l(this.low>>>t|e<<32-t,e>>>t,this.unsigned):l(32===t?e:e>>>t-32,0,this.unsigned)},B.shru=B.shiftRightUnsigned,B.shr_u=B.shiftRightUnsigned,B.toSigned=function(){return this.unsigned?l(this.low,this.high,!1):this},B.toUnsigned=function(){return this.unsigned?this:l(this.low,this.high,!0)},B.toBytes=function(t){return t?this.toBytesLE():this.toBytesBE()},B.toBytesLE=function(){var t=this.high,e=this.low;return[255&e,e>>>8&255,e>>>16&255,e>>>24,255&t,t>>>8&255,t>>>16&255,t>>>24]},B.toBytesBE=function(){var t=this.high,e=this.low;return[t>>>24,t>>>16&255,t>>>8&255,255&t,e>>>24,e>>>16&255,e>>>8&255,255&e]},n.fromBytes=function(t,e,r){return r?n.fromBytesLE(t,e):n.fromBytesBE(t,e)},n.fromBytesLE=function(t,e){return new n(t[0]|t[1]<<8|t[2]<<16|t[3]<<24,t[4]|t[5]<<8|t[6]<<16|t[7]<<24,e)},n.fromBytesBE=function(t,e){return new n(t[4]<<24|t[5]<<16|t[6]<<8|t[7],t[0]<<24|t[1]<<16|t[2]<<8|t[3],e)}},function(t,e){var r={}.toString;t.exports=Array.isArray||function(t){return"[object Array]"==r.call(t)}},function(t,e){e.read=function(t,e,r,n,i){var o,s,a=8*i-n-1,u=(1<>1,f=-7,h=r?i-1:0,c=r?-1:1,d=t[e+h];for(h+=c,o=d&(1<<-f)-1,d>>=-f,f+=a;f>0;o=256*o+t[e+h],h+=c,f-=8);for(s=o&(1<<-f)-1,o>>=-f,f+=n;f>0;s=256*s+t[e+h],h+=c,f-=8);if(0===o)o=1-l;else{if(o===u)return s?NaN:1/0*(d?-1:1);s+=Math.pow(2,n),o-=l}return(d?-1:1)*s*Math.pow(2,o-n)},e.write=function(t,e,r,n,i,o){var s,a,u,l=8*o-i-1,f=(1<>1,c=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,d=n?0:o-1,p=n?1:-1,g=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(a=isNaN(e)?1:0,s=f):(s=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-s))<1&&(s--,u*=2),(e+=s+h>=1?c/u:c*Math.pow(2,1-h))*u>=2&&(s++,u/=2),s+h>=f?(a=0,s=f):s+h>=1?(a=(e*u-1)*Math.pow(2,i),s+=h):(a=e*Math.pow(2,h-1)*Math.pow(2,i),s=0));i>=8;t[r+d]=255&a,d+=p,a/=256,i-=8);for(s=s<0;t[r+d]=255&s,d+=p,s/=256,l-=8);t[r+d-p]|=128*g}},function(t,e,r){"use strict";e.byteLength=function(t){var e=l(t),r=e[0],n=e[1];return 3*(r+n)/4-n},e.toByteArray=function(t){for(var e,r=l(t),n=r[0],s=r[1],a=new o(function(t,e,r){return 3*(e+r)/4-r}(0,n,s)),u=0,f=s>0?n-4:n,h=0;h>16&255,a[u++]=e>>8&255,a[u++]=255&e;2===s&&(e=i[t.charCodeAt(h)]<<2|i[t.charCodeAt(h+1)]>>4,a[u++]=255&e);1===s&&(e=i[t.charCodeAt(h)]<<10|i[t.charCodeAt(h+1)]<<4|i[t.charCodeAt(h+2)]>>2,a[u++]=e>>8&255,a[u++]=255&e);return a},e.fromByteArray=function(t){for(var e,r=t.length,i=r%3,o=[],s=0,a=r-i;sa?a:s+16383));1===i?(e=t[r-1],o.push(n[e>>2]+n[e<<4&63]+"==")):2===i&&(e=(t[r-2]<<8)+t[r-1],o.push(n[e>>10]+n[e>>4&63]+n[e<<2&63]+"="));return o.join("")};for(var n=[],i=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a0)throw new Error("Invalid string. Length must be a multiple of 4");var r=t.indexOf("=");return-1===r&&(r=e),[r,r===e?0:4-r%4]}function f(t,e,r){for(var i,o,s=[],a=e;a>18&63]+n[o>>12&63]+n[o>>6&63]+n[63&o]);return s.join("")}i["-".charCodeAt(0)]=62,i["_".charCodeAt(0)]=63},function(t,e){var r;r=function(){return this}();try{r=r||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(r=window)}t.exports=r},function(t,e,r){"use strict";(function(t){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +var n=r(16),i=r(15),o=r(14);function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(t,e){if(s()=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|t}function p(t,e){if(u.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var r=t.length;if(0===r)return 0;for(var n=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return V(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return Y(t).length;default:if(n)return V(t).length;e=(""+e).toLowerCase(),n=!0}}function g(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function y(t,e,r,n,i){if(0===t.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),r=+r,isNaN(r)&&(r=i?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(i)return-1;r=t.length-1}else if(r<0){if(!i)return-1;r=0}if("string"==typeof e&&(e=u.from(e,n)),u.isBuffer(e))return 0===e.length?-1:v(t,e,r,n,i);if("number"==typeof e)return e&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):v(t,[e],r,n,i);throw new TypeError("val must be string, number or Buffer")}function v(t,e,r,n,i){var o,s=1,a=t.length,u=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return-1;s=2,a/=2,u/=2,r/=2}function l(t,e){return 1===s?t[e]:t.readUInt16BE(e*s)}if(i){var f=-1;for(o=r;oa&&(r=a-u),o=r;o>=0;o--){for(var h=!0,c=0;ci&&(n=i):n=i;var o=e.length;if(o%2!=0)throw new TypeError("Invalid hex string");n>o/2&&(n=o/2);for(var s=0;s>8,i=r%256,o.push(i),o.push(n);return o}(e,t.length-r),t,r,n)}function T(t,e,r){return 0===e&&r===t.length?n.fromByteArray(t):n.fromByteArray(t.slice(e,r))}function B(t,e,r){r=Math.min(t.length,r);for(var n=[],i=e;i239?4:l>223?3:l>191?2:1;if(i+h<=r)switch(h){case 1:l<128&&(f=l);break;case 2:128==(192&(o=t[i+1]))&&(u=(31&l)<<6|63&o)>127&&(f=u);break;case 3:o=t[i+1],s=t[i+2],128==(192&o)&&128==(192&s)&&(u=(15&l)<<12|(63&o)<<6|63&s)>2047&&(u<55296||u>57343)&&(f=u);break;case 4:o=t[i+1],s=t[i+2],a=t[i+3],128==(192&o)&&128==(192&s)&&128==(192&a)&&(u=(15&l)<<18|(63&o)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(f=u)}null===f?(f=65533,h=1):f>65535&&(f-=65536,n.push(f>>>10&1023|55296),f=56320|1023&f),n.push(f),i+=h}return function(t){var e=t.length;if(e<=_)return String.fromCharCode.apply(String,t);var r="",n=0;for(;nthis.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return L(this,e,r);case"utf8":case"utf-8":return B(this,e,r);case"ascii":return P(this,e,r);case"latin1":case"binary":return C(this,e,r);case"base64":return T(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return N(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}.apply(this,arguments)},u.prototype.equals=function(t){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===u.compare(this,t)},u.prototype.inspect=function(){var t="",r=e.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,r).match(/.{2}/g).join(" "),this.length>r&&(t+=" ... ")),""},u.prototype.compare=function(t,e,r,n,i){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===r&&(r=t?t.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),e<0||r>t.length||n<0||i>this.length)throw new RangeError("out of range index");if(n>=i&&e>=r)return 0;if(n>=i)return-1;if(e>=r)return 1;if(e>>>=0,r>>>=0,n>>>=0,i>>>=0,this===t)return 0;for(var o=i-n,s=r-e,a=Math.min(o,s),l=this.slice(n,i),f=t.slice(e,r),h=0;hi)&&(r=i),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var o=!1;;)switch(n){case"hex":return m(this,t,e,r);case"utf8":case"utf-8":return w(this,t,e,r);case"ascii":return A(this,t,e,r);case"latin1":case"binary":return b(this,t,e,r);case"base64":return E(this,t,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,t,e,r);default:if(o)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),o=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var _=4096;function P(t,e,r){var n="";r=Math.min(t.length,r);for(var i=e;in)&&(r=n);for(var i="",o=e;or)throw new RangeError("Trying to access beyond buffer length")}function I(t,e,r,n,i,o){if(!u.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>i||et.length)throw new RangeError("Index out of range")}function U(t,e,r,n){e<0&&(e=65535+e+1);for(var i=0,o=Math.min(t.length-r,2);i>>8*(n?i:1-i)}function x(t,e,r,n){e<0&&(e=4294967295+e+1);for(var i=0,o=Math.min(t.length-r,4);i>>8*(n?i:3-i)&255}function k(t,e,r,n,i,o){if(r+n>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function O(t,e,r,n,o){return o||k(t,0,r,4),i.write(t,e,r,n,23,4),r+4}function M(t,e,r,n,o){return o||k(t,0,r,8),i.write(t,e,r,n,52,8),r+8}u.prototype.slice=function(t,e){var r,n=this.length;if(t=~~t,e=void 0===e?n:~~e,t<0?(t+=n)<0&&(t=0):t>n&&(t=n),e<0?(e+=n)<0&&(e=0):e>n&&(e=n),e0&&(i*=256);)n+=this[t+--e]*i;return n},u.prototype.readUInt8=function(t,e){return e||R(t,1,this.length),this[t]},u.prototype.readUInt16LE=function(t,e){return e||R(t,2,this.length),this[t]|this[t+1]<<8},u.prototype.readUInt16BE=function(t,e){return e||R(t,2,this.length),this[t]<<8|this[t+1]},u.prototype.readUInt32LE=function(t,e){return e||R(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},u.prototype.readUInt32BE=function(t,e){return e||R(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},u.prototype.readIntLE=function(t,e,r){t|=0,e|=0,r||R(t,e,this.length);for(var n=this[t],i=1,o=0;++o=(i*=128)&&(n-=Math.pow(2,8*e)),n},u.prototype.readIntBE=function(t,e,r){t|=0,e|=0,r||R(t,e,this.length);for(var n=e,i=1,o=this[t+--n];n>0&&(i*=256);)o+=this[t+--n]*i;return o>=(i*=128)&&(o-=Math.pow(2,8*e)),o},u.prototype.readInt8=function(t,e){return e||R(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},u.prototype.readInt16LE=function(t,e){e||R(t,2,this.length);var r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},u.prototype.readInt16BE=function(t,e){e||R(t,2,this.length);var r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},u.prototype.readInt32LE=function(t,e){return e||R(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},u.prototype.readInt32BE=function(t,e){return e||R(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},u.prototype.readFloatLE=function(t,e){return e||R(t,4,this.length),i.read(this,t,!0,23,4)},u.prototype.readFloatBE=function(t,e){return e||R(t,4,this.length),i.read(this,t,!1,23,4)},u.prototype.readDoubleLE=function(t,e){return e||R(t,8,this.length),i.read(this,t,!0,52,8)},u.prototype.readDoubleBE=function(t,e){return e||R(t,8,this.length),i.read(this,t,!1,52,8)},u.prototype.writeUIntLE=function(t,e,r,n){(t=+t,e|=0,r|=0,n)||I(this,t,e,r,Math.pow(2,8*r)-1,0);var i=1,o=0;for(this[e]=255&t;++o=0&&(o*=256);)this[e+i]=t/o&255;return e+r},u.prototype.writeUInt8=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,1,255,0),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},u.prototype.writeUInt16LE=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):U(this,t,e,!0),e+2},u.prototype.writeUInt16BE=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):U(this,t,e,!1),e+2},u.prototype.writeUInt32LE=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):x(this,t,e,!0),e+4},u.prototype.writeUInt32BE=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):x(this,t,e,!1),e+4},u.prototype.writeIntLE=function(t,e,r,n){if(t=+t,e|=0,!n){var i=Math.pow(2,8*r-1);I(this,t,e,r,i-1,-i)}var o=0,s=1,a=0;for(this[e]=255&t;++o>0)-a&255;return e+r},u.prototype.writeIntBE=function(t,e,r,n){if(t=+t,e|=0,!n){var i=Math.pow(2,8*r-1);I(this,t,e,r,i-1,-i)}var o=r-1,s=1,a=0;for(this[e+o]=255&t;--o>=0&&(s*=256);)t<0&&0===a&&0!==this[e+o+1]&&(a=1),this[e+o]=(t/s>>0)-a&255;return e+r},u.prototype.writeInt8=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,1,127,-128),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},u.prototype.writeInt16LE=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):U(this,t,e,!0),e+2},u.prototype.writeInt16BE=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):U(this,t,e,!1),e+2},u.prototype.writeInt32LE=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):x(this,t,e,!0),e+4},u.prototype.writeInt32BE=function(t,e,r){return t=+t,e|=0,r||I(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):x(this,t,e,!1),e+4},u.prototype.writeFloatLE=function(t,e,r){return O(this,t,e,!0,r)},u.prototype.writeFloatBE=function(t,e,r){return O(this,t,e,!1,r)},u.prototype.writeDoubleLE=function(t,e,r){return M(this,t,e,!0,r)},u.prototype.writeDoubleBE=function(t,e,r){return M(this,t,e,!1,r)},u.prototype.copy=function(t,e,r,n){if(r||(r=0),n||0===n||(n=this.length),e>=t.length&&(e=t.length),e||(e=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-e=0;--i)t[i+e]=this[i+r];else if(o<1e3||!u.TYPED_ARRAY_SUPPORT)for(i=0;i>>=0,r=void 0===r?this.length:r>>>0,t||(t=0),"number"==typeof t)for(o=e;o55295&&r<57344){if(!i){if(r>56319){(e-=3)>-1&&o.push(239,191,189);continue}if(s+1===n){(e-=3)>-1&&o.push(239,191,189);continue}i=r;continue}if(r<56320){(e-=3)>-1&&o.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320)}else i&&(e-=3)>-1&&o.push(239,191,189);if(i=null,r<128){if((e-=1)<0)break;o.push(r)}else if(r<2048){if((e-=2)<0)break;o.push(r>>6|192,63&r|128)}else if(r<65536){if((e-=3)<0)break;o.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;o.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return o}function Y(t){return n.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(F,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function G(t,e,r,n){for(var i=0;i=e.length||i>=t.length);++i)e[i+r]=t[i];return i}}).call(this,r(17))},function(t,e){var r,n,i=t.exports={};function o(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function a(t){if(r===setTimeout)return setTimeout(t,0);if((r===o||!r)&&setTimeout)return r=setTimeout,setTimeout(t,0);try{return r(t,0)}catch(e){try{return r.call(null,t,0)}catch(e){return r.call(this,t,0)}}}!function(){try{r="function"==typeof setTimeout?setTimeout:o}catch(t){r=o}try{n="function"==typeof clearTimeout?clearTimeout:s}catch(t){n=s}}();var u,l=[],f=!1,h=-1;function c(){f&&u&&(f=!1,u.length?l=u.concat(l):h=-1,l.length&&d())}function d(){if(!f){var t=a(c);f=!0;for(var e=l.length;e;){for(u=l,l=[];++h1)for(var r=1;r
',t.appendChild(e);let r=p("#picker"),n=p("#slider");ColorPicker(n,r,G)}function w(t){let e=p("#mainContents");{let t=document.createElement("div");t.id="refresh-butter",t.style.display="none",t.style.backgroundColor="#ffff88",t.style.position="absolute",t.style.top="2px",t.style.left="2px",t.style.textAlign="center",t.style.width="40%",t.textContent="Changes found, refresh to see them",document.body.appendChild(t)}let r=t.CONTENTS;if(!r){let t=document.createElement("div");return t="No controls detected",void e.appendChild(t)}if(f.LISTEN){let t=document.createElement("div");t.className="listen-label",t.textContent="Listen for OSC: ",e.appendChild(t);let r=document.createElement("img");r.src=o;let n=document.createElement("span");n.className="listen-button",n.appendChild(r),e.appendChild(n)}!function t(e,r){let n=Object.keys(e);n.sort();for(let o=0;o',e+='',e+=' '+T(n[o])+"",e+="",e+='
',e+='',e+="
",e+='
',e+=''+T(n[o])+"",e+="
",f.innerHTML=e,f.className="dir-container",directoryContainer=f.querySelector("#control_body_"+i),t(l.CONTENTS,directoryContainer)}else f.className="node control",b(f,s,l);r.appendChild(f)}}(r,e)}function A(t,e,r,n){let i=document.createElement(e);i.className=r,i.textContent=n,t.appendChild(i)}function b(t,e,r){A(t,"span","control-name",e),A(t,"span","full-path",r.FULL_PATH),A(t,"span","description",r.DESCRIPTION);let n=[0],i=0;for(let s=0;s/g,">").replace(/"/g,"""):""}function B(t,e,r,n){var i,o="",s=null,a=null;if("c"==e)if(t.RANGE&&E(t.RANGE,r).VALS){var u=E(t.RANGE,r).VALS,l=S(t.VALUE,n)||"";o+="",s="value"}else{o+='',s="value"}else if("r"==e){l=(l=S(t.VALUE,n))?"#"+P(255*(i=l)[0])+P(255*i[1])+P(255*i[2]):d,v?o+='':(o+='
'),s="color",a="color"}else if("d"==e)if(t.RANGE&&E(t.RANGE,r).VALS){u=E(t.RANGE,r).VALS,l=S(t.VALUE,n)||0;o+="",s="value"}else if(t.RANGE){var f=E(t.RANGE,r).MIN||0,h=E(t.RANGE,r).MAX||1;l=S(t.VALUE,n)||0;o+='',o+=''+T(l)+"",o+=' ('+T(f)+"-"+T(h)+")",s="parseFloat",a="float"}else{o+='',o+=''+T(l)+"",s="parseFloat",a="float"}else if("F"==e)o+='';else if("f"==e)if(t.RANGE&&E(t.RANGE,r).VALS){u=E(t.RANGE,r).VALS,l=S(t.VALUE,n)||0;o+="",s="value"}else if(t.RANGE){f=E(t.RANGE,r).MIN||0,h=E(t.RANGE,r).MAX||1,l=S(t.VALUE,n)||0;o+='',o+=''+T(l)+"",o+=' ('+T(f)+"-"+T(h)+")",s="parseFloat",a="float"}else{o+='',o+=''+T(l)+"",s="parseFloat",a="float"}else if("I"==e)o+='';else if("i"==e)if(t.RANGE&&E(t.RANGE,r).VALS){u=E(t.RANGE,r).VALS,l=S(t.VALUE,n)||0;o+="",s="value"}else if(t.RANGE){f=E(t.RANGE,r).MIN||0,h=E(t.RANGE,r).MAX||1,l=S(t.VALUE,n)||0;o+='',o+=''+T(l)+"",o+=' ('+T(f)+"-"+T(h)+")",s="parseInt",a="int"}else{o+='',o+=''+T(l)+"",s="parseInt",a="int"}else if("h"==e)if(t.RANGE&&E(t.RANGE,r).VALS){u=E(t.RANGE,r).VALS,l=S(t.VALUE,n)||0;o+="",s="parseInt64"}else if(t.RANGE){f=E(t.RANGE,r).MIN||0,h=E(t.RANGE,r).MAX||1,l=S(t.VALUE,n)||0;o+='',o+=''+T(l)+"",o+=' ('+T(f)+"-"+T(h)+")",s="parseInt64",a="int"}else{o+='',o+=''+T(l)+"",s="parseInt64",a="int"}else{if("m"==e)return null;if("N"==e)o+='';else if("s"==e)if(t.RANGE&&E(t.RANGE,r).VALS){u=E(t.RANGE,r).VALS,l=S(t.VALUE,n)||"";o+="",s="value"}else{o+='',s="value"}else if("T"==e)o+='';else{if("t"==e)return null;o+='UNKNOWN ('+T(e)+")"}}return o+='");var i,o=r.address,s=r.args[0],a='[data-full-path="'+o+'"]',u=document.querySelector(a),l=u.parentNode,f=l.querySelector("input"),h=u.attributes["data-setter"];if(h)if("color"==h.value){if(k>0)return void k--;s="#"+P((i=s).r)+P(i.g)+P(i.b)}else I(l,h.value,f.value);f.value=s}}})}function N(t){let e=t.target.parentNode,r=e.querySelector(".details"),n=r.attributes["data-full-path"].value,i=r.attributes["data-setter"],o=e.parentNode,s=[];for(let u=0;u2e3&&(k=0,O=null)},1e3),t.exports={createApp:function(t){var e;L(t.replace("http","ws")),i.retrieveHostInfo(t,e=>{e=e,f=e.EXTENSIONS,i.retrieveJson(t,t=>{m(),w(t),_(t),function(){let t=document.getElementsByTagName("input");for(let a=0;a + + + OSC Query Tool + + + + + +

OSC Query Tool

+
+ +