diff --git a/modules/gui/macosx/AudioEffects.m b/modules/gui/macosx/AudioEffects.m index ec9944772b..9f48ffb0c4 100644 --- a/modules/gui/macosx/AudioEffects.m +++ b/modules/gui/macosx/AudioEffects.m @@ -366,10 +366,50 @@ [_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")]; [_textfieldPanel setCancelButtonLabel: _NS("Cancel")]; [_textfieldPanel setOKButtonLabel: _NS("Save")]; - [_textfieldPanel setTarget:self]; - b_genericAudioProfileInInteraction = YES; - [_textfieldPanel runModalForWindow:self.window]; + __weak typeof(self) _self = self; + [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) { + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + if (returnCode != NSOKButton) { + [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]]; + return; + } + + NSArray *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"]; + + // duplicate names are not allowed in the popup control + if ([resultingText length] == 0 || [profileNames containsObject:resultingText]) { + [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]]; + + NSAlert *alert = [[NSAlert alloc] init]; + [alert setAlertStyle:NSCriticalAlertStyle]; + [alert setMessageText:_NS("Please enter a unique name for the new profile.")]; + [alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")]; + + [alert beginSheetModalForWindow:_self.window + modalDelegate:nil + didEndSelector:nil + contextInfo:nil]; + return; + } + + NSString *newProfile = [_self generateProfileString]; + + /* add string to user defaults as well as a label */ + NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]]; + [workArray addObject:newProfile]; + [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"]; + [defaults setInteger:[workArray count] - 1 forKey:@"AudioEffectSelectedProfile"]; + workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]]; + [workArray addObject:resultingText]; + [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"]; + + /* save defaults */ + [defaults synchronize]; + [_self resetProfileSelector]; + + }]; } - (void)removeAudioEffectsProfile:(id)sender @@ -601,93 +641,45 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf, - (IBAction)addPresetAction:(id)sender { /* show panel */ - VLCTextfieldPanelController *panel = [[VLCTextfieldPanelController alloc] init]; - [panel setTitle: _NS("Save current selection as new preset")]; - [panel setSubTitle: _NS("Enter a name for the new preset:")]; - [panel setCancelButtonLabel: _NS("Cancel")]; - [panel setOKButtonLabel: _NS("Save")]; - [panel setTarget:self]; - b_genericAudioProfileInInteraction = NO; - - [panel runModalForWindow:self.window]; -} - -- (void)panel:(VLCTextfieldPanelController *)panel returnValue:(NSUInteger)value text:(NSString *)text -{ - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - // EQ settings - if (!b_genericAudioProfileInInteraction) { - if (value == NSOKButton && [text length] > 0) { - NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]]; - [workArray addObject:[self generatePresetString]]; - [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"]; - workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]]; - [workArray addObject:text]; - [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"]; - workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]]; - [workArray addObject:[NSString stringWithFormat:@"%.1f", [_equalizerPreampSlider floatValue]]]; - [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"]; - workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]]; - [workArray addObject:[text decomposedStringWithCanonicalMapping]]; - [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"]; - [defaults synchronize]; - - /* update VLC internals */ - audio_output_t *p_aout = getAout(); - if (p_aout) { - var_SetString(p_aout, "equalizer-preset", [[text decomposedStringWithCanonicalMapping] UTF8String]); - vlc_object_release(p_aout); - } - - config_PutPsz(VLCIntf, "equalizer-preset", [[text decomposedStringWithCanonicalMapping] UTF8String]); + [_textfieldPanel setTitle: _NS("Save current selection as new preset")]; + [_textfieldPanel setSubTitle: _NS("Enter a name for the new preset:")]; + [_textfieldPanel setCancelButtonLabel: _NS("Cancel")]; + [_textfieldPanel setOKButtonLabel: _NS("Save")]; - /* update UI */ - [self updatePresetSelector]; - } + __weak typeof(self) _self = self; + [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - // profile settings - } else { - if (value != NSOKButton) { - [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]]; + // EQ settings + if (returnCode != NSOKButton || [resultingText length] == 0) return; - } - - NSArray *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"]; - - // duplicate names are not allowed in the popup control - if ([text length] == 0 || [profileNames containsObject:text]) { - [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]]; - NSAlert *alert = [[NSAlert alloc] init]; - [alert setAlertStyle:NSCriticalAlertStyle]; - [alert setMessageText:_NS("Please enter a unique name for the new profile.")]; - [alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")]; + NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]]; + [workArray addObject:[self generatePresetString]]; + [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"]; + workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]]; + [workArray addObject:resultingText]; + [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"]; + workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]]; + [workArray addObject:[NSString stringWithFormat:@"%.1f", [_equalizerPreampSlider floatValue]]]; + [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"]; + workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]]; + [workArray addObject:[resultingText decomposedStringWithCanonicalMapping]]; + [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"]; + [defaults synchronize]; - [alert beginSheetModalForWindow:self.window - modalDelegate:nil - didEndSelector:nil - contextInfo:nil]; - return; + /* update VLC internals */ + audio_output_t *p_aout = getAout(); + if (p_aout) { + var_SetString(p_aout, "equalizer-preset", [[resultingText decomposedStringWithCanonicalMapping] UTF8String]); + vlc_object_release(p_aout); } - - NSString *newProfile = [self generateProfileString]; - /* add string to user defaults as well as a label */ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]]; - [workArray addObject:newProfile]; - [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"]; - [defaults setInteger:[workArray count] - 1 forKey:@"AudioEffectSelectedProfile"]; - workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]]; - [workArray addObject:text]; - [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"]; + config_PutPsz(VLCIntf, "equalizer-preset", [[resultingText decomposedStringWithCanonicalMapping] UTF8String]); - /* save defaults */ - [defaults synchronize]; - [self resetProfileSelector]; - } + /* update UI */ + [_self updatePresetSelector]; + }]; } - (IBAction)deletePresetAction:(id)sender diff --git a/modules/gui/macosx/ConvertAndSave.h b/modules/gui/macosx/ConvertAndSave.h index bf75dfb5ce..3585fd07f7 100644 --- a/modules/gui/macosx/ConvertAndSave.h +++ b/modules/gui/macosx/ConvertAndSave.h @@ -166,7 +166,6 @@ - (IBAction)streamAnnouncementToggle:(id)sender; - (IBAction)sdpFileLocationSelector:(id)sender; -- (void)panel:(VLCTextfieldPanelController *)panel returnValue:(NSUInteger)value text:(NSString *)text; - (void)panel:(VLCPopupPanelController *)panel returnValue:(NSUInteger)value item:(NSUInteger)item; @end diff --git a/modules/gui/macosx/ConvertAndSave.m b/modules/gui/macosx/ConvertAndSave.m index 3796de38cf..c63842ac00 100644 --- a/modules/gui/macosx/ConvertAndSave.m +++ b/modules/gui/macosx/ConvertAndSave.m @@ -452,9 +452,32 @@ [_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")]; [_textfieldPanel setCancelButtonLabel: _NS("Cancel")]; [_textfieldPanel setOKButtonLabel: _NS("Save")]; - [_textfieldPanel setTarget:self]; - [_textfieldPanel runModalForWindow:_customizePanel]; + __weak typeof(self) _self = self; + [_textfieldPanel runModalForWindow:_customizePanel completionHandler:^(NSInteger returnCode, NSString *resultingText) { + if (returnCode != NSOKButton || [resultingText length] == 0) + return; + + /* prepare current data */ + [_self updateCurrentProfile]; + + /* add profile to arrays */ + NSMutableArray * workArray = [[NSMutableArray alloc] initWithArray:self.profileNames]; + [workArray addObject:resultingText]; + [_self setProfileNames:[[NSArray alloc] initWithArray:workArray]]; + + workArray = [[NSMutableArray alloc] initWithArray:self.profileValueList]; + [workArray addObject:[self.currentProfile componentsJoinedByString:@";"]]; + [_self setProfileValueList:[[NSArray alloc] initWithArray:workArray]]; + + /* update UI */ + [_self recreateProfilePopup]; + [_profilePopup selectItemWithTitle:resultingText]; + + /* update internals */ + [_self switchProfile:self]; + [_self storeProfilesOnDisk]; + }]; } #pragma mark - @@ -605,33 +628,6 @@ return NO; } -- (void)panel:(VLCTextfieldPanelController *)panel returnValue:(NSUInteger)value text:(NSString *)text -{ - if (value == NSOKButton) { - if ([text length] > 0) { - /* prepare current data */ - [self updateCurrentProfile]; - - /* add profile to arrays */ - NSMutableArray * workArray = [[NSMutableArray alloc] initWithArray:self.profileNames]; - [workArray addObject:text]; - [self setProfileNames:[[NSArray alloc] initWithArray:workArray]]; - - workArray = [[NSMutableArray alloc] initWithArray:self.profileValueList]; - [workArray addObject:[self.currentProfile componentsJoinedByString:@";"]]; - [self setProfileValueList:[[NSArray alloc] initWithArray:workArray]]; - - /* update UI */ - [self recreateProfilePopup]; - [_profilePopup selectItemWithTitle:text]; - - /* update internals */ - [self switchProfile:self]; - [self storeProfilesOnDisk]; - } - } -} - - (void)panel:(VLCPopupPanelController *)panel returnValue:(NSUInteger)value item:(NSUInteger)item { if (value == NSOKButton) { diff --git a/modules/gui/macosx/SharedDialogs.h b/modules/gui/macosx/SharedDialogs.h index 2be975a42e..2ebe07ac43 100644 --- a/modules/gui/macosx/SharedDialogs.h +++ b/modules/gui/macosx/SharedDialogs.h @@ -35,19 +35,25 @@ @property (readwrite, assign) NSString *subTitle; @property (readwrite, assign) NSString *OKButtonLabel; @property (readwrite, assign) NSString *CancelButtonLabel; -@property (readwrite, assign) id target; -@property (readonly) NSString *enteredText; -- (void)runModalForWindow:(NSWindow *)window; +/** + * Completion handler for textfield panel + * \param returnCode Result from panel. Can be NSOKButton or NSCancelButton. + * \param resultingText Resulting text string entered in panel. + */ +typedef void(^TextfieldPanelCompletionBlock)(NSInteger returnCode, NSString *resultingText); + +/** + * Shows the panel as a modal dialog with window as its owner. + * \param window Parent window for the dialog. + * \param handler Completion block. + */ +- (void)runModalForWindow:(NSWindow *)window completionHandler:(TextfieldPanelCompletionBlock)handler; - (IBAction)windowElementAction:(id)sender; @end -@protocol VLCTextfieldPanelController -@optional -- (void)panel:(VLCTextfieldPanelController *)view returnValue:(NSUInteger)value text:(NSString *)text; -@end @interface VLCPopupPanelController : NSWindowController diff --git a/modules/gui/macosx/SharedDialogs.m b/modules/gui/macosx/SharedDialogs.m index 28f884a030..41850e6ccc 100644 --- a/modules/gui/macosx/SharedDialogs.m +++ b/modules/gui/macosx/SharedDialogs.m @@ -23,6 +23,13 @@ #import "SharedDialogs.h" +@interface VLCTextfieldPanelController() +{ + TextfieldPanelCompletionBlock _completionBlock; +} + +@end + @implementation VLCTextfieldPanelController @@ -38,17 +45,11 @@ [self.window orderOut:sender]; [NSApp endSheet: self.window]; - if (self.target) { - if ([self.target respondsToSelector:@selector(panel:returnValue:text:)]) { - if (sender == _cancelButton) - [self.target panel:self returnValue:NSCancelButton text:NULL]; - else - [self.target panel:self returnValue:NSOKButton text:self.enteredText]; - } - } + if (_completionBlock) + _completionBlock(sender == _okButton ? NSOKButton : NSCancelButton, [_textField stringValue]); } -- (void)runModalForWindow:(NSWindow *)window +- (void)runModalForWindow:(NSWindow *)window completionHandler:(TextfieldPanelCompletionBlock)handler; { [self window]; @@ -58,12 +59,9 @@ [_okButton setTitle:self.OKButtonLabel]; [_textField setStringValue:@""]; - [NSApp beginSheet:self.window modalForWindow:window modalDelegate:self didEndSelector:NULL contextInfo:nil]; -} + _completionBlock = [handler copy]; -- (NSString *)enteredText -{ - return [_textField stringValue]; + [NSApp beginSheet:self.window modalForWindow:window modalDelegate:self didEndSelector:NULL contextInfo:nil]; } @end diff --git a/modules/gui/macosx/VideoEffects.m b/modules/gui/macosx/VideoEffects.m index 8269a29631..4109a66ae4 100644 --- a/modules/gui/macosx/VideoEffects.m +++ b/modules/gui/macosx/VideoEffects.m @@ -673,57 +673,55 @@ [_textfieldPanel setSubTitle: _NS("Enter a name for the new profile:")]; [_textfieldPanel setCancelButtonLabel: _NS("Cancel")]; [_textfieldPanel setOKButtonLabel: _NS("Save")]; - [_textfieldPanel setTarget:self]; - [_textfieldPanel runModalForWindow:self.window]; -} + __weak typeof(self) _self = self; + [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) { -- (void)panel:(VLCTextfieldPanelController *)panel returnValue:(NSUInteger)value text:(NSString *)text -{ - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - if (value != NSOKButton) { - [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]]; - return; - } + if (returnCode != NSOKButton) { + [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]]; + return; + } - NSArray *profileNames = [defaults objectForKey:@"VideoEffectProfileNames"]; + NSArray *profileNames = [defaults objectForKey:@"VideoEffectProfileNames"]; - // duplicate names are not allowed in the popup control - if ([text length] == 0 || [profileNames containsObject:text]) { - [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]]; + // duplicate names are not allowed in the popup control + if ([resultingText length] == 0 || [profileNames containsObject:resultingText]) { + [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]]; - NSAlert *alert = [[NSAlert alloc] init]; - [alert setAlertStyle:NSCriticalAlertStyle]; - [alert setMessageText:_NS("Please enter a unique name for the new profile.")]; - [alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")]; + NSAlert *alert = [[NSAlert alloc] init]; + [alert setAlertStyle:NSCriticalAlertStyle]; + [alert setMessageText:_NS("Please enter a unique name for the new profile.")]; + [alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")]; - [alert beginSheetModalForWindow:self.window - modalDelegate:nil - didEndSelector:nil - contextInfo:nil]; - return; - } + [alert beginSheetModalForWindow:_self.window + modalDelegate:nil + didEndSelector:nil + contextInfo:nil]; + return; + } - /* fetch all the current settings in a uniform string */ - NSString *newProfile = [self generateProfileString]; + /* fetch all the current settings in a uniform string */ + NSString *newProfile = [_self generateProfileString]; - /* add string to user defaults as well as a label */ + /* add string to user defaults as well as a label */ - NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfiles"]]; - [workArray addObject:newProfile]; - [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfiles"]; - [defaults setInteger:[workArray count] - 1 forKey:@"VideoEffectSelectedProfile"]; + NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfiles"]]; + [workArray addObject:newProfile]; + [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfiles"]; + [defaults setInteger:[workArray count] - 1 forKey:@"VideoEffectSelectedProfile"]; - workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfileNames"]]; - [workArray addObject:text]; - [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfileNames"]; + workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfileNames"]]; + [workArray addObject:resultingText]; + [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfileNames"]; - /* save defaults */ - [defaults synchronize]; + /* save defaults */ + [defaults synchronize]; - /* refresh UI */ - [self resetProfileSelector]; + /* refresh UI */ + [_self resetProfileSelector]; + }]; } - (void)removeProfile:(id)sender