diff --git a/CHANGES.txt b/CHANGES.txt index 4608f3a..313fc2e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,10 @@ +1.4.1: 2023-11-14 + +* fixed accel orientation when switching between rotated and non-rotated scenes, + bug only affected rjdj scenes and pdparty scenes using accel orientation +* fixed potential crash when loading tgl or bng if atom line is < 19 in length + aka malformed patch file (tangentially reported by Coti Kappa) + 1.4.0: 2023-11-10 * updated to libpd 0.14.0 (pd 0.54-1) diff --git a/PdParty.xcodeproj/project.pbxproj b/PdParty.xcodeproj/project.pbxproj index f1734a6..985f7d5 100644 --- a/PdParty.xcodeproj/project.pbxproj +++ b/PdParty.xcodeproj/project.pbxproj @@ -1357,7 +1357,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 3567T5L8KK; EXCLUDED_ARCHS = ""; FRAMEWORK_SEARCH_PATHS = ( @@ -1383,7 +1383,7 @@ "$(inherited)", "$(PROJECT_DIR)/libs/liblo", ); - MARKETING_VERSION = 1.4.0; + MARKETING_VERSION = 1.4.1; OTHER_CFLAGS = ( "-DPD", "-DHAVE_UNISTD_H", @@ -1411,7 +1411,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 3567T5L8KK; EXCLUDED_ARCHS = ""; FRAMEWORK_SEARCH_PATHS = ( @@ -1436,7 +1436,7 @@ "$(inherited)", "$(PROJECT_DIR)/libs/liblo", ); - MARKETING_VERSION = 1.4.0; + MARKETING_VERSION = 1.4.1; OTHER_CFLAGS = ( "-DNS_BLOCK_ASSERTIONS=1", "-DPD", diff --git a/doc/guide/PdParty_User_Guide.md b/doc/guide/PdParty_User_Guide.md index 235a1a4..8e397a0 100644 --- a/doc/guide/PdParty_User_Guide.md +++ b/doc/guide/PdParty_User_Guide.md @@ -1,8 +1,8 @@ PdParty User Guide ================== -Version: **1.4.0** -Date: 2023-11-10 +Version: **1.4.1** +Date: 2023-11-14 PdParty is an iOS app that allows you to run [Pure Data](http://puredata.info/) patches on Apple mobile devices using libpd. It is directly inspired by Chris McCormick's [PdDroidParty](http://droidparty.net/) and the original RjDj app by [Reality Jockey](http://rjdj.me/). It takes a step further by supporting OSC and MIDI and by implementing the native Pd gui objects for a WYSIWYG patch -> mobile device experience: @@ -889,7 +889,7 @@ The selected viewport area will be rescaled in order to fill the screen of the d See the DroidParty `pure-widgets-demo` sample and the PdParty `ViewPort` test. -As of PdParty 1.4.0+, the ViewPort canvas is *not* drawn in PdParty. This matches behavior in DroidParty. If you need a background color, you will can use additional cnv objects. +As of PdParty 1.4.0+, the ViewPort canvas is *not* drawn in PdParty. This matches behavior in DroidParty. If you need a background color, you can use additional cnv objects. ### Dynamic Background diff --git a/res/about/about.html b/res/about/about.html index 0b2b7a8..b804aa5 100644 --- a/res/about/about.html +++ b/res/about/about.html @@ -11,7 +11,7 @@ -

PdParty 1.4.0

+

PdParty 1.4.1

Copyright (c) Dan Wilcox 2011-2023

BSD Simplified License

diff --git a/src/PatchViewController.m b/src/PatchViewController.m index 588863d..994fef6 100644 --- a/src/PatchViewController.m +++ b/src/PatchViewController.m @@ -150,15 +150,6 @@ - (void)viewDidLayoutSubviews { [self.view layoutSubviews]; } -- (void)viewWillTransitionToSize:(CGSize)size - withTransitionCoordinator:(id)coordinator { - [coordinator animateAlongsideTransition:^(id context) {} - completion:^(id context) { - self.sceneManager.currentOrientation = UIApplication.sharedApplication.statusBarOrientation; - }]; - [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; -} - // lock orientation based on scene's preferred orientation mask - (UIInterfaceOrientationMask)supportedInterfaceOrientations { if(self.sceneManager.scene && !self.sceneManager.isRotated) { @@ -364,6 +355,7 @@ - (void)updateOrientation { if((self.sceneManager.scene.preferredOrientations == UIInterfaceOrientationMaskAll) || (self.sceneManager.scene.preferredOrientations == UIInterfaceOrientationMaskAllButUpsideDown)) { [(PatchView *)self.view setRotation:0]; + self.sceneManager.currentOrientation = UIApplication.sharedApplication.statusBarOrientation; } else if(UIInterfaceOrientationIsLandscape(currentOrientation)) { if(self.sceneManager.scene.preferredOrientations & (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationPortraitUpsideDown)) { @@ -379,6 +371,7 @@ - (void)updateOrientation { } else { [(PatchView *)self.view setRotation:0]; + self.sceneManager.currentOrientation = UIApplication.sharedApplication.statusBarOrientation; } } else { // default is portrait @@ -395,6 +388,7 @@ - (void)updateOrientation { } else { [(PatchView *)self.view setRotation:0]; + self.sceneManager.currentOrientation = UIApplication.sharedApplication.statusBarOrientation; } } self.sceneManager.isRotated = ([(PatchView *)self.view rotation] != 0); diff --git a/src/gui/Widget.m b/src/gui/Widget.m index c0d4fb7..793fbe8 100644 --- a/src/gui/Widget.m +++ b/src/gui/Widget.m @@ -70,6 +70,14 @@ - (id)initWithAtomLine:(NSArray *)line andGui:(Gui *)gui { if(self) { [self _init]; self.gui = gui; + if ([self.type isEqual:@"Symbol"] || + [self.type isEqual:@"List"] || + [self.type isEqual:@"Knob"] || + [self.type hasPrefix:@"Number"] || + [self.type hasSuffix:@"Radio"] || + [self.type hasSuffix:@"Slider"]) { + [self addDoubleTabInputToWidget:self]; + } } return self; } @@ -337,4 +345,74 @@ + (NSString *)stringFromFloat:(double)f withWidth:(int)width { return string; } +- (void) addDoubleTabInputToWidget:(Widget*)w { + UITapGestureRecognizer *tab = [[UITapGestureRecognizer alloc] + initWithTarget:self + action:@selector(handleWidgetTap:)]; + tab.numberOfTapsRequired = 2; + [w addGestureRecognizer:tab]; +} + +- (void)handleWidgetTap:(UITapGestureRecognizer *)gestureRecognizer { + Widget *control = (Widget *)gestureRecognizer.view; + if (control) { + [self showInputDialogForWidget:control withNumberPad:!([control.type isEqual:@"Symbol"] || [control.type isEqual:@"List"])]; + } +} + +- (void) showInputDialogForWidget: (Widget*)w withNumberPad: (BOOL) pad { + dispatch_async(dispatch_get_main_queue(), ^{ // make shure we dont affect audio + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil + message:@"set value:" + preferredStyle:UIAlertControllerStyleAlert]; + [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { + if (pad) { + textField.keyboardType = UIKeyboardTypeDecimalPad; + // add button to toggle positive/negative + UIButton *minusBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [minusBtn addTarget:self action:@selector(toggleNegative:) forControlEvents:UIControlEventTouchUpInside]; + [minusBtn setTitle:@"-/+" forState:UIControlStateNormal]; + + textField.leftView = minusBtn; + textField.leftViewMode = UITextFieldViewModeAlways; + } + textField.textAlignment = NSTextAlignmentCenter; + [textField becomeFirstResponder]; + }]; + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" + style:UIAlertActionStyleCancel + handler:nil]; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Set" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { + UITextField *textField = alertController.textFields.firstObject; + if (textField) { + if (![textField.text isEqual: @""] && ![textField.text isEqual: @"-"]) { + if (pad) { + float value = [[textField.text stringByReplacingOccurrencesOfString:@"," withString:@"."] floatValue]; + // in case the widget's min and max range is set + if ((w.minValue != 0) && (w.maxValue != 0)) { + // reflect the widget's min/max range + value = ((value >= w.minValue) && (value <= w.maxValue)) ? value : (value >= w.minValue) ? w.maxValue : w.minValue; + } + [w receiveFloat:value fromSource:@"user"]; // source has no effect here + } + else { + [w receiveSymbol:textField.text fromSource:@"user"]; // source has no effect here + } + } + } + }]; + [alertController addAction:cancelAction]; + [alertController addAction:okAction]; + UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; + [rootViewController presentViewController:alertController animated:YES completion:nil]; + }); +} + +- (void) toggleNegative: (UIButton*) btn { + UITextField *tf = (UITextField*) [btn superview]; + tf.text = ([tf.text hasPrefix:@"-"]) ? [tf.text substringFromIndex:1] : [@"-" stringByAppendingString:tf.text]; +} + @end diff --git a/src/gui/iem/Bang.m b/src/gui/iem/Bang.m index 95b0047..a2cc804 100644 --- a/src/gui/iem/Bang.m +++ b/src/gui/iem/Bang.m @@ -27,8 +27,8 @@ - (void)resumeFlash:(NSTimer *)timer; @implementation Bang - (id)initWithAtomLine:(NSArray *)line andGui:(Gui *)gui { - if(line.count < 18) { // sanity check - LogWarn(@"Bang: cannot create, atom line length < 18"); + if(line.count < 19) { // sanity check + LogWarn(@"Bang: cannot create, atom line length < 19"); return nil; } self = [super initWithAtomLine:line andGui:gui]; diff --git a/src/gui/iem/Toggle.m b/src/gui/iem/Toggle.m index 5c70f1b..a8e8786 100644 --- a/src/gui/iem/Toggle.m +++ b/src/gui/iem/Toggle.m @@ -17,8 +17,8 @@ @implementation Toggle - (id)initWithAtomLine:(NSArray *)line andGui:(Gui *)gui { - if(line.count < 18) { // sanity check - LogWarn(@"Toggle: cannot create, atom line length < 18"); + if(line.count < 19) { // sanity check + LogWarn(@"Toggle: cannot create, atom line length < 19"); return nil; } self = [super initWithAtomLine:line andGui:gui]; @@ -47,7 +47,7 @@ - (id)initWithAtomLine:(NSArray *)line andGui:(Gui *)gui { self.fillColor = [IEMWidget colorFromAtomColor:line[14]]; self.controlColor = [IEMWidget colorFromAtomColor:line[15]]; self.label.textColor = [IEMWidget colorFromAtomColor:line[16]]; - + self.nonZeroValue = [line[18] floatValue]; if(self.inits) { self.value = [line[17] floatValue]; diff --git a/src/modules/Sensors.m b/src/modules/Sensors.m index 9060421..a8e3791 100644 --- a/src/modules/Sensors.m +++ b/src/modules/Sensors.m @@ -575,7 +575,6 @@ - (void)sendAccel:(CMAccelerometerData *)accel { [self.osc sendAccel:x y:y z:z]; } -// reorient gryo data to current orientation - (void)sendGyro:(CMGyroData *)gyro { #ifdef DEBUG_SENSORS LogVerbose(@"gyro %f %f %f", gyro.rotationRate.x, gyro.rotationRate.y, gyro.rotationRate.z);