macosx/main menu: refactor and modernize dynamic menu handling (closes #22204)
authorFelix Paul Kühne <felix@feepk.net>
Tue, 16 Apr 2019 21:11:34 +0000 (23:11 +0200)
committerFelix Paul Kühne <felix@feepk.net>
Tue, 16 Apr 2019 21:12:49 +0000 (23:12 +0200)
modules/gui/macosx/menus/VLCMainMenu.m

index e5be19c..0c07b31 100644 (file)
 #import <Sparkle/Sparkle.h>
 #endif
 
+typedef NS_ENUM(NSInteger, VLCObjectType) {
+    VLCObjectTypeInterface,
+    VLCObjectTypeAout,
+    VLCObjectTypeVout,
+};
+
 @interface VLCAutoGeneratedMenuContent : NSObject
 {
-    char *psz_name;
-    vlc_object_t *vlc_object;
-    vlc_value_t value;
-    int i_type;
+    vlc_object_t *_vlcObject;
 }
-- (id)initWithVariableName:(const char *)name
-                  ofObject:(vlc_object_t *)object
-                  andValue:(vlc_value_t)value
-                    ofType:(int)type;
-- (const char *)name;
-- (vlc_value_t)value;
-- (vlc_object_t *)vlcObject;
-- (int)type;
+- (instancetype)initWithVariableName:(const char *)name
+                            ofObject:(vlc_object_t *)object
+                      withObjectType:(VLCObjectType)objectType
+                            andValue:(vlc_value_t)value
+                      ofVariableType:(int)type;
+
+@property (readonly) char *variableName;
+@property (readonly) vlc_value_t variableValue;
+@property (readonly) vlc_object_t *vlcObject;
+@property (readonly) VLCObjectType objectType;
+@property (readonly) int variableType;
 
 @end
 
 
     [self setupVarMenuItem:_add_intf
                     target:VLC_OBJECT(getIntf())
+                objectType:VLCObjectTypeInterface
                        var:"intf-add"
                   selector:@selector(toggleVar:)];
 
     if (p_mediaItem != NULL) {
         audio_output_t *p_aout = [_playerController mainAudioOutput];
         if (p_aout != NULL) {
-            [self setupVarMenuItem:_channels target:VLC_OBJECT(p_aout)
-                               var:"stereo-mode" selector:@selector(toggleVar:)];
-
-            [self setupVarMenuItem:_visual target:VLC_OBJECT(p_aout)
-                               var:"visual" selector:@selector(toggleVar:)];
+            [self setupVarMenuItem:_channels
+                            target:VLC_OBJECT(p_aout)
+                        objectType:VLCObjectTypeAout
+                               var:"stereo-mode"
+                          selector:@selector(toggleVar:)];
+
+            [self setupVarMenuItem:_visual
+                            target:VLC_OBJECT(p_aout)
+                        objectType:VLCObjectTypeAout
+                               var:"visual"
+                          selector:@selector(toggleVar:)];
             aout_Release(p_aout);
         }
 
         vout_thread_t *p_vout = [_playerController videoOutputThreadForKeyWindow];
         if (p_vout != NULL) {
-            [self setupVarMenuItem:_aspect_ratio target:VLC_OBJECT(p_vout)
-                               var:"aspect-ratio" selector: @selector(toggleVar:)];
-
-            [self setupVarMenuItem:_crop target:VLC_OBJECT(p_vout)
-                               var:"crop" selector: @selector(toggleVar:)];
-
-            [self setupVarMenuItem:_deinterlace target:VLC_OBJECT(p_vout)
-                               var:"deinterlace" selector: @selector(toggleVar:)];
-
-            [self setupVarMenuItem:_deinterlace_mode target:VLC_OBJECT(p_vout)
-                               var:"deinterlace-mode" selector: @selector(toggleVar:)];
+            [self setupVarMenuItem:_aspect_ratio
+                            target:VLC_OBJECT(p_vout)
+                        objectType:VLCObjectTypeVout
+                               var:"aspect-ratio"
+                          selector:@selector(toggleVar:)];
+
+            [self setupVarMenuItem:_crop
+                            target:VLC_OBJECT(p_vout)
+                        objectType:VLCObjectTypeVout
+                               var:"crop"
+                          selector:@selector(toggleVar:)];
+
+            [self setupVarMenuItem:_deinterlace
+                            target:VLC_OBJECT(p_vout)
+                        objectType:VLCObjectTypeVout
+                               var:"deinterlace"
+                          selector:@selector(toggleVar:)];
+
+            [self setupVarMenuItem:_deinterlace_mode
+                            target:VLC_OBJECT(p_vout)
+                        objectType:VLCObjectTypeVout
+                               var:"deinterlace-mode"
+                          selector:@selector(toggleVar:)];
 
             vout_Release(p_vout);
 
 
 - (void)lockVideosAspectRatio:(id)sender
 {
-    // FIXME: re-write the following using VLCPlayerController
     [_playerController setAspectRatioIsLocked: ![sender state]];
     [sender setState: [_playerController aspectRatioIsLocked]];
 }
 
 - (void)setupVarMenuItem:(NSMenuItem *)menuItem
                   target:(vlc_object_t *)p_object
+              objectType:(VLCObjectType)objectType
                      var:(const char *)psz_variable
                 selector:(SEL)pf_callback
 {
         [self setupVarMenu:menu
                forMenuItem:menuItem
                     target:p_object
+                objectType:objectType
                        var:psz_variable
                   selector:pf_callback];
 
         case VLC_VAR_VOID:
             data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName:psz_variable
                                                                     ofObject:p_object
+                                                              withObjectType:objectType
                                                                     andValue:val
-                                                                      ofType:i_type];
+                                                              ofVariableType:i_type];
             [menuItem setRepresentedObject:data];
             break;
 
         case VLC_VAR_BOOL:
             data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName:psz_variable
                                                                     ofObject:p_object
+                                                              withObjectType:objectType
                                                                     andValue:val
-                                                                      ofType:i_type];
+                                                              ofVariableType:i_type];
             [menuItem setRepresentedObject:data];
             if (!(i_type & VLC_VAR_ISCOMMAND))
                 [menuItem setState:val.b_bool ? NSOnState : NSOffState];
 - (void)setupVarMenu:(NSMenu *)menu
          forMenuItem:(NSMenuItem *)parent
               target:(vlc_object_t *)p_object
+          objectType:(VLCObjectType)objectType
                  var:(const char *)psz_variable
             selector:(SEL)pf_callback
 {
     [parent setEnabled:NO];
 
     /* Aspect Ratio */
-    if ([[parent title] isEqualToString: _NS("Aspect ratio")] == YES) {
+    if ([[parent title] isEqualToString:_NS("Aspect ratio")] == YES) {
         NSMenuItem *lmi_tmp2;
-        lmi_tmp2 = [menu addItemWithTitle: _NS("Lock Aspect Ratio") action: @selector(lockVideosAspectRatio:) keyEquivalent: @""];
+        lmi_tmp2 = [menu addItemWithTitle:_NS("Lock Aspect Ratio")
+                                   action:@selector(lockVideosAspectRatio:)
+                            keyEquivalent:@""];
         [lmi_tmp2 setTarget: self];
         [lmi_tmp2 setEnabled: YES];
         [lmi_tmp2 setState: [_playerController aspectRatioIsLocked]];
 
     if (var_Change(p_object, psz_variable, VLC_VAR_GETCHOICES,
                    &count, &val_list, &text_list) < 0) {
-        if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) free(val.psz_string);
+        if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
+            free(val.psz_string);
         return;
     }
 
                 lmi = [menu addItemWithTitle:title action:pf_callback keyEquivalent:@""];
                 data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName:psz_variable
                                                                         ofObject:p_object
+                                                                  withObjectType:objectType
                                                                         andValue:val_list[i]
-                                                                          ofType:i_type];
+                                                                  ofVariableType:i_type];
                 [lmi setRepresentedObject:data];
                 [lmi setTarget:self];
 
                 lmi = [menu addItemWithTitle: title action: pf_callback keyEquivalent: @""];
                 data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName:psz_variable
                                                                         ofObject:p_object
+                                                                  withObjectType:objectType
                                                                         andValue:val_list[i]
-                                                                          ofType:i_type];
+                                                                  ofVariableType:i_type];
                 [lmi setRepresentedObject:data];
                 [lmi setTarget:self];
 
         VLCAutoGeneratedMenuContent *menuContent = (VLCAutoGeneratedMenuContent *)data;
 
         p_object = [menuContent vlcObject];
-        var_Set(p_object, [menuContent name], [menuContent value]);
+        var_Set(p_object, [menuContent variableName], [menuContent variableValue]);
     }
 }
 
 
 @implementation VLCAutoGeneratedMenuContent
 
--(id)initWithVariableName:(const char *)name
-                 ofObject:(vlc_object_t *)object
-                 andValue:(vlc_value_t)val
-                   ofType:(int)type
+- (instancetype)initWithVariableName:(const char *)name
+                            ofObject:(vlc_object_t *)object
+                      withObjectType:(VLCObjectType)objectType
+                            andValue:(vlc_value_t)value
+                      ofVariableType:(int)type;
 {
     self = [super init];
 
     if (self != nil) {
-        vlc_object = vlc_object_hold(object);
-        psz_name = strdup(name);
-        i_type = type;
-        value = val;
-        if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
-            value.psz_string = strdup(val.psz_string);
+        switch (objectType) {
+            case VLCObjectTypeAout:
+                aout_Hold((audio_output_t *)object);
+                break;
+            case VLCObjectTypeVout:
+                vout_Hold((vout_thread_t *)object);
+                break;
+
+            default:
+                // No need to retain the interface because it will always be there
+                break;
+        }
+        _vlcObject = object;
+        _objectType = objectType;
+        _variableName = strdup(name);
+        _variableType = type;
+        _variableValue = value;
+        if ((type & VLC_VAR_TYPE) == VLC_VAR_STRING)
+            _variableValue.psz_string = strdup(value.psz_string);
     }
 
     return(self);
 
 - (void)dealloc
 {
-    if (vlc_object)
-        vlc_object_release(vlc_object);
-    if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
-        free(value.psz_string);
-    free(psz_name);
-}
-
-- (const char *)name
-{
-    return psz_name;
-}
-
-- (vlc_value_t)value
-{
-    return value;
-}
-
-- (vlc_object_t *)vlcObject
-{
-    return vlc_object;
-}
-
-- (int)type
-{
-    return i_type;
+    if (_vlcObject && _objectType != VLCObjectTypeInterface)
+        vlc_object_release(_vlcObject);
+    if ((_variableType & VLC_VAR_TYPE) == VLC_VAR_STRING)
+        free(_variableValue.psz_string);
+    free(_variableName);
 }
 
 @end