prefs.m 28.6 KB
Newer Older
1
2
3
/*****************************************************************************
 * prefs.m: MacOS X plugin for vlc
 *****************************************************************************
4
 * Copyright (C) 2002-2003 VideoLAN
5
 * $Id: prefs.m,v 1.21 2003/05/11 23:17:30 hartman Exp $
6
 *
7
 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8
9
10
11
12
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
13
 *
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
#include <sys/param.h>                                    /* for MAXPATHLEN */
#include <string.h>

31
32
#include "intf.h"
#include "prefs.h"
33
34

/*****************************************************************************
35
 * VLCPrefs implementation
36
37
38
39
40
41
42
43
44
45
46
 *****************************************************************************/
@implementation VLCPrefs

- (id)init
{
    self = [super init];

    if( self != nil )
    {
        p_intf = [NSApp getIntf];

47
        o_pref_panels = [[NSMutableDictionary alloc] init];
48
49
50
51
        o_toolbars = [[NSMutableDictionary alloc] init];
        o_scroll_views = [[NSMutableDictionary alloc] init];
        o_panel_views = [[NSMutableDictionary alloc] init];
        o_save_prefs = [[NSMutableDictionary alloc] init];
hartman's avatar
hartman committed
52
        b_advanced = config_GetInt( p_intf, "advanced" );
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
    }

    return( self );
}

- (void)dealloc
{
    id v1, v2;
    NSEnumerator *o_e1;
    NSEnumerator *o_e2;

#define DIC_REL1(o_dic) \
    { \
    o_e1 = [o_dic objectEnumerator]; \
    while( (v1 = [o_e1 nextObject]) ) \
    { \
        [v1 release]; \
    } \
    [o_dic removeAllObjects]; \
    [o_dic release]; \
    }

#define DIC_REL2(o_dic) \
    { \
        o_e2 = [o_dic objectEnumerator]; \
        while( (v2 = [o_e2 nextObject]) ) \
        { \
            DIC_REL1(v2); \
        } \
        [o_dic removeAllObjects]; \
    }

    DIC_REL1(o_pref_panels);
    DIC_REL2(o_toolbars);
    DIC_REL1(o_scroll_views);
    DIC_REL2(o_panel_views);
    DIC_REL1(o_save_prefs);

#undef DIC_REL1
#undef DIC_REL2

    [super dealloc];
}

- (BOOL)hasPrefs:(NSString *)o_module_name
{
gbazin's avatar
   
gbazin committed
99
    module_t *p_parser;
100
    vlc_list_t *p_list;
101
    char *psz_module_name;
gbazin's avatar
   
gbazin committed
102
    int i_index;
103
104
105
106

    psz_module_name = (char *)[o_module_name lossyCString];

    /* look for module */
107
    p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
108

109
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
110
    {
111
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
112
113

        if( !strcmp( p_parser->psz_object_name, psz_module_name ) )
114
        {
gbazin's avatar
   
gbazin committed
115
            BOOL b_has_prefs = p_parser->i_config_items != 0;
116
            vlc_list_release( p_list );
117
118
119
120
            return( b_has_prefs );
        }
    }

121
    vlc_list_release( p_list );
122
123
124
125
126
127
128
129
130

    return( NO );
}

- (void)createPrefPanel:(NSString *)o_module_name
{
    int i_pos;
    int i_module_tag;

131
    module_t *p_parser = NULL;
132
    vlc_list_t *p_list;
133
134
    module_config_t *p_item;
    char *psz_module_name;
gbazin's avatar
   
gbazin committed
135
    int i_index;
136
137
138
139
140
141

    NSPanel *o_panel;                   /* panel                        */
    NSRect s_panel_rc;                  /* panel rect                   */
    NSView *o_panel_view;               /* panel view                   */
    NSToolbar *o_toolbar;               /* panel toolbar                */
    NSMutableDictionary *o_tb_items;    /* panel toolbar items          */
142
    NSScrollView *o_scroll_view;        /* panel scroll view            */
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    NSRect s_scroll_rc;                 /* panel scroll view rect       */
    NSMutableDictionary *o_views;       /* panel scroll view docviews   */

    NSRect s_rc;                        /* rect                         */
    NSView *o_view;                     /* view                         */
    NSRect s_vrc;                       /* view rect                    */
    NSButton *o_button;                 /* button                       */
    NSRect s_brc;                       /* button rect                  */
    VLCTextField *o_text_field;         /* input field / label          */

    o_panel = [o_pref_panels objectForKey: o_module_name];
    if( o_panel != nil )
    {
        [o_panel center];
        [o_panel makeKeyAndOrderFront: nil];
        return;
159
    }
160
161
162
163

    psz_module_name = (char *)[o_module_name lossyCString];

    /* Look for the selected module */
164
    p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
165

166
    for( i_index = 0; i_index < p_list->i_count; i_index++ )
167
    {
168
        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
169

170
        if( psz_module_name
gbazin's avatar
   
gbazin committed
171
            && !strcmp( psz_module_name, p_parser->psz_object_name ) )
172
173
174
175
176
        {
            break;
        }
    }

177
    if( !p_parser || i_index == p_list->i_count )
178
    {
179
        vlc_list_release( p_list );
180
181
182
183
184
        return;
    }

    /* We found it, now we can start building its configuration interface */

185
    s_panel_rc = NSMakeRect( 0, 0, 450, 450 );
186
187
188
189
190
    o_panel = [[NSPanel alloc] initWithContentRect: s_panel_rc
                               styleMask: NSTitledWindowMask
                               backing: NSBackingStoreBuffered
                               defer: YES];
    o_toolbar = [[NSToolbar alloc] initWithIdentifier: o_module_name];
191
    [o_panel setTitle: [NSString stringWithFormat: @"%@ (%@)",
192
193
194
                                 _NS("Preferences"), o_module_name]];
    o_panel_view = [o_panel contentView];

195
    s_scroll_rc = s_panel_rc;
196
197
198
    s_scroll_rc.size.height -= 55; s_scroll_rc.origin.y += 55;
    o_scroll_view = [[NSScrollView alloc] initWithFrame: s_scroll_rc];
    [o_scroll_views setObject: o_scroll_view forKey: o_module_name];
199
    [o_scroll_view setBorderType: NSGrooveBorder];
200
201
202
203
204
205
206
207
208
209
210
211
    [o_scroll_view setHasVerticalScroller: YES];
    [o_scroll_view setDrawsBackground: NO];
    [o_scroll_view setRulersVisible: YES];
    [o_panel_view addSubview: o_scroll_view];

    o_tb_items = [[NSMutableDictionary alloc] init];
    o_views = [[NSMutableDictionary alloc] init];

    [o_save_prefs setObject: [[NSMutableArray alloc] init]
                  forKey: o_module_name];

    /* Enumerate config options and add corresponding config boxes */
gbazin's avatar
   
gbazin committed
212
    p_item = p_parser->p_config;
213
214
215
216
217
218

    i_pos = 0;
    o_view = nil;
    i_module_tag = 3;

#define X_ORIGIN 20
219
#define Y_ORIGIN (X_ORIGIN - 10)
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

#define CHECK_VIEW_HEIGHT \
    { \
        float f_new_pos = s_rc.origin.y + s_rc.size.height + X_ORIGIN; \
        if( f_new_pos > s_vrc.size.height ) \
        { \
            s_vrc.size.height = f_new_pos; \
            [o_view setFrame: s_vrc]; \
        } \
    }

#define CONTROL_LABEL( label ) \
    { \
        s_rc.origin.x += s_rc.size.width + 10; \
        s_rc.size.width = s_vrc.size.width - s_rc.origin.x - X_ORIGIN - 20; \
        o_text_field = [[NSTextField alloc] initWithFrame: s_rc]; \
        [o_text_field setDrawsBackground: NO]; \
        [o_text_field setBordered: NO]; \
        [o_text_field setEditable: NO]; \
        [o_text_field setSelectable: NO]; \
240
241
242
243
244
        if ( label ) \
        { \
            [o_text_field setStringValue: \
                [NSApp localizedString: label]]; \
        } \
245
        [o_text_field sizeToFit]; \
246
247
248
        [o_view addSubview: [o_text_field autorelease]]; \
    }

Christophe Massiot's avatar
Christophe Massiot committed
249
#define INPUT_FIELD( ctype, cname, label, w, msg, param, tip ) \
250
    { \
251
        char * psz_duptip = NULL; \
252
        if ( p_item->psz_longtext != NULL && [NSApp getEncoding] == NSISOLatin1StringEncoding ) \
253
            psz_duptip = strdup(p_item->psz_longtext); \
Christophe Massiot's avatar
Christophe Massiot committed
254
        s_rc.size.height = 25; \
255
256
257
258
259
260
261
        s_rc.size.width = w; \
        s_rc.origin.y += 10; \
        CHECK_VIEW_HEIGHT; \
        o_text_field = [[VLCTextField alloc] initWithFrame: s_rc]; \
        [o_text_field setAlignment: NSRightTextAlignment]; \
        CONTROL_CONFIG( o_text_field, o_module_name, ctype, cname ); \
        [o_text_field msg: param]; \
262
263
264
265
266
267
        if ( psz_duptip != NULL ) \
        { \
            [o_text_field setToolTip: [NSApp localizedString: \
                                       vlc_wraptext(psz_duptip, PREFS_WRAP)]]; \
            free(psz_duptip);\
        } \
268
269
270
271
272
273
274
275
276
277
        [o_view addSubview: [o_text_field autorelease]]; \
        [[NSNotificationCenter defaultCenter] addObserver: self \
            selector: @selector(configChanged:) \
            name: NSControlTextDidChangeNotification \
            object: o_text_field]; \
        CONTROL_LABEL( label ); \
        s_rc.origin.y += s_rc.size.height; \
        s_rc.origin.x = X_ORIGIN; \
    }

Christophe Massiot's avatar
Christophe Massiot committed
278
279
280
281
282
283
#define INPUT_FIELD_INTEGER( name, label, w, param, tip ) \
    INPUT_FIELD( CONFIG_ITEM_INTEGER, name, label, w, setIntValue, param, tip )
#define INPUT_FIELD_FLOAT( name, label, w, param, tip ) \
    INPUT_FIELD( CONFIG_ITEM_FLOAT, name, label, w, setFloatValue, param, tip )
#define INPUT_FIELD_STRING( name, label, w, param, tip ) \
    INPUT_FIELD( CONFIG_ITEM_STRING, name, label, w, setStringValue, param, tip )
284
285
286

    if( p_item ) do
    {
hartman's avatar
hartman committed
287
        if( p_item->b_advanced && !b_advanced )
288
289
290
        {
            continue;
        }
291
292
293
294
295
296
297
298
299
        switch( p_item->i_type )
        {

        case CONFIG_HINT_CATEGORY:
        {
            NSString *o_key;
            NSString *o_label;
            NSToolbarItem *o_tbi;

Christophe Massiot's avatar
Christophe Massiot committed
300
            o_label = [NSApp localizedString: p_item->psz_text];
301
            o_tbi = [[NSToolbarItem alloc] initWithItemIdentifier: o_label];
302
303
304
305
306
307
            [o_tbi setImage: [NSImage imageNamed: @"NSApplicationIcon"]];
            [o_tbi setLabel: o_label];
            [o_tbi setTarget: self];
            [o_tbi setAction: @selector(selectPrefView:)];

            o_key = [NSString stringWithFormat: @"%02d %@",
308
                                                i_pos, o_label];
309
310
311
312
313
314
315
316
317
318
319
320
321
            [o_tb_items setObject: o_tbi forKey: o_key];

            s_vrc = s_scroll_rc; s_vrc.size.height -= 4;
            o_view = [[VLCFlippedView alloc] initWithFrame: s_vrc];
            [o_views setObject: o_view forKey: o_label];

            s_rc.origin.x = X_ORIGIN;
            s_rc.origin.y = Y_ORIGIN;

            i_module_tag = 3;

            if( i_pos == 0 )
            {
322
                [o_scroll_view setDocumentView: o_view];
323
324
325
326
327
328
329
330
331
332
333
334
335
336
            }

            i_pos++;
        }
        break;

        case CONFIG_ITEM_MODULE:
        {
            NSBox *o_box;
            NSRect s_crc;
            NSView *o_cview;
            NSPopUpButton *o_modules;
            NSButton *o_btn_select;
            NSButton *o_btn_configure;
337
            char * psz_duptip = NULL;
338
            if ( p_item->psz_longtext != NULL && [NSApp getEncoding] == NSISOLatin1StringEncoding )
339
                psz_duptip = strdup(p_item->psz_longtext);
340
341
342

#define MODULE_BUTTON( button, title, sel ) \
    { \
Christophe Massiot's avatar
Christophe Massiot committed
343
        s_brc.size.height = 32; \
344
345
346
347
348
349
350
351
352
353
354
355
        s_brc.origin.x += s_brc.size.width + 10; \
        s_brc.size.width = s_crc.size.width - s_brc.origin.x - 10; \
        button = [[NSButton alloc] initWithFrame: s_brc]; \
        [button setButtonType: NSMomentaryPushInButton]; \
        [button setBezelStyle: NSRoundedBezelStyle]; \
        [button setTitle: title]; \
        [button setTag: i_module_tag++]; \
        [button setTarget: self]; \
        [button setAction: @selector(sel)]; \
        [o_cview addSubview: [button autorelease]]; \
    }

Christophe Massiot's avatar
Christophe Massiot committed
356
            s_rc.size.height = 107;
357
358
359
360
361
362
            s_rc.size.width = s_vrc.size.width - X_ORIGIN * 2 - 20;
            s_rc.origin.y += i_module_tag == 3 ? Y_ORIGIN : 20;

            CHECK_VIEW_HEIGHT;

            o_box = [[NSBox alloc] initWithFrame: s_rc];
Christophe Massiot's avatar
Christophe Massiot committed
363
            [o_box setTitle: [NSApp localizedString: p_item->psz_text]];
364
365
366
367
368
369
            [o_view addSubview: [o_box autorelease]];
            s_rc.origin.y += s_rc.size.height + 10;
            o_cview = [[VLCFlippedView alloc] initWithFrame: s_rc];
            [o_box setContentView: [o_cview autorelease]];
            s_crc = [o_cview bounds];

370
            s_brc = NSMakeRect( 5, 10, 200, 30 );
371
372
373
374
            o_modules = [[NSPopUpButton alloc] initWithFrame: s_brc];
            [o_modules setTag: i_module_tag++];
            [o_modules setTarget: self];
            [o_modules setAction: @selector(moduleSelected:)];
375
376
377
378
379
380
            if ( psz_duptip != NULL )
            {
                [o_modules setToolTip: [NSApp localizedString:
                                        vlc_wraptext(psz_duptip, PREFS_WRAP)]];
                free( psz_duptip );
            }
381
            [o_cview addSubview: [o_modules autorelease]];
382

383
            MODULE_BUTTON( o_btn_configure, _NS("Configure"),
384
385
                           configureModule: );

386
387
            s_brc = NSMakeRect( 8, s_brc.origin.y + s_brc.size.height + 10,
                                194, 25 );
388
389
390
            o_text_field = [[VLCTextField alloc] initWithFrame: s_brc];
            [o_text_field setTag: i_module_tag++];
            [o_text_field setAlignment: NSLeftTextAlignment];
391
            CONTROL_CONFIG( o_text_field, o_module_name,
392
393
394
395
396
397
398
399
                            CONFIG_ITEM_MODULE, p_item->psz_name );
            [[NSNotificationCenter defaultCenter] addObserver: self
                selector: @selector(configChanged:)
                name: NSControlTextDidChangeNotification
                object: o_text_field];
            [o_cview addSubview: [o_text_field autorelease]];

            s_brc.origin.x += 3;
400
            MODULE_BUTTON( o_btn_select, _NS("Select"),
401
402
403
404
405
406
                           selectModule: );

            [o_modules addItemWithTitle: _NS("None")];

            /* build a list of available modules */
            {
407
                for( i_index = 0; i_index < p_list->i_count; i_index++ )
408
                {
409
                    p_parser = (module_t *)p_list->p_values[i_index].p_object ;
gbazin's avatar
   
gbazin committed
410
411

                    if( !strcmp( p_parser->psz_capability,
412
413
                                 p_item->psz_type ) )
                    {
414
                        NSString *o_object_name = [NSString
gbazin's avatar
   
gbazin committed
415
                            stringWithCString: p_parser->psz_object_name];
416
417
418
419
420
421
422
423
424
425
                        [o_modules addItemWithTitle: o_object_name];
                    }
                }
            }

            if( p_item->psz_value != NULL )
            {
                NSString *o_value =
                    [NSString stringWithCString: p_item->psz_value];

426
427
428
                [o_text_field setStringValue: o_value];
                [o_modules selectItemWithTitle: o_value];
                [o_btn_configure setEnabled: [self hasPrefs: o_value]];
429
430
431
432
433
434
435
436
437
438
439
440
441
            }
            else
            {
                [o_modules selectItemWithTitle: _NS("None")];
                [o_btn_configure setEnabled: NO];
            }

#undef MODULE_BUTTON
        }
        break;

        case CONFIG_ITEM_STRING:
        case CONFIG_ITEM_FILE:
hartman's avatar
hartman committed
442
        case CONFIG_ITEM_DIRECTORY:
443
444
445
446
447
448
449
450
        {

            if( !p_item->ppsz_list )
            {
                char *psz_value = p_item->psz_value ?
                                  p_item->psz_value : "";

                INPUT_FIELD_STRING( p_item->psz_name, p_item->psz_text, 150,
Christophe Massiot's avatar
Christophe Massiot committed
451
452
                                    [NSString stringWithCString: psz_value],
                                    p_item->psz_longtext );
453
454
455
456
457
            }
            else
            {
                int i;
                VLCComboBox *o_combo_box;
458
                char * psz_duptip = NULL;
459
                if ( p_item->psz_longtext != NULL && [NSApp getEncoding] == NSISOLatin1StringEncoding )
460
                    psz_duptip = strdup(p_item->psz_longtext);
461

Christophe Massiot's avatar
Christophe Massiot committed
462
                s_rc.size.height = 27;
463
464
465
466
467
468
                s_rc.size.width = 150;
                s_rc.origin.y += 10;

                CHECK_VIEW_HEIGHT;

                o_combo_box = [[VLCComboBox alloc] initWithFrame: s_rc];
469
                CONTROL_CONFIG( o_combo_box, o_module_name,
470
                                CONFIG_ITEM_STRING, p_item->psz_name );
471
472
473
474
475
476
                if ( psz_duptip != NULL )
                {
                    [o_combo_box setToolTip: [NSApp localizedString:
                                        vlc_wraptext(psz_duptip, PREFS_WRAP)]];
                    free( psz_duptip );
                }
477
                [o_view addSubview: [o_combo_box autorelease]];
478
479
480
481
482
483
484
485
486
                
                for( i=0; p_item->ppsz_list[i]; i++ )
                {
                    [o_combo_box addItemWithObjectValue:
                        [NSString stringWithCString: p_item->ppsz_list[i]]];
                }
                [o_combo_box setStringValue: [NSString stringWithCString: 
                    p_item->psz_value ? p_item->psz_value : ""]];

487
488
489
490
491
492
                [[NSNotificationCenter defaultCenter] addObserver: self
                    selector: @selector(configChanged:)
                    name: NSControlTextDidChangeNotification
                    object: o_combo_box];
                [[NSNotificationCenter defaultCenter] addObserver: self
                    selector: @selector(configChanged:)
493
                    name: NSComboBoxSelectionDidChangeNotification
494
495
                    object: o_combo_box];

496
                CONTROL_LABEL( p_item->psz_text );
497
498
499
500
501
502
503
504
505
506

                s_rc.origin.y += s_rc.size.height;
                s_rc.origin.x = X_ORIGIN;
            }

        }
        break;

        case CONFIG_ITEM_INTEGER:
        {
507
            INPUT_FIELD_INTEGER( p_item->psz_name, p_item->psz_text, 70,
Christophe Massiot's avatar
Christophe Massiot committed
508
                                 p_item->i_value, p_item->psz_longtext );
509
510
511
512
513
514
        }
        break;

        case CONFIG_ITEM_FLOAT:
        {
            INPUT_FIELD_FLOAT( p_item->psz_name, p_item->psz_text, 70,
Christophe Massiot's avatar
Christophe Massiot committed
515
                               p_item->f_value, p_item->psz_longtext );
516
517
518
519
520
521
        }
        break;

        case CONFIG_ITEM_BOOL:
        {
            VLCButton *o_btn_bool;
522
            char * psz_duptip = NULL;
523
            if ( p_item->psz_longtext != NULL && [NSApp getEncoding] == NSISOLatin1StringEncoding )
524
                psz_duptip = strdup(p_item->psz_longtext);
525

Christophe Massiot's avatar
Christophe Massiot committed
526
            s_rc.size.height = 27;
527
528
529
530
531
532
533
534
            s_rc.size.width = s_vrc.size.width - X_ORIGIN * 2 - 20;
            s_rc.origin.y += 10;

            CHECK_VIEW_HEIGHT;

            o_btn_bool = [[VLCButton alloc] initWithFrame: s_rc];
            [o_btn_bool setButtonType: NSSwitchButton];
            [o_btn_bool setIntValue: p_item->i_value];
535
            [o_btn_bool setTitle:
Christophe Massiot's avatar
Christophe Massiot committed
536
                [NSApp localizedString: p_item->psz_text]];
537
538
539
540
541
542
            if ( psz_duptip != NULL )
            {
                [o_btn_bool setToolTip: [NSApp localizedString:
                                        vlc_wraptext(psz_duptip, PREFS_WRAP)]];
                free( psz_duptip );
            }
543
544
            [o_btn_bool setTarget: self];
            [o_btn_bool setAction: @selector(configChanged:)];
545
546
            CONTROL_CONFIG( o_btn_bool, o_module_name,
                            CONFIG_ITEM_BOOL, p_item->psz_name );
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
            [o_view addSubview: [o_btn_bool autorelease]];

            s_rc.origin.y += s_rc.size.height;
        }
        break;

        }

#undef INPUT_FIELD_INTEGER
#undef INPUT_FIELD_FLOAT
#undef INPUT_FIELD_STRING
#undef INPUT_FIELD
#undef CHECK_VIEW_HEIGHT
#undef CONTROL_LABEL
#undef Y_ORIGIN
#undef X_ORIGIN
    }
    while( p_item->i_type != CONFIG_HINT_END && p_item++ );

566
    vlc_list_release( p_list );
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

    [o_toolbars setObject: o_tb_items forKey: o_module_name];
    [o_toolbar setDelegate: self];
    [o_panel setToolbar: [o_toolbar autorelease]];

#define DEF_PANEL_BUTTON( tag, title, sel ) \
    { \
        o_button = [[NSButton alloc] initWithFrame: s_rc]; \
        [o_button setButtonType: NSMomentaryPushInButton]; \
        [o_button setBezelStyle: NSRoundedBezelStyle]; \
        [o_button setAction: @selector(sel)]; \
        [o_button setTarget: self]; \
        [o_button setTitle: title]; \
        [o_button setTag: tag]; \
        [o_panel_view addSubview: [o_button autorelease]]; \
    }

    s_rc.origin.y = s_panel_rc.origin.y + 14;
585
    s_rc.size.height = 25; s_rc.size.width = 105;
586
    s_rc.origin.x = s_panel_rc.size.width - s_rc.size.width - 14;
587
    DEF_PANEL_BUTTON( 0, _NS("OK"), clickedApplyCancelOK: );
588
589
590
    [o_panel setDefaultButtonCell: [o_button cell]];

    s_rc.origin.x -= s_rc.size.width;
591
    DEF_PANEL_BUTTON( 1, _NS("Cancel"), clickedApplyCancelOK: );
592
    [o_button setKeyEquivalent: @"\E"];
593

hartman's avatar
hartman committed
594
595
596
597
598
599
600
601
602
    s_rc.origin.x = 20;
    o_button = [[NSButton alloc] initWithFrame: s_rc];
    [o_button setButtonType: NSSwitchButton];
    [o_button setAction: @selector(clickedApplyCancelOK:)];
    [o_button setTarget: self];
    [o_button setTitle: _NS("Advanced")];
    [o_button setTag: 2];
    [o_panel_view addSubview: [o_button autorelease]];
    [o_button setState: b_advanced];
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671

#undef DEF_PANEL_BUTTON

    [o_pref_panels setObject: o_panel forKey: o_module_name];
    [o_panel_views setObject: o_views forKey: o_module_name];

    [o_panel center];
    [o_panel makeKeyAndOrderFront: nil];
}

- (void)destroyPrefPanel:(id)o_unknown
{
    id v1;
    NSPanel *o_panel;
    NSEnumerator *o_e1;
    NSMutableArray *o_prefs;
    NSMutableDictionary *o_dic;
    NSScrollView *o_scroll_view;
    NSString *o_module_name;

    o_module_name = (NSString *)([o_unknown isKindOfClass: [NSTimer class]] ?
                                 [o_unknown userInfo] : o_unknown);

#define DIC_REL(dic) \
    { \
    o_dic = [dic objectForKey: o_module_name]; \
    [dic removeObjectForKey: o_module_name]; \
    o_e1 = [o_dic objectEnumerator]; \
    while( (v1 = [o_e1 nextObject]) ) \
    { \
        [v1 release]; \
    } \
    [o_dic removeAllObjects]; \
    [o_dic release]; \
    }

    o_panel = [o_pref_panels objectForKey: o_module_name];
    [o_pref_panels removeObjectForKey: o_module_name];
    [o_panel release];

    DIC_REL(o_toolbars);

    o_scroll_view = [o_scroll_views objectForKey: o_module_name];
    [o_scroll_views removeObjectForKey: o_module_name];
    [o_scroll_view release];

    DIC_REL(o_panel_views);

    o_prefs = [o_save_prefs objectForKey: o_module_name];
    [o_save_prefs removeObjectForKey: o_module_name];
    [o_prefs removeAllObjects];
    [o_prefs release];

#undef DIC_REL

}

- (void)selectPrefView:(id)sender
{
    NSView *o_view;
    NSString *o_module_name;
    NSScrollView *o_scroll_view;
    NSMutableDictionary *o_views;

    o_module_name = [[sender toolbar] identifier];
    o_views = [o_panel_views objectForKey: o_module_name];
    o_view = [o_views objectForKey: [sender label]];

    o_scroll_view = [o_scroll_views objectForKey: o_module_name];
672
    [o_scroll_view setDocumentView: o_view];
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
}

- (void)moduleSelected:(id)sender
{
    NSButton *o_btn_config;
    NSString *o_module_name;
    BOOL b_has_prefs = NO;

    o_module_name = [sender titleOfSelectedItem];
    o_btn_config = [[sender superview] viewWithTag: [sender tag] + 1];

    if( ![o_module_name isEqualToString: _NS("None")] )
    {
        b_has_prefs = [self hasPrefs: o_module_name];
    }

    [o_btn_config setEnabled: b_has_prefs];
}

- (void)configureModule:(id)sender
{
    NSString *o_module_name;
    NSPopUpButton *o_modules;

697
    o_modules = [[sender superview] viewWithTag: [sender tag] - 1];
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
    o_module_name = [o_modules titleOfSelectedItem];

    [self createPrefPanel: o_module_name];
}

- (void)selectModule:(id)sender
{
    NSString *o_module_name;
    NSPopUpButton *o_modules;
    NSTextField *o_module;

    o_module = [[sender superview] viewWithTag: [sender tag] - 1];
    o_modules = [[sender superview] viewWithTag: [sender tag] - 3];
    o_module_name = [o_modules titleOfSelectedItem];

    if( [o_module_name isEqualToString: _NS("None")] )
    {
        o_module_name = [NSString string];
    }

    [o_module setStringValue: o_module_name];
    [self configChanged: o_module];
}

- (void)configChanged:(id)o_unknown
{
    id o_vlc_config = [o_unknown isKindOfClass: [NSNotification class]] ?
                      [o_unknown object] : o_unknown;

727
728
    NSString *o_module_name = [o_vlc_config moduleName];
    NSPanel *o_pref_panel = [o_pref_panels objectForKey: o_module_name];
729
730
731
732
733
    NSMutableArray *o_prefs = [o_save_prefs objectForKey: o_module_name];

    if( [o_prefs indexOfObjectIdenticalTo: o_vlc_config] == NSNotFound )
    {
        NSView *o_pref_view = [o_pref_panel contentView];
734
        NSButton *o_btn_apply = [o_pref_view viewWithTag: 2];
735
736
737
738
739
740

        [o_prefs addObject: o_vlc_config];
        [o_btn_apply setEnabled: YES];
    }
}

741
- (void)clickedApplyCancelOK:(id)sender
742
743
744
{
    id o_vlc_control;
    NSEnumerator *o_enum;
hartman's avatar
hartman committed
745

746
747
    NSWindow *o_pref_panel = [[sender superview] window];
    NSString *o_module_name = [[o_pref_panel toolbar] identifier];
hartman's avatar
hartman committed
748
    NSView *o_config_view = [sender superview];
749

hartman's avatar
hartman committed
750
    if ( [[sender title] isEqualToString: _NS("OK")] )
751
    {
752
753
754
755
756
757
        NSWindow *o_config_panel = [o_config_view window];
        NSString *o_module_name = [[o_config_panel toolbar] identifier];
        NSMutableArray *o_prefs = [o_save_prefs objectForKey: o_module_name];
    
        o_enum = [o_prefs objectEnumerator];
        while( ( o_vlc_control = [o_enum nextObject] ) )
758
        {
759
760
761
762
763
            int i_type = [o_vlc_control configType];
            NSString *o_name = [o_vlc_control configName];
            char *psz_name = (char *)[o_name lossyCString];
    
            switch( i_type )
764
            {
765
766
767
768
    
            case CONFIG_ITEM_MODULE:
            case CONFIG_ITEM_STRING:
            case CONFIG_ITEM_FILE:
hartman's avatar
hartman committed
769
            case CONFIG_ITEM_DIRECTORY:
770
771
772
773
774
775
776
                {
                    char *psz_value;
                    NSString *o_value;
    
                    o_value = [o_vlc_control stringValue];
                    psz_value = (char *)[o_value lossyCString];
    
777
                    config_PutPsz( p_intf, psz_name, psz_value );
778
779
780
781
782
783
784
                }
                break;
    
            case CONFIG_ITEM_INTEGER:
            case CONFIG_ITEM_BOOL:
                {
                    int i_value = [o_vlc_control intValue];
785

786
787
788
789
790
791
792
793
794
795
796
797
                    config_PutInt( p_intf, psz_name, i_value );
                }
                break;
    
            case CONFIG_ITEM_FLOAT:
                {
                    float f_value = [o_vlc_control floatValue];
    
                    config_PutFloat( p_intf, psz_name, f_value );
                }
                break;
    
798
799
            }
        }
800
801
    
        config_SaveConfigFile( p_intf, NULL );
802
    }
hartman's avatar
hartman committed
803
    if( [[sender title] isEqualToString: _NS("Advanced")] )
804
    {
hartman's avatar
hartman committed
805
806
807
808
809
        NSButton *o_btn_apply = [o_config_view viewWithTag: 2];
        b_advanced = !b_advanced;
        [o_btn_apply setState: b_advanced];
    }
    [o_pref_panel close];
810

hartman's avatar
hartman committed
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
    if( [self respondsToSelector: @selector(performSelectorOnMainThread:
                                            withObject:waitUntilDone:)] )
    {
        [self performSelectorOnMainThread: @selector(destroyPrefPanel:)
                                        withObject: o_module_name
                                        waitUntilDone: YES];
    }
    else
    {
        [NSTimer scheduledTimerWithTimeInterval: 0.1
                target: self selector: @selector(destroyPrefPanel:)
                userInfo: o_module_name repeats: NO];
    }
    
    if( [[sender title] isEqualToString: _NS("Advanced")] )
    {
        [self createPrefPanel: o_module_name];
828
829
830
831
832
833
834
    }
}

@end

@implementation VLCPrefs (NSToolbarDelegate)

835
836
- (NSToolbarItem *)toolbar:(NSToolbar *)o_toolbar
                   itemForItemIdentifier:(NSString *)o_item_id
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
                   willBeInsertedIntoToolbar:(BOOL)b_flag
{
    NSMutableDictionary *o_toolbar_items;
    NSString *o_module_name = [o_toolbar identifier];

    o_toolbar_items = [o_toolbars objectForKey: o_module_name];
    if( o_toolbar_items == nil )
    {
        return( nil );
    }

    return( [o_toolbar_items objectForKey: o_item_id] );
}

- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)o_toolbar
{
    return( [self toolbarDefaultItemIdentifiers: o_toolbar] );
}

- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)o_toolbar
{
    NSArray *o_ids;
    NSMutableDictionary *o_toolbar_items;
    NSString *o_module_name = [o_toolbar identifier];

    o_toolbar_items = [o_toolbars objectForKey: o_module_name];
    if( o_toolbar_items == nil )
    {
        return( nil );
866
    }
867

868
    o_ids = [[o_toolbar_items allKeys]
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
        sortedArrayUsingSelector: @selector(compare:)];

    return( o_ids );
}

@end

@implementation VLCFlippedView

- (BOOL)isFlipped
{
    return( YES );
}

@end

IMPL_CONTROL_CONFIG(Button);
IMPL_CONTROL_CONFIG(ComboBox);
IMPL_CONTROL_CONFIG(TextField);