1 /*****************************************************************************
2 * prefs.m: MacOS X plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2003 VideoLAN
5 * $Id: prefs.m,v 1.34 2003/09/19 23:03:27 hartman Exp $
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Derk-Jan Hartman <thedj at users.sf.net>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
29 #include <sys/param.h> /* for MAXPATHLEN */
35 /*****************************************************************************
36 * VLCPrefs implementation
37 *****************************************************************************/
38 @implementation VLCPrefs
46 o_empty_view = [[NSView alloc] init];
47 o_save_prefs = [[NSMutableDictionary alloc] init];
55 [o_empty_view release];
56 [o_save_prefs release];
62 p_intf = [NSApp getIntf];
63 b_advanced = config_GetInt( p_intf, "advanced" );
66 [o_advanced_ckb setState: b_advanced];
67 [o_prefs_view setBorderType: NSGrooveBorder];
68 [o_prefs_view setHasVerticalScroller: YES];
69 [o_prefs_view setDrawsBackground: NO];
70 [o_prefs_view setRulersVisible: NO];
71 [o_prefs_view setDocumentView: o_empty_view];
72 [o_tree selectRow:0 byExtendingSelection:NO];
77 [o_prefs_window setTitle: _NS("Preferences")];
78 [o_save_btn setTitle: _NS("Save")];
79 [o_cancel_btn setTitle: _NS("Cancel")];
80 [o_reset_btn setTitle: _NS("Reset All")];
81 [o_advanced_ckb setTitle: _NS("Advanced")];
86 [o_save_prefs release];
87 o_save_prefs = [[NSMutableDictionary alloc] init];
88 [self showViewForID: [[o_tree itemAtRow:[o_tree selectedRow]] getObjectID]
89 andName: [[o_tree itemAtRow:[o_tree selectedRow]] getName]];
90 [o_prefs_window center];
91 [o_prefs_window makeKeyAndOrderFront:self];
94 - (IBAction)savePrefs: (id)sender
99 o_enum = [o_save_prefs objectEnumerator];
100 while( ( o_vlc_config = [o_enum nextObject] ) )
102 int i_type = [o_vlc_config configType];
103 NSString *o_name = [o_vlc_config configName];
104 char *psz_name = (char *)[o_name UTF8String];
109 case CONFIG_ITEM_MODULE:
112 module_t *p_a_module;
113 int i_id = [[o_vlc_config selectedItem] tag];
115 p_a_module = (module_t *)vlc_object_get( p_intf, i_id );
116 if( p_a_module == NULL || p_a_module->i_object_type != VLC_OBJECT_MODULE )
121 psz_value = ( i_id == -1 ) ? "" : p_a_module->psz_object_name ;
122 config_PutPsz( p_intf, psz_name, strdup(psz_value) );
126 case CONFIG_ITEM_STRING:
127 case CONFIG_ITEM_FILE:
128 case CONFIG_ITEM_DIRECTORY:
133 o_value = [o_vlc_config stringValue];
134 psz_value = (char *)[o_value UTF8String];
136 config_PutPsz( p_intf, psz_name, psz_value );
140 case CONFIG_ITEM_INTEGER:
141 case CONFIG_ITEM_BOOL:
143 int i_value = [o_vlc_config intValue];
145 config_PutInt( p_intf, psz_name, i_value );
149 case CONFIG_ITEM_FLOAT:
151 float f_value = [o_vlc_config floatValue];
153 config_PutFloat( p_intf, psz_name, f_value );
159 config_SaveConfigFile( p_intf, NULL );
160 [o_prefs_window orderOut:self];
163 - (IBAction)closePrefs: (id)sender
165 [o_prefs_window orderOut:self];
168 - (IBAction)resetAll: (id)sender
170 NSBeginInformationalAlertSheet(_NS("Reset Preferences"), _NS("Cancel"), _NS("Continue"),
171 nil, o_prefs_window, self, @selector(sheetDidEnd: returnCode: contextInfo:), NULL, nil,
172 _NS("Beware this will reset your VLC Media Player config file.\n"
173 "Are you sure you want to continue?") );
176 - (void)sheetDidEnd:(NSWindow *)o_sheet returnCode:(int)i_return contextInfo:(void *)o_context
178 if( i_return == NSAlertAlternateReturn )
180 config_ResetAll( p_intf );
181 [self showViewForID: [[o_tree itemAtRow:[o_tree selectedRow]] getObjectID]
182 andName: [[o_tree itemAtRow:[o_tree selectedRow]] getName]];
186 - (IBAction)advancedToggle: (id)sender
188 b_advanced = !b_advanced;
189 [o_advanced_ckb setState: b_advanced];
190 [self showViewForID: [[o_tree itemAtRow:[o_tree selectedRow]] getObjectID]
191 andName: [[o_tree itemAtRow:[o_tree selectedRow]] getName]];
194 - (IBAction)openFileDialog: (id)sender
196 NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
198 [o_open_panel setTitle: _NS("Select file or directory")];
199 [o_open_panel setPrompt: _NS("Select")];
200 [o_open_panel setAllowsMultipleSelection: NO];
201 [o_open_panel setCanChooseFiles: YES];
202 [o_open_panel setCanChooseDirectories: YES];
203 [o_open_panel beginSheetForDirectory:nil
206 modalForWindow:[sender window]
208 didEndSelector: @selector(pathChosenInPanel:
211 contextInfo: sender];
214 - (void)pathChosenInPanel:(NSOpenPanel *)o_sheet withReturn:(int)i_return_code contextInfo:(void *)o_context_info
216 if( i_return_code == NSOKButton )
218 NSString *o_path = [[o_sheet filenames] objectAtIndex: 0];
219 VLCTextField *o_field = (VLCTextField *)[(VLCButton *)o_context_info tag]; /* FIXME */
220 [o_field setStringValue: o_path];
221 [self configChanged: o_field];
225 - (void)loadConfigTree
230 - (void)outlineViewSelectionIsChanging:(NSNotification *)o_notification
234 - (void)outlineViewSelectionDidChange:(NSNotification *)o_notification
236 [self showViewForID: [[o_tree itemAtRow:[o_tree selectedRow]] getObjectID]
237 andName: [[o_tree itemAtRow:[o_tree selectedRow]] getName]];
240 - (void)configChanged:(id)o_unknown
242 id o_vlc_config = [o_unknown isKindOfClass: [NSNotification class]] ?
243 [o_unknown object] : o_unknown;
245 NSString *o_name = [o_vlc_config configName];
246 [o_save_prefs setObject: o_vlc_config forKey: o_name];
249 - (void)showViewForID: (int)i_id andName: (NSString *)o_item_name
253 module_config_t *p_item;
255 int i_pos, i_module_tag, i_index;
257 NSString *o_module_name;
258 NSRect s_rc; /* rect */
259 NSView *o_view; /* view */
260 NSRect s_vrc; /* view rect */
261 VLCTextField *o_text_field; /* input field / label */
263 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
265 /* Get a pointer to the module */
266 p_parser = (module_t *)vlc_object_get( p_intf, i_id );
267 if( p_parser->i_object_type != VLC_OBJECT_MODULE )
269 /* 0OOoo something went really bad */
273 /* Enumerate config options and add corresponding config boxes */
274 o_module_name = [NSString stringWithUTF8String: p_parser->psz_object_name];
275 p_item = p_parser->p_config;
282 #define Y_ORIGIN (X_ORIGIN - 10)
284 #define CHECK_VIEW_HEIGHT \
286 float f_new_pos = s_rc.origin.y + s_rc.size.height + X_ORIGIN; \
287 if( f_new_pos > s_vrc.size.height ) \
289 s_vrc.size.height = f_new_pos; \
290 [o_view setFrame: s_vrc]; \
294 #define CONTROL_LABEL( label ) \
296 s_rc.origin.x += s_rc.size.width + 10; \
297 s_rc.size.width = s_vrc.size.width - s_rc.origin.x - X_ORIGIN - 20; \
298 o_text_field = [[NSTextField alloc] initWithFrame: s_rc]; \
299 [o_text_field setDrawsBackground: NO]; \
300 [o_text_field setBordered: NO]; \
301 [o_text_field setEditable: NO]; \
302 [o_text_field setSelectable: NO]; \
305 [o_text_field setStringValue: \
306 [NSApp localizedString: label]]; \
308 [o_text_field sizeToFit]; \
309 [o_view addSubview: [o_text_field autorelease]]; \
312 #define INPUT_FIELD( ctype, cname, label, w, msg, param, tip ) \
314 char * psz_duptip = NULL; \
315 if ( p_item->psz_longtext != NULL ) \
316 psz_duptip = strdup( p_item->psz_longtext ); \
317 s_rc.size.height = 25; \
318 s_rc.size.width = w; \
319 s_rc.origin.y += 10; \
321 o_text_field = [[VLCTextField alloc] initWithFrame: s_rc]; \
322 [o_text_field setAlignment: NSRightTextAlignment]; \
323 CONTROL_CONFIG( o_text_field, o_module_name, ctype, cname ); \
324 [o_text_field msg: param]; \
325 if ( psz_duptip != NULL ) \
327 [o_text_field setToolTip: [NSApp wrapString: [NSApp localizedString: \
328 psz_duptip] toWidth: PREFS_WRAP ]]; \
331 [o_view addSubview: [o_text_field autorelease]]; \
332 [[NSNotificationCenter defaultCenter] addObserver: self \
333 selector: @selector(configChanged:) \
334 name: NSControlTextDidChangeNotification \
335 object: o_text_field]; \
336 CONTROL_LABEL( label ); \
337 s_rc.origin.y += s_rc.size.height; \
338 s_rc.origin.x = X_ORIGIN; \
341 #define INPUT_FIELD_INTEGER( name, label, w, param, tip ) \
342 INPUT_FIELD( CONFIG_ITEM_INTEGER, name, label, w, setIntValue, param, tip )
343 #define INPUT_FIELD_FLOAT( name, label, w, param, tip ) \
344 INPUT_FIELD( CONFIG_ITEM_FLOAT, name, label, w, setFloatValue, param, tip )
345 #define INPUT_FIELD_STRING( name, label, w, param, tip ) \
346 INPUT_FIELD( CONFIG_ITEM_STRING, name, label, w, setStringValue, param, tip )
349 s_vrc = [[o_prefs_view contentView] bounds]; s_vrc.size.height -= 4;
350 o_view = [[VLCFlippedView alloc] initWithFrame: s_vrc];
351 [o_view setAutoresizingMask: NSViewWidthSizable];
352 s_rc.origin.x = X_ORIGIN;
353 s_rc.origin.y = Y_ORIGIN;
354 BOOL b_right_cat = FALSE;
358 if( p_item->i_type == CONFIG_HINT_CATEGORY )
360 if( !strcmp( p_parser->psz_object_name, "main" ) &&
361 [o_item_name isEqualToString: [NSApp localizedString: p_item->psz_text]] )
364 } else if( strcmp( p_parser->psz_object_name, "main" ) )
367 } else b_right_cat = FALSE;
368 } else if( p_item->i_type == CONFIG_HINT_END && !strcmp( p_parser->psz_object_name, "main" ) )
373 if( (p_item->b_advanced && !b_advanced ) || !b_right_cat )
377 switch( p_item->i_type )
379 case CONFIG_ITEM_MODULE:
381 VLCPopUpButton *o_modules;
382 module_t *p_a_module;
383 char * psz_duptip = NULL;
385 if ( p_item->psz_longtext != NULL )
386 psz_duptip = strdup( p_item->psz_longtext );
388 s_rc.size.height = 25;
389 s_rc.size.width = 200;
394 o_modules = [[VLCPopUpButton alloc] initWithFrame: s_rc];
395 CONTROL_CONFIG( o_modules, o_module_name,
396 CONFIG_ITEM_MODULE, p_item->psz_name );
397 [o_modules setTarget: self];
398 [o_modules setAction: @selector(configChanged:)];
399 [o_modules sendActionOn:NSLeftMouseUpMask];
401 if ( psz_duptip != NULL )
403 [o_modules setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]];
406 [o_view addSubview: [o_modules autorelease]];
408 [o_modules addItemWithTitle: _NS("Default")];
409 [[o_modules lastItem] setTag: -1];
410 [o_modules selectItem: [o_modules lastItem]];
412 /* build a list of available modules */
414 for( i_index = 0; i_index < p_list->i_count; i_index++ )
416 p_a_module = (module_t *)p_list->p_values[i_index].p_object ;
418 if( !strcmp( p_a_module->psz_capability,
421 NSString *o_description = [NSApp
422 localizedString: p_a_module->psz_longname];
423 [o_modules addItemWithTitle: o_description];
424 [[o_modules lastItem] setTag: p_a_module->i_object_id];
426 if( p_item->psz_value &&
427 !strcmp( p_item->psz_value, p_a_module->psz_object_name ) )
429 [o_modules selectItem:[o_modules lastItem]];
435 CONTROL_LABEL( p_item->psz_text );
436 s_rc.origin.y += s_rc.size.height;
437 s_rc.origin.x = X_ORIGIN;
441 case CONFIG_ITEM_FILE:
442 case CONFIG_ITEM_DIRECTORY:
444 char *psz_duptip = NULL;
445 char *psz_value = p_item->psz_value ?
446 p_item->psz_value : "";
448 if ( p_item->psz_longtext != NULL )
449 psz_duptip = strdup( p_item->psz_longtext );
452 s_rc.size.width = - 10;
453 s_rc.size.height = 25;
455 CONTROL_LABEL( p_item->psz_text );
456 s_rc.origin.x = X_ORIGIN;
457 s_rc.origin.y += s_rc.size.height;
460 VLCButton *button = [[VLCButton alloc] initWithFrame: s_rc];
461 CONTROL_CONFIG( button, o_module_name, CONFIG_ITEM_STRING , p_item->psz_name );
462 [button setButtonType: NSMomentaryPushInButton];
463 [button setBezelStyle: NSRoundedBezelStyle];
464 [button setTitle: _NS("Browse...")];
466 [button setAutoresizingMask:NSViewMinXMargin];
467 [button setFrameOrigin: NSMakePoint( s_vrc.size.width - ( 10 + [button frame].size.width), s_rc.origin.y)];
469 [button setTarget: self];
470 [button setAction: @selector(openFileDialog:)];
472 s_rc.size.height = 25;
473 s_rc.size.width = s_vrc.size.width - ( 35 + [button frame].size.width);
475 o_text_field = [[VLCTextField alloc] initWithFrame: s_rc];
476 CONTROL_CONFIG( o_text_field, o_module_name, CONFIG_ITEM_STRING , p_item->psz_name );
478 [o_text_field setStringValue: [NSApp localizedString: psz_value]];
479 if ( psz_duptip != NULL )
481 [o_text_field setToolTip: [NSApp wrapString: [NSApp localizedString:
482 psz_duptip] toWidth: PREFS_WRAP ]];
486 [[NSNotificationCenter defaultCenter] addObserver: self
487 selector: @selector(configChanged:)
488 name: NSControlTextDidChangeNotification
489 object: o_text_field];
490 [o_text_field setAutoresizingMask:NSViewWidthSizable];
491 [button setTag: (int) o_text_field ]; /* FIXME */
493 [o_view addSubview: [o_text_field autorelease]];
494 [o_view addSubview: [button autorelease]];
495 s_rc.origin.y += s_rc.size.height;
496 s_rc.origin.x = X_ORIGIN;
500 case CONFIG_ITEM_STRING:
502 if( !p_item->ppsz_list )
504 char *psz_value = p_item->psz_value ?
505 p_item->psz_value : "";
507 INPUT_FIELD_STRING( p_item->psz_name, p_item->psz_text, 200,
508 [NSApp localizedString: psz_value],
509 p_item->psz_longtext );
514 VLCComboBox *o_combo_box;
515 char * psz_duptip = NULL;
516 if ( p_item->psz_longtext != NULL )
517 psz_duptip = strdup( p_item->psz_longtext );
519 s_rc.size.height = 27;
520 s_rc.size.width = 200;
525 o_combo_box = [[VLCComboBox alloc] initWithFrame: s_rc];
526 CONTROL_CONFIG( o_combo_box, o_module_name,
527 CONFIG_ITEM_STRING, p_item->psz_name );
528 [o_combo_box setTarget: self];
529 [o_combo_box setAction: @selector(configChanged:)];
530 [o_combo_box sendActionOn:NSLeftMouseUpMask];
532 if ( psz_duptip != NULL )
534 [o_combo_box setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]];
537 [o_view addSubview: [o_combo_box autorelease]];
539 for( i=0; p_item->ppsz_list[i]; i++ )
541 [o_combo_box addItemWithObjectValue:
542 [NSApp localizedString: p_item->ppsz_list[i]]];
544 [o_combo_box setStringValue: [NSApp localizedString:
545 p_item->psz_value ? p_item->psz_value : ""]];
547 CONTROL_LABEL( p_item->psz_text );
549 s_rc.origin.y += s_rc.size.height;
550 s_rc.origin.x = X_ORIGIN;
556 case CONFIG_ITEM_INTEGER:
558 if( p_item->i_min == p_item->i_max )
560 INPUT_FIELD_INTEGER( p_item->psz_name, p_item->psz_text, 70,
561 p_item->i_value, p_item->psz_longtext );
567 char * psz_duptip = NULL;
568 if ( p_item->psz_longtext != NULL )
569 psz_duptip = strdup( p_item->psz_longtext );
571 s_rc.size.height = 27;
572 s_rc.size.width = 200;
577 o_slider = [[VLCSlider alloc] initWithFrame: s_rc];
578 [o_slider setMinValue: p_item->i_min];
579 [o_slider setMaxValue: p_item->i_max];
580 [o_slider setIntValue: p_item->i_value];
582 if ( psz_duptip != NULL )
584 [o_slider setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]];
587 [o_slider setTarget: self];
588 [o_slider setAction: @selector(configChanged:)];
589 [o_slider sendActionOn:NSLeftMouseUpMask];
590 CONTROL_CONFIG( o_slider, o_module_name,
591 CONFIG_ITEM_INTEGER, p_item->psz_name );
592 [o_view addSubview: [o_slider autorelease]];
593 CONTROL_LABEL( p_item->psz_text );
595 s_rc.origin.y += s_rc.size.height;
596 s_rc.origin.x = X_ORIGIN;
601 case CONFIG_ITEM_FLOAT:
603 if( p_item->f_min == p_item->f_max )
605 INPUT_FIELD_FLOAT( p_item->psz_name, p_item->psz_text, 70,
606 p_item->f_value, p_item->psz_longtext );
610 /* create a slider */
612 char * psz_duptip = NULL;
613 if ( p_item->psz_longtext != NULL )
614 psz_duptip = strdup( p_item->psz_longtext );
616 s_rc.size.height = 27;
617 s_rc.size.width = 200;
622 o_slider = [[VLCSlider alloc] initWithFrame: s_rc];
623 [o_slider setMinValue: p_item->f_min];
624 [o_slider setMaxValue: p_item->f_max];
625 [o_slider setFloatValue: p_item->f_value];
627 if ( psz_duptip != NULL )
629 [o_slider setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]];
632 [o_slider setTarget: self];
633 [o_slider setAction: @selector(configChanged:)];
634 [o_slider sendActionOn:NSLeftMouseUpMask];
635 CONTROL_CONFIG( o_slider, o_module_name,
636 CONFIG_ITEM_FLOAT, p_item->psz_name );
637 [o_view addSubview: [o_slider autorelease]];
638 CONTROL_LABEL( p_item->psz_text );
640 s_rc.origin.y += s_rc.size.height;
641 s_rc.origin.x = X_ORIGIN;
646 case CONFIG_ITEM_BOOL:
648 VLCButton *o_btn_bool;
649 char * psz_duptip = NULL;
651 if ( p_item->psz_longtext != NULL )
652 psz_duptip = strdup( p_item->psz_longtext );
654 s_rc.size.height = 27;
655 s_rc.size.width = s_vrc.size.width - X_ORIGIN * 2 - 20;
660 o_btn_bool = [[VLCButton alloc] initWithFrame: s_rc];
661 [o_btn_bool setButtonType: NSSwitchButton];
662 [o_btn_bool setIntValue: p_item->i_value];
663 [o_btn_bool setTitle: [NSApp localizedString: p_item->psz_text]];
664 if ( psz_duptip != NULL )
666 [o_btn_bool setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]];
669 [o_btn_bool setTarget: self];
670 [o_btn_bool setAction: @selector(configChanged:)];
671 CONTROL_CONFIG( o_btn_bool, o_module_name,
672 CONFIG_ITEM_BOOL, p_item->psz_name );
673 [o_view addSubview: [o_btn_bool autorelease]];
675 s_rc.origin.y += s_rc.size.height;
681 #undef INPUT_FIELD_INTEGER
682 #undef INPUT_FIELD_FLOAT
683 #undef INPUT_FIELD_STRING
685 #undef CHECK_VIEW_HEIGHT
690 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
691 vlc_list_release( p_list );
693 [o_prefs_view setDocumentView: o_view];
694 [o_prefs_view setNeedsDisplay: TRUE];
700 @implementation VLCPrefs (NSTableDataSource)
702 - (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
703 return (item == nil) ? [[VLCTreeItem rootItem] numberOfChildren] : [item numberOfChildren];
706 - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
707 return (item == nil) ? YES : ([item numberOfChildren] != -1);
710 - (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item {
711 return (item == nil) ? [[VLCTreeItem rootItem] childAtIndex:index] : [item childAtIndex:index];
714 - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
715 return (item == nil) ? @"" : (id)[item getName];
720 @implementation VLCTreeItem
722 static VLCTreeItem *o_root_item = nil;
724 #define IsALeafNode ((id)-1)
726 - (id)initWithName: (NSString *)o_item_name ID: (int)i_id parent:(VLCTreeItem *)o_parent_item
732 o_name = [o_item_name copy];
734 o_parent = o_parent_item;
739 + (VLCTreeItem *)rootItem {
740 if (o_root_item == nil) o_root_item = [[VLCTreeItem alloc] initWithName:@"main" ID: 0 parent:nil];
746 if (o_children != IsALeafNode) [o_children release];
751 /* Creates and returns the array of children
752 * Loads children incrementally */
753 - (NSArray *)children {
754 if (o_children == NULL) {
755 intf_thread_t *p_intf = [NSApp getIntf];
757 module_t *p_module = NULL;
758 module_config_t *p_item;
761 /* List the plugins */
762 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
763 if( !p_list ) return nil;
765 if( [[self getName] isEqualToString: @"main"] )
768 * Build a tree of the main options
770 for( i_index = 0; i_index < p_list->i_count; i_index++ )
772 p_module = (module_t *)p_list->p_values[i_index].p_object;
773 if( !strcmp( p_module->psz_object_name, "main" ) )
776 if( p_module == NULL )
778 msg_Err( p_intf, "Could not find the main module in our prefs" );
781 if( i_index < p_list->i_count )
783 /* We found the main module */
785 /* Enumerate config categories and store a reference so we can
786 * generate their config panel them when it is asked by the user. */
787 p_item = p_module->p_config;
788 o_children = [[NSMutableArray alloc] initWithCapacity:10];
792 NSString *o_child_name;
794 switch( p_item->i_type )
796 case CONFIG_HINT_CATEGORY:
797 o_child_name = [NSApp localizedString: p_item->psz_text];
798 [o_children addObject:[[VLCTreeItem alloc] initWithName: o_child_name
799 ID: p_module->i_object_id parent:self]];
803 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
805 /* Add the plugins item */
806 [o_children addObject:[[VLCTreeItem alloc] initWithName: _NS("Modules")
811 o_children = IsALeafNode;
814 else if( [[self getName] isEqualToString: _NS("Modules")] )
816 /* Add the capabilities */
817 o_children = [[NSMutableArray alloc] initWithCapacity:10];
818 for( i_index = 0; i_index < p_list->i_count; i_index++ )
820 p_module = (module_t *)p_list->p_values[i_index].p_object;
822 /* Exclude the main module */
823 if( !strcmp( p_module->psz_object_name, "main" ) )
826 /* Exclude empty plugins */
827 p_item = p_module->p_config;
828 if( !p_item ) continue;
831 if( p_item->i_type & CONFIG_ITEM )
834 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
835 if( p_item->i_type == CONFIG_HINT_END ) continue;
837 /* Create the capability tree if it doesn't already exist */
838 NSString *o_capability;
839 o_capability = [NSApp localizedString: p_module->psz_capability];
840 if( !p_module->psz_capability || !*p_module->psz_capability )
842 /* Empty capability ? Let's look at the submodules */
843 module_t * p_submodule;
844 for( j = 0; j < p_module->i_children; j++ )
846 p_submodule = (module_t*)p_module->pp_children[ j ];
847 if( p_submodule->psz_capability && *p_submodule->psz_capability )
849 o_capability = [NSApp localizedString: p_submodule->psz_capability];
850 BOOL b_found = FALSE;
851 for( j = 0; j < (int)[o_children count]; j++ )
853 if( [[[o_children objectAtIndex:j] getName] isEqualToString: o_capability] )
861 [o_children addObject:[[VLCTreeItem alloc] initWithName: o_capability
868 BOOL b_found = FALSE;
869 for( j = 0; j < (int)[o_children count]; j++ )
871 if( [[[o_children objectAtIndex:j] getName] isEqualToString: o_capability] )
879 [o_children addObject:[[VLCTreeItem alloc] initWithName: o_capability
884 else if( [[o_parent getName] isEqualToString: _NS("Modules")] )
886 /* Now add the modules */
887 o_children = [[NSMutableArray alloc] initWithCapacity:10];
888 for( i_index = 0; i_index < p_list->i_count; i_index++ )
890 p_module = (module_t *)p_list->p_values[i_index].p_object;
892 /* Exclude the main module */
893 if( !strcmp( p_module->psz_object_name, "main" ) )
896 /* Exclude empty plugins */
897 p_item = p_module->p_config;
898 if( !p_item ) continue;
901 if( p_item->i_type & CONFIG_ITEM )
904 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
905 if( p_item->i_type == CONFIG_HINT_END ) continue;
907 /* Check the capability */
908 NSString *o_capability;
909 o_capability = [NSApp localizedString: p_module->psz_capability];
910 if( !p_module->psz_capability || !*p_module->psz_capability )
912 /* Empty capability ? Let's look at the submodules */
913 module_t * p_submodule;
914 for( j = 0; j < p_module->i_children; j++ )
916 p_submodule = (module_t*)p_module->pp_children[ j ];
917 if( p_submodule->psz_capability && *p_submodule->psz_capability )
919 o_capability = [NSApp localizedString: p_submodule->psz_capability];
920 if( [o_capability isEqualToString: [self getName]] )
922 [o_children addObject:[[VLCTreeItem alloc] initWithName:
923 [NSApp localizedString: p_module->psz_object_name ]
924 ID: p_module->i_object_id parent:self]];
929 else if( [o_capability isEqualToString: [self getName]] )
931 [o_children addObject:[[VLCTreeItem alloc] initWithName:
932 [NSApp localizedString: p_module->psz_object_name ]
933 ID: p_module->i_object_id parent:self]];
939 /* all the other stuff are leafs */
940 o_children = IsALeafNode;
951 - (NSString *)getName
956 - (VLCTreeItem *)childAtIndex:(int)i_index {
957 return [[self children] objectAtIndex:i_index];
960 - (int)numberOfChildren {
961 id i_tmp = [self children];
962 return (i_tmp == IsALeafNode) ? (-1) : (int)[i_tmp count];
965 - (BOOL)hasPrefs:(NSString *)o_module_name
967 intf_thread_t *p_intf = [NSApp getIntf];
970 char *psz_module_name;
973 psz_module_name = (char *)[o_module_name UTF8String];
975 /* look for module */
976 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
978 for( i_index = 0; i_index < p_list->i_count; i_index++ )
980 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
982 if( !strcmp( p_parser->psz_object_name, psz_module_name ) )
984 BOOL b_has_prefs = p_parser->i_config_items != 0;
985 vlc_list_release( p_list );
986 return( b_has_prefs );
990 vlc_list_release( p_list );
998 @implementation VLCFlippedView
1007 IMPL_CONTROL_CONFIG(Button);
1008 IMPL_CONTROL_CONFIG(PopUpButton);
1009 IMPL_CONTROL_CONFIG(ComboBox);
1010 IMPL_CONTROL_CONFIG(TextField);
1011 IMPL_CONTROL_CONFIG(Slider);