macosx: open recent menu: for files, just show their name without the full path....
[vlc.git] / modules / gui / macosx / MainMenu.m
1 /*****************************************************************************
2  * MainMenu.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2011 Felix Paul Kühne
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 "MainMenu.h"
25 #import <vlc_common.h>
26 #import <vlc_playlist.h>
27
28 #import "intf.h"
29 #import "open.h"
30 #import "wizard.h"
31 #import "about.h"
32 #import "AudioEffects.h"
33 #import "TrackSynchronization.h"
34 #import "VideoEffects.h"
35 #import "bookmarks.h"
36 #import "simple_prefs.h"
37 #import "coredialogs.h"
38 #import "controls.h"
39 #import "playlistinfo.h"
40 #import "VideoView.h"
41 #import "CoreInteraction.h"
42 #import "MainWindow.h"
43
44 @implementation VLCMainMenu
45 static VLCMainMenu *_o_sharedInstance = nil;
46
47 + (VLCMainMenu *)sharedInstance
48 {
49     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
50 }
51
52 #pragma mark -
53 #pragma mark Initialization
54
55 - (id)init
56 {
57     if( _o_sharedInstance)
58     {
59         [self dealloc];
60         return _o_sharedInstance;
61     }
62     else
63     {
64         _o_sharedInstance = [super init];
65     }
66
67     return _o_sharedInstance;
68 }
69
70 - (void)dealloc
71 {
72     [[NSNotificationCenter defaultCenter] removeObserver: self];
73     
74     if (b_nib_about_loaded)
75         [o_about release];
76
77     if (b_nib_videoeffects_loaded)
78         [o_videoeffects release];
79
80     if (b_nib_audioeffects_loaded)
81         [o_audioeffects release];
82
83     if (b_nib_tracksynchro_loaded)
84         [o_trackSynchronization release];
85
86     [super dealloc];
87 }
88
89 - (void)awakeFromNib
90 {
91     [[NSNotificationCenter defaultCenter] addObserver: self 
92                                              selector: @selector(applicationWillFinishLaunching:)
93                                                  name: NSApplicationWillFinishLaunchingNotification
94                                                object: nil];
95 }
96
97 - (void)applicationWillFinishLaunching:(NSNotification *)o_notification
98 {
99     p_intf = VLCIntf;
100
101     NSString* o_key;
102     playlist_t *p_playlist;
103     vlc_value_t val;
104     id o_vlcmain = [VLCMain sharedInstance];
105     char * key;
106
107     /* Check if we already did this once. Opening the other nibs calls it too,
108      because VLCMain is the owner */
109     if( b_mainMenu_setup ) return;
110
111     [self initStrings];
112
113     key = config_GetPsz( p_intf, "key-quit" );
114     o_key = [NSString stringWithFormat:@"%s", key];
115     [o_mi_quit setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
116     [o_mi_quit setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
117     FREENULL( key );
118
119     key = config_GetPsz( p_intf, "key-play-pause" );
120     o_key = [NSString stringWithFormat:@"%s", key];
121     [o_mi_play setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
122     [o_mi_play setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
123     FREENULL( key );
124
125     key = config_GetPsz( p_intf, "key-stop" );
126     o_key = [NSString stringWithFormat:@"%s", key];
127     [o_mi_stop setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
128     [o_mi_stop setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
129     FREENULL( key );
130
131     key = config_GetPsz( p_intf, "key-prev" );
132     o_key = [NSString stringWithFormat:@"%s", key];
133     [o_mi_previous setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
134     [o_mi_previous setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
135     FREENULL( key );
136
137     key = config_GetPsz( p_intf, "key-next" );
138     o_key = [NSString stringWithFormat:@"%s", key];
139     [o_mi_next setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
140     [o_mi_next setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
141     FREENULL( key );
142
143     key = config_GetPsz( p_intf, "key-jump+short" );
144     o_key = [NSString stringWithFormat:@"%s", key];
145     [o_mi_fwd setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
146     [o_mi_fwd setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
147     FREENULL( key );
148
149     key = config_GetPsz( p_intf, "key-jump-short" );
150     o_key = [NSString stringWithFormat:@"%s", key];
151     [o_mi_bwd setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
152     [o_mi_bwd setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
153     FREENULL( key );
154
155     key = config_GetPsz( p_intf, "key-vol-up" );
156     o_key = [NSString stringWithFormat:@"%s", key];
157     [o_mi_vol_up setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
158     [o_mi_vol_up setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
159     FREENULL( key );
160
161     key = config_GetPsz( p_intf, "key-vol-down" );
162     o_key = [NSString stringWithFormat:@"%s", key];
163     [o_mi_vol_down setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
164     [o_mi_vol_down setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
165     FREENULL( key );
166
167     key = config_GetPsz( p_intf, "key-vol-mute" );
168     o_key = [NSString stringWithFormat:@"%s", key];
169     [o_mi_mute setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
170     [o_mi_mute setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
171     FREENULL( key );
172
173     key = config_GetPsz( p_intf, "key-toggle-fullscreen" );
174     o_key = [NSString stringWithFormat:@"%s", key];
175     [o_mi_fullscreen setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
176     [o_mi_fullscreen setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
177     FREENULL( key );
178
179     key = config_GetPsz( p_intf, "key-snapshot" );
180     o_key = [NSString stringWithFormat:@"%s", key];
181     [o_mi_snapshot setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
182     [o_mi_snapshot setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
183     FREENULL( key );
184
185     key = config_GetPsz( p_intf, "key-random" );
186     o_key = [NSString stringWithFormat:@"%s", key];
187     [o_mi_random setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
188     [o_mi_random setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
189     FREENULL( key );
190
191     key = config_GetPsz( p_intf, "key-zoom-half" );
192     o_key = [NSString stringWithFormat:@"%s", key];
193     [o_mi_half_window setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
194     [o_mi_half_window setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
195     FREENULL( key );
196
197     key = config_GetPsz( p_intf, "key-zoom-original" );
198     o_key = [NSString stringWithFormat:@"%s", key];
199     [o_mi_normal_window setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
200     [o_mi_normal_window setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
201     FREENULL( key );
202
203     key = config_GetPsz( p_intf, "key-zoom-double" );
204     o_key = [NSString stringWithFormat:@"%s", key];
205     [o_mi_double_window setKeyEquivalent: [o_vlcmain VLCKeyToString: o_key]];
206     [o_mi_double_window setKeyEquivalentModifierMask: [o_vlcmain VLCModifiersToCocoa:o_key]];
207     FREENULL( key );
208
209     [self setSubmenusEnabled: FALSE];
210
211     [[NSNotificationCenter defaultCenter] addObserver: self
212                                              selector: @selector(refreshVoutDeviceMenu:)
213                                                  name: NSApplicationDidChangeScreenParametersNotification
214                                                object: nil];
215
216     /* we're done */
217     b_mainMenu_setup = YES;
218
219     [self setupVarMenuItem: o_mi_add_intf target: (vlc_object_t *)p_intf
220                              var: "intf-add" selector: @selector(toggleVar:)];
221 }
222
223 - (void)initStrings
224 {
225     /* main menu */
226     [o_mi_about setTitle: [_NS("About VLC media player") \
227                            stringByAppendingString: @"..."]];
228     [o_mi_checkForUpdate setTitle: _NS("Check for Update...")];
229     [o_mi_prefs setTitle: _NS("Preferences...")];
230     [o_mi_add_intf setTitle: _NS("Add Interface")];
231     [o_mu_add_intf setTitle: _NS("Add Interface")];
232     [o_mi_services setTitle: _NS("Services")];
233     [o_mi_hide setTitle: _NS("Hide VLC")];
234     [o_mi_hide_others setTitle: _NS("Hide Others")];
235     [o_mi_show_all setTitle: _NS("Show All")];
236     [o_mi_quit setTitle: _NS("Quit VLC")];
237
238     [o_mu_file setTitle: _ANS("1:File")];
239     [o_mi_open_generic setTitle: _NS("Advanced Open File...")];
240     [o_mi_open_file setTitle: _NS("Open File...")];
241     [o_mi_open_disc setTitle: _NS("Open Disc...")];
242     [o_mi_open_net setTitle: _NS("Open Network...")];
243     [o_mi_open_capture setTitle: _NS("Open Capture Device...")];
244     [o_mi_open_recent setTitle: _NS("Open Recent")];
245     [o_mi_open_recent_cm setTitle: _NS("Clear Menu")];
246     [o_mi_open_wizard setTitle: _NS("Streaming/Exporting Wizard...")];
247
248     [o_mu_edit setTitle: _NS("Edit")];
249     [o_mi_cut setTitle: _NS("Cut")];
250     [o_mi_copy setTitle: _NS("Copy")];
251     [o_mi_paste setTitle: _NS("Paste")];
252     [o_mi_clear setTitle: _NS("Clear")];
253     [o_mi_select_all setTitle: _NS("Select All")];
254
255     [o_mu_controls setTitle: _NS("Playback")];
256     [o_mi_play setTitle: _NS("Play")];
257     [o_mi_stop setTitle: _NS("Stop")];
258     [o_mi_record setTitle: _NS("Record")];
259     [o_mi_rate setView: o_mi_rate_view];
260     [o_mi_rate_lbl setStringValue: _NS("Playback Speed")];
261     [o_mi_rate_lbl_gray setStringValue: _NS("Playback Speed")];
262     [o_mi_rate_slower_lbl setStringValue: _NS("Slower")];
263     [o_mi_rate_normal_lbl setStringValue: _NS("Normal")];
264     [o_mi_rate_faster_lbl setStringValue: _NS("Faster")];
265     [o_mi_trackSynchronization setTitle: _NS("Track Synchronization")];
266     [o_mi_previous setTitle: _NS("Previous")];
267     [o_mi_next setTitle: _NS("Next")];
268     [o_mi_random setTitle: _NS("Random")];
269     [o_mi_repeat setTitle: _NS("Repeat One")];
270     [o_mi_loop setTitle: _NS("Repeat All")];
271     [o_mi_quitAfterPB setTitle: _NS("Quit after Playback")];
272     [o_mi_fwd setTitle: _NS("Step Forward")];
273     [o_mi_bwd setTitle: _NS("Step Backward")];
274
275     [o_mi_program setTitle: _NS("Program")];
276     [o_mu_program setTitle: _NS("Program")];
277     [o_mi_title setTitle: _NS("Title")];
278     [o_mu_title setTitle: _NS("Title")];
279     [o_mi_chapter setTitle: _NS("Chapter")];
280     [o_mu_chapter setTitle: _NS("Chapter")];
281
282     [o_mu_audio setTitle: _NS("Audio")];
283     [o_mi_vol_up setTitle: _NS("Increase Volume")];
284     [o_mi_vol_down setTitle: _NS("Decrease Volume")];
285     [o_mi_mute setTitle: _NS("Mute")];
286     [o_mi_audiotrack setTitle: _NS("Audio Track")];
287     [o_mu_audiotrack setTitle: _NS("Audio Track")];
288     [o_mi_channels setTitle: _NS("Audio Channels")];
289     [o_mu_channels setTitle: _NS("Audio Channels")];
290     [o_mi_device setTitle: _NS("Audio Device")];
291     [o_mu_device setTitle: _NS("Audio Device")];
292     [o_mi_visual setTitle: _NS("Visualizations")];
293     [o_mu_visual setTitle: _NS("Visualizations")];
294
295     [o_mu_video setTitle: _NS("Video")];
296     [o_mi_half_window setTitle: _NS("Half Size")];
297     [o_mi_normal_window setTitle: _NS("Normal Size")];
298     [o_mi_double_window setTitle: _NS("Double Size")];
299     [o_mi_fittoscreen setTitle: _NS("Fit to Screen")];
300     [o_mi_fullscreen setTitle: _NS("Fullscreen")];
301     [o_mi_floatontop setTitle: _NS("Float on Top")];
302     [o_mi_snapshot setTitle: _NS("Snapshot")];
303     [o_mi_videotrack setTitle: _NS("Video Track")];
304     [o_mu_videotrack setTitle: _NS("Video Track")];
305     [o_mi_aspect_ratio setTitle: _NS("Aspect-ratio")];
306     [o_mu_aspect_ratio setTitle: _NS("Aspect-ratio")];
307     [o_mi_crop setTitle: _NS("Crop")];
308     [o_mu_crop setTitle: _NS("Crop")];
309     [o_mi_screen setTitle: _NS("Fullscreen Video Device")];
310     [o_mu_screen setTitle: _NS("Fullscreen Video Device")];
311     [o_mi_subtitle setTitle: _NS("Subtitles Track")];
312     [o_mu_subtitle setTitle: _NS("Subtitles Track")];
313     [o_mi_addSub setTitle: _NS("Open File...")];
314     [o_mi_deinterlace setTitle: _NS("Deinterlace")];
315     [o_mu_deinterlace setTitle: _NS("Deinterlace")];
316     [o_mi_deinterlace_mode setTitle: _NS("Deinterlace mode")];
317     [o_mu_deinterlace_mode setTitle: _NS("Deinterlace mode")];
318     [o_mi_ffmpeg_pp setTitle: _NS("Post processing")];
319     [o_mu_ffmpeg_pp setTitle: _NS("Post processing")];
320     [o_mi_teletext setTitle: _NS("Teletext")];
321     [o_mi_teletext_transparent setTitle: _NS("Transparent")];
322     [o_mi_teletext_index setTitle: _NS("Index")];
323     [o_mi_teletext_red setTitle: _NS("Red")];
324     [o_mi_teletext_green setTitle: _NS("Green")];
325     [o_mi_teletext_yellow setTitle: _NS("Yellow")];
326     [o_mi_teletext_blue setTitle: _NS("Blue")];
327
328     [o_mu_window setTitle: _NS("Window")];
329     [o_mi_minimize setTitle: _NS("Minimize Window")];
330     [o_mi_close_window setTitle: _NS("Close Window")];
331     [o_mi_player setTitle: _NS("Player...")];
332     [o_mi_controller setTitle: _NS("Main Window...")];
333     [o_mi_audioeffects setTitle: _NS("Audio Effects...")];
334     [o_mi_videoeffects setTitle: _NS("Video Filters...")];
335     [o_mi_bookmarks setTitle: _NS("Bookmarks...")];
336     [o_mi_playlist setTitle: _NS("Playlist...")];
337     [o_mi_info setTitle: _NS("Media Information...")];
338     [o_mi_messages setTitle: _NS("Messages...")];
339     [o_mi_errorsAndWarnings setTitle: _NS("Errors and Warnings...")];
340
341     [o_mi_bring_atf setTitle: _NS("Bring All to Front")];
342
343     [o_mu_help setTitle: _NS("Help")];
344     [o_mi_help setTitle: _NS("VLC media player Help...")];
345     [o_mi_readme setTitle: _NS("ReadMe / FAQ...")];
346     [o_mi_license setTitle: _NS("License")];
347     [o_mi_documentation setTitle: _NS("Online Documentation...")];
348     [o_mi_website setTitle: _NS("VideoLAN Website...")];
349     [o_mi_donation setTitle: _NS("Make a donation...")];
350     [o_mi_forum setTitle: _NS("Online Forum...")];
351
352     /* dock menu */
353     [o_dmi_play setTitle: _NS("Play")];
354     [o_dmi_stop setTitle: _NS("Stop")];
355     [o_dmi_next setTitle: _NS("Next")];
356     [o_dmi_previous setTitle: _NS("Previous")];
357     [o_dmi_mute setTitle: _NS("Mute")];
358
359     /* vout menu */
360     [o_vmi_play setTitle: _NS("Play")];
361     [o_vmi_stop setTitle: _NS("Stop")];
362     [o_vmi_prev setTitle: _NS("Previous")];
363     [o_vmi_next setTitle: _NS("Next")];
364     [o_vmi_volup setTitle: _NS("Volume Up")];
365     [o_vmi_voldown setTitle: _NS("Volume Down")];
366     [o_vmi_mute setTitle: _NS("Mute")];
367     [o_vmi_fullscreen setTitle: _NS("Fullscreen")];
368     [o_vmi_snapshot setTitle: _NS("Snapshot")];
369 }
370
371 #pragma mark -
372 #pragma mark Termination
373
374 - (void)releaseRepresentedObjects:(NSMenu *)the_menu
375 {
376     if( !p_intf ) return;
377     
378     NSArray *menuitems_array = [the_menu itemArray];
379     NSUInteger menuItemCount = [menuitems_array count];
380     for( NSUInteger i=0; i < menuItemCount; i++ )
381     {
382         NSMenuItem *one_item = [menuitems_array objectAtIndex: i];
383         if( [one_item hasSubmenu] )
384             [self releaseRepresentedObjects: [one_item submenu]];
385
386         [one_item setRepresentedObject:NULL];
387     }
388 }
389
390 #pragma mark -
391 #pragma mark Interface update
392
393 - (void)setupMenus
394 {
395     playlist_t * p_playlist = pl_Get( p_intf );
396     input_thread_t * p_input = playlist_CurrentInput( p_playlist );
397     if( p_input != NULL )
398     {
399         [o_mi_record setEnabled: var_GetBool( p_input, "can-record" )];
400
401         [self setupVarMenuItem: o_mi_program target: (vlc_object_t *)p_input
402                                  var: "program" selector: @selector(toggleVar:)];
403
404         [self setupVarMenuItem: o_mi_title target: (vlc_object_t *)p_input
405                                  var: "title" selector: @selector(toggleVar:)];
406
407         [self setupVarMenuItem: o_mi_chapter target: (vlc_object_t *)p_input
408                                  var: "chapter" selector: @selector(toggleVar:)];
409
410         [self setupVarMenuItem: o_mi_audiotrack target: (vlc_object_t *)p_input
411                                  var: "audio-es" selector: @selector(toggleVar:)];
412
413         [self setupVarMenuItem: o_mi_videotrack target: (vlc_object_t *)p_input
414                                  var: "video-es" selector: @selector(toggleVar:)];
415
416         [self setupVarMenuItem: o_mi_subtitle target: (vlc_object_t *)p_input
417                                  var: "spu-es" selector: @selector(toggleVar:)];
418
419         /* special case for "Open File" inside the subtitles menu item */
420         if( [o_mi_videotrack isEnabled] == YES )
421             [o_mi_subtitle setEnabled: YES];
422
423         audio_output_t * p_aout = input_GetAout( p_input );
424         if( p_aout != NULL )
425         {
426             [self setupVarMenuItem: o_mi_channels target: (vlc_object_t *)p_aout
427                                      var: "audio-channels" selector: @selector(toggleVar:)];
428
429             [self setupVarMenuItem: o_mi_device target: (vlc_object_t *)p_aout
430                                      var: "audio-device" selector: @selector(toggleVar:)];
431
432             [self setupVarMenuItem: o_mi_visual target: (vlc_object_t *)p_aout
433                                      var: "visual" selector: @selector(toggleVar:)];
434             vlc_object_release( (vlc_object_t *)p_aout );
435         }
436
437         vout_thread_t * p_vout = input_GetVout( p_input );
438
439         if( p_vout != NULL )
440         {
441             vlc_object_t * p_dec_obj;
442
443             [self setupVarMenuItem: o_mi_aspect_ratio target: (vlc_object_t *)p_vout
444                                      var: "aspect-ratio" selector: @selector(toggleVar:)];
445
446             [self setupVarMenuItem: o_mi_crop target: (vlc_object_t *) p_vout
447                                      var: "crop" selector: @selector(toggleVar:)];
448
449             [self setupVarMenuItem: o_mi_screen target: (vlc_object_t *)p_vout
450                                      var: "video-device" selector: @selector(toggleVar:)];
451
452             [self setupVarMenuItem: o_mi_deinterlace target: (vlc_object_t *)p_vout
453                                      var: "deinterlace" selector: @selector(toggleVar:)];
454
455             [self setupVarMenuItem: o_mi_deinterlace_mode target: (vlc_object_t *)p_vout
456                                      var: "deinterlace-mode" selector: @selector(toggleVar:)];
457
458 #if 1
459             [self setupVarMenuItem: o_mi_ffmpeg_pp target:
460              (vlc_object_t *)p_vout var:"postprocess" selector:
461              @selector(toggleVar:)];
462 #endif
463             vlc_object_release( (vlc_object_t *)p_vout );
464         }
465         vlc_object_release( p_input );
466     }
467     else
468     {
469         [o_mi_record setEnabled: NO];
470     }
471 }
472
473 - (void)refreshVoutDeviceMenu:(NSNotification *)o_notification
474 {
475     int x, y = 0;
476     vout_thread_t * p_vout = getVout();
477     if( !p_vout )
478         return;
479
480     /* clean the menu before adding new entries */
481     if( [o_mi_screen hasSubmenu] )
482     {
483         y = [[o_mi_screen submenu] numberOfItems] - 1;
484         while( x != y )
485         {
486             [[o_mi_screen submenu] removeItemAtIndex: x];
487             x++;
488         }
489     }
490
491     [self setupVarMenuItem: o_mi_screen target: (vlc_object_t *)p_vout
492                              var: "video-device" selector: @selector(toggleVar:)];
493     vlc_object_release( (vlc_object_t *)p_vout );
494 }
495
496 - (void)setSubmenusEnabled:(BOOL)b_enabled
497 {
498     [o_mi_program setEnabled: b_enabled];
499     [o_mi_title setEnabled: b_enabled];
500     [o_mi_chapter setEnabled: b_enabled];
501     [o_mi_audiotrack setEnabled: b_enabled];
502     [o_mi_visual setEnabled: b_enabled];
503     [o_mi_videotrack setEnabled: b_enabled];
504     [o_mi_subtitle setEnabled: b_enabled];
505     [o_mi_channels setEnabled: b_enabled];
506     [o_mi_deinterlace setEnabled: b_enabled];
507     [o_mi_deinterlace_mode setEnabled: b_enabled];
508     [o_mi_ffmpeg_pp setEnabled: b_enabled];
509     [o_mi_device setEnabled: b_enabled];
510     [o_mi_screen setEnabled: b_enabled];
511     [o_mi_aspect_ratio setEnabled: b_enabled];
512     [o_mi_crop setEnabled: b_enabled];
513     [o_mi_teletext setEnabled: b_enabled];
514 }
515
516 - (void)setRateControlsEnabled:(BOOL)b_enabled
517 {
518     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
519     [o_mi_rate_sld setEnabled: b_enabled];
520     [o_mi_rate_sld setIntValue: [[VLCCoreInteraction sharedInstance] playbackRate]];
521     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
522     if (i == 0)
523         i = 1;
524     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%ix", i]];
525     if (b_enabled) {
526         [o_mi_rate_lbl setHidden: NO];
527         [o_mi_rate_lbl_gray setHidden: YES];
528     }
529     else
530     {
531         [o_mi_rate_lbl setHidden: YES];
532         [o_mi_rate_lbl_gray setHidden: NO];
533     }
534     [o_pool release];
535 }
536
537 #pragma mark -
538 #pragma mark Recent Items
539 - (IBAction)openRecentItem:(id)item
540 {
541     [[VLCMain sharedInstance] application: nil openFile: [[[[NSDocumentController sharedDocumentController] recentDocumentURLs] objectAtIndex: [item tag]] absoluteString]];
542 }
543
544 - (IBAction)clearRecentItems:(id)sender
545 {
546     [[NSDocumentController sharedDocumentController] clearRecentDocuments: nil];
547 }
548
549 #pragma mark -
550 #pragma mark Playback
551 - (IBAction)toggleRecord:(id)sender
552 {
553     [[VLCCoreInteraction sharedInstance] toggleRecord];
554 }
555
556 - (void)updateRecordState:(BOOL)b_value
557 {
558     [o_mi_record setState:b_value];
559 }
560
561 - (IBAction)setPlaybackRate:(id)sender
562 {
563     [[VLCCoreInteraction sharedInstance] setPlaybackRate: [o_mi_rate_sld intValue]];
564     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
565     if (i == 0)
566         i = 1;
567     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%ix", i]];
568 }
569
570 - (void)updatePlaybackRate
571 {
572     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
573     if (i == 0)
574         i = 1;
575     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%ix", i]];
576     [o_mi_rate_sld setIntValue: i];
577 }
578
579 #pragma mark -
580 #pragma video menu
581 - (IBAction)toggleFullscreen:(id)sender
582 {
583     [[VLCCoreInteraction sharedInstance] toggleFullscreen];
584 }
585
586 - (IBAction)resizeVideoWindow:(id)sender
587 {
588     input_thread_t *p_input = pl_CurrentInput( VLCIntf );
589     if (p_input)
590     {
591         vout_thread_t *p_vout = getVout();
592         if (p_vout)
593         {
594             if (sender == o_mi_half_window)
595                 var_SetFloat( p_vout, "zoom", 0.5 );
596             else if (sender == o_mi_normal_window)
597                 var_SetFloat( p_vout, "zoom", 1.0 );
598             else if (sender == o_mi_double_window)
599                 var_SetFloat( p_vout, "zoom", 2.0 );
600             else
601             {
602                 var_ToggleBool( p_vout, "autoscale" );
603             }
604             vlc_object_release( p_vout );
605         }
606         vlc_object_release( p_input );
607     }
608 }
609
610 - (IBAction)floatOnTop:(id)sender
611 {
612     input_thread_t *p_input = pl_CurrentInput( VLCIntf );
613     if (p_input)
614     {
615         vout_thread_t *p_vout = getVout();
616         if (p_vout)
617         {
618             var_ToggleBool( p_vout, "video-on-top" );
619             vlc_object_release( p_vout );
620         }
621         vlc_object_release( p_input );
622     }
623 }
624
625 - (IBAction)createVideoSnapshot:(id)sender
626 {
627     input_thread_t *p_input = pl_CurrentInput( VLCIntf );
628     if (p_input)
629     {
630         vout_thread_t *p_vout = getVout();
631         if (p_vout)
632         {
633             var_TriggerCallback( p_vout, "video-snapshot" );
634             vlc_object_release( p_vout );
635         }
636         vlc_object_release( p_input );
637     }
638 }
639
640 - (id)voutMenu
641 {
642     return o_vout_menu;
643 }
644
645 #pragma mark -
646 #pragma mark Panels
647
648 - (IBAction)intfOpenFile:(id)sender
649 {
650     [[[VLCMain sharedInstance] open] openFile];
651 }
652
653 - (IBAction)intfOpenFileGeneric:(id)sender
654 {
655     [[[VLCMain sharedInstance] open] openFileGeneric];
656 }
657
658 - (IBAction)intfOpenDisc:(id)sender
659 {
660     [[[VLCMain sharedInstance] open] openDisc];
661 }
662
663 - (IBAction)intfOpenNet:(id)sender
664 {
665     [[[VLCMain sharedInstance] open] openNet];
666 }
667
668 - (IBAction)intfOpenCapture:(id)sender
669 {
670     [[[VLCMain sharedInstance] open] openCapture];
671 }
672
673 - (IBAction)showWizard:(id)sender
674 {
675     [[[VLCMain sharedInstance] wizard] resetWizard];
676     [[[VLCMain sharedInstance] wizard] showWizard];
677 }
678
679 - (IBAction)showVideoEffects:(id)sender
680 {
681     if( o_videoeffects == nil )
682         o_videoeffects = [[VLCVideoEffects alloc] init];
683
684     if( !b_nib_videoeffects_loaded )
685         b_nib_videoeffects_loaded = [NSBundle loadNibNamed:@"VideoEffects" owner: NSApp];
686
687     [o_videoeffects toggleWindow:sender];
688 }
689
690 - (IBAction)showTrackSynchronization:(id)sender
691 {
692     if (!o_trackSynchronization)
693         o_trackSynchronization = [[VLCTrackSynchronization alloc] init];
694
695     if (!b_nib_tracksynchro_loaded)
696         b_nib_tracksynchro_loaded = [NSBundle loadNibNamed:@"SyncTracks" owner:NSApp];
697
698     [o_trackSynchronization toggleWindow:sender];
699 }
700
701 - (IBAction)showAudioEffects:(id)sender
702 {
703     if (!o_audioeffects)
704         o_audioeffects = [[VLCAudioEffects alloc] init];
705
706     if (!b_nib_audioeffects_loaded)
707         b_nib_audioeffects_loaded = [NSBundle loadNibNamed:@"AudioEffects" owner:NSApp];
708
709     [o_audioeffects toggleWindow:sender];
710 }
711
712 - (IBAction)showBookmarks:(id)sender
713 {
714     [[[VLCMain sharedInstance] bookmarks] showBookmarks];
715 }
716
717 - (IBAction)viewPreferences:(id)sender
718 {
719     [[[VLCMain sharedInstance] simplePreferences] showSimplePrefs];
720 }
721
722 #pragma mark -
723 #pragma mark Help and Docs
724
725 - (void)initAbout
726 {
727     if(! o_about )
728         o_about = [[VLAboutBox alloc] init];
729
730     if( !b_nib_about_loaded )
731         b_nib_about_loaded = [NSBundle loadNibNamed:@"About" owner: NSApp];
732 }
733
734 - (IBAction)viewAbout:(id)sender
735 {
736     [self initAbout];
737     [o_about showAbout];
738 }
739
740 - (IBAction)showLicense:(id)sender
741 {
742     [self initAbout];
743     [o_about showGPL: sender];
744 }
745
746 - (IBAction)viewHelp:(id)sender
747 {
748     [self initAbout];
749     [o_about showHelp];
750 }
751
752 - (IBAction)openReadMe:(id)sender
753 {
754     NSString * o_path = [[NSBundle mainBundle] pathForResource: @"README.MacOSX" ofType: @"rtf"];
755
756     [[NSWorkspace sharedWorkspace] openFile: o_path withApplication: @"TextEdit"];
757 }
758
759 - (IBAction)openDocumentation:(id)sender
760 {
761     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/doc/"];
762
763     [[NSWorkspace sharedWorkspace] openURL: o_url];
764 }
765
766 - (IBAction)openWebsite:(id)sender
767 {
768     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/"];
769
770     [[NSWorkspace sharedWorkspace] openURL: o_url];
771 }
772
773 - (IBAction)openForum:(id)sender
774 {
775     NSURL * o_url = [NSURL URLWithString: @"http://forum.videolan.org/"];
776
777     [[NSWorkspace sharedWorkspace] openURL: o_url];
778 }
779
780 - (IBAction)openDonate:(id)sender
781 {
782     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/contribute.html#paypal"];
783
784     [[NSWorkspace sharedWorkspace] openURL: o_url];
785 }
786
787 #pragma mark -
788 #pragma mark Errors, warnings and messages
789
790 - (IBAction)viewErrorsAndWarnings:(id)sender
791 {
792     [[[[VLCMain sharedInstance] coreDialogProvider] errorPanel] showPanel];
793 }
794
795 - (IBAction)showInformationPanel:(id)sender
796 {
797     [[[VLCMain sharedInstance] info] initPanel];
798 }
799
800 #pragma mark -
801 #pragma mark convinience stuff for other objects
802 - (void)setPlay
803 {
804     [o_mi_play setTitle: _NS("Play")];
805     [o_dmi_play setTitle: _NS("Play")];
806     [o_vmi_play setTitle: _NS("Play")];
807 }
808
809 - (void)setPause
810 {
811     [o_mi_play setTitle: _NS("Pause")];
812     [o_dmi_play setTitle: _NS("Pause")];
813     [o_vmi_play setTitle: _NS("Pause")];
814 }
815
816 - (void)setRepeatOne
817 {
818     [o_mi_repeat setState: NSOnState];
819     [o_mi_loop setState: NSOffState];
820 }
821
822 - (void)setRepeatAll
823 {
824     [o_mi_repeat setState: NSOffState];
825     [o_mi_loop setState: NSOnState];
826 }
827
828 - (void)setRepeatOff
829 {
830     [o_mi_repeat setState: NSOffState];
831     [o_mi_loop setState: NSOffState];
832 }
833
834 - (void)setShuffle
835 {
836     bool b_value;
837     playlist_t *p_playlist = pl_Get( VLCIntf );
838     b_value = var_GetBool( p_playlist, "random" );
839         [o_mi_random setState: b_value];
840 }
841
842 #pragma mark -
843 #pragma mark Dynamic menu creation and validation
844
845 - (void)setupVarMenuItem:(NSMenuItem *)o_mi
846                   target:(vlc_object_t *)p_object
847                      var:(const char *)psz_variable
848                 selector:(SEL)pf_callback
849 {
850     vlc_value_t val, text;
851     int i_type = var_Type( p_object, psz_variable );
852
853     switch( i_type & VLC_VAR_TYPE )
854     {
855         case VLC_VAR_VOID:
856         case VLC_VAR_BOOL:
857         case VLC_VAR_VARIABLE:
858         case VLC_VAR_STRING:
859         case VLC_VAR_INTEGER:
860             break;
861         default:
862             /* Variable doesn't exist or isn't handled */
863             return;
864     }
865
866     /* Make sure we want to display the variable */
867     if( i_type & VLC_VAR_HASCHOICE )
868     {
869         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
870         if( val.i_int == 0 ) return;
871         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
872             return;
873     }
874
875     /* Get the descriptive name of the variable */
876     var_Change( p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL );
877     [o_mi setTitle: [[VLCMain sharedInstance] localizedString: text.psz_string ?
878                      text.psz_string : psz_variable ]];
879
880     if( i_type & VLC_VAR_HASCHOICE )
881     {
882         NSMenu *o_menu = [o_mi submenu];
883         
884         [self setupVarMenu: o_menu forMenuItem: o_mi target:p_object
885                        var:psz_variable selector:pf_callback];
886         
887         free( text.psz_string );
888         return;
889     }
890     if( var_Get( p_object, psz_variable, &val ) < 0 )
891     {
892         return;
893     }
894
895     VLCAutoGeneratedMenuContent *o_data;
896     switch( i_type & VLC_VAR_TYPE )
897     {
898         case VLC_VAR_VOID:
899             o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
900                                                                       andValue: val ofType: i_type];
901             [o_mi setRepresentedObject: [o_data autorelease]];
902             break;
903
904         case VLC_VAR_BOOL:
905             o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
906                                                                       andValue: val ofType: i_type];
907             [o_mi setRepresentedObject: [o_data autorelease]];
908             if( !( i_type & VLC_VAR_ISCOMMAND ) )
909                 [o_mi setState: val.b_bool ? TRUE : FALSE ];
910             break;
911
912         default:
913             break;
914     }
915
916     if( ( i_type & VLC_VAR_TYPE ) == VLC_VAR_STRING ) free( val.psz_string );
917     free( text.psz_string );
918 }
919
920
921 - (void)setupVarMenu:(NSMenu *)o_menu
922          forMenuItem: (NSMenuItem *)o_parent
923               target:(vlc_object_t *)p_object
924                  var:(const char *)psz_variable
925             selector:(SEL)pf_callback
926 {
927     vlc_value_t val, val_list, text_list;
928     int i_type, i;
929
930     /* remove previous items */
931     if (OSX_LEOPARD)
932     {
933         int i_nb_items;
934         i_nb_items = [o_menu numberOfItems];
935         for( i = 0; i < i_nb_items; i++ )
936             [o_menu removeItemAtIndex: 0];
937     }
938     else
939     {
940         /* this is more efficient then the legacy code, but 10.6+ only */
941         [o_menu removeAllItems];
942     }
943
944     /* Check the type of the object variable */
945     i_type = var_Type( p_object, psz_variable );
946
947     /* Make sure we want to display the variable */
948     if( i_type & VLC_VAR_HASCHOICE )
949     {
950         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
951         if( val.i_int == 0 ) return;
952         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
953             return;
954     }
955     else
956         return;
957
958     switch( i_type & VLC_VAR_TYPE )
959     {
960         case VLC_VAR_VOID:
961         case VLC_VAR_BOOL:
962         case VLC_VAR_VARIABLE:
963         case VLC_VAR_STRING:
964         case VLC_VAR_INTEGER:
965             break;
966         default:
967             /* Variable doesn't exist or isn't handled */
968             return;
969     }
970
971     if( var_Get( p_object, psz_variable, &val ) < 0 )
972     {
973         return;
974     }
975
976     if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST,
977                    &val_list, &text_list ) < 0 )
978     {
979         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
980         return;
981     }
982
983     /* make (un)sensitive */
984     [o_parent setEnabled: ( val_list.p_list->i_count > 1 )];
985
986     /* Aspect Ratio */
987     if( [[o_parent title] isEqualToString: _NS("Aspect-ratio")] == YES )
988     {
989         NSMenuItem *o_lmi_tmp2;
990         o_lmi_tmp2 = [o_menu addItemWithTitle: _NS("Lock Aspect Ratio") action: @selector(lockVideosAspectRatio:) keyEquivalent: @""];
991         [o_lmi_tmp2 setTarget: self];
992         [o_lmi_tmp2 setEnabled: YES];
993         [o_lmi_tmp2 setState: [[VLCCoreInteraction sharedInstance] aspectRatioIsLocked]];
994         [o_parent setEnabled: YES];
995         [o_menu addItem: [NSMenuItem separatorItem]];
996     }
997
998     /* special case for the subtitles items */
999     if( [[o_parent title] isEqualToString: _NS("Subtitles Track")] == YES )
1000     {
1001         NSMenuItem * o_lmi_tmp;
1002         o_lmi_tmp = [o_menu addItemWithTitle: _NS("Open File...") action: @selector(addSubtitleFile:) keyEquivalent: @""];
1003         [o_lmi_tmp setTarget: self];
1004         [o_lmi_tmp setEnabled: YES];
1005         [o_parent setEnabled: YES];
1006         [o_menu addItem: [NSMenuItem separatorItem]];
1007     }
1008
1009     for( i = 0; i < val_list.p_list->i_count; i++ )
1010     {
1011         NSMenuItem * o_lmi;
1012         NSString *o_title = @"";
1013         VLCAutoGeneratedMenuContent *o_data;
1014
1015         switch( i_type & VLC_VAR_TYPE )
1016         {
1017             case VLC_VAR_STRING:
1018
1019                 o_title = [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string ?
1020                            text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string ];
1021
1022                 o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
1023                 o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
1024                                                                           andValue: val_list.p_list->p_values[i] ofType: i_type];
1025                 [o_lmi setRepresentedObject: [o_data autorelease]];
1026                 [o_lmi setTarget: self];
1027
1028                 if( !strcmp( val.psz_string, val_list.p_list->p_values[i].psz_string ) && !( i_type & VLC_VAR_ISCOMMAND ) )
1029                     [o_lmi setState: TRUE ];
1030
1031                 break;
1032
1033             case VLC_VAR_INTEGER:
1034
1035                 o_title = text_list.p_list->p_values[i].psz_string ?
1036                 [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string] :
1037                 [NSString stringWithFormat: @"%"PRId64,
1038                  val_list.p_list->p_values[i].i_int];
1039
1040                 o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
1041                 o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
1042                                                                           andValue: val_list.p_list->p_values[i] ofType: i_type];
1043                 [o_lmi setRepresentedObject: [o_data autorelease]];
1044                 [o_lmi setTarget: self];
1045
1046                 if( val_list.p_list->p_values[i].i_int == val.i_int && !( i_type & VLC_VAR_ISCOMMAND ) )
1047                     [o_lmi setState: TRUE ];
1048                 break;
1049
1050             default:
1051                 break;
1052         }
1053     }
1054
1055     /* special case for the subtitles sub-menu
1056      * In case that we don't have any subs, we don't want a separator item at the end */
1057     if( [[o_parent title] isEqualToString: _NS("Subtitles Track")] == YES )
1058     {
1059         if( [o_menu numberOfItems] == 2 )
1060             [o_menu removeItemAtIndex: 1];
1061     }
1062
1063     /* clean up everything */
1064     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
1065     var_FreeList( &val_list, &text_list );
1066 }
1067
1068 - (IBAction)toggleVar:(id)sender
1069 {
1070     NSMenuItem *o_mi = (NSMenuItem *)sender;
1071     VLCAutoGeneratedMenuContent *o_data = [o_mi representedObject];
1072     [NSThread detachNewThreadSelector: @selector(toggleVarThread:)
1073                              toTarget: self withObject: o_data];
1074
1075     return;
1076 }
1077
1078 - (int)toggleVarThread: (id)data
1079 {
1080     vlc_object_t *p_object;
1081     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
1082
1083     assert([data isKindOfClass:[VLCAutoGeneratedMenuContent class]]);
1084     VLCAutoGeneratedMenuContent *menuContent = (VLCAutoGeneratedMenuContent *)data;
1085
1086     p_object = [menuContent vlcObject];
1087
1088     if( p_object != NULL )
1089     {
1090         var_Set( p_object, [menuContent name], [menuContent value] );
1091         vlc_object_release( p_object );
1092         [o_pool release];
1093         return true;
1094     }
1095     [o_pool release];
1096     return VLC_EGENERIC;
1097 }
1098
1099 @end
1100
1101 @implementation VLCMainMenu (NSMenuValidation)
1102
1103 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
1104 {
1105     NSString *o_title = [o_mi title];
1106     BOOL bEnabled = TRUE;
1107     vlc_value_t val;
1108     playlist_t * p_playlist = pl_Get( p_intf );
1109     input_thread_t * p_input = playlist_CurrentInput( p_playlist );
1110
1111     /* Recent Items Menu */
1112     if( [o_title isEqualToString: _NS("Clear Menu")] )
1113     {
1114         NSMenu * o_menu = [o_mi_open_recent submenu];
1115         int i_nb_items = [o_menu numberOfItems];
1116         NSArray * o_docs = [[NSDocumentController sharedDocumentController] recentDocumentURLs];
1117         UInt32 i_nb_docs = [o_docs count];
1118
1119         if( i_nb_items > 1 )
1120         {
1121             while( --i_nb_items )
1122             {
1123                 [o_menu removeItemAtIndex: 0];
1124             }
1125         }
1126
1127         if( i_nb_docs > 0 )
1128         {
1129             NSURL * o_url;
1130             NSString * o_doc;
1131             NSMenuItem *o_menuitem;
1132
1133             [o_menu insertItem: [NSMenuItem separatorItem] atIndex: 0];
1134
1135             while( TRUE )
1136             {
1137                 i_nb_docs--;
1138
1139                 o_url = [o_docs objectAtIndex: i_nb_docs];
1140
1141                 if( [o_url isFileURL] )
1142                     o_doc = [[NSFileManager defaultManager] displayNameAtPath: [o_url path]];
1143                 else
1144                     o_doc = [o_url absoluteString];
1145
1146                 o_menuitem = [o_menu insertItemWithTitle: o_doc
1147                                      action: @selector(openRecentItem:)
1148                               keyEquivalent: @"" atIndex: 0];
1149                 [o_menuitem setTarget: self];
1150                 [o_menuitem setTag: i_nb_docs];
1151                 if ([o_url isFileURL])
1152                 {
1153                     [o_menuitem setImage: [[NSWorkspace sharedWorkspace] iconForFile: [o_url path]]];
1154                     [[o_menuitem image] setSize: NSMakeSize(16,16)];
1155                 }
1156
1157                 if( i_nb_docs == 0 )
1158                     break;
1159             }
1160         }
1161         else
1162         {
1163             bEnabled = FALSE;
1164         }
1165     }
1166     else if( [o_title isEqualToString: _NS("Stop")] )
1167     {
1168         if( p_input == NULL )
1169         {
1170             bEnabled = FALSE;
1171         }
1172         [self setupMenus]; /* Make sure input menu is up to date */
1173     }
1174     else if( [o_title isEqualToString: _NS("Previous")] ||
1175             [o_title isEqualToString: _NS("Next")] )
1176     {
1177         PL_LOCK;
1178         bEnabled = playlist_CurrentSize( p_playlist ) > 1;
1179         PL_UNLOCK;
1180     }
1181     else if( [o_title isEqualToString: _NS("Random")] )
1182     {
1183         int i_state;
1184         var_Get( p_playlist, "random", &val );
1185         i_state = val.b_bool ? NSOnState : NSOffState;
1186         [o_mi setState: i_state];
1187     }
1188     else if( [o_title isEqualToString: _NS("Repeat One")] )
1189     {
1190         int i_state;
1191         var_Get( p_playlist, "repeat", &val );
1192         i_state = val.b_bool ? NSOnState : NSOffState;
1193         [o_mi setState: i_state];
1194     }
1195     else if( [o_title isEqualToString: _NS("Repeat All")] )
1196     {
1197         int i_state;
1198         var_Get( p_playlist, "loop", &val );
1199         i_state = val.b_bool ? NSOnState : NSOffState;
1200         [o_mi setState: i_state];
1201     }
1202     else if( [o_title isEqualToString: _NS("Quit after Playback")] )
1203     {
1204         int i_state;
1205         var_Get( p_playlist, "play-and-exit", &val );
1206         i_state = val.b_bool ? NSOnState : NSOffState;
1207         [o_mi setState: i_state];
1208     }
1209     else if( [o_title isEqualToString: _NS("Step Forward")] ||
1210             [o_title isEqualToString: _NS("Step Backward")] ||
1211             [o_title isEqualToString: _NS("Jump To Time")])
1212     {
1213         if( p_input != NULL )
1214         {
1215             var_Get( p_input, "can-seek", &val);
1216             bEnabled = val.b_bool;
1217         }
1218         else bEnabled = FALSE;
1219     }
1220     else if( [o_title isEqualToString: _NS("Mute")] )
1221     {
1222         //FIXME [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
1223         [self setupMenus]; /* Make sure audio menu is up to date */
1224     }
1225     else if( [o_title isEqualToString: _NS("Half Size")] ||
1226             [o_title isEqualToString: _NS("Normal Size")] ||
1227             [o_title isEqualToString: _NS("Double Size")] ||
1228             [o_title isEqualToString: _NS("Fit to Screen")] ||
1229             [o_title isEqualToString: _NS("Snapshot")] ||
1230             [o_title isEqualToString: _NS("Fullscreen")] ||
1231             [o_title isEqualToString: _NS("Float on Top")] )
1232     {
1233         bEnabled = FALSE;
1234
1235         if( p_input != NULL )
1236         {
1237             vout_thread_t *p_vout = input_GetVout( p_input );
1238             if( p_vout != NULL )
1239             {
1240                 if( [o_title isEqualToString: _NS("Float on Top")] )
1241                 {
1242                     [o_mi setState: var_GetBool( p_vout, "video-on-top" )];
1243                 }
1244
1245                 bEnabled = TRUE;
1246
1247                 vlc_object_release( (vlc_object_t *)p_vout );
1248             }
1249         }
1250         if( [o_title isEqualToString: _NS("Fullscreen")] )
1251         {
1252         [o_mi setState: var_GetBool( p_playlist, "fullscreen" )];
1253             bEnabled = TRUE;
1254         }
1255         [self setupMenus]; /* Make sure video menu is up to date */
1256     }
1257
1258     /* Special case for telx menu */
1259     if( [o_title isEqualToString: _NS("Normal Size")] )
1260     {
1261         NSMenuItem *item = [[o_mi menu] itemWithTitle:_NS("Teletext")];
1262                 bool b_telx = p_input && var_GetInteger( p_input, "teletext-es" ) >= 0;
1263
1264         [[item submenu] setAutoenablesItems:NO];
1265         for( int k=0; k < [[item submenu] numberOfItems]; k++ )
1266         {
1267             [[[item submenu] itemAtIndex:k] setEnabled: b_telx];
1268         }
1269     }
1270
1271     if( p_input ) vlc_object_release( p_input );
1272
1273     return( bEnabled );
1274 }
1275
1276 @end
1277
1278
1279 /*****************************************************************************
1280  * VLCAutoGeneratedMenuContent implementation
1281  *****************************************************************************
1282  * Object connected to a playlistitem which remembers the data belonging to
1283  * the variable of the autogenerated menu
1284  *****************************************************************************/
1285 @implementation VLCAutoGeneratedMenuContent
1286
1287 -(id) initWithVariableName:(const char *)name ofObject:(vlc_object_t *)object
1288                   andValue:(vlc_value_t)val ofType:(int)type
1289 {
1290     self = [super init];
1291
1292     if( self != nil )
1293     {
1294         _vlc_object = vlc_object_hold( object );
1295         psz_name = strdup( name );
1296         i_type = type;
1297         value = val;
1298         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING )
1299             value.psz_string = strdup( val.psz_string );
1300     }
1301
1302     return( self );
1303 }
1304
1305 - (void)dealloc
1306 {
1307     vlc_object_release( _vlc_object );
1308     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING )
1309         free( value.psz_string );
1310     free( psz_name );
1311     [super dealloc];
1312 }
1313
1314 - (const char *)name
1315 {
1316     return psz_name;
1317 }
1318
1319 - (vlc_value_t)value
1320 {
1321     return value;
1322 }
1323
1324 - (vlc_object_t *)vlcObject
1325 {
1326     return vlc_object_hold( _vlc_object );
1327 }
1328
1329
1330 - (int)type
1331 {
1332     return i_type;
1333 }
1334
1335 @end