macosx: Implemented the Subs/OSD and Input categories of the Simple Prefs
[vlc.git] / modules / gui / macosx / simple_prefs.m
1 /*****************************************************************************
2 * simple_prefs.m: Simple Preferences for Mac OS X
3 *****************************************************************************
4 * Copyright (C) 2008 the VideoLAN team
5 * $Id$
6 *
7 * Authors: Felix Paul K├╝hne <fkuehne at videolan dot org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
23
24 #import "simple_prefs.h"
25 #import "prefs.h"
26
27 static NSString* VLCSPrefsToolbarIdentifier = @"Our Simple Preferences Toolbar Identifier";
28 static NSString* VLCIntfSettingToolbarIdentifier = @"Intf Settings Item Identifier";
29 static NSString* VLCAudioSettingToolbarIdentifier = @"Audio Settings Item Identifier";
30 static NSString* VLCVideoSettingToolbarIdentifier = @"Video Settings Item Identifier";
31 static NSString* VLCOSDSettingToolbarIdentifier = @"Subtitles Settings Item Identifier";
32 static NSString* VLCInputSettingToolbarIdentifier = @"Input Settings Item Identifier";
33 static NSString* VLCHotkeysSettingToolbarIdentifier = @"Hotkeys Settings Item Identifier";
34
35 @implementation VLCSimplePrefs
36
37 static VLCSimplePrefs *_o_sharedInstance = nil;
38
39 + (VLCSimplePrefs *)sharedInstance
40 {
41     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
42 }
43
44 - (id)init
45 {
46     if (_o_sharedInstance) {
47         [self dealloc];
48     } else {
49         p_intf = VLCIntf;
50         _o_sharedInstance = [super init];
51     }
52     
53     return _o_sharedInstance;
54 }
55
56 - (void)dealloc
57 {
58     [o_currentlyShownCategoryView release];
59     [o_sprefs_toolbar release];
60     
61     [super dealloc];
62 }
63
64 - (void)awakeFromNib
65 {
66     [self initStrings];
67
68     [self resetControls];
69     
70     /* setup the toolbar */
71     o_sprefs_toolbar = [[[NSToolbar alloc] initWithIdentifier: VLCSPrefsToolbarIdentifier] autorelease];
72     [o_sprefs_toolbar setAllowsUserCustomization: NO];
73     [o_sprefs_toolbar setAutosavesConfiguration: NO];
74     [o_sprefs_toolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
75     [o_sprefs_toolbar setSizeMode: NSToolbarSizeModeRegular];
76     [o_sprefs_toolbar setDelegate: self];
77     [o_sprefs_win setToolbar: o_sprefs_toolbar];
78 }
79
80 - (NSToolbarItem *) toolbar: (NSToolbar *)o_sprefs_toolbar 
81       itemForItemIdentifier: (NSString *)o_itemIdent 
82   willBeInsertedIntoToolbar: (BOOL)b_willBeInserted
83 {
84     NSToolbarItem *o_toolbarItem = nil;
85     
86     if( [o_itemIdent isEqual: VLCIntfSettingToolbarIdentifier] )
87     {
88         o_toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: o_itemIdent] autorelease];
89
90         [o_toolbarItem setLabel: _NS("Interface")];
91         [o_toolbarItem setPaletteLabel: _NS("Interface settings")];
92
93         [o_toolbarItem setToolTip: _NS("Interface settings")];
94         [o_toolbarItem setImage: [NSImage imageNamed: @"spref_cone_Interface_64"]];
95
96         [o_toolbarItem setTarget: self];
97         [o_toolbarItem setAction: @selector(showInterfaceSettings)];
98
99         [o_toolbarItem setEnabled: YES];
100         [o_toolbarItem setAutovalidates: YES];
101     }
102     else if( [o_itemIdent isEqual: VLCAudioSettingToolbarIdentifier] )
103     {
104         o_toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: o_itemIdent] autorelease];
105
106         [o_toolbarItem setLabel: _NS("Audio")];
107         [o_toolbarItem setPaletteLabel: _NS("General Audio settings")];
108
109         [o_toolbarItem setToolTip: _NS("General Audio settings")];
110         [o_toolbarItem setImage: [NSImage imageNamed: @"spref_cone_Audio_64"]];
111
112         [o_toolbarItem setTarget: self];
113         [o_toolbarItem setAction: @selector(showAudioSettings)];
114
115         [o_toolbarItem setEnabled: YES];
116         [o_toolbarItem setAutovalidates: YES];
117     }
118     else if( [o_itemIdent isEqual: VLCVideoSettingToolbarIdentifier] )
119     {
120         o_toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: o_itemIdent] autorelease];
121
122         [o_toolbarItem setLabel: _NS("Video")];
123         [o_toolbarItem setPaletteLabel: _NS("General Video settings")];
124
125         [o_toolbarItem setToolTip: _NS("General Video settings")];
126         [o_toolbarItem setImage: [NSImage imageNamed: @"spref_cone_Video_64"]];
127
128         [o_toolbarItem setTarget: self];
129         [o_toolbarItem setAction: @selector(showVideoSettings)];
130
131         [o_toolbarItem setEnabled: YES];
132         [o_toolbarItem setAutovalidates: YES];
133     }
134     else if( [o_itemIdent isEqual: VLCOSDSettingToolbarIdentifier] )
135     {
136         o_toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: o_itemIdent] autorelease];
137
138         [o_toolbarItem setLabel: _NS("Subtitles & OSD")];
139         [o_toolbarItem setPaletteLabel: _NS("Subtitles & OSD settings")];
140
141         [o_toolbarItem setToolTip: _NS("Subtitles & OSD settings")];
142         [o_toolbarItem setImage: [NSImage imageNamed: @"spref_cone_Subtitles_64"]];
143
144         [o_toolbarItem setTarget: self];
145         [o_toolbarItem setAction: @selector(showOSDSettings)];
146
147         [o_toolbarItem setEnabled: YES];
148         [o_toolbarItem setAutovalidates: YES];
149     }
150     else if( [o_itemIdent isEqual: VLCInputSettingToolbarIdentifier] )
151     {
152         o_toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: o_itemIdent] autorelease];
153
154         [o_toolbarItem setLabel: _NS("Input & Codecs")];
155         [o_toolbarItem setPaletteLabel: _NS("Input & Codec settings")];
156
157         [o_toolbarItem setToolTip: _NS("Input & Codec settings")];
158         [o_toolbarItem setImage: [NSImage imageNamed: @"spref_cone_Input_64"]];
159
160         [o_toolbarItem setTarget: self];
161         [o_toolbarItem setAction: @selector(showInputSettings)];
162
163         [o_toolbarItem setEnabled: YES];
164         [o_toolbarItem setAutovalidates: YES];
165     }
166
167     return o_toolbarItem;
168 }
169
170 - (NSArray *)toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar
171 {
172     return [NSArray arrayWithObjects: VLCIntfSettingToolbarIdentifier, VLCAudioSettingToolbarIdentifier, VLCVideoSettingToolbarIdentifier, 
173         VLCOSDSettingToolbarIdentifier, VLCInputSettingToolbarIdentifier, NSToolbarFlexibleSpaceItemIdentifier, nil];
174 }
175
176 - (NSArray *)toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar
177 {
178     return [NSArray arrayWithObjects: VLCIntfSettingToolbarIdentifier, VLCAudioSettingToolbarIdentifier, VLCVideoSettingToolbarIdentifier, 
179         VLCOSDSettingToolbarIdentifier, VLCInputSettingToolbarIdentifier, NSToolbarFlexibleSpaceItemIdentifier, nil];
180 }
181
182 - (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
183 {
184     return [NSArray arrayWithObjects: VLCIntfSettingToolbarIdentifier, VLCAudioSettingToolbarIdentifier, VLCVideoSettingToolbarIdentifier, 
185         VLCOSDSettingToolbarIdentifier, VLCInputSettingToolbarIdentifier, nil];
186 }
187
188 - (void)initStrings
189 {
190     msg_Warn( p_intf, "localisation of the simple preferences is not implemented!" );
191 }
192
193 - (void)resetControls
194 {
195     module_config_t *p_item;
196     int i, y = 0;
197     char *psz_tmp;
198
199     #define SetupIntList( object, name ) \
200     [object removeAllItems]; \
201     p_item = config_FindConfig( VLC_OBJECT(p_intf), name ); \
202     for( i = 0; i < p_item->i_list; i++ ) \
203     { \
204         if( p_item->ppsz_list_text[i] != NULL) \
205             [object addItemWithTitle: _NS( p_item->ppsz_list_text[i] )]; \
206         else \
207             [object addItemWithTitle: [NSString stringWithUTF8String: p_item->ppsz_list[i]]]; \
208     } \
209     if( p_item->value.i < [object numberOfItems] ) \
210         [object selectItemAtIndex: p_item->value.i]; \
211     else \
212         [object selectItemAtIndex: 0]
213
214     #define SetupStringList( object, name ) \
215         [object removeAllItems]; \
216         y = 0; \
217         p_item = config_FindConfig( VLC_OBJECT(p_intf), name ); \
218         for( i = 0; p_item->ppsz_list[i] != nil; i++ ) \
219         { \
220             [object addItemWithTitle: _NS( p_item->ppsz_list_text[i] )]; \
221             if( p_item->value.psz && !strcmp( p_item->value.psz, p_item->ppsz_list[i] ) ) \
222                 y = i; \
223         } \
224         [object selectItemAtIndex: y]
225
226     /**********************
227      * interface settings *
228      **********************/
229     SetupStringList( o_intf_lang_pop, "language" );
230     SetupIntList( o_intf_art_pop, "album-art" );
231
232     [o_intf_meta_ckb setState: config_GetInt( p_intf, "fetch-meta" )];
233     [o_intf_fspanel_ckb setState: config_GetInt( p_intf, "macosx-fspanel" )];
234     [o_intf_embedded_ckb setState: config_GetInt( p_intf, "embedded-video" )];
235
236     /******************
237      * audio settings *
238      ******************/
239     [o_audio_enable_ckb setState: config_GetInt( p_intf, "audio" )];
240     [o_audio_vol_fld setIntValue: config_GetInt( p_intf, "volume" )];
241     [o_audio_vol_sld setIntValue: config_GetInt( p_intf, "volume" )];
242
243     [o_audio_spdif_ckb setState: config_GetInt( p_intf, "spdif" )];
244
245     SetupIntList( o_audio_dolby_pop, "force-dolby-surround" );
246
247     [o_audio_lang_fld setStringValue: [NSString stringWithUTF8String: config_GetPsz( p_intf, "audio-language" )]];
248
249     [o_audio_headphone_ckb setState: config_GetInt( p_intf, "headphone-dolby" )];
250     
251     psz_tmp = config_GetPsz( p_intf, "audio-filter" );
252     if( psz_tmp )
253         [o_audio_norm_ckb setState: (int)strstr( psz_tmp, "normvol" )];
254     [o_audio_norm_fld setFloatValue: config_GetFloat( p_intf, "norm-max-level" )];
255     
256     // visualizer
257     msg_Warn( p_intf, "visualizer not implemented!" );
258     
259     /* Last.FM is optional */
260     if( module_Exists( p_intf, "audioscrobbler" ) )
261     {
262         [o_audio_lastuser_fld setStringValue: [NSString stringWithUTF8String: config_GetPsz( p_intf, "lastfm-username" )]];
263         [o_audio_lastpwd_fld setStringValue: [NSString stringWithUTF8String: config_GetPsz( p_intf, "lastfm-password" )]];
264
265         if( config_ExistIntf( VLC_OBJECT( p_intf ), "audioscrobbler" ) )
266             [o_audio_last_ckb setState: NSOnState];
267         else
268             [o_audio_last_ckb setState: NSOffState];
269     }
270
271     /******************
272      * video settings *
273      ******************/
274     [o_video_enable_ckb setState: config_GetInt( p_intf, "video" )];
275     [o_video_fullscreen_ckb setState: config_GetInt( p_intf, "fullscreen" )];
276     [o_video_onTop_ckb setState: config_GetInt( p_intf, "video-on-top" )];
277     [o_video_skipFrames_ckb setState: config_GetInt( p_intf, "skip-frames" )];
278     [o_video_black_ckb setState: config_GetInt( p_intf, "macosx-black" )];
279
280     msg_Warn( p_intf, "vout module and display device selectors not implemented!" );
281
282     if( config_GetPsz( p_intf, "snapshot-path" ) != NULL )
283         [o_video_snap_folder_fld setStringValue: [NSString stringWithUTF8String: config_GetPsz( p_intf, "snapshot-path" )]];
284     [o_video_snap_prefix_fld setStringValue: [NSString stringWithUTF8String: config_GetPsz( p_intf, "snapshot-prefix" )]];
285     [o_video_snap_seqnum_ckb setState: config_GetInt( p_intf, "snapshot-sequential" )];
286     
287     p_item = config_FindConfig( VLC_OBJECT(p_intf), "snapshot-format" );
288     for( i = 0; p_item->ppsz_list[i] != nil; i++ )
289     {
290         [o_video_snap_format_pop addItemWithTitle: [NSString stringWithUTF8String: p_item->ppsz_list[i]]];
291         if( p_item->value.psz && !strcmp( p_item->value.psz, p_item->ppsz_list[i] ) )
292             y = i;
293     }
294     [o_video_snap_format_pop selectItemAtIndex: y];
295
296     /***************************
297      * input & codecs settings *
298      ***************************/
299     [o_input_serverport_fld setIntValue: config_GetInt( p_intf, "server-port" )];
300     if( config_GetPsz( p_intf, "http-proxy" ) != NULL )
301         [o_input_httpproxy_fld setStringValue: [NSString stringWithUTF8String: config_GetPsz( p_intf, "http-proxy" )]];
302     [o_input_postproc_fld setIntValue: config_GetInt( p_intf, "ffmpeg-pp-q" )];
303
304     SetupIntList( o_input_avi_pop, "avi-index" );
305
306     [o_input_rtsp_ckb setState: config_GetInt( p_intf, "rtsp-tcp" )];
307
308     psz_tmp = config_GetPsz( p_intf, "access-filter" );
309     if( psz_tmp )
310     {
311         [o_input_record_ckb setState: (int)strstr( psz_tmp, "record" )];
312         [o_input_dump_ckb setState: (int)strstr( psz_tmp, "dump" )];
313         [o_input_bandwidth_ckb setState: (int)strstr( psz_tmp, "bandwidth" )];
314         [o_input_timeshift_ckb setState: (int)strstr( psz_tmp, "timeshift" )];
315     }
316
317     [o_input_cachelevel_pop removeAllItems];
318     [o_input_cachelevel_pop addItemsWithTitles: 
319         [NSArray arrayWithObjects: _NS("Custom"), _NS("Lowest latency"), _NS("Low latency"), _NS("Normal"),
320             _NS("High latency"), _NS("Higher latency"), nil]];
321     [[o_input_cachelevel_pop itemAtIndex: 0] setTag: 0];
322     [[o_input_cachelevel_pop itemAtIndex: 1] setTag: 100];
323     [[o_input_cachelevel_pop itemAtIndex: 2] setTag: 200];
324     [[o_input_cachelevel_pop itemAtIndex: 3] setTag: 300];
325     [[o_input_cachelevel_pop itemAtIndex: 4] setTag: 400];
326     [[o_input_cachelevel_pop itemAtIndex: 5] setTag: 500];
327     
328 #define TestCaC( name ) \
329     b_cache_equal =  b_cache_equal && \
330         ( i_cache == config_GetInt( p_intf, name ) )
331
332 #define TestCaCi( name, int ) \
333         b_cache_equal = b_cache_equal &&  \
334         ( ( i_cache * int ) == config_GetInt( p_intf, name ) )
335
336     /* Select the accurate value of the PopupButton */
337     bool b_cache_equal = true;
338     int i_cache = config_GetInt( p_intf, "file-caching");
339     
340     TestCaC( "udp-caching" );
341     if( module_Exists (p_intf, "dvdread") )
342         TestCaC( "dvdread-caching" );
343     if( module_Exists (p_intf, "dvdnav") )
344         TestCaC( "dvdnav-caching" );
345     TestCaC( "tcp-caching" );
346     TestCaC( "fake-caching" ); 
347     TestCaC( "cdda-caching" );
348     TestCaC( "screen-caching" ); 
349     TestCaC( "vcd-caching" );
350     TestCaCi( "rtsp-caching", 4 ); 
351     TestCaCi( "ftp-caching", 2 );
352     TestCaCi( "http-caching", 4 );
353     if(module_Exists (p_intf, "access_realrtsp"))
354         TestCaCi( "realrtsp-caching", 10 );
355     TestCaCi( "mms-caching", 19 );
356     if( b_cache_equal )
357         [o_input_cachelevel_pop selectItemWithTag: i_cache];
358     else
359         [o_input_cachelevel_pop selectItemWithTitle: _NS("Custom")];
360
361     /*********************
362      * subtitle settings *
363      *********************/
364     [o_osd_osd_ckb setState: config_GetInt( p_intf, "osd" )];
365     
366     [o_osd_encoding_pop removeAllItems];
367     y = 0;
368     p_item = config_FindConfig( VLC_OBJECT(p_intf), "subsdec-encoding" );
369     for( i = 0; p_item->ppsz_list[i] != nil; i++ )
370     {
371         if( p_item->ppsz_list[i] != "" )
372             [o_osd_encoding_pop addItemWithTitle: _NS( p_item->ppsz_list[i] )];
373         else
374             [o_osd_encoding_pop addItemWithTitle: @" "];
375
376         if( p_item->value.psz && !strcmp( p_item->value.psz, p_item->ppsz_list[i] ) )
377             y = i;
378     }
379     [o_osd_encoding_pop selectItemAtIndex: y];
380     
381     [o_osd_lang_fld setStringValue: [NSString stringWithUTF8String: config_GetPsz( p_intf, "sub-language" )]];
382     if( config_GetPsz( p_intf, "freetype-font" ) != NULL )
383         [o_osd_font_fld setStringValue: [NSString stringWithUTF8String: config_GetPsz( p_intf, "freetype-font" )]];
384
385     SetupIntList( o_osd_font_color_pop, "freetype-color" );
386     SetupIntList( o_osd_font_size_pop, "freetype-rel-fontsize" );
387     SetupIntList( o_osd_font_effect_pop, "freetype-effect" );
388
389     /********************
390      * hotkeys settings *
391      ********************/
392 }
393
394 - (void)showSimplePrefs
395 {
396     /* we want to show the interface settings, if no category was chosen */
397     if( [o_sprefs_toolbar selectedItemIdentifier] == nil )
398     {
399         [o_sprefs_toolbar setSelectedItemIdentifier: VLCIntfSettingToolbarIdentifier];
400         [self showInterfaceSettings];
401     }
402
403     [o_sprefs_win makeKeyAndOrderFront: self];
404 }
405
406 - (IBAction)buttonAction:(id)sender
407 {
408     if( sender == o_sprefs_cancel_btn )
409         [o_sprefs_win orderOut: sender];
410     else if( sender == o_sprefs_save_btn )
411     {
412         [self saveChangedSettings];
413         [o_sprefs_win orderOut: sender];
414     }
415     else if( sender == o_sprefs_reset_btn )
416         NSBeginInformationalAlertSheet( _NS("Reset Preferences"), _NS("Cancel"),
417                                         _NS("Continue"), nil, o_sprefs_win, self,
418                                         @selector(sheetDidEnd: returnCode: contextInfo:), NULL, nil,
419                                         _NS("Beware this will reset the VLC media player preferences.\n"
420                                             "Are you sure you want to continue?") );
421     else if( sender == o_sprefs_basicFull_matrix )
422     {
423         [o_sprefs_win orderOut: self];
424         [[[VLCMain sharedInstance] getPreferences] showPrefs];
425         [self resetControls];
426     }
427     else
428         msg_Err( p_intf, "unknown buttonAction sender" );
429 }
430
431 - (void)sheetDidEnd:(NSWindow *)o_sheet 
432          returnCode:(int)i_return
433         contextInfo:(void *)o_context
434 {
435     if( i_return == NSAlertAlternateReturn )
436     {
437         config_ResetAll( p_intf );
438         b_intfSettingChanged = b_videoSettingChanged = b_audioSettingChanged = YES;
439         [self resetControls];
440     }
441 }
442
443 - (void)saveChangedSettings
444 {
445     module_config_t *p_item;
446     char *psz_tmp;
447     int i;
448     
449 #define SaveIntList( object, name ) \
450     p_item = config_FindConfig( VLC_OBJECT(p_intf), name ); \
451     if( [object indexOfSelectedItem] >= 0 ) \
452         config_PutInt( p_intf, name, p_item->pi_list[[object indexOfSelectedItem]] ); \
453     else \
454         config_PutInt( p_intf, name, [object intValue] ) \
455                     
456 #define SaveStringList( object, name ) \
457     p_item = config_FindConfig( VLC_OBJECT(p_intf), name ); \
458     if( [object indexOfSelectedItem] >= 0 ) \
459         config_PutPsz( p_intf, name, strdup( p_item->ppsz_list[[object indexOfSelectedItem]] ) ); \
460     else \
461         config_PutPsz( p_intf, name, strdup( [[VLCMain sharedInstance] delocalizeString: [object stringValue]] ) )
462
463     /**********************
464      * interface settings *
465      **********************/
466     if( b_intfSettingChanged )
467     {
468         SaveStringList( o_intf_lang_pop, "language" );
469         SaveIntList( o_intf_art_pop, "album-art" );
470
471         config_PutInt( p_intf, "fetch-meta", [o_intf_meta_ckb state] );
472         config_PutInt( p_intf, "macosx-fspanel", [o_intf_fspanel_ckb state] );
473         config_PutInt( p_intf, "embedded-video", [o_intf_embedded_ckb state] );
474
475         /* okay, let's save our changes to vlcrc */
476         i = config_SaveConfigFile( p_intf, "main" );
477         i = config_SaveConfigFile( p_intf, "macosx" );
478
479         if( i != 0 )
480         {
481             msg_Err( p_intf, "An error occured while saving the Interface settings using SimplePrefs" );
482             i = 0;
483         }
484
485         b_intfSettingChanged = NO;
486     }
487     
488     /******************
489      * audio settings *
490      ******************/
491     if( b_audioSettingChanged )
492     {
493         config_PutInt( p_intf, "audio", [o_audio_enable_ckb state] );
494         config_PutInt( p_intf, "volume", [o_audio_vol_sld intValue] );
495         config_PutInt( p_intf, "spdif", [o_audio_spdif_ckb state] );
496
497         SaveIntList( o_audio_dolby_pop, "force-dolby-surround" );
498
499         config_PutPsz( p_intf, "audio-language", [[o_audio_lang_fld stringValue] UTF8String] );
500         config_PutInt( p_intf, "headphone-dolby", [o_audio_headphone_ckb state] );
501
502         psz_tmp = config_GetPsz( p_intf, "audio-filter" );
503         if(! psz_tmp)
504             config_PutPsz( p_intf, "audio-filter", "volnorm" );
505         else if( (int)strstr( psz_tmp, "normvol" ) == NO )
506         {
507             /* work-around a GCC 4.0.1 bug */
508             psz_tmp = (char *)[[NSString stringWithFormat: @"%s:volnorm", psz_tmp] UTF8String];
509             config_PutPsz( p_intf, "audio-filter", psz_tmp );
510         }
511         else
512         {
513             psz_tmp = (char *)[[[NSString stringWithUTF8String: psz_tmp] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@":volnorm"]] UTF8String];
514             psz_tmp = (char *)[[[NSString stringWithUTF8String: psz_tmp] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"volnorm:"]] UTF8String];
515             psz_tmp = (char *)[[[NSString stringWithUTF8String: psz_tmp] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"volnorm"]] UTF8String];
516             config_PutPsz( p_intf, "audio-filter", psz_tmp );
517         }
518         config_PutFloat( p_intf, "norm-max-level", [o_audio_norm_fld floatValue] );
519
520         msg_Warn( p_intf, "visualizer not implemented!" );
521
522         /* Last.FM is optional */
523         if( module_Exists( p_intf, "audioscrobbler" ) )
524         {    
525             if( [o_audio_last_ckb state] == NSOnState )
526                 config_AddIntf( VLC_OBJECT( p_intf ), "audioscrobbler" );
527             else
528                 config_RemoveIntf( VLC_OBJECT( p_intf ), "audioscrobbler" );
529
530             config_PutPsz( p_intf, "lastfm-username", [[o_audio_lastuser_fld stringValue] UTF8String] );
531             config_PutPsz( p_intf, "lastfm-password", [[o_audio_lastuser_fld stringValue] UTF8String] );
532         }
533
534         /* okay, let's save our changes to vlcrc */
535         i = config_SaveConfigFile( p_intf, "main" );
536         i = i + config_SaveConfigFile( p_intf, "audioscrobbler" );
537         i = i + config_SaveConfigFile( p_intf, "volnorm" );
538
539         if( i != 0 )
540         {
541             msg_Err( p_intf, "An error occured while saving the Audio settings using SimplePrefs" );
542             i = 0;
543         }
544         b_audioSettingChanged = NO;
545     }
546     
547     /******************
548      * video settings *
549      ******************/
550     if( b_videoSettingChanged )
551     {
552         config_PutInt( p_intf, "video", [o_video_enable_ckb state] );
553         config_PutInt( p_intf, "fullscreen", [o_video_fullscreen_ckb state] );
554         config_PutInt( p_intf, "video-on-top", [o_video_onTop_ckb state] );
555         config_PutInt( p_intf, "skip-frames", [o_video_skipFrames_ckb state] );
556         config_PutInt( p_intf, "macosx-black", [o_video_black_ckb state] );
557
558         msg_Warn( p_intf, "vout module and display device selectors not implemented!" );
559
560         config_PutPsz( p_intf, "snapshot-path", [[o_video_snap_folder_fld stringValue] UTF8String] );
561         config_PutPsz( p_intf, "snapshot-prefix", [[o_video_snap_prefix_fld stringValue] UTF8String] );
562         config_PutInt( p_intf, "snapshot-sequential", [o_video_snap_seqnum_ckb state] );
563
564         if( [o_video_snap_format_pop indexOfSelectedItem] >= 0 )
565             config_PutPsz( p_intf, "snapshot-format", [[[o_video_snap_format_pop selectedItem] title] UTF8String] );
566
567         i = config_SaveConfigFile( p_intf, "main" );
568         i = i + config_SaveConfigFile( p_intf, "macosx" );
569
570         if( i != 0 )
571         {
572             msg_Err( p_intf, "An error occured while saving the Video settings using SimplePrefs" );
573             i = 0;
574         }
575         b_videoSettingChanged = NO;
576     }
577     
578     /***************************
579      * input & codecs settings *
580      ***************************/
581     if( b_inputSettingChanged )
582     {
583         config_PutInt( p_intf, "server-port", [o_input_serverport_fld intValue] );
584         config_PutPsz( p_intf, "http-proxy", [[o_input_httpproxy_fld stringValue] UTF8String] );
585         config_PutInt( p_intf, "ffmpeg-pp-q", [o_input_postproc_fld intValue] );
586
587         SaveIntList( o_input_avi_pop, "avi-index" );
588
589         config_PutInt( p_intf, "rtsp-tcp", [o_input_rtsp_ckb state] );
590
591         #define CaCi( name, int ) config_PutInt( p_intf, name, int * [[o_input_cachelevel_pop selectedItem] tag] )
592         #define CaC( name ) CaCi( name, 1 )
593         msg_Dbg( p_intf, "Adjusting all cache values at: %i", [[o_input_cachelevel_pop selectedItem] tag] );
594         CaC( "udp-caching" );
595         if( module_Exists (p_intf, "dvdread" ) )
596         {
597             CaC( "dvdread-caching" );
598             i = i + config_SaveConfigFile( p_intf, "dvdread" );
599         }
600         if( module_Exists (p_intf, "dvdnav" ) )
601         {
602             CaC( "dvdnav-caching" );
603             i = i + config_SaveConfigFile( p_intf, "dvdnav" );
604         }
605         CaC( "tcp-caching" ); CaC( "vcd-caching" );
606         CaC( "fake-caching" ); CaC( "cdda-caching" ); CaC( "file-caching" );
607         CaC( "screen-caching" );
608         CaCi( "rtsp-caching", 4 ); CaCi( "ftp-caching", 2 );
609         CaCi( "http-caching", 4 );
610         if( module_Exists (p_intf, "access_realrtsp" ) )
611         {
612             CaCi( "realrtsp-caching", 10 );
613             i = i + config_SaveConfigFile( p_intf, "access_realrtsp" );
614         }
615         CaCi( "mms-caching", 19 );
616
617         #define SaveAccessFilter( object, name ) \
618         if( [object state] == NSOnState ) \
619         { \
620             if( b_first ) \
621             { \
622                 [o_temp appendString: name]; \
623                 b_first = NO; \
624             } \
625             else \
626                 [o_temp appendFormat: @":%@", name]; \
627         }
628
629         BOOL b_first = YES;
630         NSMutableString *o_temp = [[NSMutableString alloc] init];
631         SaveAccessFilter( o_input_record_ckb, @"record" );
632         SaveAccessFilter( o_input_dump_ckb, @"dump" );
633         SaveAccessFilter( o_input_bandwidth_ckb, @"bandwidth" );
634         SaveAccessFilter( o_input_timeshift_ckb, @"timeshift" );
635         config_PutPsz( p_intf, "access-filter", [o_temp UTF8String] );
636         [o_temp release];
637
638         i = config_SaveConfigFile( p_intf, "main" );
639         i = i + config_SaveConfigFile( p_intf, "ffmpeg" );
640         i = i + config_SaveConfigFile( p_intf, "access_http" );
641         i = i + config_SaveConfigFile( p_intf, "access_file" );
642         i = i + config_SaveConfigFile( p_intf, "access_tcp" );
643         i = i + config_SaveConfigFile( p_intf, "access_fake" );
644         i = i + config_SaveConfigFile( p_intf, "cdda" );
645         i = i + config_SaveConfigFile( p_intf, "screen" );
646         i = i + config_SaveConfigFile( p_intf, "vcd" );
647         i = i + config_SaveConfigFile( p_intf, "access_ftp" );
648         i = i + config_SaveConfigFile( p_intf, "access_mms" );
649         i = i + config_SaveConfigFile( p_intf, "live555" );
650
651         if( i != 0 )
652         {
653             msg_Err( p_intf, "An error occured while saving the Input settings using SimplePrefs" );
654             i = 0;
655         }
656         b_inputSettingChanged = NO;
657     }
658     
659     /**********************
660      * subtitles settings *
661      **********************/
662     if( b_osdSettingChanged )
663     {
664         config_PutInt( p_intf, "osd", [o_osd_osd_ckb state] );
665
666         if( [o_osd_encoding_pop indexOfSelectedItem] >= 0 )
667             config_PutPsz( p_intf, "subsdec-encoding", [[[o_osd_encoding_pop selectedItem] title] UTF8String] );
668
669         config_PutPsz( p_intf, "sub-language", [[o_osd_lang_fld stringValue] UTF8String] );
670         config_PutPsz( p_intf, "freetype-font", [[o_osd_font_fld stringValue] UTF8String] );
671
672         SaveIntList( o_osd_font_color_pop, "freetype-color" );
673         SaveIntList( o_osd_font_size_pop, "freetype-rel-fontsize" );
674         SaveIntList( o_osd_font_effect_pop, "freetype-effect" );
675
676         i = config_SaveConfigFile( p_intf, NULL );
677
678         if( i != 0 )
679         {
680             msg_Err( p_intf, "An error occured while saving the OSD/Subtitle settings using SimplePrefs" );
681             i = 0;
682         }
683         b_osdSettingChanged = NO;
684     }
685     
686     /********************
687      * hotkeys settings *
688      ********************/
689 }
690
691 - (void)showSettingsForCategory: (id)o_new_category_view
692 {
693     NSRect o_win_rect, o_view_rect, o_old_view_rect;
694     o_win_rect = [o_sprefs_win frame];
695     o_view_rect = [o_new_category_view frame];
696     
697     if( o_currentlyShownCategoryView != nil )
698     {
699         /* restore our window's height, if we've shown another category previously */
700         o_old_view_rect = [o_currentlyShownCategoryView frame];
701         o_win_rect.size.height = o_win_rect.size.height - o_old_view_rect.size.height;
702
703         /* remove our previous category view */
704         [o_currentlyShownCategoryView removeFromSuperviewWithoutNeedingDisplay];
705     }
706     
707     o_win_rect.size.height = o_win_rect.size.height + o_view_rect.size.height;
708     
709     [o_sprefs_win displayIfNeeded];
710     [o_sprefs_win setFrame: o_win_rect display:YES animate: YES];
711     
712     [o_new_category_view setFrame: NSMakeRect( 0, 
713                                                [o_sprefs_controls_box frame].size.height, 
714                                                o_view_rect.size.width, 
715                                                o_view_rect.size.height )];
716     [o_new_category_view setNeedsDisplay: YES];
717     [o_new_category_view setAutoresizesSubviews: YES];
718     [[o_sprefs_win contentView] addSubview: o_new_category_view];
719     
720     /* keep our current category for further reference */
721     [o_currentlyShownCategoryView release];
722     o_currentlyShownCategoryView = o_new_category_view;
723     [o_currentlyShownCategoryView retain];
724 }
725
726 - (IBAction)interfaceSettingChanged:(id)sender
727 {
728     b_intfSettingChanged = YES;
729 }
730
731 - (void)showInterfaceSettings
732 {
733     msg_Dbg( p_intf, "showing interface settings" );
734     [self showSettingsForCategory: o_intf_view];
735 }
736
737 - (IBAction)audioSettingChanged:(id)sender
738 {
739     if( sender == o_audio_vol_sld )
740         [o_audio_vol_fld setIntValue: [o_audio_vol_sld intValue]];
741     
742     if( sender == o_audio_vol_fld )
743         [o_audio_vol_sld setIntValue: [o_audio_vol_fld intValue]];
744     
745     b_audioSettingChanged = YES;
746 }
747
748 - (void)showAudioSettings
749 {
750     msg_Dbg( p_intf, "showing audio settings" );
751     [self showSettingsForCategory: o_audio_view];
752 }
753
754 - (IBAction)videoSettingChanged:(id)sender
755 {
756     if( sender == o_video_snap_folder_btn )
757     {
758         o_selectFolderPanel = [[NSOpenPanel alloc] init];
759         [o_selectFolderPanel setCanChooseDirectories: YES];
760         [o_selectFolderPanel setCanChooseFiles: NO];
761         [o_selectFolderPanel setResolvesAliases: YES];
762         [o_selectFolderPanel setAllowsMultipleSelection: NO];
763         [o_selectFolderPanel setMessage: _NS("Choose the folder to save your video snapshots to.")];
764         [o_selectFolderPanel setCanCreateDirectories: YES];
765         [o_selectFolderPanel setPrompt: _NS("Choose")];
766         [o_selectFolderPanel beginSheetForDirectory: nil file: nil modalForWindow: o_sprefs_win 
767                                       modalDelegate: self 
768                                      didEndSelector: @selector(savePanelDidEnd:returnCode:contextInfo:)
769                                         contextInfo: o_video_snap_folder_btn];
770     }
771     else
772         b_videoSettingChanged = YES;
773 }
774
775 - (void)savePanelDidEnd:(NSOpenPanel * )panel returnCode: (int)returnCode contextInfo: (void *)contextInfo
776 {
777     if( returnCode == NSOKButton )
778     {
779         if( contextInfo == o_video_snap_folder_btn )
780         {
781             [o_video_snap_folder_fld setStringValue: [o_selectFolderPanel filename]];
782             b_videoSettingChanged = YES;
783         }
784         else if( contextInfo == o_osd_font_btn )
785         {
786             [o_osd_font_fld setStringValue: [o_selectFolderPanel filename]];
787             b_osdSettingChanged = YES;
788         }
789     }
790
791     [o_selectFolderPanel release];
792 }
793
794 - (void)showVideoSettings
795 {
796     msg_Dbg( p_intf, "showing video settings" );
797     [self showSettingsForCategory: o_video_view];
798 }
799
800 - (IBAction)osdSettingChanged:(id)sender
801 {
802     if( sender == o_osd_font_btn )
803     {
804         o_selectFolderPanel = [[NSOpenPanel alloc] init];
805         [o_selectFolderPanel setCanChooseDirectories: NO];
806         [o_selectFolderPanel setCanChooseFiles: YES];
807         [o_selectFolderPanel setResolvesAliases: YES];
808         [o_selectFolderPanel setAllowsMultipleSelection: NO];
809         [o_selectFolderPanel setMessage: _NS("Choose the font to display your Subtitles with.")];
810         [o_selectFolderPanel setCanCreateDirectories: NO];
811         [o_selectFolderPanel setPrompt: _NS("Choose")];
812         [o_selectFolderPanel setAllowedFileTypes: [NSArray arrayWithObjects: @"dfont", @"ttf", @"otf", @"FFIL", nil]];
813         [o_selectFolderPanel beginSheetForDirectory: @"/System/Library/Fonts/" file: nil modalForWindow: o_sprefs_win 
814                                       modalDelegate: self 
815                                      didEndSelector: @selector(savePanelDidEnd:returnCode:contextInfo:)
816                                         contextInfo: o_osd_font_btn];
817     }
818     else
819         b_osdSettingChanged = YES;
820 }
821
822 - (void)showOSDSettings
823 {
824     msg_Dbg( p_intf, "showing OSD settings" );
825     [self showSettingsForCategory: o_osd_view];
826 }
827
828 - (IBAction)inputSettingChanged:(id)sender
829 {
830     b_inputSettingChanged = YES;
831 }
832
833 - (void)showInputSettings
834 {
835     msg_Dbg( p_intf, "showing Input Settings" );
836     [self showSettingsForCategory: o_input_view];
837 }
838
839 @end