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