]> git.sesse.net Git - vlc/blob - modules/gui/macosx/prefs_widgets.m
6772ea1611e28903fa5252412a202e394f93552a
[vlc] / modules / gui / macosx / prefs_widgets.m
1 /*****************************************************************************
2  * prefs_widgets.m: Preferences controls
3  *****************************************************************************
4  * Copyright (C) 2002-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Derk-Jan Hartman <hartman at videolan.org>
8  *          Jérôme Decoodt <djc at videolan.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32 #include "vlc_keys.h"
33
34 #include "intf.h"
35 #include "prefs_widgets.h"
36
37 #define PREFS_WRAP 300
38 #define OFFSET_RIGHT 20
39 #define OFFSET_BETWEEN 2
40
41 #define UPWARDS_WHITE_ARROW                 "\xE2\x87\xA7"
42 #define OPTION_KEY                          "\xE2\x8C\xA5"
43 #define UP_ARROWHEAD                        "\xE2\x8C\x83"
44 #define PLACE_OF_INTEREST_SIGN              "\xE2\x8C\x98"
45
46 #define POPULATE_A_KEY( o_menu, string, value )                             \
47 {                                                                           \
48     NSMenuItem *o_mi;                                                       \
49 /*  Normal */                                                               \
50     o_mi = [[NSMenuItem alloc] initWithTitle:string                         \
51         action:nil keyEquivalent:@""];                                      \
52     [o_mi setKeyEquivalentModifierMask:                                     \
53         0];                                                                 \
54     [o_mi setAlternate: NO];                                                \
55     [o_mi setTag:                                                           \
56         ( value )];                                                         \
57     [o_menu addItem: o_mi];                                                 \
58 /*  Ctrl */                                                                 \
59     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
60         [[NSString stringWithUTF8String:                                    \
61             UP_ARROWHEAD                                                    \
62         ] stringByAppendingString: string]                                  \
63         action:nil keyEquivalent:@""];                                      \
64     [o_mi setKeyEquivalentModifierMask:                                     \
65         NSControlKeyMask];                                                  \
66     [o_mi setAlternate: YES];                                               \
67     [o_mi setTag:                                                           \
68         KEY_MODIFIER_CTRL | ( value )];                                     \
69     [o_menu addItem: o_mi];                                                 \
70 /* Ctrl+Alt */                                                              \
71     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
72         [[NSString stringWithUTF8String:                                    \
73             UP_ARROWHEAD OPTION_KEY                                         \
74         ] stringByAppendingString: string]                                  \
75         action:nil keyEquivalent:@""];                                      \
76     [o_mi setKeyEquivalentModifierMask:                                     \
77         NSControlKeyMask | NSAlternateKeyMask];                             \
78     [o_mi setAlternate: YES];                                               \
79     [o_mi setTag:                                                           \
80         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT) | ( value )];                \
81     [o_menu addItem: o_mi];                                                 \
82 /* Ctrl+Shift */                                                            \
83     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
84         [[NSString stringWithUTF8String:                                    \
85             UP_ARROWHEAD UPWARDS_WHITE_ARROW                                \
86         ] stringByAppendingString: string]                                  \
87         action:nil keyEquivalent:@""];                                      \
88     [o_mi setKeyEquivalentModifierMask:                                     \
89        NSControlKeyMask | NSShiftKeyMask];                                  \
90     [o_mi setAlternate: YES];                                               \
91     [o_mi setTag:                                                           \
92         (KEY_MODIFIER_CTRL | KEY_MODIFIER_SHIFT) | ( value )];              \
93     [o_menu addItem: o_mi];                                                 \
94 /* Ctrl+Apple */                                                            \
95     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
96         [[NSString stringWithUTF8String:                                    \
97             UP_ARROWHEAD PLACE_OF_INTEREST_SIGN                             \
98         ] stringByAppendingString: string]                                  \
99         action:nil keyEquivalent:@""];                                      \
100     [o_mi setKeyEquivalentModifierMask:                                     \
101         NSControlKeyMask | NSCommandKeyMask];                               \
102     [o_mi setAlternate: YES];                                               \
103     [o_mi setTag:                                                           \
104         (KEY_MODIFIER_CTRL | KEY_MODIFIER_COMMAND) | ( value )];            \
105     [o_menu addItem: o_mi];                                                 \
106 /* Ctrl+Alt+Shift */                                                        \
107     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
108         [[NSString stringWithUTF8String:                                    \
109             UP_ARROWHEAD OPTION_KEY UPWARDS_WHITE_ARROW                     \
110         ] stringByAppendingString: string]                                  \
111         action:nil keyEquivalent:@""];                                      \
112     [o_mi setKeyEquivalentModifierMask:                                     \
113         NSControlKeyMask | NSAlternateKeyMask | NSShiftKeyMask];            \
114     [o_mi setAlternate: YES];                                               \
115     [o_mi setTag:                                                           \
116         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT) |       \
117              ( value )];                                                    \
118     [o_menu addItem: o_mi];                                                 \
119 /* Ctrl+Alt+Apple */                                                        \
120     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
121         [[NSString stringWithUTF8String:                                    \
122             UP_ARROWHEAD OPTION_KEY PLACE_OF_INTEREST_SIGN                  \
123         ] stringByAppendingString: string]                                  \
124         action:nil keyEquivalent:@""];                                      \
125     [o_mi setKeyEquivalentModifierMask:                                     \
126         NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask];          \
127     [o_mi setAlternate: YES];                                               \
128     [o_mi setTag:                                                           \
129         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_COMMAND) |     \
130             ( value )];                                                     \
131     [o_menu addItem: o_mi];                                                 \
132 /* Ctrl+Shift+Apple */                                                      \
133     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
134         [[NSString stringWithUTF8String:                                    \
135             UP_ARROWHEAD UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN         \
136         ] stringByAppendingString: string]                                  \
137         action:nil keyEquivalent:@""];                                      \
138     [o_mi setKeyEquivalentModifierMask:                                     \
139         NSControlKeyMask | NSShiftKeyMask | NSCommandKeyMask];              \
140     [o_mi setAlternate: YES];                                               \
141     [o_mi setTag:                                                           \
142         (KEY_MODIFIER_CTRL | KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) |   \
143             ( value )];                                                     \
144     [o_menu addItem: o_mi];                                                 \
145 /* Ctrl+Alt+Shift+Apple */                                                  \
146     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
147         [[NSString stringWithUTF8String:                                    \
148             UP_ARROWHEAD OPTION_KEY UPWARDS_WHITE_ARROW                     \
149                 PLACE_OF_INTEREST_SIGN                                      \
150         ] stringByAppendingString: string]                                  \
151         action:nil keyEquivalent:@""];                                      \
152     [o_mi setKeyEquivalentModifierMask:                                     \
153         NSControlKeyMask | NSAlternateKeyMask | NSShiftKeyMask |            \
154             NSCommandKeyMask];                                              \
155     [o_mi setAlternate: YES];                                               \
156     [o_mi setTag:                                                           \
157         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT |        \
158             KEY_MODIFIER_COMMAND) | ( value )];                             \
159     [o_menu addItem: o_mi];                                                 \
160 /* Alt */                                                                   \
161     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
162         [[NSString stringWithUTF8String:                                    \
163             OPTION_KEY                                                      \
164         ] stringByAppendingString: string]                                  \
165         action:nil keyEquivalent:@""];                                      \
166     [o_mi setKeyEquivalentModifierMask:                                     \
167         NSAlternateKeyMask];                                                \
168     [o_mi setAlternate: YES];                                               \
169     [o_mi setTag:                                                           \
170         KEY_MODIFIER_ALT | ( value )];                                      \
171     [o_menu addItem: o_mi];                                                 \
172 /* Alt+Shift */                                                             \
173     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
174         [[NSString stringWithUTF8String:                                    \
175             OPTION_KEY UPWARDS_WHITE_ARROW                                  \
176         ] stringByAppendingString: string]                                  \
177         action:nil keyEquivalent:@""];                                      \
178     [o_mi setKeyEquivalentModifierMask:                                     \
179         NSAlternateKeyMask | NSShiftKeyMask];                               \
180     [o_mi setAlternate: YES];                                               \
181     [o_mi setTag:                                                           \
182         (KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT) | ( value )];               \
183     [o_menu addItem: o_mi];                                                 \
184 /* Alt+Apple */                                                             \
185     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
186         [[NSString stringWithUTF8String:                                    \
187             OPTION_KEY PLACE_OF_INTEREST_SIGN                               \
188         ] stringByAppendingString: string]                                  \
189         action:nil keyEquivalent:@""];                                      \
190     [o_mi setKeyEquivalentModifierMask:                                     \
191         NSAlternateKeyMask | NSCommandKeyMask];                             \
192     [o_mi setAlternate: YES];                                               \
193     [o_mi setTag:                                                           \
194         (KEY_MODIFIER_ALT | KEY_MODIFIER_COMMAND) | ( value )];             \
195     [o_menu addItem: o_mi];                                                 \
196 /* Alt+Shift+Apple */                                                       \
197     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
198         [[NSString stringWithUTF8String:                                    \
199             OPTION_KEY UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN           \
200         ] stringByAppendingString: string]                                  \
201         action:nil keyEquivalent:@""];                                      \
202     [o_mi setKeyEquivalentModifierMask:                                     \
203         NSAlternateKeyMask | NSShiftKeyMask | NSCommandKeyMask];            \
204     [o_mi setAlternate: YES];                                               \
205     [o_mi setTag:                                                           \
206         (KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) |    \
207             ( value )];                                                     \
208     [o_menu addItem: o_mi];                                                 \
209 /* Shift */                                                                 \
210     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
211         [[NSString stringWithUTF8String:                                    \
212             UPWARDS_WHITE_ARROW                                             \
213         ] stringByAppendingString: string]                                  \
214         action:nil keyEquivalent:@""];                                      \
215     [o_mi setKeyEquivalentModifierMask:                                     \
216         NSShiftKeyMask];                                                    \
217     [o_mi setAlternate: YES];                                               \
218     [o_mi setTag:                                                           \
219         KEY_MODIFIER_SHIFT | ( value )];                                    \
220     [o_menu addItem: o_mi];                                                 \
221 /* Shift+Apple */                                                           \
222     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
223         [[NSString stringWithUTF8String:                                    \
224             UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN                      \
225         ] stringByAppendingString: string]                                  \
226         action:nil keyEquivalent:@""];                                      \
227     [o_mi setKeyEquivalentModifierMask:                                     \
228         NSShiftKeyMask | NSCommandKeyMask];                                 \
229     [o_mi setAlternate: YES];                                               \
230     [o_mi setTag:                                                           \
231         (KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) | ( value )];           \
232     [o_menu addItem: o_mi];                                                 \
233 /* Apple */                                                                 \
234     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
235         [[NSString stringWithUTF8String:                                    \
236         PLACE_OF_INTEREST_SIGN                                              \
237         ] stringByAppendingString: string]                                  \
238         action:nil keyEquivalent:@""];                                      \
239     [o_mi setKeyEquivalentModifierMask:                                     \
240         NSCommandKeyMask];                                                  \
241     [o_mi setAlternate: YES];                                               \
242     [o_mi setTag:                                                           \
243         KEY_MODIFIER_COMMAND | ( value )];                                  \
244     [o_menu addItem: o_mi];                                                 \
245 }
246
247 #define ADD_LABEL( o_label, superFrame, x_offset, my_y_offset, label )      \
248 {                                                                           \
249     NSRect s_rc = superFrame;                                               \
250     s_rc.size.height = 17;                                                  \
251     s_rc.origin.x = x_offset - 3;                                           \
252     s_rc.origin.y = superFrame.size.height - 17 + my_y_offset;              \
253     o_label = [[[NSTextField alloc] initWithFrame: s_rc] retain];           \
254     [o_label setDrawsBackground: NO];                                       \
255     [o_label setBordered: NO];                                              \
256     [o_label setEditable: NO];                                              \
257     [o_label setSelectable: NO];                                            \
258     [o_label setStringValue: label];                                        \
259     [o_label setFont:[NSFont systemFontOfSize:0]];                          \
260     [o_label sizeToFit];                                                    \
261 }
262
263 #define ADD_TEXTFIELD( o_textfield, superFrame, x_offset, my_y_offset,      \
264     my_width, tooltip, init_value )                                         \
265 {                                                                           \
266     NSRect s_rc = superFrame;                                               \
267     s_rc.origin.x = x_offset;                                               \
268     s_rc.origin.y = my_y_offset;                                            \
269     s_rc.size.height = 22;                                                  \
270     s_rc.size.width = my_width;                                             \
271     o_textfield = [[[NSTextField alloc] initWithFrame: s_rc] retain];       \
272     [o_textfield setFont:[NSFont systemFontOfSize:0]];                      \
273     [o_textfield setToolTip: tooltip];                                      \
274     [o_textfield setStringValue: init_value];                               \
275 }
276
277 #define ADD_COMBO( o_combo, superFrame, x_offset, my_y_offset, x2_offset,   \
278     tooltip )                                                               \
279 {                                                                           \
280     NSRect s_rc = superFrame;                                               \
281     s_rc.origin.x = x_offset + 2;                                           \
282     s_rc.origin.y = my_y_offset;                                            \
283     s_rc.size.height = 26;                                                  \
284     s_rc.size.width = superFrame.size.width + 2 - s_rc.origin.x -           \
285         (x2_offset);                                                        \
286     o_combo = [[[NSComboBox alloc] initWithFrame: s_rc] retain];            \
287     [o_combo setFont:[NSFont systemFontOfSize:0]];                          \
288     [o_combo setToolTip: tooltip];                                          \
289     [o_combo setUsesDataSource:TRUE];                                       \
290     [o_combo setDataSource:self];                                           \
291     [o_combo setNumberOfVisibleItems:10];                                   \
292     [o_combo setCompletes:YES];                                             \
293 }
294
295 #define ADD_RIGHT_BUTTON( o_button, superFrame, x_offset, my_y_offset,      \
296     tooltip, title )                                                        \
297 {                                                                           \
298     NSRect s_rc = superFrame;                                               \
299     o_button = [[[NSButton alloc] initWithFrame: s_rc] retain];             \
300     [o_button setButtonType: NSMomentaryPushInButton];                      \
301     [o_button setBezelStyle: NSRoundedBezelStyle];                          \
302     [o_button setTitle: title];                                             \
303     [o_button setFont:[NSFont systemFontOfSize:0]];                         \
304     [o_button sizeToFit];                                                   \
305     s_rc = [o_button frame];                                                \
306     s_rc.origin.x = superFrame.size.width - [o_button frame].size.width - 6;\
307     s_rc.origin.y = my_y_offset - 6;                                        \
308     s_rc.size.width += 12;                                                  \
309     [o_button setFrame: s_rc];                                              \
310     [o_button setToolTip: tooltip];                                         \
311     [o_button setTarget: self];                                             \
312     [o_button setAction: @selector(openFileDialog:)];                       \
313 }
314
315 #define ADD_POPUP( o_popup, superFrame, x_offset, my_y_offset, x2_offset,   \
316     tooltip )                                                               \
317 {                                                                           \
318     NSRect s_rc = superFrame;                                               \
319     s_rc.origin.x = x_offset - 1;                                           \
320     s_rc.origin.y = my_y_offset;                                            \
321     s_rc.size.height = 26;                                                  \
322     s_rc.size.width = superFrame.size.width + 2 - s_rc.origin.x -           \
323         (x2_offset);                                                        \
324     o_popup = [[[NSPopUpButton alloc] initWithFrame: s_rc] retain];         \
325     [o_popup setFont:[NSFont systemFontOfSize:0]];                          \
326     [o_popup setToolTip: tooltip];                                          \
327 }
328
329 #define ADD_STEPPER( o_stepper, superFrame, x_offset, my_y_offset, tooltip, \
330     lower, higher )                                                         \
331 {                                                                           \
332     NSRect s_rc = superFrame;                                               \
333     s_rc.origin.x = x_offset;                                               \
334     s_rc.origin.y = my_y_offset;                                            \
335     s_rc.size.height = 23;                                                  \
336     s_rc.size.width = 23;                                                   \
337     o_stepper = [[[NSStepper alloc] initWithFrame: s_rc] retain];           \
338     [o_stepper setFont:[NSFont systemFontOfSize:0]];                        \
339     [o_stepper setToolTip: tooltip];                                        \
340     [o_stepper setMaxValue: higher];                                        \
341     [o_stepper setMinValue: lower];                                         \
342     [o_stepper setTarget: self];                                            \
343     [o_stepper setAction: @selector(stepperChanged:)];                      \
344     [o_stepper sendActionOn:NSLeftMouseUpMask | NSLeftMouseDownMask |       \
345         NSLeftMouseDraggedMask];                                            \
346 }
347
348 #define ADD_SLIDER( o_slider, superFrame, x_offset, my_y_offset, my_width,  \
349     tooltip, lower, higher )                                                \
350 {                                                                           \
351     NSRect s_rc = superFrame;                                               \
352     s_rc.origin.x = x_offset;                                               \
353     s_rc.origin.y = my_y_offset;                                            \
354     s_rc.size.height = 21;                                                  \
355     s_rc.size.width = my_width;                                             \
356     o_slider = [[[NSSlider alloc] initWithFrame: s_rc] retain];             \
357     [o_slider setFont:[NSFont systemFontOfSize:0]];                         \
358     [o_slider setToolTip: tooltip];                                         \
359     [o_slider setMaxValue: higher];                                         \
360     [o_slider setMinValue: lower];                                          \
361 }
362
363 #define ADD_CHECKBOX( o_checkbox, superFrame, x_offset, my_y_offset, label, \
364     tooltip, init_value, position )                                         \
365 {                                                                           \
366     NSRect s_rc = superFrame;                                               \
367     s_rc.size.height = 18;                                                  \
368     s_rc.origin.x = x_offset - 2;                                           \
369     s_rc.origin.y = superFrame.size.height - 18 + my_y_offset;              \
370     o_checkbox = [[[NSButton alloc] initWithFrame: s_rc] retain];           \
371     [o_checkbox setFont:[NSFont systemFontOfSize:0]];                       \
372     [o_checkbox setButtonType: NSSwitchButton];                             \
373     [o_checkbox setImagePosition: position];                                \
374     [o_checkbox setIntValue: init_value];                                   \
375     [o_checkbox setTitle: label];                                           \
376     [o_checkbox setToolTip: tooltip];                                       \
377     [o_checkbox sizeToFit];                                                 \
378 }
379
380 @implementation VLCConfigControl
381 - (id)initWithFrame: (NSRect)frame
382 {
383     return [self initWithFrame: frame
384                     item: nil];
385 }
386
387 - (id)initWithFrame: (NSRect)frame
388         item: (module_config_t *)_p_item
389 {
390     self = [super initWithFrame: frame];
391
392     if( self != nil )
393     {
394         p_item = _p_item;
395         psz_name = p_item->psz_name;
396         o_label = NULL;
397         i_type = p_item->i_type;
398         i_view_type = 0;
399         b_advanced = p_item->b_advanced;
400         [self setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin ];
401     }
402     return (self);
403 }
404
405 - (void)setYPos:(int)i_yPos
406 {
407     NSRect frame = [self frame];
408     frame.origin.y = i_yPos;
409     [self setFrame:frame];
410 }
411
412 - (void)dealloc
413 {
414     if( o_label ) [o_label release];
415     if( psz_name ) free( psz_name );
416     [super dealloc];
417 }
418
419 + (int)calcVerticalMargin: (int)i_curItem lastItem: (int)i_lastItem
420 {
421     int i_margin;
422     switch( i_curItem )
423     {
424     case CONFIG_ITEM_STRING:
425         switch( i_lastItem )
426         {
427         case CONFIG_ITEM_STRING:
428             i_margin = 8;
429             break;
430         case CONFIG_ITEM_STRING_LIST:
431             i_margin = 7;
432             break;
433         case CONFIG_ITEM_FILE:
434             i_margin = 8;
435             break;
436         case CONFIG_ITEM_MODULE:
437             i_margin = 4;
438             break;
439         case CONFIG_ITEM_INTEGER:
440             i_margin = 7;
441             break;
442         case CONFIG_ITEM_RANGED_INTEGER:
443             i_margin = 5;
444             break;
445         case CONFIG_ITEM_BOOL:
446             i_margin = 7;
447             break;
448         case CONFIG_ITEM_KEY_BEFORE_10_3:
449             i_margin = 7;
450             break;
451         case CONFIG_ITEM_KEY_AFTER_10_3:
452             i_margin = 6;
453             break;
454         case CONFIG_ITEM_MODULE_LIST:
455             i_margin = 8;
456             break;
457         default:
458             i_margin = 20;
459             break;
460         }
461         break;
462     case CONFIG_ITEM_STRING_LIST:
463         switch( i_lastItem )
464         {
465         case CONFIG_ITEM_STRING:
466             i_margin = 8;
467             break;
468         case CONFIG_ITEM_STRING_LIST:
469             i_margin = 7;
470             break;
471         case CONFIG_ITEM_FILE:
472             i_margin = 6;
473             break;
474         case CONFIG_ITEM_MODULE:
475             i_margin = 4;
476             break;
477         case CONFIG_ITEM_INTEGER:
478             i_margin = 7;
479             break;
480         case CONFIG_ITEM_RANGED_INTEGER:
481             i_margin = 5;
482             break;
483         case CONFIG_ITEM_BOOL:
484             i_margin = 7;
485             break;
486         case CONFIG_ITEM_KEY_BEFORE_10_3:
487             i_margin = 7;
488             break;
489         case CONFIG_ITEM_KEY_AFTER_10_3:
490             i_margin = 6;
491             break;
492         case CONFIG_ITEM_MODULE_LIST:
493             i_margin = 8;
494             break;
495         default:
496             i_margin = 20;
497             break;
498         }
499         break;
500     case CONFIG_ITEM_FILE:
501         switch( i_lastItem )
502         {
503         case CONFIG_ITEM_STRING:
504             i_margin = 13;
505             break;
506         case CONFIG_ITEM_STRING_LIST:
507             i_margin = 10;
508             break;
509         case CONFIG_ITEM_FILE:
510             i_margin = 9;
511             break;
512         case CONFIG_ITEM_MODULE:
513             i_margin = 9;
514             break;
515         case CONFIG_ITEM_INTEGER:
516             i_margin = 10;
517             break;
518         case CONFIG_ITEM_RANGED_INTEGER:
519             i_margin = 8;
520             break;
521         case CONFIG_ITEM_BOOL:
522             i_margin = 10;
523             break;
524         case CONFIG_ITEM_KEY_BEFORE_10_3:
525             i_margin = 10;
526             break;
527         case CONFIG_ITEM_KEY_AFTER_10_3:
528             i_margin = 9;
529             break;
530         case CONFIG_ITEM_MODULE_LIST:
531             i_margin = 11;
532             break;
533         default:
534             i_margin = 23;
535             break;
536         }
537         break;
538     case CONFIG_ITEM_MODULE:
539         switch( i_lastItem )
540         {
541         case CONFIG_ITEM_STRING:
542             i_margin = 8;
543             break;
544         case CONFIG_ITEM_STRING_LIST:
545             i_margin = 7;
546             break;
547         case CONFIG_ITEM_FILE:
548             i_margin = 6;
549             break;
550         case CONFIG_ITEM_MODULE:
551             i_margin = 5;
552             break;
553         case CONFIG_ITEM_INTEGER:
554             i_margin = 7;
555             break;
556         case CONFIG_ITEM_RANGED_INTEGER:
557             i_margin = 6;
558             break;
559         case CONFIG_ITEM_BOOL:
560             i_margin = 8;
561             break;
562         case CONFIG_ITEM_KEY_BEFORE_10_3:
563             i_margin = 8;
564             break;
565         case CONFIG_ITEM_KEY_AFTER_10_3:
566             i_margin = 7;
567             break;
568         case CONFIG_ITEM_MODULE_LIST:
569             i_margin = 9;
570             break;
571         default:
572             i_margin = 20;
573             break;
574         }
575         break;
576     case CONFIG_ITEM_INTEGER:
577         switch( i_lastItem )
578         {
579         case CONFIG_ITEM_STRING:
580             i_margin = 8;
581             break;
582         case CONFIG_ITEM_STRING_LIST:
583             i_margin = 7;
584             break;
585         case CONFIG_ITEM_FILE:
586             i_margin = 6;
587             break;
588         case CONFIG_ITEM_MODULE:
589             i_margin = 4;
590             break;
591         case CONFIG_ITEM_INTEGER:
592             i_margin = 7;
593             break;
594         case CONFIG_ITEM_RANGED_INTEGER:
595             i_margin = 5;
596             break;
597         case CONFIG_ITEM_BOOL:
598             i_margin = 7;
599             break;
600         case CONFIG_ITEM_KEY_BEFORE_10_3:
601             i_margin = 7;
602             break;
603         case CONFIG_ITEM_KEY_AFTER_10_3:
604             i_margin = 6;
605             break;
606         case CONFIG_ITEM_MODULE_LIST:
607             i_margin = 8;
608             break;
609         default:
610             i_margin = 20;
611             break;
612         }
613         break;
614     case CONFIG_ITEM_RANGED_INTEGER:
615         switch( i_lastItem )
616         {
617         case CONFIG_ITEM_STRING:
618             i_margin = 8;
619             break;
620         case CONFIG_ITEM_STRING_LIST:
621             i_margin = 7;
622             break;
623         case CONFIG_ITEM_FILE:
624             i_margin = 8;
625             break;
626         case CONFIG_ITEM_MODULE:
627             i_margin = 4;
628             break;
629         case CONFIG_ITEM_INTEGER:
630             i_margin = 7;
631             break;
632         case CONFIG_ITEM_RANGED_INTEGER:
633             i_margin = 5;
634             break;
635         case CONFIG_ITEM_BOOL:
636             i_margin = 7;
637             break;
638         case CONFIG_ITEM_KEY_BEFORE_10_3:
639             i_margin = 7;
640             break;
641         case CONFIG_ITEM_KEY_AFTER_10_3:
642             i_margin = 6;
643             break;
644         case CONFIG_ITEM_MODULE_LIST:
645             i_margin = 8;
646             break;
647         default:
648             i_margin = 20;
649             break;
650         }
651         break;
652     case CONFIG_ITEM_BOOL:
653         switch( i_lastItem )
654         {
655         case CONFIG_ITEM_STRING:
656             i_margin = 10;
657             break;
658         case CONFIG_ITEM_STRING_LIST:
659             i_margin = 9;
660             break;
661         case CONFIG_ITEM_FILE:
662             i_margin = 8;
663             break;
664         case CONFIG_ITEM_MODULE:
665             i_margin = 6;
666             break;
667         case CONFIG_ITEM_INTEGER:
668             i_margin = 9;
669             break;
670         case CONFIG_ITEM_RANGED_INTEGER:
671             i_margin = 7;
672             break;
673         case CONFIG_ITEM_BOOL:
674             i_margin = 7;
675             break;
676         case CONFIG_ITEM_KEY_BEFORE_10_3:
677             i_margin = 7;
678             break;
679         case CONFIG_ITEM_KEY_AFTER_10_3:
680             i_margin = 5;
681             break;
682         case CONFIG_ITEM_MODULE_LIST:
683             i_margin = 10;
684             break;
685         default:
686             i_margin = 20;
687             break;
688         }
689         break;
690     case CONFIG_ITEM_KEY_BEFORE_10_3:
691         switch( i_lastItem )
692         {
693         case CONFIG_ITEM_STRING:
694             i_margin = 6;
695             break;
696         case CONFIG_ITEM_STRING_LIST:
697             i_margin = 5;
698             break;
699         case CONFIG_ITEM_FILE:
700             i_margin = 4;
701             break;
702         case CONFIG_ITEM_MODULE:
703             i_margin = 2;
704             break;
705         case CONFIG_ITEM_INTEGER:
706             i_margin = 5;
707             break;
708         case CONFIG_ITEM_RANGED_INTEGER:
709             i_margin = 3;
710             break;
711         case CONFIG_ITEM_BOOL:
712             i_margin = 3;
713             break;
714         case CONFIG_ITEM_KEY_BEFORE_10_3:
715             i_margin = 10;
716             break;
717         case CONFIG_ITEM_KEY_AFTER_10_3:
718             i_margin = 6;
719             break;
720         case CONFIG_ITEM_MODULE_LIST:
721             i_margin = 6;
722             break;
723         default:
724             i_margin = 18;
725             break;
726         }
727         break;
728     case CONFIG_ITEM_KEY_AFTER_10_3:
729         switch( i_lastItem )
730         {
731         case CONFIG_ITEM_STRING:
732             i_margin = 8;
733             break;
734         case CONFIG_ITEM_STRING_LIST:
735             i_margin = 7;
736             break;
737         case CONFIG_ITEM_FILE:
738             i_margin = 6;
739             break;
740         case CONFIG_ITEM_MODULE:
741             i_margin = 6;
742             break;
743         case CONFIG_ITEM_INTEGER:
744             i_margin = 7;
745             break;
746         case CONFIG_ITEM_RANGED_INTEGER:
747             i_margin = 5;
748             break;
749         case CONFIG_ITEM_BOOL:
750             i_margin = 7;
751             break;
752         case CONFIG_ITEM_KEY_BEFORE_10_3:
753             i_margin = 7;
754             break;
755         case CONFIG_ITEM_KEY_AFTER_10_3:
756             i_margin = 8;
757             break;
758         case CONFIG_ITEM_MODULE_LIST:
759             i_margin = 10;
760             break;
761         default:
762             i_margin = 20;
763             break;
764         }
765         break;
766     case CONFIG_ITEM_MODULE_LIST:
767         switch( i_lastItem )
768         {
769         case CONFIG_ITEM_STRING:
770             i_margin = 10;
771             break;
772         case CONFIG_ITEM_STRING_LIST:
773             i_margin = 7;
774             break;
775         case CONFIG_ITEM_FILE:
776             i_margin = 6;
777             break;
778         case CONFIG_ITEM_MODULE:
779             i_margin = 6;
780             break;
781         case CONFIG_ITEM_INTEGER:
782             i_margin = 9;
783             break;
784         case CONFIG_ITEM_RANGED_INTEGER:
785             i_margin = 5;
786             break;
787         case CONFIG_ITEM_BOOL:
788             i_margin = 7;
789             break;
790         case CONFIG_ITEM_KEY_BEFORE_10_3:
791             i_margin = 7;
792             break;
793         case CONFIG_ITEM_KEY_AFTER_10_3:
794             i_margin = 5;
795             break;
796         case CONFIG_ITEM_MODULE_LIST:
797             i_margin = 8;
798             break;
799         default:
800             i_margin = 20;
801             break;
802         }
803         break;
804     default:
805         i_margin = 20;
806         break;
807     }
808     return i_margin;
809 }
810
811 + (VLCConfigControl *)newControl: (module_config_t *)_p_item
812                       withView: (NSView *)o_parent_view
813 {
814     VLCConfigControl *p_control = NULL;
815
816     switch( _p_item->i_type )
817     {
818     case CONFIG_ITEM_STRING:
819         if( !_p_item->i_list )
820         {
821             p_control = [[StringConfigControl alloc]
822                     initWithItem: _p_item
823                     withView: o_parent_view];
824         }
825         else
826         {
827             p_control = [[StringListConfigControl alloc]
828                     initWithItem: _p_item
829                     withView: o_parent_view];
830         }
831         break;
832     case CONFIG_ITEM_FILE:
833     case CONFIG_ITEM_DIRECTORY:
834         p_control = [[FileConfigControl alloc]
835                     initWithItem: _p_item
836                     withView: o_parent_view];
837         break;
838     case CONFIG_ITEM_MODULE:
839     case CONFIG_ITEM_MODULE_CAT:
840         p_control = [[ModuleConfigControl alloc]
841                     initWithItem: _p_item
842                     withView: o_parent_view];
843         break;
844     case CONFIG_ITEM_INTEGER:
845         if( _p_item->i_list )
846         {
847             p_control = [[IntegerListConfigControl alloc]
848                         initWithItem: _p_item
849                         withView: o_parent_view];
850         }
851         else if( _p_item->min.i != 0 || _p_item->max.i != 0 )
852         {
853             p_control = [[RangedIntegerConfigControl alloc]
854                         initWithItem: _p_item
855                         withView: o_parent_view];
856         }
857         else
858         {
859             p_control = [[IntegerConfigControl alloc]
860                         initWithItem: _p_item
861                         withView: o_parent_view];
862         }
863         break;
864     case CONFIG_ITEM_BOOL:
865         p_control = [[BoolConfigControl alloc]
866                     initWithItem: _p_item
867                     withView: o_parent_view];
868         break;
869     case CONFIG_ITEM_FLOAT:
870         if( _p_item->min.f != 0 || _p_item->max.f != 0 )
871         {
872             p_control = [[RangedFloatConfigControl alloc]
873                         initWithItem: _p_item
874                         withView: o_parent_view];
875         }
876         else
877         {
878             p_control = [[FloatConfigControl alloc]
879                         initWithItem: _p_item
880                         withView: o_parent_view];
881         }
882         break;
883     case CONFIG_ITEM_KEY:
884         p_control = [[KeyConfigControl alloc]
885                         initWithItem: _p_item
886                         withView: o_parent_view];
887         break;
888     case CONFIG_ITEM_MODULE_LIST:
889     case CONFIG_ITEM_MODULE_LIST_CAT:
890         p_control = [[ModuleListConfigControl alloc]
891                     initWithItem: _p_item
892                     withView: o_parent_view];
893         break;
894     default:
895         break;
896     }
897     return p_control;
898 }
899
900 - (NSString *)getName
901 {
902     return [[VLCMain sharedInstance] localizedString: psz_name];
903 }
904
905 - (int)getType
906 {
907     return i_type;
908 }
909
910 - (int)getViewType
911 {
912     return i_view_type;
913 }
914
915 - (BOOL)isAdvanced
916 {
917     return b_advanced;
918 }
919
920 - (int)intValue
921 {
922     return 0;
923 }
924
925 - (float)floatValue
926 {
927     return 0;
928 }
929
930 - (char *)stringValue
931 {
932     return NULL;
933 }
934
935 - (void)applyChanges
936 {
937     vlc_value_t val;
938     switch( p_item->i_type )
939     {
940     case CONFIG_ITEM_STRING:
941     case CONFIG_ITEM_FILE:
942     case CONFIG_ITEM_DIRECTORY:
943     case CONFIG_ITEM_MODULE:
944     case CONFIG_ITEM_MODULE_LIST:
945     case CONFIG_ITEM_MODULE_LIST_CAT:
946         config_PutPsz( VLCIntf, psz_name, [self stringValue] );
947         break;
948     case CONFIG_ITEM_KEY:
949         /* So you don't need to restart to have the changes take effect */
950         val.i_int = [self intValue];
951         var_Set( VLCIntf->p_libvlc, psz_name, val );
952     case CONFIG_ITEM_INTEGER:
953     case CONFIG_ITEM_BOOL:
954         config_PutInt( VLCIntf, psz_name, [self intValue] );
955         break;
956     case CONFIG_ITEM_FLOAT:
957         config_PutFloat( VLCIntf, psz_name, [self floatValue] );
958         break;
959     }
960 }
961
962 - (int)getLabelSize
963 {
964     return [o_label frame].size.width;
965 }
966
967 - (void) alignWithXPosition:(int)i_xPos;
968 {
969     /* FIXME: not implemented atm, but created to shut up the warning
970      * about "method definition not found" -- FK @ 7/24/05 */
971 }
972 @end
973
974 @implementation StringConfigControl
975 - (id) initWithItem: (module_config_t *)_p_item
976            withView: (NSView *)o_parent_view
977 {
978     NSRect mainFrame = [o_parent_view frame];
979     NSString *o_labelString, *o_textfieldString, *o_textfieldTooltip;
980     mainFrame.size.height = 22;
981     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
982     mainFrame.origin.x = LEFTMARGIN;
983     mainFrame.origin.y = 0;
984
985     if( [super initWithFrame: mainFrame item: _p_item] != nil )
986     {
987         i_view_type = CONFIG_ITEM_STRING;
988         /* add the label */
989         if( p_item->psz_text )
990             o_labelString = [[VLCMain sharedInstance]
991                                 localizedString: (char *)p_item->psz_text];
992         else
993             o_labelString = [NSString stringWithString:@""];
994         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
995         [o_label setAutoresizingMask:NSViewNotSizable ];
996         [self addSubview: o_label];
997
998         /* build the textfield */
999         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1000             [[VLCMain sharedInstance] localizedString: (char *)p_item->psz_longtext]
1001                                          toWidth: PREFS_WRAP];
1002         if( p_item->value.psz )
1003             o_textfieldString = [[VLCMain sharedInstance]
1004                                     localizedString: (char *)p_item->value.psz];
1005         else
1006             o_textfieldString = [NSString stringWithString: @""];
1007         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1008                         0, mainFrame.size.width - [o_label frame].size.width -
1009                         2, o_textfieldTooltip, o_textfieldString )
1010         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
1011         [self addSubview: o_textfield];
1012     }
1013     return self;
1014 }
1015
1016 - (void) alignWithXPosition:(int)i_xPos
1017 {
1018     NSRect frame;
1019     NSRect superFrame = [self frame];
1020     frame = [o_label frame];
1021     frame.origin.x = i_xPos - frame.size.width - 3;
1022     [o_label setFrame:frame];
1023
1024     frame = [o_textfield frame];
1025     frame.origin.x = i_xPos + 2;
1026     frame.size.width = superFrame.size.width - frame.origin.x - 1;
1027     [o_textfield setFrame:frame];
1028 }
1029
1030 - (void)dealloc
1031 {
1032     [o_textfield release];
1033     [super dealloc];
1034 }
1035
1036 - (char *)stringValue
1037 {
1038     return strdup( [[VLCMain sharedInstance] delocalizeString:
1039                         [o_textfield stringValue]] );
1040 }
1041 @end
1042
1043 @implementation StringListConfigControl
1044 - (id) initWithItem: (module_config_t *)_p_item
1045            withView: (NSView *)o_parent_view
1046 {
1047     NSRect mainFrame = [o_parent_view frame];
1048     NSString *o_labelString, *o_textfieldTooltip;
1049     mainFrame.size.height = 22;
1050     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1051     mainFrame.origin.x = LEFTMARGIN;
1052     mainFrame.origin.y = 0;
1053
1054     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1055     {
1056         int i_index;
1057         i_view_type = CONFIG_ITEM_STRING_LIST;
1058         /* add the label */
1059         if( p_item->psz_text )
1060             o_labelString = [[VLCMain sharedInstance]
1061                                 localizedString: (char *)p_item->psz_text];
1062         else
1063             o_labelString = [NSString stringWithString:@""];
1064         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1065         [o_label setAutoresizingMask:NSViewNotSizable ];
1066         [self addSubview: o_label];
1067
1068         /* build the textfield */
1069         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1070             [[VLCMain sharedInstance]
1071                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1072         ADD_COMBO( o_combo, mainFrame, [o_label frame].size.width,
1073             -2, 0, o_textfieldTooltip )
1074         [o_combo setAutoresizingMask:NSViewWidthSizable ];
1075         for( i_index = 0; i_index < p_item->i_list; i_index++ )
1076             if( p_item->value.psz &&
1077                 !strcmp( p_item->value.psz, p_item->ppsz_list[i_index] ) )
1078                 [o_combo selectItemAtIndex: i_index];
1079         [self addSubview: o_combo];
1080     }
1081     return self;
1082 }
1083
1084 - (void) alignWithXPosition:(int)i_xPos
1085 {
1086     NSRect frame;
1087     NSRect superFrame = [self frame];
1088     frame = [o_label frame];
1089     frame.origin.x = i_xPos - frame.size.width - 3;
1090     [o_label setFrame:frame];
1091
1092     frame = [o_combo frame];
1093     frame.origin.x = i_xPos + 2;
1094     frame.size.width = superFrame.size.width - frame.origin.x + 2;
1095     [o_combo setFrame:frame];
1096 }
1097
1098 - (void)dealloc
1099 {
1100     [o_combo release];
1101     [super dealloc];
1102 }
1103
1104 - (char *)stringValue
1105 {
1106     if( [o_combo indexOfSelectedItem] >= 0 )
1107         return strdup( p_item->ppsz_list[[o_combo indexOfSelectedItem]] );
1108     else
1109         return strdup( [[VLCMain sharedInstance]
1110                             delocalizeString: [o_combo stringValue]] );
1111 }
1112 @end
1113
1114 @implementation StringListConfigControl (NSComboBoxDataSource)
1115 - (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox
1116 {
1117         return p_item->i_list;
1118 }
1119
1120 - (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)i_index
1121 {
1122     if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
1123     {
1124         return [[VLCMain sharedInstance]
1125                     localizedString: (char *)p_item->ppsz_list_text[i_index]];
1126     } else return [[VLCMain sharedInstance]
1127                     localizedString: (char *)p_item->ppsz_list[i_index]];
1128 }
1129 @end
1130
1131 @implementation FileConfigControl
1132 - (id) initWithItem: (module_config_t *)_p_item
1133            withView: (NSView *)o_parent_view
1134 {
1135     NSRect mainFrame = [o_parent_view frame];
1136     NSString *o_labelString, *o_buttonTooltip, *o_textfieldString;
1137     NSString *o_textfieldTooltip;
1138     mainFrame.size.height = 46;
1139     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1140     mainFrame.origin.x = LEFTMARGIN;
1141     mainFrame.origin.y = 0;
1142
1143     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1144     {
1145         i_view_type = CONFIG_ITEM_FILE;
1146
1147         /* is it a directory */
1148         b_directory = ( [self getType] == CONFIG_ITEM_DIRECTORY ) ? YES : NO;
1149
1150         /* add the label */
1151         if( p_item->psz_text )
1152             o_labelString = [[VLCMain sharedInstance]
1153                                 localizedString: (char *)p_item->psz_text];
1154         else
1155             o_labelString = [NSString stringWithString:@""];
1156         ADD_LABEL( o_label, mainFrame, 0, 3, o_labelString )
1157         [o_label setAutoresizingMask:NSViewNotSizable ];
1158         [self addSubview: o_label];
1159
1160         /* build the button */
1161         o_buttonTooltip = [[VLCMain sharedInstance]
1162                 wrapString: [[VLCMain sharedInstance]
1163                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1164         ADD_RIGHT_BUTTON( o_button, mainFrame, 0, 0, o_buttonTooltip,
1165                             _NS("Browse...") )
1166         [o_button setAutoresizingMask:NSViewMinXMargin ];
1167         [self addSubview: o_button];
1168
1169         /* build the textfield */
1170         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1171             [[VLCMain sharedInstance]
1172                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1173         if( p_item->value.psz )
1174             o_textfieldString = [NSString stringWithFormat: @"%s", (char *)p_item->value.psz];
1175         else
1176             o_textfieldString = [NSString stringWithString: @""];
1177         ADD_TEXTFIELD( o_textfield, mainFrame, 12, 2, mainFrame.size.width -
1178                         8 - [o_button frame].size.width,
1179                         o_textfieldTooltip, o_textfieldString )
1180         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
1181         [self addSubview: o_textfield];
1182     }
1183     return self;
1184 }
1185
1186 - (void) alignWithXPosition:(int)i_xPos
1187 {
1188     ;
1189 }
1190
1191 - (void)dealloc
1192 {
1193     [o_textfield release];
1194     [o_button release];
1195     [super dealloc];
1196 }
1197
1198 - (IBAction)openFileDialog: (id)sender
1199 {
1200     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
1201
1202     [o_open_panel setTitle: (b_directory)?
1203         _NS("Select a directory"):_NS("Select a file")];
1204     [o_open_panel setPrompt: _NS("Select")];
1205     [o_open_panel setAllowsMultipleSelection: NO];
1206     [o_open_panel setCanChooseFiles: !b_directory];
1207     [o_open_panel setCanChooseDirectories: b_directory];
1208     [o_open_panel beginSheetForDirectory:nil
1209         file:nil
1210         types:nil
1211         modalForWindow:[sender window]
1212         modalDelegate: self
1213         didEndSelector: @selector(pathChosenInPanel:
1214                         withReturn:
1215                         contextInfo:)
1216         contextInfo: nil];
1217 }
1218
1219 - (void)pathChosenInPanel:(NSOpenPanel *)o_sheet
1220     withReturn:(int)i_return_code contextInfo:(void  *)o_context_info
1221 {
1222     if( i_return_code == NSOKButton )
1223     {
1224         NSString *o_path = [[o_sheet filenames] objectAtIndex: 0];
1225         [o_textfield setStringValue: o_path];
1226     }
1227 }
1228
1229 - (char *)stringValue
1230 {
1231     if( [[o_textfield stringValue] length] != 0)
1232         return strdup( [[o_textfield stringValue] fileSystemRepresentation] );
1233     else
1234         return NULL;
1235 }
1236 @end
1237
1238 @implementation ModuleConfigControl
1239 - (id) initWithItem: (module_config_t *)_p_item
1240            withView: (NSView *)o_parent_view
1241 {
1242     NSRect mainFrame = [o_parent_view frame];
1243     NSString *o_labelString, *o_popupTooltip;
1244     mainFrame.size.height = 22;
1245     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1246     mainFrame.origin.x = LEFTMARGIN;
1247     mainFrame.origin.y = 0;
1248
1249     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1250     {
1251         int i_index;
1252         vlc_list_t *p_list;
1253         module_t *p_parser;
1254         i_view_type = CONFIG_ITEM_MODULE;
1255
1256         /* add the label */
1257         if( p_item->psz_text )
1258             o_labelString = [[VLCMain sharedInstance]
1259                                 localizedString: (char *)p_item->psz_text];
1260         else
1261             o_labelString = [NSString stringWithString:@""];
1262         ADD_LABEL( o_label, mainFrame, 0, -1, o_labelString )
1263         [o_label setAutoresizingMask:NSViewNotSizable ];
1264         [self addSubview: o_label];
1265
1266         /* build the popup */
1267         o_popupTooltip = [[VLCMain sharedInstance] wrapString:
1268             [[VLCMain sharedInstance]
1269                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1270         ADD_POPUP( o_popup, mainFrame, [o_label frame].size.width,
1271             -2, 0, o_popupTooltip )
1272         [o_popup setAutoresizingMask:NSViewWidthSizable ];
1273         [o_popup addItemWithTitle: _NS("Default")];
1274         [[o_popup lastItem] setTag: -1];
1275         [o_popup selectItem: [o_popup lastItem]];
1276
1277         /* build a list of available modules */
1278         p_list = vlc_list_find( VLCIntf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1279         for( i_index = 0; i_index < p_list->i_count; i_index++ )
1280         {
1281             p_parser = (module_t *)p_list->p_values[i_index].p_object;
1282
1283             if( p_item->i_type == CONFIG_ITEM_MODULE )
1284             {
1285                 if( module_IsCapable( p_parser, p_item->psz_type ) )
1286                 {
1287                     NSString *o_description = [[VLCMain sharedInstance]
1288                         localizedString: module_GetLongName( p_parser )];
1289                     [o_popup addItemWithTitle: o_description];
1290
1291                     if( p_item->value.psz &&
1292                 !strcmp( p_item->value.psz, module_GetObjName( p_parser ) ) )
1293                         [o_popup selectItem:[o_popup lastItem]];
1294                 }
1295             }
1296             else
1297             {
1298                 int i;
1299
1300                 if( !strcmp( module_GetObjName( p_parser ), "main" ) )
1301                     continue;
1302                 unsigned int confsize;
1303                 unsigned int unused;
1304                 module_GetConfig( p_parser, &confsize );
1305                 for ( i = 0; i < confsize; i++ )
1306                 {
1307                     module_config_t *p_config = module_GetConfig( p_parser, &unused ) + i;
1308                     /* Hack: required subcategory is stored in i_min */
1309                     if( p_config->i_type == CONFIG_SUBCATEGORY &&
1310                         p_config->value.i == p_item->min.i )
1311                     {
1312                         NSString *o_description = [[VLCMain sharedInstance]
1313                             localizedString: module_GetLongName( p_parser )];
1314                         [o_popup addItemWithTitle: o_description];
1315
1316                         if( p_item->value.psz && !strcmp(p_item->value.psz,
1317                                                 module_GetObjName( p_parser )) )
1318                             [o_popup selectItem:[o_popup lastItem]];
1319                     }
1320                 }
1321             }
1322         }
1323         vlc_list_release( p_list );
1324         [self addSubview: o_popup];
1325     }
1326     return self;
1327 }
1328
1329 - (void) alignWithXPosition:(int)i_xPos
1330 {
1331     NSRect frame;
1332     NSRect superFrame = [self frame];
1333     frame = [o_label frame];
1334     frame.origin.x = i_xPos - frame.size.width - 3;
1335     [o_label setFrame:frame];
1336
1337     frame = [o_popup frame];
1338     frame.origin.x = i_xPos - 1;
1339     frame.size.width = superFrame.size.width - frame.origin.x + 2;
1340     [o_popup setFrame:frame];
1341 }
1342
1343 - (void)dealloc
1344 {
1345     [o_popup release];
1346     [super dealloc];
1347 }
1348
1349 - (char *)stringValue
1350 {
1351     NSString *newval = [o_popup titleOfSelectedItem];
1352     char *returnval = NULL;
1353     int i_module_index;
1354     vlc_list_t *p_list;
1355     module_t *p_parser;
1356
1357     p_list = vlc_list_find( VLCIntf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1358     for( i_module_index = 0; i_module_index < p_list->i_count; i_module_index++ )
1359     {
1360         p_parser = (module_t *)p_list->p_values[i_module_index].p_object;
1361
1362         if( p_item->i_type == CONFIG_ITEM_MODULE )
1363         {
1364             if( module_IsCapable( p_parser, p_item->psz_type ) )
1365             {
1366                 NSString *o_description = [[VLCMain sharedInstance]
1367                     localizedString: module_GetLongName( p_parser )];
1368                 if( [newval isEqualToString: o_description] )
1369                 {
1370                     returnval = strdup( module_GetObjName( p_parser ));
1371                     break;
1372                 }
1373             }
1374         }
1375         else
1376         {
1377             int i;
1378
1379             if( !strcmp( module_GetObjName( p_parser ), "main" ) )
1380                 continue;
1381             unsigned int confsize, unused;
1382             module_GetConfig( p_parser, &confsize );
1383             for ( i = 0; i < confsize; i++ )
1384             {
1385                 module_config_t *p_config = module_GetConfig( p_parser, &unused ) + i;
1386                 /* Hack: required subcategory is stored in i_min */
1387                 if( p_config->i_type == CONFIG_SUBCATEGORY &&
1388                     p_config->value.i == p_item->min.i )
1389                 {
1390                     NSString *o_description = [[VLCMain sharedInstance]
1391                         localizedString: module_GetLongName( p_parser )];
1392                     if( [newval isEqualToString: o_description] )
1393                     {
1394                         returnval = strdup(module_GetObjName( p_parser ));
1395                         break;
1396                     }
1397                 }
1398             }
1399         }
1400     }
1401     vlc_list_release( p_list );
1402     return returnval;
1403 }
1404 @end
1405
1406 @implementation IntegerConfigControl
1407 - (id) initWithItem: (module_config_t *)_p_item
1408            withView: (NSView *)o_parent_view
1409 {
1410     NSRect mainFrame = [o_parent_view frame];
1411     NSString *o_labelString, *o_tooltip;
1412     mainFrame.size.height = 23;
1413     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1414     mainFrame.origin.x = LEFTMARGIN;
1415     mainFrame.origin.y = 0;
1416
1417     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1418     {
1419         i_view_type = CONFIG_ITEM_INTEGER;
1420
1421         o_tooltip = [[VLCMain sharedInstance] wrapString:
1422             [[VLCMain sharedInstance]
1423                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1424
1425         /* add the label */
1426         if( p_item->psz_text )
1427             o_labelString = [[VLCMain sharedInstance]
1428                                 localizedString: (char *)p_item->psz_text];
1429         else
1430             o_labelString = [NSString stringWithString:@""];
1431         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1432         [o_label setAutoresizingMask:NSViewNotSizable ];
1433         [self addSubview: o_label];
1434
1435         /* build the stepper */
1436         ADD_STEPPER( o_stepper, mainFrame, mainFrame.size.width - 19,
1437             0, o_tooltip, -1600, 1600)
1438         [o_stepper setIntValue: p_item->value.i];
1439         [o_stepper setAutoresizingMask:NSViewMaxXMargin ];
1440         [self addSubview: o_stepper];
1441
1442         ADD_TEXTFIELD( o_textfield, mainFrame, mainFrame.size.width - 19 - 52,
1443             1, 49, o_tooltip, @"" )
1444         [o_textfield setIntValue: p_item->value.i];
1445         [o_textfield setDelegate: self];
1446         [[NSNotificationCenter defaultCenter] addObserver: self
1447             selector: @selector(textfieldChanged:)
1448             name: NSControlTextDidChangeNotification
1449             object: o_textfield];
1450         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1451         [self addSubview: o_textfield];
1452     }
1453     return self;
1454 }
1455
1456 - (void) alignWithXPosition:(int)i_xPos
1457 {
1458     NSRect frame;
1459     frame = [o_label frame];
1460     frame.origin.x = i_xPos - frame.size.width - 3;
1461     [o_label setFrame:frame];
1462
1463     frame = [o_textfield frame];
1464     frame.origin.x = i_xPos + 2;
1465     [o_textfield setFrame:frame];
1466
1467     frame = [o_stepper frame];
1468     frame.origin.x = i_xPos + [o_textfield frame].size.width + 5;
1469     [o_stepper setFrame:frame];
1470 }
1471
1472 - (void)dealloc
1473 {
1474     [o_stepper release];
1475     [o_textfield release];
1476     [super dealloc];
1477 }
1478
1479 - (IBAction)stepperChanged:(id)sender
1480 {
1481     [o_textfield setIntValue: [o_stepper intValue]];
1482 }
1483
1484 - (void)textfieldChanged:(NSNotification *)o_notification
1485 {
1486     [o_stepper setIntValue: [o_textfield intValue]];
1487 }
1488
1489 - (int)intValue
1490 {
1491     return [o_textfield intValue];
1492 }
1493
1494 @end
1495
1496 @implementation IntegerListConfigControl
1497
1498 - (id) initWithItem: (module_config_t *)_p_item
1499            withView: (NSView *)o_parent_view
1500 {
1501     NSRect mainFrame = [o_parent_view frame];
1502     NSString *o_labelString, *o_textfieldTooltip;
1503     mainFrame.size.height = 22;
1504     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1505     mainFrame.origin.x = LEFTMARGIN;
1506     mainFrame.origin.y = 0;
1507
1508     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1509     {
1510         int i_index;
1511         i_view_type = CONFIG_ITEM_STRING_LIST;
1512
1513         /* add the label */
1514         if( p_item->psz_text )
1515             o_labelString = [[VLCMain sharedInstance]
1516                 localizedString: (char *)p_item->psz_text];
1517         else
1518             o_labelString = [NSString stringWithString:@""];
1519         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1520         [o_label setAutoresizingMask:NSViewNotSizable ];
1521         [self addSubview: o_label];
1522
1523         /* build the textfield */
1524         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1525             [[VLCMain sharedInstance]
1526                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1527         ADD_COMBO( o_combo, mainFrame, [o_label frame].size.width,
1528             -2, 0, o_textfieldTooltip )
1529         [o_combo setAutoresizingMask:NSViewWidthSizable ];
1530         for( i_index = 0; i_index < p_item->i_list; i_index++ )
1531         {
1532             if( p_item->value.i == p_item->pi_list[i_index] )
1533             {
1534                 [o_combo selectItemAtIndex: i_index];
1535             }
1536         }
1537         [self addSubview: o_combo];
1538     }
1539     return self;
1540 }
1541
1542 - (void) alignWithXPosition:(int)i_xPos
1543 {
1544     NSRect frame;
1545     NSRect superFrame = [self frame];
1546     frame = [o_label frame];
1547     frame.origin.x = i_xPos - frame.size.width - 3;
1548     [o_label setFrame:frame];
1549
1550     frame = [o_combo frame];
1551     frame.origin.x = i_xPos + 2;
1552     frame.size.width = superFrame.size.width - frame.origin.x + 2;
1553     [o_combo setFrame:frame];
1554 }
1555
1556 - (void)dealloc
1557 {
1558     [o_combo release];
1559     [super dealloc];
1560 }
1561
1562 - (int)intValue
1563 {
1564     if( [o_combo indexOfSelectedItem] >= 0 )
1565         return p_item->pi_list[[o_combo indexOfSelectedItem]];
1566     else
1567         return [o_combo intValue];
1568 }
1569 @end
1570
1571 @implementation IntegerListConfigControl (NSComboBoxDataSource)
1572 - (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox
1573 {
1574     return p_item->i_list;
1575 }
1576
1577 - (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)i_index
1578 {
1579     if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
1580         return [[VLCMain sharedInstance]
1581                     localizedString: (char *)p_item->ppsz_list_text[i_index]];
1582     else
1583         return [NSString stringWithFormat: @"%i", p_item->pi_list[i_index]];
1584 }
1585 @end
1586
1587 @implementation RangedIntegerConfigControl
1588 - (id) initWithItem: (module_config_t *)_p_item
1589            withView: (NSView *)o_parent_view
1590 {
1591     NSRect mainFrame = [o_parent_view frame];
1592     NSString *o_labelString, *o_tooltip;
1593     mainFrame.size.height = 50;
1594     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1595     mainFrame.origin.x = LEFTMARGIN;
1596     mainFrame.origin.y = 0;
1597
1598     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1599     {
1600         i_view_type = CONFIG_ITEM_RANGED_INTEGER;
1601
1602         /* add the label */
1603         if( p_item->psz_text )
1604             o_labelString = [[VLCMain sharedInstance]
1605                                 localizedString: (char *)p_item->psz_text];
1606         else
1607             o_labelString = [NSString stringWithString:@""];
1608         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1609         [o_label setAutoresizingMask:NSViewNotSizable ];
1610         [self addSubview: o_label];
1611
1612         /* build the textfield */
1613         o_tooltip = [[VLCMain sharedInstance] wrapString:
1614             [[VLCMain sharedInstance]
1615                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1616         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1617             28, 49, o_tooltip, @"" )
1618         [o_textfield setIntValue: p_item->value.i];
1619         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1620         [o_textfield setDelegate: self];
1621         [[NSNotificationCenter defaultCenter] addObserver: self
1622             selector: @selector(textfieldChanged:)
1623             name: NSControlTextDidChangeNotification
1624             object: o_textfield];
1625         [self addSubview: o_textfield];
1626
1627         /* build the mintextfield */
1628         ADD_LABEL( o_textfield_min, mainFrame, 12, -30, @"-8888" )
1629         [o_textfield_min setIntValue: p_item->min.i];
1630         [o_textfield_min setAutoresizingMask:NSViewMaxXMargin ];
1631         [o_textfield_min setAlignment:NSRightTextAlignment];
1632         [self addSubview: o_textfield_min];
1633
1634         /* build the maxtextfield */
1635         ADD_LABEL( o_textfield_max, mainFrame,
1636                     mainFrame.size.width - 31, -30, @"8888" )
1637         [o_textfield_max setIntValue: p_item->max.i];
1638         [o_textfield_max setAutoresizingMask:NSViewMinXMargin ];
1639         [self addSubview: o_textfield_max];
1640
1641         /* build the slider */
1642         ADD_SLIDER( o_slider, mainFrame, [o_textfield_min frame].origin.x +
1643             [o_textfield_min frame].size.width + 6, -1, mainFrame.size.width -
1644             [o_textfield_max frame].size.width -
1645             [o_textfield_max frame].size.width - 14 -
1646             [o_textfield_min frame].origin.x, o_tooltip,
1647             p_item->min.i, p_item->max.i )
1648         [o_slider setIntValue: p_item->value.i];
1649         [o_slider setAutoresizingMask:NSViewWidthSizable ];
1650         [o_slider setTarget: self];
1651         [o_slider setAction: @selector(sliderChanged:)];
1652         [o_slider sendActionOn:NSLeftMouseUpMask | NSLeftMouseDownMask |
1653             NSLeftMouseDraggedMask];
1654         [self addSubview: o_slider];
1655
1656     }
1657     return self;
1658 }
1659
1660 - (void) alignWithXPosition:(int)i_xPos
1661 {
1662     NSRect frame;
1663     frame = [o_label frame];
1664     frame.origin.x = i_xPos - frame.size.width - 3;
1665     [o_label setFrame:frame];
1666
1667     frame = [o_textfield frame];
1668     frame.origin.x = i_xPos + 2;
1669     [o_textfield setFrame:frame];
1670 }
1671
1672 - (void)dealloc
1673 {
1674     [o_textfield release];
1675     [o_textfield_min release];
1676     [o_textfield_max release];
1677     [o_slider release];
1678     [super dealloc];
1679 }
1680
1681 - (IBAction)sliderChanged:(id)sender
1682 {
1683     [o_textfield setIntValue: [o_slider intValue]];
1684 }
1685
1686 - (void)textfieldChanged:(NSNotification *)o_notification
1687 {
1688     [o_slider setIntValue: [o_textfield intValue]];
1689 }
1690
1691 - (int)intValue
1692 {
1693     return [o_slider intValue];
1694 }
1695 @end
1696
1697 @implementation FloatConfigControl
1698 - (id) initWithItem: (module_config_t *)_p_item
1699            withView: (NSView *)o_parent_view
1700 {
1701     NSRect mainFrame = [o_parent_view frame];
1702     NSString *o_labelString, *o_tooltip;
1703     mainFrame.size.height = 23;
1704     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1705     mainFrame.origin.x = LEFTMARGIN;
1706     mainFrame.origin.y = 0;
1707
1708     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1709     {
1710         i_view_type = CONFIG_ITEM_INTEGER;
1711
1712         o_tooltip = [[VLCMain sharedInstance] wrapString:
1713             [[VLCMain sharedInstance]
1714                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1715
1716         /* add the label */
1717         if( p_item->psz_text )
1718             o_labelString = [[VLCMain sharedInstance]
1719                                 localizedString: (char *)p_item->psz_text];
1720         else
1721             o_labelString = [NSString stringWithString:@""];
1722         ADD_LABEL( o_label, mainFrame, 0, -2, o_labelString )
1723         [o_label setAutoresizingMask:NSViewNotSizable ];
1724         [self addSubview: o_label];
1725
1726         /* build the stepper */
1727         ADD_STEPPER( o_stepper, mainFrame, mainFrame.size.width - 19,
1728             0, o_tooltip, -1600, 1600)
1729         [o_stepper setFloatValue: p_item->value.f];
1730         [o_stepper setAutoresizingMask:NSViewMaxXMargin ];
1731         [self addSubview: o_stepper];
1732
1733         /* build the textfield */
1734         ADD_TEXTFIELD( o_textfield, mainFrame, mainFrame.size.width - 19 - 52,
1735             1, 49, o_tooltip, @"" )
1736         [o_textfield setFloatValue: p_item->value.f];
1737         [o_textfield setDelegate: self];
1738         [[NSNotificationCenter defaultCenter] addObserver: self
1739             selector: @selector(textfieldChanged:)
1740             name: NSControlTextDidChangeNotification
1741             object: o_textfield];
1742         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1743         [self addSubview: o_textfield];
1744     }
1745     return self;
1746 }
1747
1748 - (void) alignWithXPosition:(int)i_xPos
1749 {
1750     NSRect frame;
1751     frame = [o_label frame];
1752     frame.origin.x = i_xPos - frame.size.width - 3;
1753     [o_label setFrame:frame];
1754
1755     frame = [o_textfield frame];
1756     frame.origin.x = i_xPos + 2;
1757     [o_textfield setFrame:frame];
1758
1759     frame = [o_stepper frame];
1760     frame.origin.x = i_xPos + [o_textfield frame].size.width + 5;
1761     [o_stepper setFrame:frame];
1762 }
1763
1764 - (void)dealloc
1765 {
1766     [o_stepper release];
1767     [o_textfield release];
1768     [super dealloc];
1769 }
1770
1771 - (IBAction)stepperChanged:(id)sender
1772 {
1773     [o_textfield setFloatValue: [o_stepper floatValue]];
1774 }
1775
1776 - (void)textfieldChanged:(NSNotification *)o_notification
1777 {
1778     [o_stepper setFloatValue: [o_textfield floatValue]];
1779 }
1780
1781 - (float)floatValue
1782 {
1783     return [o_stepper floatValue];
1784 }
1785 @end
1786
1787 @implementation RangedFloatConfigControl
1788 - (id) initWithItem: (module_config_t *)_p_item
1789            withView: (NSView *)o_parent_view
1790 {
1791     NSRect mainFrame = [o_parent_view frame];
1792     NSString *o_labelString, *o_tooltip;
1793     mainFrame.size.height = 50;
1794     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1795     mainFrame.origin.x = LEFTMARGIN;
1796     mainFrame.origin.y = 0;
1797
1798     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1799     {
1800         i_view_type = CONFIG_ITEM_RANGED_INTEGER;
1801
1802         /* add the label */
1803         if( p_item->psz_text )
1804             o_labelString = [[VLCMain sharedInstance]
1805                                 localizedString: (char *)p_item->psz_text];
1806         else
1807             o_labelString = [NSString stringWithString:@""];
1808         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1809         [o_label setAutoresizingMask:NSViewNotSizable ];
1810         [self addSubview: o_label];
1811
1812         /* build the textfield */
1813         o_tooltip = [[VLCMain sharedInstance] wrapString:
1814             [[VLCMain sharedInstance]
1815                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1816         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1817             28, 49, o_tooltip, @"" )
1818         [o_textfield setFloatValue: p_item->value.f];
1819         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1820         [o_textfield setDelegate: self];
1821         [[NSNotificationCenter defaultCenter] addObserver: self
1822             selector: @selector(textfieldChanged:)
1823             name: NSControlTextDidChangeNotification
1824             object: o_textfield];
1825         [self addSubview: o_textfield];
1826
1827         /* build the mintextfield */
1828         ADD_LABEL( o_textfield_min, mainFrame, 12, -30, @"-8888" )
1829         [o_textfield_min setFloatValue: p_item->min.f];
1830         [o_textfield_min setAutoresizingMask:NSViewMaxXMargin ];
1831         [o_textfield_min setAlignment:NSRightTextAlignment];
1832         [self addSubview: o_textfield_min];
1833
1834         /* build the maxtextfield */
1835         ADD_LABEL( o_textfield_max, mainFrame, mainFrame.size.width - 31,
1836             -30, @"8888" )
1837         [o_textfield_max setFloatValue: p_item->max.f];
1838         [o_textfield_max setAutoresizingMask:NSViewMinXMargin ];
1839         [self addSubview: o_textfield_max];
1840
1841         /* build the slider */
1842         ADD_SLIDER( o_slider, mainFrame, [o_textfield_min frame].origin.x +
1843             [o_textfield_min frame].size.width + 6, -1, mainFrame.size.width -
1844             [o_textfield_max frame].size.width -
1845             [o_textfield_max frame].size.width - 14 -
1846             [o_textfield_min frame].origin.x, o_tooltip, p_item->min.f,
1847             p_item->max.f )
1848         [o_slider setFloatValue: p_item->value.f];
1849         [o_slider setAutoresizingMask:NSViewWidthSizable ];
1850         [o_slider setTarget: self];
1851         [o_slider setAction: @selector(sliderChanged:)];
1852         [o_slider sendActionOn:NSLeftMouseUpMask | NSLeftMouseDownMask |
1853             NSLeftMouseDraggedMask];
1854         [self addSubview: o_slider];
1855
1856     }
1857     return self;
1858 }
1859
1860 - (void) alignWithXPosition:(int)i_xPos
1861 {
1862     NSRect frame;
1863     frame = [o_label frame];
1864     frame.origin.x = i_xPos - frame.size.width - 3;
1865     [o_label setFrame:frame];
1866
1867     frame = [o_textfield frame];
1868     frame.origin.x = i_xPos + 2;
1869     [o_textfield setFrame:frame];
1870 }
1871
1872 - (void)dealloc
1873 {
1874     [o_textfield release];
1875     [o_textfield_min release];
1876     [o_textfield_max release];
1877     [o_slider release];
1878     [super dealloc];
1879 }
1880
1881 - (IBAction)sliderChanged:(id)sender
1882 {
1883     [o_textfield setFloatValue: [o_slider floatValue]];
1884 }
1885
1886 - (void)textfieldChanged:(NSNotification *)o_notification
1887 {
1888     [o_slider setFloatValue: [o_textfield floatValue]];
1889 }
1890
1891 - (float)floatValue
1892 {
1893     return [o_slider floatValue];
1894 }
1895
1896 @end
1897
1898 @implementation BoolConfigControl
1899
1900 - (id) initWithItem: (module_config_t *)_p_item
1901            withView: (NSView *)o_parent_view
1902 {
1903     NSRect mainFrame = [o_parent_view frame];
1904     NSString *o_labelString, *o_tooltip;
1905     mainFrame.size.height = 17;
1906     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1907     mainFrame.origin.x = LEFTMARGIN;
1908     mainFrame.origin.y = 0;
1909
1910     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1911     {
1912         i_view_type = CONFIG_ITEM_BOOL;
1913
1914         /* add the checkbox */
1915         o_tooltip = [[VLCMain sharedInstance]
1916             wrapString: [[VLCMain sharedInstance]
1917             localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1918         ADD_CHECKBOX( o_checkbox, mainFrame, 0,
1919                         0, @"", o_tooltip, p_item->value.i, NSImageLeft)
1920         [o_checkbox setAutoresizingMask:NSViewNotSizable ];
1921         [self addSubview: o_checkbox];
1922         /* add the label */
1923         if( p_item->psz_text )
1924             o_labelString = [[VLCMain sharedInstance]
1925                                 localizedString: (char *)p_item->psz_text];
1926         else
1927             o_labelString = [NSString stringWithString:@""];
1928         ADD_LABEL( o_label, mainFrame, [o_checkbox frame].size.width, 0, o_labelString )
1929         [o_label setAutoresizingMask:NSViewNotSizable ];
1930         [self addSubview: o_label];
1931     }
1932     return self;
1933 }
1934
1935 - (void)dealloc
1936 {
1937     [o_checkbox release];
1938     [super dealloc];
1939 }
1940
1941 - (int)intValue
1942 {
1943     return [o_checkbox intValue];
1944 }
1945
1946 @end
1947
1948 @implementation KeyConfigControl
1949 - (id) initWithItem: (module_config_t *)_p_item
1950            withView: (NSView *)o_parent_view
1951 {
1952     NSRect mainFrame = [o_parent_view frame];
1953     NSString *o_labelString, *o_tooltip;
1954     mainFrame.size.height = 22;
1955     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1956     mainFrame.origin.x = LEFTMARGIN;
1957     mainFrame.origin.y = 0;
1958
1959     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1960     {
1961         i_view_type = CONFIG_ITEM_KEY_AFTER_10_3;
1962
1963         /* add the label */
1964         if( p_item->psz_text )
1965             o_labelString = [[VLCMain sharedInstance]
1966                 localizedString: (char *)p_item->psz_text];
1967         else
1968             o_labelString = [NSString stringWithString:@""];
1969         ADD_LABEL( o_label, mainFrame, 0, -1, o_labelString )
1970         [o_label setAutoresizingMask:NSViewNotSizable ];
1971         [self addSubview: o_label];
1972
1973         /* build the popup */
1974         o_tooltip = [[VLCMain sharedInstance] wrapString:
1975             [[VLCMain sharedInstance]
1976                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1977         ADD_POPUP( o_popup, mainFrame, [o_label frame].origin.x +
1978             [o_label frame].size.width + 3,
1979             -2, 0, o_tooltip )
1980         [o_popup setAutoresizingMask:NSViewWidthSizable ];
1981
1982         if( o_keys_menu == nil )
1983         {
1984             unsigned int i;
1985             o_keys_menu = [[NSMenu alloc] initWithTitle: @"Keys Menu"];
1986             for ( i = 0; i < sizeof(vlc_keys) / sizeof(key_descriptor_t); i++)
1987                 if( vlc_keys[i].psz_key_string && *vlc_keys[i].psz_key_string )
1988                     POPULATE_A_KEY( o_keys_menu,
1989                         [NSString stringWithUTF8String:vlc_keys[i].psz_key_string]
1990                         , vlc_keys[i].i_key_code)
1991         }
1992         [o_popup setMenu:[o_keys_menu copyWithZone:nil]];
1993         [o_popup selectItem:[[o_popup menu] itemWithTag:p_item->value.i]];
1994         [self addSubview: o_popup];
1995
1996     }
1997     return self;
1998 }
1999
2000 - (void) alignWithXPosition:(int)i_xPos
2001 {
2002     NSRect frame;
2003     NSRect superFrame = [self frame];
2004     frame = [o_label frame];
2005     frame.origin.x = i_xPos - frame.size.width - 3;
2006     [o_label setFrame:frame];
2007
2008     frame = [o_popup frame];
2009     frame.origin.x = i_xPos - 1;
2010     frame.size.width = superFrame.size.width - frame.origin.x + 2;
2011     [o_popup setFrame:frame];
2012 }
2013
2014 - (void)dealloc
2015 {
2016     [o_popup release];
2017     [super dealloc];
2018 }
2019
2020 - (int)intValue
2021 {
2022     return [o_popup selectedTag];
2023 }
2024 @end
2025
2026 @implementation ModuleListConfigControl
2027 - (id) initWithItem: (module_config_t *)_p_item
2028            withView: (NSView *)o_parent_view
2029 {
2030 if( _p_item->i_type == CONFIG_ITEM_MODULE_LIST )
2031 //TODO....
2032         return nil;
2033
2034 //Fill our array to know how may items we have...
2035     vlc_list_t *p_list;
2036     module_t *p_parser;
2037     int i_module_index;
2038     NSRect mainFrame = [o_parent_view frame];
2039     NSString *o_labelString, *o_textfieldString, *o_tooltip;
2040
2041     o_modulearray = [[NSMutableArray alloc] initWithCapacity:10];
2042     /* build a list of available modules */
2043     p_list = vlc_list_find( VLCIntf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
2044     for( i_module_index = 0; i_module_index < p_list->i_count; i_module_index++ )
2045     {
2046         int i;
2047         p_parser = (module_t *)p_list->p_values[i_module_index].p_object;
2048
2049         if( !strcmp( module_GetObjName( p_parser ), "main" ) )
2050             continue;
2051
2052         unsigned int confsize;
2053         module_GetConfig( p_parser, &confsize );
2054
2055         for ( i = 0; i < confsize; i++ )
2056         {
2057             unsigned int unused;
2058             module_config_t *p_config = module_GetConfig( p_parser, &unused ) + i;
2059             NSString *o_modulelongname, *o_modulename;
2060             NSNumber *o_moduleenabled = nil;
2061
2062             /* Hack: required subcategory is stored in i_min */
2063             if( p_config->i_type == CONFIG_SUBCATEGORY &&
2064                 p_config->value.i == _p_item->min.i )
2065             {
2066                 o_modulelongname = [NSString stringWithUTF8String:
2067                                         module_GetLongName( p_parser )];
2068                 o_modulename = [NSString stringWithUTF8String:
2069                                         module_GetObjName( p_parser )];
2070
2071                 if( _p_item->value.psz &&
2072                     strstr( _p_item->value.psz, module_GetObjName( p_parser ) ) )
2073                     o_moduleenabled = [NSNumber numberWithBool:YES];
2074                 else
2075                     o_moduleenabled = [NSNumber numberWithBool:NO];
2076
2077                 [o_modulearray addObject:[NSMutableArray
2078                     arrayWithObjects: o_modulename, o_modulelongname,
2079                     o_moduleenabled, nil]];
2080             }
2081         }
2082     }
2083     vlc_list_release( p_list );
2084
2085     mainFrame.size.height = 30 + 18 * [o_modulearray count];
2086     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
2087     mainFrame.origin.x = LEFTMARGIN;
2088     mainFrame.origin.y = 0;
2089     if( [super initWithFrame: mainFrame item: _p_item] != nil )
2090     {
2091         i_view_type = CONFIG_ITEM_MODULE_LIST;
2092
2093         /* add the label */
2094         if( p_item->psz_text )
2095             o_labelString = [[VLCMain sharedInstance]
2096                                 localizedString: (char *)p_item->psz_text];
2097         else
2098             o_labelString = [NSString stringWithString:@""];
2099         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
2100         [o_label setAutoresizingMask:NSViewNotSizable ];
2101         [self addSubview: o_label];
2102
2103         /* build the textfield */
2104         o_tooltip = [[VLCMain sharedInstance] wrapString:
2105             [[VLCMain sharedInstance]
2106                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
2107         if( p_item->value.psz )
2108             o_textfieldString = [[VLCMain sharedInstance]
2109                 localizedString: (char *)p_item->value.psz];
2110         else
2111             o_textfieldString = [NSString stringWithString: @""];
2112         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
2113             mainFrame.size.height - 22, mainFrame.size.width -
2114             [o_label frame].size.width - 2, o_tooltip, o_textfieldString )
2115         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
2116         [self addSubview: o_textfield];
2117
2118
2119 {
2120     NSRect s_rc = mainFrame;
2121     s_rc.size.height = mainFrame.size.height - 30;
2122     s_rc.size.width = mainFrame.size.width - 12;
2123     s_rc.origin.x = 12;
2124     s_rc.origin.y = 0;
2125     o_scrollview = [[[NSScrollView alloc] initWithFrame: s_rc] retain];
2126     [o_scrollview setDrawsBackground: NO];
2127     [o_scrollview setBorderType: NSBezelBorder];
2128     [o_scrollview setAutohidesScrollers:YES];
2129
2130     NSTableView *o_tableview;
2131     o_tableview = [[NSTableView alloc] initWithFrame : s_rc];
2132     [o_tableview setUsesAlternatingRowBackgroundColors:YES];
2133     [o_tableview setHeaderView:nil];
2134 /* TODO: find a good way to fix the row height and text size*/
2135 /* FIXME: support for multiple selection... */
2136 //    [o_tableview setAllowsMultipleSelection:YES];
2137
2138     NSCell *o_headerCell = [[NSCell alloc] initTextCell:@"Enabled"];
2139     NSCell *o_dataCell = [[NSButtonCell alloc] init];
2140     [(NSButtonCell*)o_dataCell setButtonType:NSSwitchButton];
2141     [o_dataCell setTitle:@""];
2142     [o_dataCell setFont:[NSFont systemFontOfSize:0]];
2143     NSTableColumn *o_tableColumn = [[NSTableColumn alloc]
2144         initWithIdentifier:@"Enabled"];
2145     [o_tableColumn setHeaderCell: o_headerCell];
2146     [o_tableColumn setDataCell: o_dataCell];
2147     [o_tableColumn setWidth:17];
2148     [o_tableview addTableColumn: o_tableColumn];
2149
2150     o_headerCell = [[NSCell alloc] initTextCell:@"Module Name"];
2151     o_dataCell = [[NSTextFieldCell alloc] init];
2152     [o_dataCell setFont:[NSFont systemFontOfSize:12]];
2153     o_tableColumn = [[NSTableColumn alloc]
2154         initWithIdentifier:@"Module"];
2155     [o_tableColumn setHeaderCell: o_headerCell];
2156     [o_tableColumn setDataCell: o_dataCell];
2157     [o_tableColumn setWidth:388 - 17];
2158     [o_tableview addTableColumn: o_tableColumn];
2159     [o_tableview registerForDraggedTypes:[NSArray arrayWithObjects:
2160             @"VLC media player module", nil]];
2161
2162     [o_tableview setDataSource:self];
2163     [o_tableview setTarget: self];
2164     [o_tableview setAction: @selector(tableChanged:)];
2165     [o_tableview sendActionOn:NSLeftMouseUpMask | NSLeftMouseDownMask |
2166         NSLeftMouseDraggedMask];
2167     [o_scrollview setDocumentView: o_tableview];
2168 }
2169     [o_scrollview setAutoresizingMask:NSViewWidthSizable ];
2170     [self addSubview: o_scrollview];
2171
2172
2173     }
2174     return self;
2175 }
2176
2177 - (void) alignWithXPosition:(int)i_xPos
2178 {
2179     ;
2180 }
2181
2182 - (IBAction)tableChanged:(id)sender
2183 {
2184     NSString *o_newstring = @"";
2185     unsigned int i;
2186     for( i = 0 ; i < [o_modulearray count] ; i++ )
2187         if( [[[o_modulearray objectAtIndex:i] objectAtIndex:2]
2188             boolValue] != NO )
2189         {
2190             o_newstring = [o_newstring stringByAppendingString:
2191                 [[o_modulearray objectAtIndex:i] objectAtIndex:0]];
2192             o_newstring = [o_newstring stringByAppendingString:@":"];
2193         }
2194
2195     [o_textfield setStringValue: [o_newstring
2196         substringToIndex: ([o_newstring length])?[o_newstring length] - 1:0]];
2197 }
2198
2199 - (void)dealloc
2200 {
2201     [o_scrollview release];
2202     [super dealloc];
2203 }
2204
2205
2206 - (char *)stringValue
2207 {
2208     return strdup( [[o_textfield stringValue] UTF8String] );
2209 }
2210
2211 @end
2212
2213 @implementation ModuleListConfigControl (NSTableDataSource)
2214
2215 - (BOOL)tableView:(NSTableView*)table writeRows:(NSArray*)rows
2216     toPasteboard:(NSPasteboard*)pb
2217 {
2218     // We only want to allow dragging of selected rows.
2219     NSEnumerator    *iter = [rows objectEnumerator];
2220     NSNumber        *row;
2221     while ((row = [iter nextObject]) != nil)
2222     {
2223         if (![table isRowSelected:[row intValue]])
2224             return NO;
2225     }
2226
2227     [pb declareTypes:[NSArray
2228         arrayWithObject:@"VLC media player module"] owner:nil];
2229     [pb setPropertyList:rows forType:@"VLC media player module"];
2230     return YES;
2231 }
2232
2233 - (NSDragOperation)tableView:(NSTableView*)table
2234     validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row
2235     proposedDropOperation:(NSTableViewDropOperation)op
2236 {
2237     // Make drops at the end of the table go to the end.
2238     if (row == -1)
2239     {
2240         row = [table numberOfRows];
2241         op = NSTableViewDropAbove;
2242         [table setDropRow:row dropOperation:op];
2243     }
2244
2245     // We don't ever want to drop onto a row, only between rows.
2246     if (op == NSTableViewDropOn)
2247         [table setDropRow:(row+1) dropOperation:NSTableViewDropAbove];
2248     return NSTableViewDropAbove;
2249 }
2250
2251 - (BOOL)tableView:(NSTableView*)table acceptDrop:(id <NSDraggingInfo>)info
2252     row:(int)dropRow dropOperation:(NSTableViewDropOperation)op;
2253 {
2254     NSPasteboard    *pb = [info draggingPasteboard];
2255     NSDragOperation srcMask = [info draggingSourceOperationMask];
2256     BOOL accepted = NO;
2257
2258     NS_DURING
2259
2260         NSArray *array;
2261
2262         // Intra-table drag - data is the array of rows.
2263         if (!accepted && (array =
2264             [pb propertyListForType:@"VLC media player module"]) != NULL)
2265         {
2266             NSEnumerator *iter = nil;
2267             id val;
2268             BOOL isCopy = (srcMask & NSDragOperationMove) ? NO:YES;
2269             // Move the modules
2270             iter = [array objectEnumerator];
2271             while ((val = [iter nextObject]) != NULL)
2272             {
2273                 NSArray *o_tmp = [[o_modulearray objectAtIndex:
2274                     [val intValue]] mutableCopyWithZone:nil];
2275                 [o_modulearray removeObject:o_tmp];
2276                 [o_modulearray insertObject:o_tmp
2277                     atIndex:(dropRow>[val intValue]) ? dropRow - 1 : dropRow];
2278                 dropRow++;
2279             }
2280
2281             // Select the newly-dragged items.
2282             iter = [array objectEnumerator];
2283 //TODO...
2284             [table deselectAll:self];
2285
2286             [self tableChanged:self];
2287             [table setNeedsDisplay:YES];
2288             // Indicate that we finished the drag.
2289             accepted = YES;
2290         }
2291         [table reloadData];
2292         [table setNeedsDisplay:YES];
2293
2294         NS_HANDLER
2295
2296             // An exception occurred. Uh-oh. Update the track table so that
2297             // it stays consistent, and re-raise the exception.
2298             [table reloadData];
2299             [localException raise];
2300             [table setNeedsDisplay:YES];
2301     NS_ENDHANDLER
2302
2303     return accepted;
2304 }
2305
2306 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
2307 {
2308     return [o_modulearray count];
2309 }
2310
2311 - (id)tableView:(NSTableView *)aTableView
2312     objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
2313 {
2314     if( [[aTableColumn identifier] isEqualToString: @"Enabled"] )
2315         return [[o_modulearray objectAtIndex:rowIndex] objectAtIndex:2];
2316     if( [[aTableColumn identifier] isEqualToString: @"Module"] )
2317         return [[o_modulearray objectAtIndex:rowIndex] objectAtIndex:1];
2318
2319     return nil;
2320 }
2321
2322 - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject
2323     forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
2324 {
2325     [[o_modulearray objectAtIndex:rowIndex] replaceObjectAtIndex:2
2326         withObject: anObject];
2327 }
2328 @end