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