prefs.m
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:43k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * prefs.m: MacOS X module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2004 VideoLAN
  5.  * $Id: prefs.m 8571 2004-08-29 15:11:50Z hartman $
  6.  *
  7.  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  8.  *          Derk-Jan Hartman <hartman at videolan dot org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdlib.h>                                      /* malloc(), free() */
  28. #include <sys/param.h>                                    /* for MAXPATHLEN */
  29. #include <string.h>
  30. #include "intf.h"
  31. #include "prefs.h"
  32. #include "vlc_keys.h"
  33. /*****************************************************************************
  34.  * VLCPrefs implementation
  35.  *****************************************************************************/
  36. @implementation VLCPrefs
  37. - (id)init
  38. {
  39.     self = [super init];
  40.     if( self != nil )
  41.     {
  42.         o_empty_view = [[NSView alloc] init];
  43.         o_save_prefs = [[NSMutableDictionary alloc] init];
  44.     }
  45.     return( self );
  46. }
  47. - (void)dealloc
  48. {
  49.     [o_empty_view release];
  50.     [o_save_prefs release];
  51.     [super dealloc];
  52. }
  53. - (void)awakeFromNib
  54. {
  55.     p_intf = VLCIntf;
  56.     b_advanced = config_GetInt( p_intf, "advanced" );
  57.     [self initStrings];
  58.     [o_advanced_ckb setState: b_advanced];
  59.     [o_prefs_view setBorderType: NSGrooveBorder];
  60.     [o_prefs_view setHasVerticalScroller: YES];
  61.     [o_prefs_view setDrawsBackground: NO];
  62.     [o_prefs_view setRulersVisible: NO];
  63.     [o_prefs_view setDocumentView: o_empty_view];
  64.     [o_tree selectRow:0 byExtendingSelection:NO];
  65. }
  66. - (void)initStrings
  67. {
  68.     [o_prefs_window setTitle: _NS("Preferences")];
  69.     [o_save_btn setTitle: _NS("Save")];
  70.     [o_cancel_btn setTitle: _NS("Cancel")];
  71.     [o_reset_btn setTitle: _NS("Reset All")];
  72.     [o_advanced_ckb setTitle: _NS("Advanced")];
  73. }
  74. - (void)showPrefs
  75. {
  76.     [o_save_prefs release];
  77.     o_save_prefs = [[NSMutableDictionary alloc] init];
  78.     [self showViewForID: [[o_tree itemAtRow:[o_tree selectedRow]] getObjectID]
  79.         andName: [[o_tree itemAtRow:[o_tree selectedRow]] getName]];
  80.     [o_prefs_window center];
  81.     [o_prefs_window makeKeyAndOrderFront:self];
  82. }
  83. - (IBAction)savePrefs: (id)sender
  84. {
  85.     id o_vlc_config;
  86.     NSEnumerator *o_enum;
  87.     o_enum = [o_save_prefs objectEnumerator];
  88.     while( ( o_vlc_config = [o_enum nextObject] ) )
  89.     {
  90.         int i_type = [o_vlc_config configType];
  91.         NSString *o_name = [o_vlc_config configName];
  92.         char *psz_name = (char *)[o_name UTF8String];
  93.         switch( i_type )
  94.         {
  95.     
  96.         case CONFIG_ITEM_MODULE:
  97.             {
  98.                 char *psz_value;
  99.                 module_t *p_a_module;
  100.                 int i_id = [[o_vlc_config selectedItem] tag];
  101.                 
  102.                 p_a_module = (module_t *)vlc_object_get( p_intf, i_id );
  103.                 if( p_a_module == NULL || p_a_module->i_object_type != VLC_OBJECT_MODULE )
  104.                 {
  105.                     i_id = -1;
  106.                 }
  107.                 
  108.                 psz_value = ( i_id == -1 ) ? "" :  p_a_module->psz_object_name ;
  109.                 config_PutPsz( p_intf, psz_name, strdup(psz_value) );
  110.             }
  111.             break;
  112.     
  113.         case CONFIG_ITEM_STRING:
  114.             {
  115.                 char *psz_value;
  116.                 NSString *o_value = [o_vlc_config stringValue];
  117.                 psz_value = (char *)[o_value UTF8String];
  118.     
  119.                 config_PutPsz( p_intf, psz_name, psz_value );
  120.             }
  121.             break;
  122.         case CONFIG_ITEM_FILE:
  123.         case CONFIG_ITEM_DIRECTORY:
  124.             {
  125.                 char *psz_value;
  126.                 NSString *o_value = [o_vlc_config stringValue];
  127.                 psz_value = (char *)[o_value fileSystemRepresentation];
  128.     
  129.                 config_PutPsz( p_intf, psz_name, psz_value );
  130.             }
  131.             break;
  132.     
  133.         case CONFIG_ITEM_INTEGER:
  134.         case CONFIG_ITEM_BOOL:
  135.             {
  136.                 int i_value = [o_vlc_config intValue];
  137.     
  138.                 config_PutInt( p_intf, psz_name, i_value );
  139.             }
  140.             break;
  141.     
  142.         case CONFIG_ITEM_FLOAT:
  143.             {
  144.                 float f_value = [o_vlc_config floatValue];
  145.     
  146.                 config_PutFloat( p_intf, psz_name, f_value );
  147.             }
  148.             break;
  149.         case CONFIG_ITEM_KEY:
  150.             {
  151.                 unsigned int i_key = config_GetInt( p_intf, psz_name );
  152.                 unsigned int i_new_key = 0;
  153.                 if( [o_vlc_config class] == [VLCMatrix class] )
  154.                 {
  155.                     int i;
  156.                     NSButtonCell *o_current_cell;
  157.                     NSArray *o_cells = [o_vlc_config cells];
  158.                     i_new_key = (i_key & ~KEY_MODIFIER);
  159.                     for( i = 0; i < [o_cells count]; i++ )
  160.                     {
  161.                         o_current_cell = [o_cells objectAtIndex:i];
  162.                         if( [[o_current_cell title] isEqualToString:_NS("Command")] && 
  163.                             [o_current_cell state] == NSOnState )
  164.                                 i_new_key |= KEY_MODIFIER_COMMAND;
  165.                         if( [[o_current_cell title] isEqualToString:_NS("Control")] && 
  166.                             [o_current_cell state] == NSOnState )
  167.                                 i_new_key |= KEY_MODIFIER_CTRL;
  168.                         if( [[o_current_cell title] isEqualToString:_NS("Option/Alt")] && 
  169.                             [o_current_cell state] == NSOnState )
  170.                                 i_new_key |= KEY_MODIFIER_ALT;
  171.                         if( [[o_current_cell title] isEqualToString:_NS("Shift")] && 
  172.                             [o_current_cell state] == NSOnState )
  173.                                 i_new_key |= KEY_MODIFIER_SHIFT;
  174.                     }
  175.                 }
  176.                 else
  177.                 {
  178.                     i_new_key = (i_key & KEY_MODIFIER);
  179.                     i_new_key |= StringToKey([[o_vlc_config stringValue] cString]);
  180.                 }
  181.                 config_PutInt( p_intf, psz_name, i_new_key );
  182.             }
  183.             break;
  184.         }
  185.     }
  186.     config_SaveConfigFile( p_intf, NULL );
  187.     [o_prefs_window orderOut:self];
  188. }
  189. - (IBAction)closePrefs: (id)sender
  190. {
  191.     [o_prefs_window orderOut:self];
  192. }
  193. - (IBAction)resetAll: (id)sender
  194. {
  195.     NSBeginInformationalAlertSheet(_NS("Reset Preferences"), _NS("Cancel"), _NS("Continue"), 
  196.         nil, o_prefs_window, self, @selector(sheetDidEnd: returnCode: contextInfo:), NULL, nil,
  197.         _NS("Beware this will reset your VLC media player preferences.n"
  198.             "Are you sure you want to continue?") );
  199. }
  200. - (void)sheetDidEnd:(NSWindow *)o_sheet returnCode:(int)i_return contextInfo:(void *)o_context
  201. {
  202.     if( i_return == NSAlertAlternateReturn )
  203.     {
  204.         config_ResetAll( p_intf );
  205.         [self showViewForID: [[o_tree itemAtRow:[o_tree selectedRow]] getObjectID]
  206.             andName: [[o_tree itemAtRow:[o_tree selectedRow]] getName]];
  207.     }
  208. }
  209. - (IBAction)advancedToggle: (id)sender
  210. {
  211.     b_advanced = !b_advanced;
  212.     [o_advanced_ckb setState: b_advanced];
  213.     [self showViewForID: [[o_tree itemAtRow:[o_tree selectedRow]] getObjectID]
  214.         andName: [[o_tree itemAtRow:[o_tree selectedRow]] getName]];
  215. }
  216. - (IBAction)openFileDialog: (id)sender
  217. {
  218.     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
  219.     
  220.     [o_open_panel setTitle: _NS("Select file or directory")];
  221.     [o_open_panel setPrompt: _NS("Select")];
  222.     [o_open_panel setAllowsMultipleSelection: NO];
  223.     [o_open_panel setCanChooseFiles: YES];
  224.     [o_open_panel setCanChooseDirectories: YES];
  225.     [o_open_panel beginSheetForDirectory:nil
  226.         file:nil
  227.         types:nil
  228.         modalForWindow:[sender window]
  229.         modalDelegate: self
  230.         didEndSelector: @selector(pathChosenInPanel: 
  231.                         withReturn:
  232.                         contextInfo:)
  233.         contextInfo: sender];
  234. }
  235. - (void)pathChosenInPanel:(NSOpenPanel *)o_sheet withReturn:(int)i_return_code contextInfo:(void  *)o_context_info
  236. {
  237.     if( i_return_code == NSOKButton )
  238.     {
  239.         NSString *o_path = [[o_sheet filenames] objectAtIndex: 0];
  240.         VLCTextField *o_field = (VLCTextField *)[(VLCButton *)o_context_info tag]; /* FIXME */
  241.         [o_field setStringValue: o_path];
  242.         [self configChanged: o_field];
  243.     }
  244. }
  245. - (void)loadConfigTree
  246. {
  247.     
  248. }
  249. - (void)outlineViewSelectionIsChanging:(NSNotification *)o_notification
  250. {
  251. }
  252. - (void)outlineViewSelectionDidChange:(NSNotification *)o_notification
  253. {
  254.     [self showViewForID: [[o_tree itemAtRow:[o_tree selectedRow]] getObjectID]
  255.         andName: [[o_tree itemAtRow:[o_tree selectedRow]] getName]];
  256. }
  257. - (void)configChanged:(id)o_unknown
  258. {
  259.     id o_vlc_config = [o_unknown isKindOfClass: [NSNotification class]] ?
  260.                       [o_unknown object] : o_unknown;
  261.     NSString *o_name = [o_vlc_config configName];
  262.     [o_save_prefs setObject: o_vlc_config forKey: o_name];
  263. }
  264. - (void)showViewForID: (int)i_id andName: (NSString *)o_item_name
  265. {
  266.     vlc_list_t *p_list;
  267.     module_t *p_parser;
  268.     module_config_t *p_item;
  269.     
  270.     int i_pos, i_module_tag, i_index;
  271.     
  272.     NSString *o_module_name;
  273.     NSRect s_rc;                        /* rect                         */
  274.     NSView *o_view;                     /* view                         */
  275.     NSRect s_vrc;                       /* view rect                    */
  276.     VLCTextField *o_text_field;         /* input field / label          */
  277.     
  278.     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  279.     /* Get a pointer to the module */
  280.     p_parser = (module_t *)vlc_object_get( p_intf, i_id );
  281.     if( p_parser->i_object_type != VLC_OBJECT_MODULE )
  282.     {
  283.         /* 0OOoo something went really bad */
  284.         vlc_list_release( p_list );
  285.         return;
  286.     }
  287.     
  288.     /* Enumerate config options and add corresponding config boxes */
  289.     o_module_name = [NSString stringWithUTF8String: p_parser->psz_object_name];
  290.     p_item = p_parser->p_config;
  291.     i_pos = 0;
  292.     o_view = nil;
  293.     i_module_tag = 3;
  294. #define X_ORIGIN 20
  295. #define Y_ORIGIN (X_ORIGIN - 10)
  296. #define CHECK_VIEW_HEIGHT 
  297.     { 
  298.         float f_new_pos = s_rc.origin.y + s_rc.size.height + X_ORIGIN; 
  299.         if( f_new_pos > s_vrc.size.height ) 
  300.         { 
  301.             s_vrc.size.height = f_new_pos; 
  302.             [o_view setFrame: s_vrc]; 
  303.         } 
  304.     }
  305. #define CONTROL_LABEL( label ) 
  306.     { 
  307.         s_rc.origin.x += s_rc.size.width + 10; 
  308.         s_rc.size.width = s_vrc.size.width - s_rc.origin.x - X_ORIGIN - 20; 
  309.         o_text_field = [[NSTextField alloc] initWithFrame: s_rc]; 
  310.         [o_text_field setDrawsBackground: NO]; 
  311.         [o_text_field setBordered: NO]; 
  312.         [o_text_field setEditable: NO]; 
  313.         [o_text_field setSelectable: NO]; 
  314.         if ( label ) 
  315.         { 
  316.             [o_text_field setStringValue: 
  317.                 [[VLCMain sharedInstance] localizedString: label]]; 
  318.         } 
  319.         [o_text_field sizeToFit]; 
  320.         [o_view addSubview: [o_text_field autorelease]]; 
  321.     }
  322. #define INPUT_FIELD( ctype, cname, label, w, msg, param, tip ) 
  323.     { 
  324.         char * psz_duptip = NULL; 
  325.         if ( p_item->psz_longtext != NULL ) 
  326.             psz_duptip = strdup( p_item->psz_longtext ); 
  327.         s_rc.size.height = 25; 
  328.         s_rc.size.width = w; 
  329.         s_rc.origin.y += 10; 
  330.         CHECK_VIEW_HEIGHT; 
  331.         o_text_field = [[VLCTextField alloc] initWithFrame: s_rc]; 
  332.         [o_text_field setAlignment: NSRightTextAlignment]; 
  333.         CONTROL_CONFIG( o_text_field, o_module_name, ctype, cname ); 
  334.         [o_text_field msg: param]; 
  335.         if ( psz_duptip != NULL ) 
  336.         { 
  337.             [o_text_field setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: 
  338.                                        psz_duptip] toWidth: PREFS_WRAP ]]; 
  339.             free(psz_duptip);
  340.         } 
  341.         [o_view addSubview: [o_text_field autorelease]]; 
  342.         [[NSNotificationCenter defaultCenter] addObserver: self 
  343.             selector: @selector(configChanged:) 
  344.             name: NSControlTextDidChangeNotification 
  345.             object: o_text_field]; 
  346.         CONTROL_LABEL( label ); 
  347.         s_rc.origin.y += s_rc.size.height; 
  348.         s_rc.origin.x = X_ORIGIN; 
  349.     }
  350. #define INPUT_FIELD_INTEGER( name, label, w, param, tip ) 
  351.     INPUT_FIELD( CONFIG_ITEM_INTEGER, name, label, w, setIntValue, param, tip )
  352. #define INPUT_FIELD_FLOAT( name, label, w, param, tip ) 
  353.     INPUT_FIELD( CONFIG_ITEM_FLOAT, name, label, w, setFloatValue, param, tip )
  354. #define INPUT_FIELD_STRING( name, label, w, param, tip ) 
  355.     INPUT_FIELD( CONFIG_ITEM_STRING, name, label, w, setStringValue, param, tip )
  356.     /* Init View */
  357.     s_vrc = [[o_prefs_view contentView] bounds]; s_vrc.size.height -= 4;
  358.     o_view = [[VLCFlippedView alloc] initWithFrame: s_vrc];
  359.     [o_view setAutoresizingMask: NSViewWidthSizable];
  360.     s_rc.origin.x = X_ORIGIN;
  361.     s_rc.origin.y = Y_ORIGIN;
  362.     BOOL b_right_cat = TRUE;
  363.     if( p_item ) do
  364.     {
  365.         if( p_item->i_type == CONFIG_HINT_CATEGORY )
  366.         {
  367.             if( !strcmp( p_parser->psz_object_name, "main" ) &&
  368.                 [o_item_name isEqualToString: [[VLCMain sharedInstance] localizedString: p_item->psz_text]] )
  369.             {
  370.                 b_right_cat = TRUE;
  371.             } else if( strcmp( p_parser->psz_object_name, "main" ) )
  372.             {
  373.                  b_right_cat = TRUE;
  374.             } else b_right_cat = FALSE; 
  375.         } else if( p_item->i_type == CONFIG_HINT_END && !strcmp( p_parser->psz_object_name, "main" ) )
  376.         {
  377.             b_right_cat = FALSE;
  378.         }
  379.         
  380.         if( (p_item->b_advanced && !b_advanced ) || !b_right_cat )
  381.         {
  382.             continue;
  383.         }
  384.         switch( p_item->i_type )
  385.         {
  386.             case CONFIG_ITEM_MODULE:
  387.             {
  388.                 VLCPopUpButton *o_modules;
  389.                 module_t *p_a_module;
  390.                 char * psz_duptip = NULL;
  391.                 if ( p_item->psz_longtext != NULL )
  392.                     psz_duptip = strdup( p_item->psz_longtext );
  393.                 s_rc.size.height = 25;
  394.                 s_rc.size.width = 200;
  395.                 s_rc.origin.y += 10;
  396.                 
  397.                 CHECK_VIEW_HEIGHT;
  398.     
  399.                 o_modules = [[VLCPopUpButton alloc] initWithFrame: s_rc];
  400.                 CONTROL_CONFIG( o_modules, o_module_name,
  401.                                     CONFIG_ITEM_MODULE, p_item->psz_name );
  402.                 [o_modules setTarget: self];
  403.                 [o_modules setAction: @selector(configChanged:)];
  404.                 [o_modules sendActionOn:NSLeftMouseUpMask];
  405.                 
  406.                 if ( psz_duptip != NULL )
  407.                 {
  408.                     [o_modules setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]];
  409.                     free( psz_duptip );
  410.                 }
  411.                 [o_view addSubview: [o_modules autorelease]];
  412.                 [o_modules addItemWithTitle: _NS("Default")];
  413.                 [[o_modules lastItem] setTag: -1];
  414.                 [o_modules selectItem: [o_modules lastItem]];
  415.                 /* build a list of available modules */
  416.                 {
  417.                     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  418.                     {
  419.                         p_a_module = (module_t *)p_list->p_values[i_index].p_object ;
  420.     
  421.                         if( !strcmp( p_a_module->psz_capability,
  422.                                     p_item->psz_type ) )
  423.                         {
  424.                             NSString *o_description = [[VLCMain sharedInstance]
  425.                                 localizedString: p_a_module->psz_longname];
  426.                             [o_modules addItemWithTitle: o_description];
  427.                             [[o_modules lastItem] setTag: p_a_module->i_object_id];
  428.                             if( p_item->psz_value &&
  429.                                 !strcmp( p_item->psz_value, p_a_module->psz_object_name ) )
  430.                             {
  431.                                 [o_modules selectItem:[o_modules lastItem]];
  432.                             }
  433.                         }
  434.                     }
  435.                 }
  436.                 CONTROL_LABEL( p_item->psz_text );
  437.                 s_rc.origin.y += s_rc.size.height;
  438.                 s_rc.origin.x = X_ORIGIN;
  439.             }
  440.             break;
  441.             case CONFIG_ITEM_FILE:
  442.             case CONFIG_ITEM_DIRECTORY:
  443.             {
  444.                 char *psz_duptip = NULL;
  445.                 char *psz_value = p_item->psz_value ?
  446.                                     p_item->psz_value : "";
  447.                 if ( p_item->psz_longtext != NULL )
  448.                     psz_duptip = strdup( p_item->psz_longtext );
  449.                 s_rc.origin.y += 10;
  450.                 s_rc.size.width = - 10;
  451.                 s_rc.size.height = 25;
  452.                 CHECK_VIEW_HEIGHT;
  453.                 CONTROL_LABEL( p_item->psz_text );
  454.                 s_rc.origin.x = X_ORIGIN;
  455.                 s_rc.origin.y += s_rc.size.height;
  456.                 CHECK_VIEW_HEIGHT;
  457.                 VLCButton *button = [[VLCButton alloc] initWithFrame: s_rc];
  458.                 CONTROL_CONFIG( button, o_module_name, CONFIG_ITEM_STRING , p_item->psz_name );
  459.                 [button setButtonType: NSMomentaryPushInButton];
  460.                 [button setBezelStyle: NSRoundedBezelStyle];
  461.                 [button setTitle: _NS("Browse...")];
  462.                 [button sizeToFit];
  463.                 [button setAutoresizingMask:NSViewMinXMargin];
  464.                 [button setFrameOrigin: NSMakePoint( s_vrc.size.width - ( 10 + [button frame].size.width), s_rc.origin.y)];
  465.                 [button setTarget: self];
  466.                 [button setAction: @selector(openFileDialog:)];
  467.                 s_rc.size.height = 25;
  468.                 s_rc.size.width = s_vrc.size.width - ( 35 + [button frame].size.width);
  469.                 
  470.                 o_text_field = [[VLCTextField alloc] initWithFrame: s_rc];
  471.                 CONTROL_CONFIG( o_text_field, o_module_name, CONFIG_ITEM_STRING , p_item->psz_name );
  472.                 [o_text_field setStringValue: [[VLCMain sharedInstance] localizedString: psz_value]];
  473.                 if ( psz_duptip != NULL )
  474.                 {
  475.                     [o_text_field setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString:
  476.                                             psz_duptip] toWidth: PREFS_WRAP ]];
  477.                     free(psz_duptip);
  478.                 }
  479.                 
  480.                 [[NSNotificationCenter defaultCenter] addObserver: self
  481.                     selector: @selector(configChanged:)
  482.                     name: NSControlTextDidChangeNotification
  483.                     object: o_text_field];
  484.                 [o_text_field setAutoresizingMask:NSViewWidthSizable];
  485.                 [button setTag: (int) o_text_field ]; /* FIXME */
  486.                 
  487.                 [o_view addSubview: [o_text_field autorelease]];
  488.                 [o_view addSubview: [button autorelease]];
  489.                 s_rc.origin.y += s_rc.size.height;
  490.                 s_rc.origin.x = X_ORIGIN;
  491.             }
  492.             break;
  493.             
  494.             case CONFIG_ITEM_STRING:            
  495.             {
  496.                 if( !p_item->ppsz_list )
  497.                 {
  498.                     char *psz_value = p_item->psz_value ?
  499.                                     p_item->psz_value : "";
  500.     
  501.                     INPUT_FIELD_STRING( p_item->psz_name, p_item->psz_text, 200,
  502.                                         [[VLCMain sharedInstance] localizedString: psz_value],
  503.                                         p_item->psz_longtext );
  504.                 }
  505.                 else
  506.                 {
  507.                     int i;
  508.                     VLCComboBox *o_combo_box;
  509.                     char * psz_duptip = NULL;
  510.                     if ( p_item->psz_longtext != NULL )
  511.                         psz_duptip = strdup( p_item->psz_longtext );
  512.     
  513.                     s_rc.size.height = 25;
  514.                     s_rc.size.width = 200;
  515.                     s_rc.origin.y += 10;
  516.     
  517.                     CHECK_VIEW_HEIGHT;
  518.     
  519.                     o_combo_box = [[VLCComboBox alloc] initWithFrame: s_rc];
  520.                     CONTROL_CONFIG( o_combo_box, o_module_name,
  521.                                     CONFIG_ITEM_STRING, p_item->psz_name );
  522.                     [o_combo_box setTarget: self];
  523.                     [o_combo_box setAction: @selector(configChanged:)];
  524.                     [o_combo_box sendActionOn:NSLeftMouseUpMask];
  525.                     [[NSNotificationCenter defaultCenter] addObserver: self
  526.                         selector: @selector(configChanged:)
  527.                         name: NSControlTextDidChangeNotification
  528.                         object: o_combo_box];
  529.                     if ( psz_duptip != NULL )
  530.                     {
  531.                         [o_combo_box setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]];
  532.                         free( psz_duptip );
  533.                     }
  534.                     [o_view addSubview: [o_combo_box autorelease]];
  535.                     
  536.                     for( i=0; p_item->ppsz_list[i]; i++ )
  537.                     {
  538.                         [o_combo_box addItemWithObjectValue:
  539.                             [[VLCMain sharedInstance] localizedString: p_item->ppsz_list[i]]];
  540.                     }
  541.                     [o_combo_box setStringValue: [[VLCMain sharedInstance] localizedString: 
  542.                         p_item->psz_value ? p_item->psz_value : ""]];
  543.     
  544.                     CONTROL_LABEL( p_item->psz_text );
  545.     
  546.                     s_rc.origin.y += s_rc.size.height;
  547.                     s_rc.origin.x = X_ORIGIN;
  548.                 }
  549.     
  550.             }
  551.             break;
  552.     
  553.             case CONFIG_ITEM_INTEGER:
  554.             {
  555.                 if( p_item->i_min == p_item->i_max )
  556.                 {
  557.                     INPUT_FIELD_INTEGER( p_item->psz_name, p_item->psz_text, 70,
  558.                         p_item->i_value, p_item->psz_longtext );
  559.                 }
  560.                 else
  561.                 {
  562.                     /*create a slider */
  563.                     VLCSlider *o_slider;
  564.                     char * psz_duptip = NULL;
  565.                     if ( p_item->psz_longtext != NULL )
  566.                         psz_duptip = strdup( p_item->psz_longtext );
  567.         
  568.                     s_rc.size.height = 27;
  569.                     s_rc.size.width = 200;
  570.                     s_rc.origin.y += 10;
  571.         
  572.                     CHECK_VIEW_HEIGHT;
  573.         
  574.                     o_slider = [[VLCSlider alloc] initWithFrame: s_rc];
  575.                     [o_slider setMinValue: p_item->i_min];
  576.                     [o_slider setMaxValue: p_item->i_max];
  577.                     [o_slider setIntValue: p_item->i_value];
  578.                     if ( psz_duptip != NULL )
  579.                     {
  580.                         [o_slider setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]];
  581.                         free( psz_duptip );
  582.                     }
  583.                     [o_slider setTarget: self];
  584.                     [o_slider setAction: @selector(configChanged:)];
  585.                     [o_slider sendActionOn:NSLeftMouseUpMask];
  586.                     CONTROL_CONFIG( o_slider, o_module_name,
  587.                                     CONFIG_ITEM_INTEGER, p_item->psz_name );
  588.                     [o_view addSubview: [o_slider autorelease]];
  589.                     CONTROL_LABEL( p_item->psz_text );
  590.         
  591.                     s_rc.origin.y += s_rc.size.height;
  592.                     s_rc.origin.x = X_ORIGIN;
  593.                 }
  594.             }
  595.             break;
  596.     
  597.             case CONFIG_ITEM_FLOAT:
  598.             {
  599.                 if( p_item->f_min == p_item->f_max )
  600.                 {
  601.                     INPUT_FIELD_FLOAT( p_item->psz_name, p_item->psz_text, 70,
  602.                         p_item->f_value, p_item->psz_longtext );
  603.                 }
  604.                 else
  605.                 {
  606.                     /* create a slider */
  607.                     VLCSlider *o_slider;
  608.                     char * psz_duptip = NULL;
  609.                     if ( p_item->psz_longtext != NULL )
  610.                         psz_duptip = strdup( p_item->psz_longtext );
  611.         
  612.                     s_rc.size.height = 27;
  613.                     s_rc.size.width = 200;
  614.                     s_rc.origin.y += 10;
  615.         
  616.                     CHECK_VIEW_HEIGHT;
  617.         
  618.                     o_slider = [[VLCSlider alloc] initWithFrame: s_rc];
  619.                     [o_slider setMinValue: p_item->f_min];
  620.                     [o_slider setMaxValue: p_item->f_max];
  621.                     [o_slider setFloatValue: p_item->f_value];
  622.                     if ( psz_duptip != NULL )
  623.                     {
  624.                         [o_slider setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]];
  625.                         free( psz_duptip );
  626.                     }
  627.                     [o_slider setTarget: self];
  628.                     [o_slider setAction: @selector(configChanged:)];
  629.                     [o_slider sendActionOn:NSLeftMouseUpMask];
  630.                     CONTROL_CONFIG( o_slider, o_module_name,
  631.                                     CONFIG_ITEM_FLOAT, p_item->psz_name );
  632.                     [o_view addSubview: [o_slider autorelease]];
  633.                     CONTROL_LABEL( p_item->psz_text );
  634.         
  635.                     s_rc.origin.y += s_rc.size.height;
  636.                     s_rc.origin.x = X_ORIGIN;
  637.                 }
  638.             }
  639.             break;
  640.     
  641.             case CONFIG_ITEM_BOOL:
  642.             {
  643.                 VLCButton *o_btn_bool;
  644.                 char * psz_duptip = NULL;
  645.                 if ( p_item->psz_longtext != NULL )
  646.                     psz_duptip = strdup( p_item->psz_longtext );
  647.     
  648.                 s_rc.size.height = 27;
  649.                 s_rc.size.width = s_vrc.size.width - X_ORIGIN * 2 - 20;
  650.                 s_rc.origin.y += 10;
  651.     
  652.                 CHECK_VIEW_HEIGHT;
  653.     
  654.                 o_btn_bool = [[VLCButton alloc] initWithFrame: s_rc];
  655.                 [o_btn_bool setButtonType: NSSwitchButton];
  656.                 [o_btn_bool setIntValue: p_item->i_value];
  657.                 [o_btn_bool setTitle: [[VLCMain sharedInstance] localizedString: p_item->psz_text]];
  658.                 if ( psz_duptip != NULL )
  659.                 {
  660.                     [o_btn_bool setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]];
  661.                     free( psz_duptip );
  662.                 }
  663.                 [o_btn_bool setTarget: self];
  664.                 [o_btn_bool setAction: @selector(configChanged:)];
  665.                 CONTROL_CONFIG( o_btn_bool, o_module_name,
  666.                                 CONFIG_ITEM_BOOL, p_item->psz_name );
  667.                 [o_view addSubview: [o_btn_bool autorelease]];
  668.     
  669.                 s_rc.origin.y += s_rc.size.height;
  670.             }
  671.             break;
  672.             case CONFIG_ITEM_KEY:
  673.             {
  674.                 int i;
  675.                 char *psz_duptip = NULL;
  676.                 VLCComboBox *o_combo_box;
  677.                 if ( p_item->psz_longtext != NULL )
  678.                     psz_duptip = strdup( p_item->psz_longtext );
  679.                 s_rc.origin.y += 10;
  680.                 s_rc.size.width = - 10;
  681.                 s_rc.size.height = 20;
  682.                 CHECK_VIEW_HEIGHT;
  683.                 CONTROL_LABEL( p_item->psz_text );
  684.                 s_rc.origin.x = X_ORIGIN;
  685.                 s_rc.origin.y += s_rc.size.height;
  686.                 s_rc.size.width = s_vrc.size.width - X_ORIGIN * 2;
  687.                 CHECK_VIEW_HEIGHT;
  688.                 VLCMatrix *o_matrix = [[VLCMatrix alloc] initWithFrame: s_rc mode: NSHighlightModeMatrix cellClass: [NSButtonCell class] numberOfRows:2 numberOfColumns:2];
  689.                 NSArray *o_cells = [o_matrix cells];
  690.                 for( i=0; i < [o_cells count]; i++ )
  691.                 {
  692.                     NSButtonCell *o_current_cell = [o_cells objectAtIndex:i];
  693.                     [o_current_cell setButtonType: NSSwitchButton];
  694.                     [o_current_cell setControlSize: NSSmallControlSize];
  695.                     if( psz_duptip != NULL )
  696.                     {
  697.                         [o_matrix setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP] forCell: o_current_cell];
  698.                     }
  699.                     switch( i )
  700.                     {
  701.                         case 0:
  702.                             [o_current_cell setTitle:_NS("Command")];
  703.                             [o_current_cell setState: p_item->i_value & KEY_MODIFIER_COMMAND];
  704.                             break;
  705.                         case 1:
  706.                             [o_current_cell setTitle:_NS("Control")];
  707.                             [o_current_cell setState: p_item->i_value & KEY_MODIFIER_CTRL];
  708.                             break;
  709.                         case 2:
  710.                             [o_current_cell setTitle:_NS("Option/Alt")];
  711.                             [o_current_cell setState: p_item->i_value & KEY_MODIFIER_ALT];
  712.                             break;
  713.                         case 3:
  714.                             [o_current_cell setTitle:_NS("Shift")];
  715.                             [o_current_cell setState: p_item->i_value & KEY_MODIFIER_SHIFT];
  716.                             break;
  717.                     }
  718.                     [o_current_cell setTarget: self];
  719.                     [o_current_cell setAction: @selector(configChanged:)];
  720.                     [o_current_cell sendActionOn:NSLeftMouseUpMask];
  721.                 }
  722.                 CONTROL_CONFIG( o_matrix, o_module_name,
  723.                                 CONFIG_ITEM_KEY, p_item->psz_name );
  724.                 [o_matrix sizeToCells];
  725.                 [o_view addSubview: [o_matrix autorelease]];
  726.                 s_rc.origin.x += [o_matrix frame].size.width + 20;
  727.                 s_rc.size.height = 25;
  728.                 s_rc.size.width = 100;
  729.                 CHECK_VIEW_HEIGHT;
  730.                 o_combo_box = [[VLCComboBox alloc] initWithFrame: s_rc];
  731.                 CONTROL_CONFIG( o_combo_box, o_module_name,
  732.                                 CONFIG_ITEM_KEY, p_item->psz_name );
  733.                 [o_combo_box setTarget: self];
  734.                 [o_combo_box setAction: @selector(configChanged:)];
  735.                 [o_combo_box sendActionOn:NSLeftMouseUpMask];
  736.                 [[NSNotificationCenter defaultCenter] addObserver: self
  737.                         selector: @selector(configChanged:)
  738.                         name: NSControlTextDidChangeNotification
  739.                         object: o_combo_box];
  740.                 if ( psz_duptip != NULL )
  741.                 {
  742.                     [o_combo_box setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]];
  743.                 }
  744.                 [o_view addSubview: [o_combo_box autorelease]];
  745.                 
  746.                 for( i = 0; i < sizeof(vlc_keys) / sizeof(key_descriptor_t); i++ )
  747.                 {
  748.                     
  749.                     if( vlc_keys[i].psz_key_string && *vlc_keys[i].psz_key_string )
  750.                     [o_combo_box addItemWithObjectValue: [[VLCMain sharedInstance] localizedString:vlc_keys[i].psz_key_string]];
  751.                 }
  752.                 
  753.                 [o_combo_box setStringValue: [[VLCMain sharedInstance] localizedString:KeyToString(( ((unsigned int)p_item->i_value) & ~KEY_MODIFIER ))]];
  754.                 
  755.                 s_rc.origin.y += s_rc.size.height;
  756.                 s_rc.origin.x = X_ORIGIN;
  757.                 if( psz_duptip ) free( psz_duptip );
  758.             }
  759.             break;
  760.     
  761.             }
  762.     
  763.     #undef INPUT_FIELD_INTEGER
  764.     #undef INPUT_FIELD_FLOAT
  765.     #undef INPUT_FIELD_STRING
  766.     #undef INPUT_FIELD
  767.     #undef CHECK_VIEW_HEIGHT
  768.     #undef CONTROL_LABEL
  769.     #undef Y_ORIGIN
  770.     #undef X_ORIGIN
  771.         }
  772.         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
  773.         vlc_object_release( p_parser );
  774.         vlc_list_release( p_list );
  775.     
  776.     [o_prefs_view setDocumentView: o_view];
  777.     [o_prefs_view setNeedsDisplay: TRUE];
  778. }
  779. @end
  780. @implementation VLCPrefs (NSTableDataSource)
  781. - (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
  782.     return (item == nil) ? [[VLCTreeItem rootItem] numberOfChildren] : [item numberOfChildren];
  783. }
  784. - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
  785.     return (item == nil) ? YES : ([item numberOfChildren] != -1);
  786. }
  787. - (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item {
  788.     return (item == nil) ? [[VLCTreeItem rootItem] childAtIndex:index] : [item childAtIndex:index];
  789. }
  790. - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
  791.     return (item == nil) ? @"" : (id)[item getName];
  792. }
  793. @end
  794. @implementation VLCTreeItem
  795. static VLCTreeItem *o_root_item = nil;
  796. #define IsALeafNode ((id)-1)
  797. - (id)initWithName: (NSString *)o_item_name ID: (int)i_id parent:(VLCTreeItem *)o_parent_item
  798. {
  799.     self = [super init];
  800.     if( self != nil )
  801.     {
  802.         o_name = [o_item_name copy];
  803.         i_object_id = i_id;
  804.         o_parent = o_parent_item;
  805.     }
  806.     return( self );
  807. }
  808. + (VLCTreeItem *)rootItem {
  809.    if (o_root_item == nil) o_root_item = [[VLCTreeItem alloc] initWithName:@"main" ID: 0 parent:nil];
  810.    return o_root_item;       
  811. }
  812. - (void)dealloc
  813. {
  814.     if (o_children != IsALeafNode) [o_children release];
  815.     [o_name release];
  816.     [super dealloc];
  817. }
  818. /* Creates and returns the array of children
  819.  * Loads children incrementally */
  820. - (NSArray *)children {
  821.     if (o_children == NULL) {
  822.         intf_thread_t *p_intf = VLCIntf;
  823.         vlc_list_t      *p_list;
  824.         module_t        *p_module = NULL;
  825.         module_config_t *p_item;
  826.         int i_index,j;
  827.         /* List the modules */
  828.         p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  829.         if( !p_list ) return nil;
  830.         if( [[self getName] isEqualToString: @"main"] )
  831.         {
  832.             /*
  833.             * Build a tree of the main options
  834.             */
  835.             for( i_index = 0; i_index < p_list->i_count; i_index++ )
  836.             {
  837.                 p_module = (module_t *)p_list->p_values[i_index].p_object;
  838.                 if( !strcmp( p_module->psz_object_name, "main" ) )
  839.                     break;
  840.             }
  841.             if( p_module == NULL )
  842.             {
  843.                 msg_Err( p_intf, "could not find the main module in our preferences" );
  844.                 return nil;
  845.             }
  846.             if( i_index < p_list->i_count )
  847.             {
  848.                 /* We found the main module */
  849.         
  850.                 /* Enumerate config categories and store a reference so we can
  851.                  * generate their config panel them when it is asked by the user. */
  852.                 p_item = p_module->p_config;
  853.                 o_children = [[NSMutableArray alloc] initWithCapacity:10];
  854.                 if( p_item ) do
  855.                 {
  856.                     NSString *o_child_name;
  857.                     
  858.                     switch( p_item->i_type )
  859.                     {
  860.                     case CONFIG_HINT_CATEGORY:
  861.                         o_child_name = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
  862.                         [o_children addObject:[[VLCTreeItem alloc] initWithName: o_child_name
  863.                             ID: p_module->i_object_id parent:self]];
  864.                         break;
  865.                     }
  866.                 }
  867.                 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
  868.                 
  869.                 /* Add the modules item */
  870.                 [o_children addObject:[[VLCTreeItem alloc] initWithName: _NS("Modules")
  871.                     ID: 0 parent:self]];
  872.             }
  873.             else
  874.             {
  875.                 o_children = IsALeafNode;
  876.             }
  877.         }
  878.         else if( [[self getName] isEqualToString: _NS("Modules")] )
  879.         {
  880.             /* Add the capabilities */
  881.             o_children = [[NSMutableArray alloc] initWithCapacity:10];
  882.             for( i_index = 0; i_index < p_list->i_count; i_index++ )
  883.             {
  884.                 p_module = (module_t *)p_list->p_values[i_index].p_object;
  885.         
  886.                 /* Exclude the main module */
  887.                 if( !strcmp( p_module->psz_object_name, "main" ) )
  888.                     continue;
  889.         
  890.                 /* Exclude empty modules */
  891.                 p_item = p_module->p_config;
  892.                 if( !p_item ) continue;
  893.                 do
  894.                 {
  895.                     if( p_item->i_type & CONFIG_ITEM )
  896.                         break;
  897.                 }
  898.                 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
  899.                 if( p_item->i_type == CONFIG_HINT_END ) continue;
  900.         
  901.                 /* Create the capability tree if it doesn't already exist */
  902.                 NSString *o_capability;
  903.                 o_capability = [[VLCMain sharedInstance] localizedString: p_module->psz_capability];
  904.                 if( !p_module->psz_capability || !*p_module->psz_capability )
  905.                 {
  906.                     /* Empty capability ? Let's look at the submodules */
  907.                     module_t * p_submodule;
  908.                     for( j = 0; j < p_module->i_children; j++ )
  909.                     {
  910.                         p_submodule = (module_t*)p_module->pp_children[ j ];
  911.                         if( p_submodule->psz_capability && *p_submodule->psz_capability )
  912.                         {
  913.                             o_capability = [[VLCMain sharedInstance] localizedString: p_submodule->psz_capability];
  914.                             BOOL b_found = FALSE;
  915.                             for( j = 0; j < (int)[o_children count]; j++ )
  916.                             {
  917.                                 if( [[[o_children objectAtIndex:j] getName] isEqualToString: o_capability] )
  918.                                 {
  919.                                     b_found = TRUE;
  920.                                     break;
  921.                                 }
  922.                             }
  923.                             if( !b_found )
  924.                             {
  925.                                 [o_children addObject:[[VLCTreeItem alloc] initWithName: o_capability
  926.                                 ID: 0 parent:self]];
  927.                             }
  928.                         }
  929.                     }
  930.                 }
  931.                 BOOL b_found = FALSE;
  932.                 for( j = 0; j < (int)[o_children count]; j++ )
  933.                 {
  934.                     if( [[[o_children objectAtIndex:j] getName] isEqualToString: o_capability] )
  935.                     {
  936.                         b_found = TRUE;
  937.                         break;
  938.                     }
  939.                 }
  940.                 if( !b_found )
  941.                 {
  942.                     [o_children addObject:[[VLCTreeItem alloc] initWithName: o_capability
  943.                     ID: 0 parent:self]];
  944.                 }
  945.             }
  946.         }
  947.         else if( [[o_parent getName] isEqualToString: _NS("Modules")] )
  948.         {
  949.             /* Now add the modules */
  950.             o_children = [[NSMutableArray alloc] initWithCapacity:10];
  951.             for( i_index = 0; i_index < p_list->i_count; i_index++ )
  952.             {
  953.                 p_module = (module_t *)p_list->p_values[i_index].p_object;
  954.         
  955.                 /* Exclude the main module */
  956.                 if( !strcmp( p_module->psz_object_name, "main" ) )
  957.                     continue;
  958.         
  959.                 /* Exclude empty modules */
  960.                 p_item = p_module->p_config;
  961.                 if( !p_item ) continue;
  962.                 do
  963.                 {
  964.                     if( p_item->i_type & CONFIG_ITEM )
  965.                         break;
  966.                 }
  967.                 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
  968.                 if( p_item->i_type == CONFIG_HINT_END ) continue;
  969.         
  970.                 /* Check the capability */
  971.                 NSString *o_capability;
  972.                 o_capability = [[VLCMain sharedInstance] localizedString: p_module->psz_capability];
  973.                 if( !p_module->psz_capability || !*p_module->psz_capability )
  974.                 {
  975.                     /* Empty capability ? Let's look at the submodules */
  976.                     module_t * p_submodule;
  977.                     for( j = 0; j < p_module->i_children; j++ )
  978.                     {
  979.                         p_submodule = (module_t*)p_module->pp_children[ j ];
  980.                         if( p_submodule->psz_capability && *p_submodule->psz_capability )
  981.                         {
  982.                             o_capability = [[VLCMain sharedInstance] localizedString: p_submodule->psz_capability];
  983.                             if( [o_capability isEqualToString: [self getName]] )
  984.                             {
  985.                             [o_children addObject:[[VLCTreeItem alloc] initWithName:
  986.                                 [[VLCMain sharedInstance] localizedString: p_module->psz_object_name ]
  987.                                 ID: p_module->i_object_id parent:self]];
  988.                             }
  989.                         }
  990.                     }
  991.                 }
  992.                 else if( [o_capability isEqualToString: [self getName]] )
  993.                 {
  994.                     [o_children addObject:[[VLCTreeItem alloc] initWithName:
  995.                         [[VLCMain sharedInstance] localizedString: p_module->psz_object_name ]
  996.                         ID: p_module->i_object_id parent:self]];
  997.                 }
  998.             }
  999.         }
  1000.         else
  1001.         {
  1002.             /* all the other stuff are leafs */
  1003.             o_children = IsALeafNode;
  1004.         }
  1005.         vlc_list_release( p_list );
  1006.     }
  1007.     return o_children;
  1008. }
  1009. - (int)getObjectID
  1010. {
  1011.     return i_object_id;
  1012. }
  1013. - (NSString *)getName
  1014. {
  1015.     return o_name;
  1016. }
  1017. - (VLCTreeItem *)childAtIndex:(int)i_index {
  1018.     return [[self children] objectAtIndex:i_index];
  1019. }
  1020. - (int)numberOfChildren {
  1021.     id i_tmp = [self children];
  1022.     return (i_tmp == IsALeafNode) ? (-1) : (int)[i_tmp count];
  1023. }
  1024. - (BOOL)hasPrefs:(NSString *)o_module_name
  1025. {
  1026.     intf_thread_t *p_intf = VLCIntf;
  1027.     module_t *p_parser;
  1028.     vlc_list_t *p_list;
  1029.     char *psz_module_name;
  1030.     int i_index;
  1031.     psz_module_name = (char *)[o_module_name UTF8String];
  1032.     /* look for module */
  1033.     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
  1034.     for( i_index = 0; i_index < p_list->i_count; i_index++ )
  1035.     {
  1036.         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
  1037.         if( !strcmp( p_parser->psz_object_name, psz_module_name ) )
  1038.         {
  1039.             BOOL b_has_prefs = p_parser->i_config_items != 0;
  1040.             vlc_list_release( p_list );
  1041.             return( b_has_prefs );
  1042.         }
  1043.     }
  1044.     vlc_list_release( p_list );
  1045.     return( NO );
  1046. }
  1047. @end
  1048. @implementation VLCFlippedView
  1049. - (BOOL)isFlipped
  1050. {
  1051.     return( YES );
  1052. }
  1053. @end
  1054. IMPL_CONTROL_CONFIG(Button);
  1055. IMPL_CONTROL_CONFIG(PopUpButton);
  1056. IMPL_CONTROL_CONFIG(ComboBox);
  1057. IMPL_CONTROL_CONFIG(TextField);
  1058. IMPL_CONTROL_CONFIG(Slider);
  1059. IMPL_CONTROL_CONFIG(Matrix);