simple_prefs.m 63.6 KB
Newer Older
1
2
3
/*****************************************************************************
* simple_prefs.m: Simple Preferences for Mac OS X
*****************************************************************************
4
* Copyright (C) 2008-2014 VLC authors and VideoLAN
5
* $Id$
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
*
* Authors: Felix Paul Kühne <fkuehne at videolan dot org>
*
* 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.
*
* 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
23
24
25
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
26

27
#import "CompatibilityFixes.h"
28
29
#import "simple_prefs.h"
#import "prefs.h"
30
#import <vlc_keys.h>
31
#import <vlc_interface.h>
32
#import <vlc_dialog.h>
33
#import <vlc_modules.h>
34
#import <vlc_plugin.h>
35
#import <vlc_config_cat.h>
36
#import "misc.h"
37
38
#import "intf.h"
#import "AppleRemote.h"
39
#import "CoreInteraction.h"
40

41
#ifdef HAVE_SPARKLE
42
#import <Sparkle/Sparkle.h>                        //for o_intf_last_updateLabel
43
#endif
44

45
46
47
48
49
50
51
52
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
static const char *const ppsz_language[] =
{
    "auto",
    "en",
    "ar",
    "bn",
    "pt_BR",
    "en_GB",
    "el",
    "bg",
    "ca",
    "zh_TW",
    "cs",
    "cy",
    "da",
    "nl",
    "fi",
    "et",
    "eu",
    "fr",
    "ga",
    "gd",
    "gl",
    "ka",
    "de",
    "he",
    "hr",
    "hu",
    "hy",
    "is",
    "id",
    "it",
    "ja",
    "ko",
    "lt",
    "mn",
    "ms",
    "nb",
    "nn",
    "kk",
    "km",
    "ne",
    "oc",
    "fa",
    "pl",
    "pt_PT",
    "pa",
    "ro",
    "ru",
    "zh_CN",
    "si",
    "sr",
    "sk",
    "sl",
    "ckb",
    "es",
    "sv",
    "te",
    "tr",
    "uk",
    "vi",
    "wa",
    NULL,
};

static const char *const ppsz_language_text[] =
{
    N_("Auto"),
    "American English",
    "ﻉﺮﺒﻳ",
    "বাংলা",
    "Português Brasileiro",
    "British English",
    "Νέα Ελληνικά",
    "български език",
    "Català",
    "正體中文",
    "Čeština",
    "Cymraeg",
    "Dansk",
    "Nederlands",
    "Suomi",
    "eesti keel",
    "Euskara",
    "Français",
    "Gaeilge",
    "Gàidhlig",
    "Galego",
    "ქართული",
    "Deutsch",
    "עברית",
    "hrvatski",
    "Magyar",
    "հայերեն",
    "íslenska",
    "Bahasa Indonesia",
    "Italiano",
    "日本語",
    "한국어",
    "lietuvių",
    "Монгол хэл",
    "Melayu",
    "Bokmål",
    "Nynorsk",
    "Қазақ тілі",
    "ភាសាខ្មែរ",
    "नेपाली",
    "Occitan",
    "ﻑﺍﺮﺳی",
    "Polski",
    "Português",
    "ਪੰਜਾਬੀ",
    "Română",
    "Русский",
    "简体中文",
    "සිංහල",
    "српски",
    "Slovensky",
    "slovenščina",
    "کوردیی سۆرانی",
    "Español",
    "Svenska",
    "తెలుగు",
    "Türkçe",
    "украї́нська мо́ва",
    "tiếng Việt",
    "Walon",
};

174
175
176
static NSString* VLCSPrefsToolbarIdentifier = @"Our Simple Preferences Toolbar Identifier";
static NSString* VLCIntfSettingToolbarIdentifier = @"Intf Settings Item Identifier";
static NSString* VLCAudioSettingToolbarIdentifier = @"Audio Settings Item Identifier";
177
static NSString* VLCVideoSettingToolbarIdentifier = @"Video Settings Item Identifier";
178
179
180
static NSString* VLCOSDSettingToolbarIdentifier = @"Subtitles Settings Item Identifier";
static NSString* VLCInputSettingToolbarIdentifier = @"Input Settings Item Identifier";
static NSString* VLCHotkeysSettingToolbarIdentifier = @"Hotkeys Settings Item Identifier";
181

182
@interface VLCSimplePrefs() <NSToolbarDelegate, NSWindowDelegate>
183
{
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    BOOL _audioSettingChanged;
    BOOL _intfSettingChanged;
    BOOL _videoSettingChanged;
    BOOL _osdSettingChanged;
    BOOL _inputSettingChanged;
    BOOL _hotkeyChanged;
    id _currentlyShownCategoryView;

    NSOpenPanel *_selectFolderPanel;
    NSArray *_hotkeyDescriptions;
    NSArray *_hotkeyNames;
    NSArray *_hotkeysNonUseableKeys;
    NSMutableArray *_hotkeySettings;
    NSString *_keyInTransition;
198
199
200
201
202

    intf_thread_t *p_intf;
}
@end

203
204
@implementation VLCSimplePrefs

205
206
#pragma mark Initialisation

207
208
- (id)init
{
209
210
211
    self = [super init];
    p_intf = VLCIntf;
    return self;
212
213
214
215
216
}

- (void)awakeFromNib
{
    [self initStrings];
217

218
#ifdef HAVE_SPARKLE
219
    [_intf_updateCheckbox bind:@"value"
220
221
222
223
                   toObject:[SUUpdater sharedUpdater]
                withKeyPath:@"automaticallyChecksForUpdates"
                    options:nil];
#else
224
225
    [_intf_updateCheckbox setState:NSOffState];
    [_intf_updateCheckbox setEnabled:NO];
226
227
#endif

228
    /* setup the toolbar */
229
230
231
232
233
234
235
    NSToolbar * toolbar = [[NSToolbar alloc] initWithIdentifier: VLCSPrefsToolbarIdentifier];
    [toolbar setAllowsUserCustomization: NO];
    [toolbar setAutosavesConfiguration: NO];
    [toolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
    [toolbar setSizeMode: NSToolbarSizeModeRegular];
    [toolbar setDelegate: self];
    [_window setToolbar:toolbar];
236

237
238
    [_window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
    [_window setHidesOnDeactivate:YES];
239

240
241
    [_hotkeys_listbox setTarget:self];
    [_hotkeys_listbox setDoubleAction:@selector(hotkeyTableDoubleClick:)];
242

243
    /* setup useful stuff */
244
    _hotkeysNonUseableKeys = [NSArray arrayWithObjects:@"Command-c", @"Command-x", @"Command-v", @"Command-a", @"Command-," , @"Command-h", @"Command-Alt-h", @"Command-Shift-o", @"Command-o", @"Command-d", @"Command-n", @"Command-s", @"Command-l", @"Command-r", @"Command-3", @"Command-m", @"Command-w", @"Command-Shift-w", @"Command-Shift-c", @"Command-Shift-p", @"Command-i", @"Command-e", @"Command-Shift-e", @"Command-b", @"Command-Shift-m", @"Command-Ctrl-m", @"Command-?", @"Command-Alt-?", nil];
245
246
}

247
248
#define CreateToolbarItem(name, desc, img, sel) \
    toolbarItem = create_toolbar_item(itemIdent, name, desc, img, self, @selector(sel));
249
static inline NSToolbarItem *
250
create_toolbar_item(NSString *itemIdent, NSString *name, NSString *desc, NSString *img, id target, SEL selector)
251
{
252
    NSToolbarItem *toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier: itemIdent];
253

254
255
    [toolbarItem setLabel:name];
    [toolbarItem setPaletteLabel:desc];
256

257
258
    [toolbarItem setToolTip:desc];
    [toolbarItem setImage:[NSImage imageNamed:img]];
259

260
261
    [toolbarItem setTarget:target];
    [toolbarItem setAction:selector];
262

263
264
    [toolbarItem setEnabled:YES];
    [toolbarItem setAutovalidates:YES];
265

266
    return toolbarItem;
267
268
}

269
270
271
- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar
      itemForItemIdentifier:(NSString *)itemIdent
  willBeInsertedIntoToolbar:(BOOL)willBeInserted
272
{
273
    NSToolbarItem *toolbarItem = nil;
274

275
    if ([itemIdent isEqual: VLCIntfSettingToolbarIdentifier]) {
276
        CreateToolbarItem(_NS("Interface"), _NS("Interface Settings"), @"spref_cone_Interface_64", showInterfaceSettings);
277
    } else if ([itemIdent isEqual: VLCAudioSettingToolbarIdentifier]) {
278
        CreateToolbarItem(_NS("Audio"), _NS("Audio Settings"), @"spref_cone_Audio_64", showAudioSettings);
279
    } else if ([itemIdent isEqual: VLCVideoSettingToolbarIdentifier]) {
280
        CreateToolbarItem(_NS("Video"), _NS("Video Settings"), @"spref_cone_Video_64", showVideoSettings);
281
    } else if ([itemIdent isEqual: VLCOSDSettingToolbarIdentifier]) {
282
        CreateToolbarItem(_NS(SUBPIC_TITLE), _NS("Subtitle & On Screen Display Settings"), @"spref_cone_Subtitles_64", showOSDSettings);
283
    } else if ([itemIdent isEqual: VLCInputSettingToolbarIdentifier]) {
284
        CreateToolbarItem(_NS(INPUT_TITLE), _NS("Input & Codec Settings"), @"spref_cone_Input_64", showInputSettings);
285
    } else if ([itemIdent isEqual: VLCHotkeysSettingToolbarIdentifier]) {
286
        CreateToolbarItem(_NS("Hotkeys"), _NS("Hotkeys settings"), @"spref_cone_Hotkeys_64", showHotkeySettings);
287
288
    }

289
    return toolbarItem;
290
291
292
293
}

- (NSArray *)toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar
{
294
    return [NSArray arrayWithObjects:VLCIntfSettingToolbarIdentifier, VLCAudioSettingToolbarIdentifier, VLCVideoSettingToolbarIdentifier,
295
             VLCOSDSettingToolbarIdentifier, VLCInputSettingToolbarIdentifier, VLCHotkeysSettingToolbarIdentifier,
296
             NSToolbarFlexibleSpaceItemIdentifier, nil];
297
298
299
300
}

- (NSArray *)toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar
{
301
    return [NSArray arrayWithObjects:VLCIntfSettingToolbarIdentifier, VLCAudioSettingToolbarIdentifier, VLCVideoSettingToolbarIdentifier,
302
             VLCOSDSettingToolbarIdentifier, VLCInputSettingToolbarIdentifier, VLCHotkeysSettingToolbarIdentifier,
303
             NSToolbarFlexibleSpaceItemIdentifier, nil];
304
305
306
307
}

- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
{
308
309
    return [NSArray arrayWithObjects:VLCIntfSettingToolbarIdentifier, VLCAudioSettingToolbarIdentifier, VLCVideoSettingToolbarIdentifier,
             VLCOSDSettingToolbarIdentifier, VLCInputSettingToolbarIdentifier, VLCHotkeysSettingToolbarIdentifier, nil];
310
311
312
313
}

- (void)initStrings
{
314
    /* audio */
315
316
317
318
319
320
321
322
323
324
325
326
    [_audio_dolbyLabel setStringValue: _NS("Force detection of Dolby Surround")];
    [_audio_effectsBox setTitle: _NS("Audio Effects")];
    [_audio_enableCheckbox setTitle: _NS("Enable audio")];
    [_audio_generalBox setTitle: _NS("General Audio")];
    [_audio_langLabel setStringValue: _NS("Preferred Audio language")];
    [_audio_lastCheckbox setTitle: _NS("Enable Last.fm submissions")];
    [_audio_lastpwdLabel setStringValue: _NS("Password")];
    [_audio_lastuserLabel setStringValue: _NS("Username")];
    [_audio_spdifCheckbox setTitle: _NS("Use S/PDIF when available")];
    [_audio_visualLabel setStringValue: _NS("Visualization")];
    [_audio_autosavevol_yesButtonCell setTitle: _NS("Keep audio level between sessions")];
    [_audio_autosavevol_noButtonCell setTitle: _NS("Always reset audio start level to:")];
327
328

    /* hotkeys */
329
330
331
332
333
334
335
336
    [_hotkeys_changeButton setTitle: _NS("Change")];
    [_hotkeys_change_win setTitle: _NS("Change Hotkey")];
    [_hotkeys_change_cancelButton setTitle: _NS("Cancel")];
    [_hotkeys_change_okButton setTitle: _NS("OK")];
    [_hotkeys_clearButton setTitle: _NS("Clear")];
    [_hotkeysLabel setStringValue: _NS("Select an action to change the associated hotkey:")];
    [[[_hotkeys_listbox tableColumnWithIdentifier: @"action"] headerCell] setStringValue: _NS("Action")];
    [[[_hotkeys_listbox tableColumnWithIdentifier: @"shortcut"] headerCell] setStringValue: _NS("Shortcut")];
337
338

    /* input */
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
    [_input_recordBox setTitle: _NS("Record directory or filename")];
    [_input_recordButton setTitle: _NS("Browse...")];
    [_input_recordButton setToolTip: _NS("Directory or filename where the records will be stored")];
    [_input_aviLabel setStringValue: _NS("Repair AVI Files")];
    [_input_cachelevelLabel setStringValue: _NS("Default Caching Level")];
    [_input_cachingBox setTitle: _NS("Caching")];
    [_input_cachelevel_customLabel setStringValue: _NS("Use the complete preferences to configure custom caching values for each access module.")];
    [_input_muxBox setTitle: _NS("Codecs / Muxers")];
    [_input_netBox setTitle: _NS("Network")];
    [_input_avcodec_hwLabel setStringValue: _NS("Hardware Acceleration")];
    [_input_postprocLabel setStringValue: _NS("Post-Processing Quality")];
    [_input_rtspCheckbox setTitle: _NS("Use RTP over RTSP (TCP)")];
    [_input_skipLoopLabel setStringValue: _NS("Skip the loop filter for H.264 decoding")];
    [_input_mkv_preload_dirCheckbox setTitle: _NS("Preload MKV files in the same directory")];
    [_input_urlhandlerButton setTitle: _NS("Edit default application settings for network protocols")];
354
355

    /* url handler */
356
357
358
359
    [_urlhandler_titleLabel setStringValue: _NS("Open network streams using the following protocols")];
    [_urlhandler_subtitleLabel setStringValue: _NS("Note that these are system-wide settings.")];
    [_urlhandler_saveButton setTitle: _NS("Save")];
    [_urlhandler_cancelButton setTitle: _NS("Cancel")];
360
361

    /* interface */
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
    [_intf_languageLabel setStringValue: _NS("Language")];
    [_intf_styleLabel setStringValue: _NS("Interface style")];
    [_intf_style_darkButtonCell setTitle: _NS("Dark")];
    [_intf_style_brightButtonCell setTitle: _NS("Bright")];
    [_intf_embeddedCheckbox setTitle: _NS("Show video within the main window")];
    [_intf_nativefullscreenCheckbox setTitle: _NS("Use the native fullscreen mode")];
    [_intf_fspanelCheckbox setTitle: _NS("Show Fullscreen Controller")];
    [_intf_networkBox setTitle: _NS("Privacy / Network Interaction")];
    [_intf_appleremoteCheckbox setTitle: _NS("Control playback with the Apple Remote")];
    [_intf_appleremote_sysvolCheckbox setTitle: _NS("Control system volume with the Apple Remote")];
    [_intf_mediakeysCheckbox setTitle: _NS("Control playback with media keys")];
    [_intf_artCheckbox setTitle: _NS("Allow metadata network access")];
    [_intf_updateCheckbox setTitle: _NS("Automatically check for updates")];
    [_intf_last_updateLabel setStringValue: @""];
    [_intf_enableGrowlCheckbox setTitle: _NS("Enable Growl notifications (on playlist item change)")];
    [_intf_autoresizeCheckbox setTitle: _NS("Resize interface to the native video size")];
    [_intf_pauseminimizedCheckbox setTitle: _NS("Pause the video playback when minimized")];
    [_intf_luahttpBox setTitle:_NS("Lua HTTP")];
    [_intf_luahttppwdLabel setStringValue:_NS("Password")];
    [_intf_pauseitunesLabel setStringValue:_NS("Control external music players")];
    [_intf_continueplaybackLabel setStringValue:_NS("Continue playback")];
383

384
    /* Subtitles and OSD */
385
386
387
388
389
390
391
392
393
394
395
396
397
398
    [_osd_encodingLabel setStringValue: _NS("Default Encoding")];
    [_osd_fontBox setTitle: _NS("Display Settings")];
    [_osd_fontButton setTitle: _NS("Choose...")];
    [_osd_font_colorLabel setStringValue: _NS("Font color")];
    [_osd_font_sizeLabel setStringValue: _NS("Font size")];
    [_osd_fontLabel setStringValue: _NS("Font")];
    [_osd_langBox setTitle: _NS("Subtitle languages")];
    [_osd_langLabel setStringValue: _NS("Preferred subtitle language")];
    [_osd_osdBox setTitle: _NS("On Screen Display")];
    [_osd_osdCheckbox setTitle: _NS("Enable OSD")];
    [_osd_opacityLabel setStringValue: _NS("Opacity")];
    [_osd_forceboldCheckbox setTitle: _NS("Force bold")];
    [_osd_outline_colorLabel setStringValue: _NS("Outline color")];
    [_osd_outline_thicknessLabel setStringValue: _NS("Outline thickness")];
399
400

    /* video */
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
    [_video_blackCheckbox setTitle: _NS("Black screens in Fullscreen mode")];
    [_video_deviceLabel setStringValue: _NS("Fullscreen Video Device")];
    [_video_displayBox setTitle: _NS("Display")];
    [_video_enableCheckbox setTitle: _NS("Enable video")];
    [_video_fullscreenCheckbox setTitle: _NS("Fullscreen")];
    [_video_videodecoCheckbox setTitle: _NS("Window decorations")];
    [_video_onTopCheckbox setTitle: _NS("Float on Top")];
    [_video_skipFramesCheckbox setTitle: _NS("Skip frames")];
    [_video_snapBox setTitle: _NS("Video snapshots")];
    [_video_snap_folderButton setTitle: _NS("Browse...")];
    [_video_snap_folderLabel setStringValue: _NS("Folder")];
    [_video_snap_formatLabel setStringValue: _NS("Format")];
    [_video_snap_prefixLabel setStringValue: _NS("Prefix")];
    [_video_snap_seqnumCheckbox setTitle: _NS("Sequential numbering")];
    [_video_deinterlaceLabel setStringValue: _NS("Deinterlace")];
    [_video_deinterlace_modeLabel setStringValue: _NS("Deinterlace mode")];
    [_video_videoBox setTitle: _NS("Video")];
418

419
    /* generic stuff */
420
421
422
423
424
    [_showAllButton setTitle: _NS("Show All")];
    [_cancelButton setTitle: _NS("Cancel")];
    [_resetButton setTitle: _NS("Reset All")];
    [_saveButton setTitle: _NS("Save")];
    [_window setTitle: _NS("Preferences")];
425
426
}

427
428
/* TODO: move this part to core */
#define config_GetLabel(a,b) __config_GetLabel(VLC_OBJECT(a),b)
429
static inline char * __config_GetLabel(vlc_object_t *p_this, const char *psz_name)
430
431
432
{
    module_config_t *p_config;

433
    p_config = config_FindConfig(p_this, psz_name);
434
435

    /* sanity checks */
436
437
    if (!p_config) {
        msg_Err(p_this, "option %s does not exist", psz_name);
438
439
440
        return NULL;
    }

441
    if (p_config->psz_longtext)
442
        return p_config->psz_longtext;
443
    else if (p_config->psz_text)
444
445
        return p_config->psz_text;
    else
446
        msg_Warn(p_this, "option %s does not include any help", psz_name);
447
448
449
450

    return NULL;
}

451
452
453
#pragma mark -
#pragma mark Setup controls

454
455
456
457
458
- (void)setupButton: (NSPopUpButton *)object forStringList: (const char *)name
{
    module_config_t *p_item;

    [object removeAllItems];
459
    p_item = config_FindConfig(VLC_OBJECT(p_intf), name);
460
    /* serious problem, if no item found */
461
    assert(p_item);
462

463
464
465
466
467
468
469
470
471
    char **values, **texts;
    ssize_t count = config_GetPszChoices(VLC_OBJECT(VLCIntf), name,
                                         &values, &texts);
    if (count < 0) {
        msg_Err(p_intf, "Cannot get choices for %s", name);
        return;
    }
    for (ssize_t i = 0; i < count && texts; i++) {
        if (texts[i] == NULL || values[i] == NULL)
472
            continue;
473
474
475
476

        if (strcmp(texts[i], "") != 0) {
            NSMenuItem *mi = [[NSMenuItem alloc] initWithTitle: toNSStr(texts[i]) action: NULL keyEquivalent: @""];
            [mi setRepresentedObject: toNSStr(values[i])];
477
            [[object menu] addItem:mi];
478
479
480
481
482
483

            if (p_item->value.psz && !strcmp(p_item->value.psz, values[i]))
                [object selectItem: [object lastItem]];
            
        } else {
            [[object menu] addItem: [NSMenuItem separatorItem]];
484
        }
485
486
487

        free(texts[i]);
        free(values[i]);
488
    }
489
490
491
492
493
494
495
496
497
498
499
500

    free(texts);
    free(values);

    if (p_item->psz_longtext)
        [object setToolTip: _NS(p_item->psz_longtext)];
}

// just for clarification that this is a module list
- (void)setupButton: (NSPopUpButton *)object forModuleList: (const char *)name
{
    [self setupButton: object forStringList: name];
501
502
503
504
505
506
507
}

- (void)setupButton: (NSPopUpButton *)object forIntList: (const char *)name
{
    module_config_t *p_item;

    [object removeAllItems];
508
    p_item = config_FindConfig(VLC_OBJECT(p_intf), name);
509
510

    /* serious problem, if no item found */
511
    assert(p_item);
512

513
514
515
516
517
518
    int64_t *values;
    char **texts;
    ssize_t count = config_GetIntChoices(VLC_OBJECT(VLCIntf), name, &values, &texts);
    for (ssize_t i = 0; i < count; i++) {
        NSMenuItem *mi = [[NSMenuItem alloc] initWithTitle: toNSStr(texts[i]) action: NULL keyEquivalent: @""];
        [mi setRepresentedObject:[NSNumber numberWithInt:values[i]]];
519
        [[object menu] addItem:mi];
520
521

        if (p_item->value.i == values[i])
522
            [object selectItem:[object lastItem]];
523
524

        free(texts[i]);
525
    }
526
527
528
529
    free(texts);

    if (p_item->psz_longtext)
        [object setToolTip: _NS(p_item->psz_longtext)];
530
531
}

532
533
- (void)setupButton: (NSButton *)object forBoolValue: (const char *)name
{
534
    [object setState: config_GetInt(p_intf, name)];
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
535
    [object setToolTip: _NS(config_GetLabel(p_intf, name))];
536
537
}

538
- (void)setupField:(NSTextField *)object forOption:(const char *)psz_option
539
{
540
    char *psz_tmp = config_GetPsz(p_intf, psz_option);
541
542
    [object setStringValue: [NSString stringWithUTF8String:psz_tmp ?: ""]];
    [object setToolTip: _NS(config_GetLabel(p_intf, psz_option))];
543
    free(psz_tmp);
544
545
}

546
547
548
- (void)resetControls
{
    module_config_t *p_item;
549
    int i, y = 0;
550
551
552
553
554
    char *psz_tmp;

    /**********************
     * interface settings *
     **********************/
555
556
557
558
    NSUInteger sel = 0;
    const char *pref = NULL;
    pref = [[[NSUserDefaults standardUserDefaults] objectForKey:@"language"] UTF8String];
    for (int x = 0; ppsz_language[x] != NULL; x++) {
559
        [_intf_languagePopup addItemWithTitle:[NSString stringWithUTF8String:ppsz_language_text[x]]];
560
561
562
563
564
        if (pref) {
            if (!strcmp(ppsz_language[x], pref))
                sel = x;
        }
    }
565
    [_intf_languagePopup selectItemAtIndex:sel];
566

567
    [self setupButton:_intf_artCheckbox forBoolValue: "metadata-network-access"];
568

569
    [self setupButton:_intf_fspanelCheckbox forBoolValue: "macosx-fspanel"];
570

571
    [self setupButton:_intf_nativefullscreenCheckbox forBoolValue: "macosx-nativefullscreenmode"];
572

573
    [self setupButton:_intf_embeddedCheckbox forBoolValue: "embedded-video"];
574

575
576
    [self setupButton:_intf_appleremoteCheckbox forBoolValue: "macosx-appleremote"];
    [self setupButton:_intf_appleremote_sysvolCheckbox forBoolValue: "macosx-appleremote-sysvol"];
577

578
    [self setupButton:_intf_mediakeysCheckbox forBoolValue: "macosx-mediakeys"];
579

580
#ifdef HAVE_SPARKLE
581
    if ([[SUUpdater sharedUpdater] lastUpdateCheckDate] != NULL)
582
        [_intf_last_updateLabel setStringValue: [NSString stringWithFormat: _NS("Last check on: %@"), [[[SUUpdater sharedUpdater] lastUpdateCheckDate] descriptionWithLocale: [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]]]];
583
    else
584
        [_intf_last_updateLabel setStringValue: _NS("No check was performed yet.")];
585
586
#endif

587
    psz_tmp = config_GetPsz(p_intf, "control");
588
    if (psz_tmp) {
589
        [_intf_enableGrowlCheckbox setState: (NSInteger)strstr(psz_tmp, "growl")];
590
591
        free(psz_tmp);
    } else
592
        [_intf_enableGrowlCheckbox setState: NSOffState];
593
    if (config_GetInt(p_intf, "macosx-interfacestyle")) {
594
595
        [_intf_style_darkButtonCell setState: YES];
        [_intf_style_brightButtonCell setState: NO];
596
    } else {
597
598
        [_intf_style_darkButtonCell setState: NO];
        [_intf_style_brightButtonCell setState: YES];
599
    }
600
601
602
603
604
    [self setupButton:_intf_autoresizeCheckbox forBoolValue: "macosx-video-autoresize"];
    [self setupButton:_intf_pauseminimizedCheckbox forBoolValue: "macosx-pause-minimized"];
    [self setupField:_intf_luahttppwdTextField forOption: "http-password"];
    [self setupButton:_intf_pauseitunesPopup forIntList: "macosx-control-itunes"];
    [self setupButton:_intf_continueplaybackPopup forIntList: "macosx-continue-playback"];
605
606
607
608

    /******************
     * audio settings *
     ******************/
609
    [self setupButton:_audio_enableCheckbox forBoolValue: "audio"];
610

611
    if (config_GetInt(p_intf, "volume-save")) {
612
613
614
615
        [_audio_autosavevol_yesButtonCell setState: NSOnState];
        [_audio_autosavevol_noButtonCell setState: NSOffState];
        [_audio_volTextField setEnabled: NO];
        [_audio_volSlider setEnabled: NO];
616

617
618
        [_audio_volSlider setIntValue: 100];
        [_audio_volTextField setIntValue: 100];
619
    } else {
620
621
622
623
        [_audio_autosavevol_yesButtonCell setState: NSOffState];
        [_audio_autosavevol_noButtonCell setState: NSOnState];
        [_audio_volTextField setEnabled: YES];
        [_audio_volSlider setEnabled: YES];
624

625
        i = var_InheritInteger(p_intf, "auhal-volume");
626
        i = i * 200. / AOUT_VOLUME_MAX;
627
628
        [_audio_volSlider setIntValue: i];
        [_audio_volTextField setIntValue: i];
629
    }
630

631
    [self setupButton:_audio_spdifCheckbox forBoolValue: "spdif"];
632

633
634
    [self setupButton:_audio_dolbyPopup forIntList: "force-dolby-surround"];
    [self setupField:_audio_langTextField forOption: "audio-language"];
635

636
    [self setupButton:_audio_visualPopup forModuleList: "audio-visual"];
637

638
    /* Last.FM is optional */
639
    if (module_exists("audioscrobbler")) {
640
641
        [self setupField:_audio_lastuserTextField forOption:"lastfm-username"];
        [self setupField:_audio_lastpwdSecureTextField forOption:"lastfm-password"];
642

643
        if (config_ExistIntf(VLC_OBJECT(p_intf), "audioscrobbler")) {
644
645
646
            [_audio_lastCheckbox setState: NSOnState];
            [_audio_lastuserTextField setEnabled: YES];
            [_audio_lastpwdSecureTextField setEnabled: YES];
647
        } else {
648
649
650
            [_audio_lastCheckbox setState: NSOffState];
            [_audio_lastuserTextField setEnabled: NO];
            [_audio_lastpwdSecureTextField setEnabled: NO];
651
        }
652
    } else
653
        [_audio_lastCheckbox setEnabled: NO];
654
655
656
657

    /******************
     * video settings *
     ******************/
658
659
660
661
662
663
664
665
    [self setupButton:_video_enableCheckbox forBoolValue: "video"];
    [self setupButton:_video_fullscreenCheckbox forBoolValue: "fullscreen"];
    [self setupButton:_video_onTopCheckbox forBoolValue: "video-on-top"];
    [self setupButton:_video_skipFramesCheckbox forBoolValue: "skip-frames"];
    [self setupButton:_video_blackCheckbox forBoolValue: "macosx-black"];
    [self setupButton:_video_videodecoCheckbox forBoolValue: "video-deco"];

    [_video_devicePopup removeAllItems];
666
667
    i = 0;
    y = [[NSScreen screens] count];
668
669
    [_video_devicePopup addItemWithTitle: _NS("Default")];
    [[_video_devicePopup lastItem] setTag: 0];
670
    while (i < y) {
671
        NSRect s_rect = [[[NSScreen screens] objectAtIndex:i] frame];
672
        [_video_devicePopup addItemWithTitle:
673
674
         [NSString stringWithFormat: @"%@ %i (%ix%i)", _NS("Screen"), i+1,
                   (int)s_rect.size.width, (int)s_rect.size.height]];
675
        [[_video_devicePopup lastItem] setTag: (int)[[[NSScreen screens] objectAtIndex:i] displayID]];
676
677
        i++;
    }
678
679
    [_video_devicePopup selectItemAtIndex: 0];
    [_video_devicePopup selectItemWithTag: config_GetInt(p_intf, "macosx-vdev")];
680

681
682
683
684
685
686
    [self setupField:_video_snap_folderTextField forOption:"snapshot-path"];
    [self setupField:_video_snap_prefixTextField forOption:"snapshot-prefix"];
    [self setupButton:_video_snap_seqnumCheckbox forBoolValue: "snapshot-sequential"];
    [self setupButton:_video_snap_formatPopup forStringList: "snapshot-format"];
    [self setupButton:_video_deinterlacePopup forIntList: "deinterlace"];
    [self setupButton:_video_deinterlace_modePopup forStringList: "deinterlace-mode"];
687

688
    // set lion fullscreen mode restrictions
689
    [self enableLionFullscreenMode: [_intf_nativefullscreenCheckbox state]];
690

691
692
693
    /***************************
     * input & codecs settings *
     ***************************/
694
695
696
697
    [self setupField:_input_recordTextField forOption:"input-record-path"];
    [_input_postprocTextField setIntValue: config_GetInt(p_intf, "postproc-q")];
    [_input_postprocTextField setToolTip: _NS(config_GetLabel(p_intf, "postproc-q"))];
    [self setupButton:_input_avcodec_hwPopup forModuleList: "avcodec-hw"];
698

699
    [self setupButton:_input_aviPopup forIntList: "avi-index"];
700

701
702
    [self setupButton:_input_rtspCheckbox forBoolValue: "rtsp-tcp"];
    [self setupButton:_input_skipLoopPopup forIntList: "avcodec-skiploopfilter"];
703

704
    [self setupButton:_input_mkv_preload_dirCheckbox forBoolValue: "mkv-preload-local-dir"];
705

706
707
    [_input_cachelevelPopup removeAllItems];
    [_input_cachelevelPopup addItemsWithTitles: [NSArray arrayWithObjects:_NS("Custom"), _NS("Lowest latency"),
708
     _NS("Low latency"), _NS("Normal"), _NS("High latency"), _NS("Higher latency"), nil]];
709
710
711
712
713
714
    [[_input_cachelevelPopup itemAtIndex: 0] setTag: 0];
    [[_input_cachelevelPopup itemAtIndex: 1] setTag: 100];
    [[_input_cachelevelPopup itemAtIndex: 2] setTag: 200];
    [[_input_cachelevelPopup itemAtIndex: 3] setTag: 300];
    [[_input_cachelevelPopup itemAtIndex: 4] setTag: 500];
    [[_input_cachelevelPopup itemAtIndex: 5] setTag: 1000];
715

716
    #define TestCaC(name, factor) \
717
    cache_equal = cache_equal && \
718
    (i_cache * factor == config_GetInt(p_intf, name));
719
720

    /* Select the accurate value of the PopupButton */
721
    bool cache_equal = true;
722
    int i_cache = config_GetInt(p_intf, "file-caching");
723

724
725
726
    TestCaC("network-caching", 10/3);
    TestCaC("disc-caching", 1);
    TestCaC("live-caching", 1);
727
728
729
    if (cache_equal) {
        [_input_cachelevelPopup selectItemWithTag: i_cache];
        [_input_cachelevel_customLabel setHidden: YES];
730
    } else {
731
732
        [_input_cachelevelPopup selectItemWithTitle: _NS("Custom")];
        [_input_cachelevel_customLabel setHidden: NO];
733
    }
734
    #undef TestCaC
735
736
737
738

    /*********************
     * subtitle settings *
     *********************/
739
    [self setupButton:_osd_osdCheckbox forBoolValue: "osd"];
740

741
742
    [self setupButton:_osd_encodingPopup forStringList: "subsdec-encoding"];
    [self setupField:_osd_langTextField forOption: "sub-language" ];
743

744
745
746
    [self setupField:_osd_fontTextField forOption: "freetype-font"];
    [self setupButton:_osd_font_colorPopup forIntList: "freetype-color"];
    [self setupButton:_osd_font_sizePopup forIntList: "freetype-rel-fontsize"];
747
    i = config_GetInt(p_intf, "freetype-opacity") * 100.0 / 255.0 + 0.5;
748
749
750
751
752
753
754
    [_osd_opacityTextField setIntValue: i];
    [_osd_opacitySlider setIntValue: i];
    [_osd_opacitySlider setToolTip: _NS(config_GetLabel(p_intf, "freetype-opacity"))];
    [_osd_opacityTextField setToolTip: [_osd_opacitySlider toolTip]];
    [self setupButton:_osd_forceboldCheckbox forBoolValue: "freetype-bold"];
    [self setupButton:_osd_outline_colorPopup forIntList: "freetype-outline-color"];
    [self setupButton:_osd_outline_thicknessPopup forIntList: "freetype-outline-thickness"];
755

756
757
758
    /********************
     * hotkeys settings *
     ********************/
759
    const struct hotkey *p_hotkeys = p_intf->p_libvlc->p_hotkeys;
760
761
762
    _hotkeySettings = [[NSMutableArray alloc] init];
    NSMutableArray *tempArray_desc = [[NSMutableArray alloc] init];
    NSMutableArray *tempArray_names = [[NSMutableArray alloc] init];
763

764
765
    /* Get the main Module */
    module_t *p_main = module_get_main();
766
    assert(p_main);
767
768
    unsigned confsize;
    module_config_t *p_config;
769

770
    p_config = module_config_get (p_main, &confsize);
771

772
    for (size_t i = 0; i < confsize; i++) {
773
        module_config_t *p_item = p_config + i;
774

775
776
777
        if (CONFIG_ITEM(p_item->i_type) && p_item->psz_name != NULL
           && !strncmp(p_item->psz_name , "key-", 4)
           && !EMPTY_STR(p_item->psz_text)) {
778
779
            [tempArray_desc addObject: _NS(p_item->psz_text)];
            [tempArray_names addObject: [NSString stringWithUTF8String:p_item->psz_name]];
780
            if (p_item->value.psz)
781
                [_hotkeySettings addObject: [NSString stringWithUTF8String:p_item->value.psz]];
782
            else
783
                [_hotkeySettings addObject: [NSString string]];
784
        }
785
    }
786
    module_config_free (p_config);
787

788
789
    _hotkeyDescriptions = [[NSArray alloc] initWithArray:tempArray_desc copyItems: YES];
    _hotkeyNames = [[NSArray alloc] initWithArray:tempArray_names copyItems: YES];
790

791
    [_hotkeys_listbox reloadData];
792
793
}

794
795
796
#pragma mark -
#pragma mark General actions

797
798
799
- (void)showSimplePrefs
{
    /* we want to show the interface settings, if no category was chosen */
800
801
    if ([[_window toolbar] selectedItemIdentifier] == nil) {
        [[_window toolbar] setSelectedItemIdentifier: VLCIntfSettingToolbarIdentifier];
802
803
        [self showInterfaceSettings];
    }
804

805
    [self resetControls];
806

807
808
    [_window center];
    [_window makeKeyAndOrderFront: self];
809
810
}

811
812
- (void)showSimplePrefsWithLevel:(NSInteger)i_window_level
{
813
    [_window setLevel: i_window_level];
814
815
816
    [self showSimplePrefs];
}

817
818
- (IBAction)buttonAction:(id)sender
{
819
    if (sender == _cancelButton) {
820
        [[NSFontPanel sharedFontPanel] close];
821
822
        [_window orderOut: sender];
    } else if (sender == _saveButton) {
823
        [self saveChangedSettings];
824
        [[NSFontPanel sharedFontPanel] close];
825
826
827
828
        [_window orderOut: sender];
    } else if (sender == _showAllButton) {
        [_window orderOut: self];
        [[[VLCMain sharedInstance] preferences] showPrefsWithLevel:[_window level]];
829
830
    } else
        msg_Warn(p_intf, "unknown buttonAction sender");
831
832
}

833
834
835
836
837
838
839
840
841
842
843
844
845
- (IBAction)resetPreferences:(NSControl *)sender
{
    NSBeginInformationalAlertSheet(_NS("Reset Preferences"), _NS("Cancel"),
                                   _NS("Continue"), nil, [sender window], self,
                                   @selector(sheetDidEnd: returnCode: contextInfo:), NULL, nil, @"%@",
                                   _NS("This will reset VLC media player's preferences.\n\n"
                                       "Note that VLC will restart during the process, so your current "
                                       "playlist will be emptied and eventual playback, streaming or "
                                       "transcoding activities will stop immediately.\n\n"
                                       "The Media Library will not be affected.\n\n"
                                       "Are you sure you want to continue?"));
}

846
- (void)sheetDidEnd:(NSWindow *)o_sheet
847
848
849
         returnCode:(int)i_return
        contextInfo:(void *)o_context
{
850
    if (i_return == NSAlertAlternateReturn) {
851
        /* reset VLC's config */
852
        config_ResetAll(p_intf);
853
        [self resetControls];
854
855

        /* force config file creation, since libvlc won't exit normally */
856
        config_SaveConfigFile(p_intf);
857
858

        /* reset OS X defaults */
859
        [[VLCMain sharedInstance] resetAndReinitializeUserDefaults];
860
861
862
863
864
865
866
867
868
869

        /* Relaunch now */
        const char * path = [[[NSBundle mainBundle] executablePath] UTF8String];

        /* For some reason we need to fork(), not just execl(), which reports a ENOTSUP then. */
        if (fork() != 0) {
            exit(0);
            return;
        }
        execl(path, path, NULL);
870
871
872
    }
}

873
static inline void save_int_list(intf_thread_t * p_intf, id object, const char * name)
874
{
875
876
877
878
879
    NSNumber *p_valueobject = (NSNumber *)[[object selectedItem] representedObject];
    if (p_valueobject) {
        assert([p_valueobject isKindOfClass:[NSNumber class]]);
        config_PutInt(p_intf, name, [p_valueobject intValue]);
    }
880
881
}

882
static inline void save_string_list(intf_thread_t * p_intf, id object, const char * name)
883
{
884
885
886
887
888
    NSString *p_stringobject = (NSString *)[[object selectedItem] representedObject];
    if (p_stringobject) {
        assert([p_stringobject isKindOfClass:[NSString class]]);
        config_PutPsz(p_intf, name, [p_stringobject UTF8String]);
    }
889
890
891
892
}

- (void)saveChangedSettings
{
893
894
    NSString *tmpString;
    NSRange tmpRange;
895

896
#define SaveIntList(object, name) save_int_list(p_intf, object, name)
897

898
#define SaveStringList(object, name) save_string_list(p_intf, object, name)
899
#define SaveModuleList(object, name) SaveStringList(object, name)
900

901
#define getString(name) [NSString stringWithFormat:@"%s", config_GetPsz(p_intf, name)]
902

903
904
905
    /**********************
     * interface settings *
     **********************/
906
907
    if (_intfSettingChanged) {
        NSUInteger index = [_intf_languagePopup indexOfSelectedItem];
908
909
910
911
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:[NSString stringWithUTF8String:ppsz_language[index]] forKey:@"language"];
        [defaults synchronize];

912
        config_PutInt(p_intf, "metadata-network-access", [_intf_artCheckbox state]);
913

914
915
        config_PutInt(p_intf, "macosx-fspanel", [_intf_fspanelCheckbox state]);
        config_PutInt(p_intf, "embedded-video", [_intf_embeddedCheckbox state]);
916

917
918
919
920
921
922
923
924
        config_PutInt(p_intf, "macosx-appleremote", [_intf_appleremoteCheckbox state]);
        config_PutInt(p_intf, "macosx-appleremote-sysvol", [_intf_appleremote_sysvolCheckbox state]);
        config_PutInt(p_intf, "macosx-mediakeys", [_intf_mediakeysCheckbox state]);
        config_PutInt(p_intf, "macosx-interfacestyle", [_intf_style_darkButtonCell state]);
        config_PutInt(p_intf, "macosx-nativefullscreenmode", [_intf_nativefullscreenCheckbox state]);
        config_PutInt(p_intf, "macosx-pause-minimized", [_intf_pauseminimizedCheckbox state]);
        config_PutInt(p_intf, "macosx-video-autoresize", [_intf_autoresizeCheckbox state]);
        if ([_intf_enableGrowlCheckbox state] == NSOnState) {
925
            tmpString = getString("control");
926
            tmpRange = [tmpString rangeOfString:@"growl"];
927
            if ([tmpString length] > 0 && tmpRange.location == NSNotFound)
928
            {
929
                tmpString = [tmpString stringByAppendingString: @":growl"];
930
                config_PutPsz(p_intf, "control", [tmpString UTF8String]);
931
            }
932
            else
933
934
935
936
                config_PutPsz(p_intf, "control", "growl");
        } else {
            tmpString = getString("control");
            if (! [tmpString isEqualToString:@""])
937
            {
938
939
940
                tmpString = [tmpString stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@":growl"]];
                tmpString = [tmpString stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"growl:"]];
                tmpString = [tmpString stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"growl"]];
941
                config_PutPsz(p_intf, "control", [tmpString UTF8String]);
942
943
            }
        }
944
        config_PutPsz(p_intf, "http-password", [[_intf_luahttppwdTextField stringValue] UTF8String]);
945

946
947
        SaveIntList(_intf_pauseitunesPopup, "macosx-control-itunes");
        SaveIntList(_intf_continueplaybackPopup, "macosx-continue-playback");
948

949
        /* activate stuff without restart */
950
        if ([_intf_appleremoteCheckbox state] == YES)
951
952
953
            [[[VLCMain sharedInstance] appleRemoteController] startListening: [VLCMain sharedInstance]];
        else
            [[[VLCMain sharedInstance] appleRemoteController] stopListening: [VLCMain sharedInstance]];
954
        _intfSettingChanged = NO;
955
    }
956

957
958
959
    /******************
     * audio settings *
     ******************/
960
961
962
963
964
965
966
    if (_audioSettingChanged) {
        config_PutInt(p_intf, "audio", [_audio_enableCheckbox state]);
        config_PutInt(p_intf, "volume-save", [_audio_autosavevol_yesButtonCell state]);
        var_SetBool(p_intf, "volume-save", [_audio_autosavevol_yesButtonCell state]);
        config_PutInt(p_intf, "spdif", [_audio_spdifCheckbox state]);
        if ([_audio_volTextField isEnabled])
            config_PutInt(p_intf, "auhal-volume", ([_audio_volTextField intValue] * AOUT_VOLUME_MAX) / 200);
967

968
        SaveIntList(_audio_dolbyPopup, "force-dolby-surround");
969

970
        config_PutPsz(p_intf, "audio-language", [[_audio_langTextField stringValue] UTF8String]);
971

972
        SaveModuleList(_audio_visualPopup, "audio-visual");
973

974
        /* Last.FM is optional */
975
        if (module_exists("audioscrobbler")) {
976
977
            [_audio_lastCheckbox setEnabled: YES];
            if ([_audio_lastCheckbox state] == NSOnState)
978
                config_AddIntf(p_intf, "audioscrobbler");
979
            else
980
                config_RemoveIntf(p_intf, "audioscrobbler");
981

982
983
            config_PutPsz(p_intf, "lastfm-username", [[_audio_lastuserTextField stringValue] UTF8String]);
            config_PutPsz(p_intf