]> git.sesse.net Git - vlc/blob - modules/gui/macosx/MainMenu.m
df315a6d7c99a511fa58d5d25b4a76ae1cbe16c4
[vlc] / 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 "vout.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_rate setView: o_mi_rate_view];
259     [o_mi_rate_lbl setStringValue: _NS("Playback Speed")];
260     [o_mi_rate_lbl_gray setStringValue: _NS("Playback Speed")];
261     [o_mi_rate_slower_lbl setStringValue: _NS("Slower")];
262     [o_mi_rate_normal_lbl setStringValue: _NS("Normal")];
263     [o_mi_rate_faster_lbl setStringValue: _NS("Faster")];
264     [o_mi_trackSynchronization setTitle: _NS("Track Synchronization")];
265     [o_mi_previous setTitle: _NS("Previous")];
266     [o_mi_next setTitle: _NS("Next")];
267     [o_mi_random setTitle: _NS("Random")];
268     [o_mi_repeat setTitle: _NS("Repeat One")];
269     [o_mi_loop setTitle: _NS("Repeat All")];
270     [o_mi_quitAfterPB setTitle: _NS("Quit after Playback")];
271     [o_mi_fwd setTitle: _NS("Step Forward")];
272     [o_mi_bwd setTitle: _NS("Step Backward")];
273
274     [o_mi_program setTitle: _NS("Program")];
275     [o_mu_program setTitle: _NS("Program")];
276     [o_mi_title setTitle: _NS("Title")];
277     [o_mu_title setTitle: _NS("Title")];
278     [o_mi_chapter setTitle: _NS("Chapter")];
279     [o_mu_chapter setTitle: _NS("Chapter")];
280
281     [o_mu_audio setTitle: _NS("Audio")];
282     [o_mi_vol_up setTitle: _NS("Increase Volume")];
283     [o_mi_vol_down setTitle: _NS("Decrease Volume")];
284     [o_mi_mute setTitle: _NS("Mute")];
285     [o_mi_audiotrack setTitle: _NS("Audio Track")];
286     [o_mu_audiotrack setTitle: _NS("Audio Track")];
287     [o_mi_channels setTitle: _NS("Audio Channels")];
288     [o_mu_channels setTitle: _NS("Audio Channels")];
289     [o_mi_device setTitle: _NS("Audio Device")];
290     [o_mu_device setTitle: _NS("Audio Device")];
291     [o_mi_visual setTitle: _NS("Visualizations")];
292     [o_mu_visual setTitle: _NS("Visualizations")];
293
294     [o_mu_video setTitle: _NS("Video")];
295     [o_mi_half_window setTitle: _NS("Half Size")];
296     [o_mi_normal_window setTitle: _NS("Normal Size")];
297     [o_mi_double_window setTitle: _NS("Double Size")];
298     [o_mi_fittoscreen setTitle: _NS("Fit to Screen")];
299     [o_mi_fullscreen setTitle: _NS("Fullscreen")];
300     [o_mi_floatontop setTitle: _NS("Float on Top")];
301     [o_mi_snapshot setTitle: _NS("Snapshot")];
302     [o_mi_videotrack setTitle: _NS("Video Track")];
303     [o_mu_videotrack setTitle: _NS("Video Track")];
304     [o_mi_aspect_ratio setTitle: _NS("Aspect-ratio")];
305     [o_mu_aspect_ratio setTitle: _NS("Aspect-ratio")];
306     [o_mi_crop setTitle: _NS("Crop")];
307     [o_mu_crop setTitle: _NS("Crop")];
308     [o_mi_screen setTitle: _NS("Fullscreen Video Device")];
309     [o_mu_screen setTitle: _NS("Fullscreen Video Device")];
310     [o_mi_subtitle setTitle: _NS("Subtitles Track")];
311     [o_mu_subtitle setTitle: _NS("Subtitles Track")];
312     [o_mi_addSub setTitle: _NS("Open File...")];
313     [o_mi_deinterlace setTitle: _NS("Deinterlace")];
314     [o_mu_deinterlace setTitle: _NS("Deinterlace")];
315     [o_mi_deinterlace_mode setTitle: _NS("Deinterlace mode")];
316     [o_mu_deinterlace_mode setTitle: _NS("Deinterlace mode")];
317     [o_mi_ffmpeg_pp setTitle: _NS("Post processing")];
318     [o_mu_ffmpeg_pp setTitle: _NS("Post processing")];
319     [o_mi_teletext setTitle: _NS("Teletext")];
320     [o_mi_teletext_transparent setTitle: _NS("Transparent")];
321     [o_mi_teletext_index setTitle: _NS("Index")];
322     [o_mi_teletext_red setTitle: _NS("Red")];
323     [o_mi_teletext_green setTitle: _NS("Green")];
324     [o_mi_teletext_yellow setTitle: _NS("Yellow")];
325     [o_mi_teletext_blue setTitle: _NS("Blue")];
326
327     [o_mu_window setTitle: _NS("Window")];
328     [o_mi_minimize setTitle: _NS("Minimize Window")];
329     [o_mi_close_window setTitle: _NS("Close Window")];
330     [o_mi_player setTitle: _NS("Player...")];
331     [o_mi_controller setTitle: _NS("Main Window...")];
332     [o_mi_audioeffects setTitle: _NS("Audio Effects...")];
333     [o_mi_videoeffects setTitle: _NS("Video Filters...")];
334     [o_mi_bookmarks setTitle: _NS("Bookmarks...")];
335     [o_mi_playlist setTitle: _NS("Playlist...")];
336     [o_mi_info setTitle: _NS("Media Information...")];
337     [o_mi_messages setTitle: _NS("Messages...")];
338     [o_mi_errorsAndWarnings setTitle: _NS("Errors and Warnings...")];
339
340     [o_mi_bring_atf setTitle: _NS("Bring All to Front")];
341
342     [o_mu_help setTitle: _NS("Help")];
343     [o_mi_help setTitle: _NS("VLC media player Help...")];
344     [o_mi_readme setTitle: _NS("ReadMe / FAQ...")];
345     [o_mi_license setTitle: _NS("License")];
346     [o_mi_documentation setTitle: _NS("Online Documentation...")];
347     [o_mi_website setTitle: _NS("VideoLAN Website...")];
348     [o_mi_donation setTitle: _NS("Make a donation...")];
349     [o_mi_forum setTitle: _NS("Online Forum...")];
350
351     /* dock menu */
352     [o_dmi_play setTitle: _NS("Play")];
353     [o_dmi_stop setTitle: _NS("Stop")];
354     [o_dmi_next setTitle: _NS("Next")];
355     [o_dmi_previous setTitle: _NS("Previous")];
356     [o_dmi_mute setTitle: _NS("Mute")];
357
358     /* vout menu */
359     [o_vmi_play setTitle: _NS("Play")];
360     [o_vmi_stop setTitle: _NS("Stop")];
361     [o_vmi_prev setTitle: _NS("Previous")];
362     [o_vmi_next setTitle: _NS("Next")];
363     [o_vmi_volup setTitle: _NS("Volume Up")];
364     [o_vmi_voldown setTitle: _NS("Volume Down")];
365     [o_vmi_mute setTitle: _NS("Mute")];
366     [o_vmi_fullscreen setTitle: _NS("Fullscreen")];
367     [o_vmi_snapshot setTitle: _NS("Snapshot")];
368 }
369
370 #pragma mark -
371 #pragma mark Termination
372
373 - (void)releaseRepresentedObjects:(NSMenu *)the_menu
374 {
375     if( !p_intf ) return;
376     
377     NSArray *menuitems_array = [the_menu itemArray];
378     NSUInteger menuItemCount = [menuitems_array count];
379     for( NSUInteger i=0; i < menuItemCount; i++ )
380     {
381         NSMenuItem *one_item = [menuitems_array objectAtIndex: i];
382         if( [one_item hasSubmenu] )
383             [self releaseRepresentedObjects: [one_item submenu]];
384
385         [one_item setRepresentedObject:NULL];
386     }
387 }
388
389 #pragma mark -
390 #pragma mark Interface update
391
392 - (void)setupMenus
393 {
394     playlist_t * p_playlist = pl_Get( p_intf );
395     input_thread_t * p_input = playlist_CurrentInput( p_playlist );
396     if( p_input != NULL )
397     {
398         [self setupVarMenuItem: o_mi_program target: (vlc_object_t *)p_input
399                                  var: "program" selector: @selector(toggleVar:)];
400
401         [self setupVarMenuItem: o_mi_title target: (vlc_object_t *)p_input
402                                  var: "title" selector: @selector(toggleVar:)];
403
404         [self setupVarMenuItem: o_mi_chapter target: (vlc_object_t *)p_input
405                                  var: "chapter" selector: @selector(toggleVar:)];
406
407         [self setupVarMenuItem: o_mi_audiotrack target: (vlc_object_t *)p_input
408                                  var: "audio-es" selector: @selector(toggleVar:)];
409
410         [self setupVarMenuItem: o_mi_videotrack target: (vlc_object_t *)p_input
411                                  var: "video-es" selector: @selector(toggleVar:)];
412
413         [self setupVarMenuItem: o_mi_subtitle target: (vlc_object_t *)p_input
414                                  var: "spu-es" selector: @selector(toggleVar:)];
415
416         /* special case for "Open File" inside the subtitles menu item */
417         if( [o_mi_videotrack isEnabled] == YES )
418             [o_mi_subtitle setEnabled: YES];
419
420         audio_output_t * p_aout = input_GetAout( p_input );
421         if( p_aout != NULL )
422         {
423             [self setupVarMenuItem: o_mi_channels target: (vlc_object_t *)p_aout
424                                      var: "audio-channels" selector: @selector(toggleVar:)];
425
426             [self setupVarMenuItem: o_mi_device target: (vlc_object_t *)p_aout
427                                      var: "audio-device" selector: @selector(toggleVar:)];
428
429             [self setupVarMenuItem: o_mi_visual target: (vlc_object_t *)p_aout
430                                      var: "visual" selector: @selector(toggleVar:)];
431             vlc_object_release( (vlc_object_t *)p_aout );
432         }
433
434         vout_thread_t * p_vout = input_GetVout( p_input );
435
436         if( p_vout != NULL )
437         {
438             vlc_object_t * p_dec_obj;
439
440             [self setupVarMenuItem: o_mi_aspect_ratio target: (vlc_object_t *)p_vout
441                                      var: "aspect-ratio" selector: @selector(toggleVar:)];
442
443             [self setupVarMenuItem: o_mi_crop target: (vlc_object_t *) p_vout
444                                      var: "crop" selector: @selector(toggleVar:)];
445
446             [self setupVarMenuItem: o_mi_screen target: (vlc_object_t *)p_vout
447                                      var: "video-device" selector: @selector(toggleVar:)];
448
449             [self setupVarMenuItem: o_mi_deinterlace target: (vlc_object_t *)p_vout
450                                      var: "deinterlace" selector: @selector(toggleVar:)];
451
452             [self setupVarMenuItem: o_mi_deinterlace_mode target: (vlc_object_t *)p_vout
453                                      var: "deinterlace-mode" selector: @selector(toggleVar:)];
454
455 #if 1
456             [self setupVarMenuItem: o_mi_ffmpeg_pp target:
457              (vlc_object_t *)p_vout var:"postprocess" selector:
458              @selector(toggleVar:)];
459 #endif
460             vlc_object_release( (vlc_object_t *)p_vout );
461         }
462         vlc_object_release( p_input );
463     }
464 }
465
466 - (void)refreshVoutDeviceMenu:(NSNotification *)o_notification
467 {
468     int x, y = 0;
469     vout_thread_t * p_vout = getVout();
470     if( !p_vout )
471         return;
472
473     /* clean the menu before adding new entries */
474     if( [o_mi_screen hasSubmenu] )
475     {
476         y = [[o_mi_screen submenu] numberOfItems] - 1;
477         msg_Dbg( VLCIntf, "%i items in submenu", y );
478         while( x != y )
479         {
480             msg_Dbg( VLCIntf, "removing item %i of %i", x, y );
481             [[o_mi_screen submenu] removeItemAtIndex: x];
482             x++;
483         }
484     }
485
486     [self setupVarMenuItem: o_mi_screen target: (vlc_object_t *)p_vout
487                              var: "video-device" selector: @selector(toggleVar:)];
488     vlc_object_release( (vlc_object_t *)p_vout );
489 }
490
491 - (void)setSubmenusEnabled:(BOOL)b_enabled
492 {
493     [o_mi_program setEnabled: b_enabled];
494     [o_mi_title setEnabled: b_enabled];
495     [o_mi_chapter setEnabled: b_enabled];
496     [o_mi_audiotrack setEnabled: b_enabled];
497     [o_mi_visual setEnabled: b_enabled];
498     [o_mi_videotrack setEnabled: b_enabled];
499     [o_mi_subtitle setEnabled: b_enabled];
500     [o_mi_channels setEnabled: b_enabled];
501     [o_mi_deinterlace setEnabled: b_enabled];
502     [o_mi_deinterlace_mode setEnabled: b_enabled];
503     [o_mi_ffmpeg_pp setEnabled: b_enabled];
504     [o_mi_device setEnabled: b_enabled];
505     [o_mi_screen setEnabled: b_enabled];
506     [o_mi_aspect_ratio setEnabled: b_enabled];
507     [o_mi_crop setEnabled: b_enabled];
508     [o_mi_teletext setEnabled: b_enabled];
509 }
510
511 - (void)setRateControlsEnabled:(BOOL)b_enabled
512 {
513     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
514     [o_mi_rate_sld setEnabled: b_enabled];
515     [o_mi_rate_sld setIntValue: [[VLCCoreInteraction sharedInstance] playbackRate]];
516     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
517     if (i == 0)
518         i = 1;
519     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%ix", i]];
520     if (b_enabled) {
521         [o_mi_rate_lbl setHidden: NO];
522         [o_mi_rate_lbl_gray setHidden: YES];
523     }
524     else
525     {
526         [o_mi_rate_lbl setHidden: YES];
527         [o_mi_rate_lbl_gray setHidden: NO];
528     }
529     [o_pool release];
530 }
531
532 #pragma mark -
533 #pragma mark Recent Items
534 - (void)openRecentItem:(id)item
535 {
536     [[VLCMain sharedInstance] application: nil openFile: [item title]];
537 }
538
539 - (IBAction)clearRecentItems:(id)sender
540 {
541     [[NSDocumentController sharedDocumentController]
542      clearRecentDocuments: nil];
543 }
544
545 #pragma mark -
546 #pragma mark Playback
547 - (IBAction)setPlaybackRate:(id)sender
548 {
549     [[VLCCoreInteraction sharedInstance] setPlaybackRate: [o_mi_rate_sld intValue]];
550     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
551     if (i == 0)
552         i = 1;
553     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%ix", i]];
554 }
555
556 - (void)updatePlaybackRate
557 {
558     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
559     if (i == 0)
560         i = 1;
561     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%ix", i]];
562     [o_mi_rate_sld setIntValue: i];
563 }
564
565 #pragma mark -
566 #pragma video menu
567 - (IBAction)toggleFullscreen:(id)sender
568 {
569     [[VLCCoreInteraction sharedInstance] toggleFullscreen];
570 }
571
572 - (IBAction)resizeVideoWindow:(id)sender
573 {
574     input_thread_t *p_input = pl_CurrentInput( VLCIntf );
575     if (p_input)
576     {
577         vout_thread_t *p_vout = getVout();
578         if (p_vout)
579         {
580             if (sender == o_mi_half_window)
581                 var_SetFloat( p_vout, "zoom", 0.5 );
582             else if (sender == o_mi_normal_window)
583                 var_SetFloat( p_vout, "zoom", 1.0 );
584             else if (sender == o_mi_double_window)
585                 var_SetFloat( p_vout, "zoom", 2.0 );
586             else
587             {
588                 var_ToggleBool( p_vout, "autoscale" );
589             }
590             vlc_object_release( p_vout );
591         }
592         vlc_object_release( p_input );
593     }
594 }
595
596 - (IBAction)floatOnTop:(id)sender
597 {
598     input_thread_t *p_input = pl_CurrentInput( VLCIntf );
599     if (p_input)
600     {
601         vout_thread_t *p_vout = getVout();
602         if (p_vout)
603         {
604             var_ToggleBool( p_vout, "video-on-top" );
605             vlc_object_release( p_vout );
606         }
607         vlc_object_release( p_input );
608     }
609 }
610
611 - (IBAction)createVideoSnapshot:(id)sender
612 {
613     input_thread_t *p_input = pl_CurrentInput( VLCIntf );
614     if (p_input)
615     {
616         vout_thread_t *p_vout = getVout();
617         if (p_vout)
618         {
619             var_TriggerCallback( p_vout, "video-snapshot" );
620             vlc_object_release( p_vout );
621         }
622         vlc_object_release( p_input );
623     }
624 }
625
626 - (id)voutMenu
627 {
628     return o_vout_menu;
629 }
630
631 #pragma mark -
632 #pragma mark Panels
633
634 - (IBAction)intfOpenFile:(id)sender
635 {
636     [[[VLCMain sharedInstance] open] openFile];
637 }
638
639 - (IBAction)intfOpenFileGeneric:(id)sender
640 {
641     [[[VLCMain sharedInstance] open] openFileGeneric];
642 }
643
644 - (IBAction)intfOpenDisc:(id)sender
645 {
646     [[[VLCMain sharedInstance] open] openDisc];
647 }
648
649 - (IBAction)intfOpenNet:(id)sender
650 {
651     [[[VLCMain sharedInstance] open] openNet];
652 }
653
654 - (IBAction)intfOpenCapture:(id)sender
655 {
656     [[[VLCMain sharedInstance] open] openCapture];
657 }
658
659 - (IBAction)showWizard:(id)sender
660 {
661     [[[VLCMain sharedInstance] wizard] resetWizard];
662     [[[VLCMain sharedInstance] wizard] showWizard];
663 }
664
665 - (IBAction)showVideoEffects:(id)sender
666 {
667     if( o_videoeffects == nil )
668         o_videoeffects = [[VLCVideoEffects alloc] init];
669
670     if( !b_nib_videoeffects_loaded )
671         b_nib_videoeffects_loaded = [NSBundle loadNibNamed:@"VideoEffects" owner: NSApp];
672
673     [o_videoeffects toggleWindow:sender];
674 }
675
676 - (IBAction)showTrackSynchronization:(id)sender
677 {
678     if (!o_trackSynchronization)
679         o_trackSynchronization = [[VLCTrackSynchronization alloc] init];
680
681     if (!b_nib_tracksynchro_loaded)
682         b_nib_tracksynchro_loaded = [NSBundle loadNibNamed:@"SyncTracks" owner:NSApp];
683
684     [o_trackSynchronization toggleWindow:sender];
685 }
686
687 - (IBAction)showAudioEffects:(id)sender
688 {
689     if (!o_audioeffects)
690         o_audioeffects = [[VLCAudioEffects alloc] init];
691
692     if (!b_nib_audioeffects_loaded)
693         b_nib_audioeffects_loaded = [NSBundle loadNibNamed:@"AudioEffects" owner:NSApp];
694
695     [o_audioeffects toggleWindow:sender];
696 }
697
698 - (IBAction)showBookmarks:(id)sender
699 {
700     [[[VLCMain sharedInstance] bookmarks] showBookmarks];
701 }
702
703 - (IBAction)viewPreferences:(id)sender
704 {
705     [[[VLCMain sharedInstance] simplePreferences] showSimplePrefs];
706 }
707
708 #pragma mark -
709 #pragma mark Help and Docs
710
711 - (void)initAbout
712 {
713     if(! o_about )
714         o_about = [[VLAboutBox alloc] init];
715
716     if( !b_nib_about_loaded )
717         b_nib_about_loaded = [NSBundle loadNibNamed:@"About" owner: NSApp];
718 }
719
720 - (IBAction)viewAbout:(id)sender
721 {
722     [self initAbout];
723     [o_about showAbout];
724 }
725
726 - (IBAction)showLicense:(id)sender
727 {
728     [self initAbout];
729     [o_about showGPL: sender];
730 }
731
732 - (IBAction)viewHelp:(id)sender
733 {
734     [self initAbout];
735     [o_about showHelp];
736 }
737
738 - (IBAction)openReadMe:(id)sender
739 {
740     NSString * o_path = [[NSBundle mainBundle] pathForResource: @"README.MacOSX" ofType: @"rtf"];
741
742     [[NSWorkspace sharedWorkspace] openFile: o_path withApplication: @"TextEdit"];
743 }
744
745 - (IBAction)openDocumentation:(id)sender
746 {
747     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/doc/"];
748
749     [[NSWorkspace sharedWorkspace] openURL: o_url];
750 }
751
752 - (IBAction)openWebsite:(id)sender
753 {
754     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/"];
755
756     [[NSWorkspace sharedWorkspace] openURL: o_url];
757 }
758
759 - (IBAction)openForum:(id)sender
760 {
761     NSURL * o_url = [NSURL URLWithString: @"http://forum.videolan.org/"];
762
763     [[NSWorkspace sharedWorkspace] openURL: o_url];
764 }
765
766 - (IBAction)openDonate:(id)sender
767 {
768     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/contribute.html#paypal"];
769
770     [[NSWorkspace sharedWorkspace] openURL: o_url];
771 }
772
773 #pragma mark -
774 #pragma mark Errors, warnings and messages
775
776 - (IBAction)viewErrorsAndWarnings:(id)sender
777 {
778     [[[[VLCMain sharedInstance] coreDialogProvider] errorPanel] showPanel];
779 }
780
781 - (IBAction)showInformationPanel:(id)sender
782 {
783     [[[VLCMain sharedInstance] info] initPanel];
784 }
785
786 #pragma mark -
787 #pragma mark convinience stuff for other objects
788 - (void)setPlay
789 {
790     [o_mi_play setTitle: _NS("Play")];
791     [o_dmi_play setTitle: _NS("Play")];
792     [o_vmi_play setTitle: _NS("Play")];
793 }
794
795 - (void)setPause
796 {
797     [o_mi_play setTitle: _NS("Pause")];
798     [o_dmi_play setTitle: _NS("Pause")];
799     [o_vmi_play setTitle: _NS("Pause")];
800 }
801
802 - (void)setRepeatOne
803 {
804     [o_mi_repeat setState: NSOnState];
805     [o_mi_loop setState: NSOffState];
806 }
807
808 - (void)setRepeatAll
809 {
810     [o_mi_repeat setState: NSOffState];
811     [o_mi_loop setState: NSOnState];
812 }
813
814 - (void)setRepeatOff
815 {
816     [o_mi_repeat setState: NSOffState];
817     [o_mi_loop setState: NSOffState];
818 }
819
820 - (void)setShuffle
821 {
822     bool b_value;
823     playlist_t *p_playlist = pl_Get( VLCIntf );
824     b_value = var_GetBool( p_playlist, "random" );
825         [o_mi_random setState: b_value];
826 }
827
828 #pragma mark -
829 #pragma mark Dynamic menu creation and validation
830
831 - (void)setupVarMenuItem:(NSMenuItem *)o_mi
832                   target:(vlc_object_t *)p_object
833                      var:(const char *)psz_variable
834                 selector:(SEL)pf_callback
835 {
836     vlc_value_t val, text;
837     int i_type = var_Type( p_object, psz_variable );
838
839     switch( i_type & VLC_VAR_TYPE )
840     {
841         case VLC_VAR_VOID:
842         case VLC_VAR_BOOL:
843         case VLC_VAR_VARIABLE:
844         case VLC_VAR_STRING:
845         case VLC_VAR_INTEGER:
846             break;
847         default:
848             /* Variable doesn't exist or isn't handled */
849             return;
850     }
851
852     /* Make sure we want to display the variable */
853     if( i_type & VLC_VAR_HASCHOICE )
854     {
855         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
856         if( val.i_int == 0 ) return;
857         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
858             return;
859     }
860
861     /* Get the descriptive name of the variable */
862     var_Change( p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL );
863     [o_mi setTitle: [[VLCMain sharedInstance] localizedString: text.psz_string ?
864                      text.psz_string : psz_variable ]];
865
866     if( i_type & VLC_VAR_HASCHOICE )
867     {
868         NSMenu *o_menu = [o_mi submenu];
869         
870         [self setupVarMenu: o_menu forMenuItem: o_mi target:p_object
871                        var:psz_variable selector:pf_callback];
872         
873         free( text.psz_string );
874         return;
875     }
876     if( var_Get( p_object, psz_variable, &val ) < 0 )
877     {
878         return;
879     }
880
881     VLCAutoGeneratedMenuContent *o_data;
882     switch( i_type & VLC_VAR_TYPE )
883     {
884         case VLC_VAR_VOID:
885             o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
886                                                                       andValue: val ofType: i_type];
887             [o_mi setRepresentedObject: [o_data autorelease]];
888             break;
889
890         case VLC_VAR_BOOL:
891             o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
892                                                                       andValue: val ofType: i_type];
893             [o_mi setRepresentedObject: [o_data autorelease]];
894             if( !( i_type & VLC_VAR_ISCOMMAND ) )
895                 [o_mi setState: val.b_bool ? TRUE : FALSE ];
896             break;
897
898         default:
899             break;
900     }
901
902     if( ( i_type & VLC_VAR_TYPE ) == VLC_VAR_STRING ) free( val.psz_string );
903     free( text.psz_string );
904 }
905
906
907 - (void)setupVarMenu:(NSMenu *)o_menu
908          forMenuItem: (NSMenuItem *)o_parent
909               target:(vlc_object_t *)p_object
910                  var:(const char *)psz_variable
911             selector:(SEL)pf_callback
912 {
913     vlc_value_t val, val_list, text_list;
914     int i_type, i, i_nb_items;
915
916     /* remove previous items */
917     i_nb_items = [o_menu numberOfItems];
918     for( i = 0; i < i_nb_items; i++ )
919         [o_menu removeItemAtIndex: 0];
920
921     /* Check the type of the object variable */
922     i_type = var_Type( p_object, psz_variable );
923
924     /* Make sure we want to display the variable */
925     if( i_type & VLC_VAR_HASCHOICE )
926     {
927         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
928         if( val.i_int == 0 ) return;
929         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
930             return;
931     }
932     else
933         return;
934
935     switch( i_type & VLC_VAR_TYPE )
936     {
937         case VLC_VAR_VOID:
938         case VLC_VAR_BOOL:
939         case VLC_VAR_VARIABLE:
940         case VLC_VAR_STRING:
941         case VLC_VAR_INTEGER:
942             break;
943         default:
944             /* Variable doesn't exist or isn't handled */
945             return;
946     }
947
948     if( var_Get( p_object, psz_variable, &val ) < 0 )
949     {
950         return;
951     }
952
953     if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST,
954                    &val_list, &text_list ) < 0 )
955     {
956         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
957         return;
958     }
959
960     /* make (un)sensitive */
961     [o_parent setEnabled: ( val_list.p_list->i_count > 1 )];
962
963     /* Aspect Ratio */
964     if( [[o_parent title] isEqualToString: _NS("Aspect-ratio")] == YES )
965     {
966         NSMenuItem *o_lmi_tmp2;
967         o_lmi_tmp2 = [o_menu addItemWithTitle: _NS("Lock Aspect Ratio") action: @selector(lockVideosAspectRatio:) keyEquivalent: @""];
968         [o_lmi_tmp2 setTarget: self];
969         [o_lmi_tmp2 setEnabled: YES];
970         [o_lmi_tmp2 setState: [[VLCCoreInteraction sharedInstance] aspectRatioIsLocked]];
971         [o_parent setEnabled: YES];
972         [o_menu addItem: [NSMenuItem separatorItem]];
973     }
974
975     /* special case for the subtitles items */
976     if( [[o_parent title] isEqualToString: _NS("Subtitles Track")] == YES )
977     {
978         NSMenuItem * o_lmi_tmp;
979         o_lmi_tmp = [o_menu addItemWithTitle: _NS("Open File...") action: @selector(addSubtitleFile:) keyEquivalent: @""];
980         [o_lmi_tmp setTarget: self];
981         [o_lmi_tmp setEnabled: YES];
982         [o_parent setEnabled: YES];
983         [o_menu addItem: [NSMenuItem separatorItem]];
984     }
985
986     for( i = 0; i < val_list.p_list->i_count; i++ )
987     {
988         NSMenuItem * o_lmi;
989         NSString *o_title = @"";
990         VLCAutoGeneratedMenuContent *o_data;
991
992         switch( i_type & VLC_VAR_TYPE )
993         {
994             case VLC_VAR_STRING:
995
996                 o_title = [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string ?
997                            text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string ];
998
999                 o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
1000                 o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
1001                                                                           andValue: val_list.p_list->p_values[i] ofType: i_type];
1002                 [o_lmi setRepresentedObject: [o_data autorelease]];
1003                 [o_lmi setTarget: self];
1004
1005                 if( !strcmp( val.psz_string, val_list.p_list->p_values[i].psz_string ) && !( i_type & VLC_VAR_ISCOMMAND ) )
1006                     [o_lmi setState: TRUE ];
1007
1008                 break;
1009
1010             case VLC_VAR_INTEGER:
1011
1012                 o_title = text_list.p_list->p_values[i].psz_string ?
1013                 [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string] :
1014                 [NSString stringWithFormat: @"%"PRId64,
1015                  val_list.p_list->p_values[i].i_int];
1016
1017                 o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
1018                 o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
1019                                                                           andValue: val_list.p_list->p_values[i] ofType: i_type];
1020                 [o_lmi setRepresentedObject: [o_data autorelease]];
1021                 [o_lmi setTarget: self];
1022
1023                 if( val_list.p_list->p_values[i].i_int == val.i_int && !( i_type & VLC_VAR_ISCOMMAND ) )
1024                     [o_lmi setState: TRUE ];
1025                 break;
1026
1027             default:
1028                 break;
1029         }
1030     }
1031
1032     /* special case for the subtitles sub-menu
1033      * In case that we don't have any subs, we don't want a separator item at the end */
1034     if( [[o_parent title] isEqualToString: _NS("Subtitles Track")] == YES )
1035     {
1036         if( [o_menu numberOfItems] == 2 )
1037             [o_menu removeItemAtIndex: 1];
1038     }
1039
1040     /* clean up everything */
1041     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
1042     var_FreeList( &val_list, &text_list );
1043 }
1044
1045 - (IBAction)toggleVar:(id)sender
1046 {
1047     NSMenuItem *o_mi = (NSMenuItem *)sender;
1048     VLCAutoGeneratedMenuContent *o_data = [o_mi representedObject];
1049     [NSThread detachNewThreadSelector: @selector(toggleVarThread:)
1050                              toTarget: self withObject: o_data];
1051
1052     return;
1053 }
1054
1055 - (int)toggleVarThread: (id)data
1056 {
1057     vlc_object_t *p_object;
1058     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
1059
1060     assert([data isKindOfClass:[VLCAutoGeneratedMenuContent class]]);
1061     VLCAutoGeneratedMenuContent *menuContent = (VLCAutoGeneratedMenuContent *)data;
1062
1063     p_object = [menuContent vlcObject];
1064
1065     if( p_object != NULL )
1066     {
1067         var_Set( p_object, [menuContent name], [menuContent value] );
1068         vlc_object_release( p_object );
1069         [o_pool release];
1070         return true;
1071     }
1072     [o_pool release];
1073     return VLC_EGENERIC;
1074 }
1075
1076 @end
1077
1078 @implementation VLCMainMenu (NSMenuValidation)
1079
1080 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
1081 {
1082     NSString *o_title = [o_mi title];
1083     BOOL bEnabled = TRUE;
1084     vlc_value_t val;
1085     playlist_t * p_playlist = pl_Get( p_intf );
1086     input_thread_t * p_input = playlist_CurrentInput( p_playlist );
1087
1088     /* Recent Items Menu */
1089     if( [o_title isEqualToString: _NS("Clear Menu")] )
1090     {
1091         NSMenu * o_menu = [o_mi_open_recent submenu];
1092         int i_nb_items = [o_menu numberOfItems];
1093         NSArray * o_docs = [[NSDocumentController sharedDocumentController]
1094                             recentDocumentURLs];
1095         UInt32 i_nb_docs = [o_docs count];
1096
1097         if( i_nb_items > 1 )
1098         {
1099             while( --i_nb_items )
1100             {
1101                 [o_menu removeItemAtIndex: 0];
1102             }
1103         }
1104
1105         if( i_nb_docs > 0 )
1106         {
1107             NSURL * o_url;
1108             NSString * o_doc;
1109
1110             [o_menu insertItem: [NSMenuItem separatorItem] atIndex: 0];
1111
1112             while( TRUE )
1113             {
1114                 i_nb_docs--;
1115
1116                 o_url = [o_docs objectAtIndex: i_nb_docs];
1117
1118                 if( [o_url isFileURL] )
1119                     o_doc = [o_url path];
1120                 else
1121                     o_doc = [o_url absoluteString];
1122
1123                 [o_menu insertItemWithTitle: o_doc
1124                                      action: @selector(openRecentItem:)
1125                               keyEquivalent: @"" atIndex: 0];
1126
1127                 if( i_nb_docs == 0 )
1128                     break;
1129             }
1130         }
1131         else
1132         {
1133             bEnabled = FALSE;
1134         }
1135     }
1136     else if( [o_title isEqualToString: _NS("Stop")] )
1137     {
1138         if( p_input == NULL )
1139         {
1140             bEnabled = FALSE;
1141         }
1142         [self setupMenus]; /* Make sure input menu is up to date */
1143     }
1144     else if( [o_title isEqualToString: _NS("Previous")] ||
1145             [o_title isEqualToString: _NS("Next")] )
1146     {
1147         PL_LOCK;
1148         bEnabled = playlist_CurrentSize( p_playlist ) > 1;
1149         PL_UNLOCK;
1150     }
1151     else if( [o_title isEqualToString: _NS("Random")] )
1152     {
1153         int i_state;
1154         var_Get( p_playlist, "random", &val );
1155         i_state = val.b_bool ? NSOnState : NSOffState;
1156         [o_mi setState: i_state];
1157     }
1158     else if( [o_title isEqualToString: _NS("Repeat One")] )
1159     {
1160         int i_state;
1161         var_Get( p_playlist, "repeat", &val );
1162         i_state = val.b_bool ? NSOnState : NSOffState;
1163         [o_mi setState: i_state];
1164     }
1165     else if( [o_title isEqualToString: _NS("Repeat All")] )
1166     {
1167         int i_state;
1168         var_Get( p_playlist, "loop", &val );
1169         i_state = val.b_bool ? NSOnState : NSOffState;
1170         [o_mi setState: i_state];
1171     }
1172     else if( [o_title isEqualToString: _NS("Quit after Playback")] )
1173     {
1174         int i_state;
1175         var_Get( p_playlist, "play-and-exit", &val );
1176         i_state = val.b_bool ? NSOnState : NSOffState;
1177         [o_mi setState: i_state];
1178     }
1179     else if( [o_title isEqualToString: _NS("Step Forward")] ||
1180             [o_title isEqualToString: _NS("Step Backward")] ||
1181             [o_title isEqualToString: _NS("Jump To Time")])
1182     {
1183         if( p_input != NULL )
1184         {
1185             var_Get( p_input, "can-seek", &val);
1186             bEnabled = val.b_bool;
1187         }
1188         else bEnabled = FALSE;
1189     }
1190     else if( [o_title isEqualToString: _NS("Mute")] )
1191     {
1192         //FIXME [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
1193         [self setupMenus]; /* Make sure audio menu is up to date */
1194     }
1195     else if( [o_title isEqualToString: _NS("Half Size")] ||
1196             [o_title isEqualToString: _NS("Normal Size")] ||
1197             [o_title isEqualToString: _NS("Double Size")] ||
1198             [o_title isEqualToString: _NS("Fit to Screen")] ||
1199             [o_title isEqualToString: _NS("Snapshot")] ||
1200             [o_title isEqualToString: _NS("Fullscreen")] ||
1201             [o_title isEqualToString: _NS("Float on Top")] )
1202     {
1203         bEnabled = FALSE;
1204
1205         if( p_input != NULL )
1206         {
1207             vout_thread_t *p_vout = input_GetVout( p_input );
1208             if( p_vout != NULL )
1209             {
1210                 if( [o_title isEqualToString: _NS("Float on Top")] )
1211                 {
1212                     [o_mi setState: var_GetBool( p_vout, "video-on-top" )];
1213                 }
1214
1215                 bEnabled = TRUE;
1216
1217                 vlc_object_release( (vlc_object_t *)p_vout );
1218             }
1219         }
1220         if( [o_title isEqualToString: _NS("Fullscreen")] )
1221         {
1222         [o_mi setState: var_GetBool( p_playlist, "fullscreen" )];
1223             bEnabled = TRUE;
1224         }
1225         [self setupMenus]; /* Make sure video menu is up to date */
1226     }
1227
1228     /* Special case for telx menu */
1229     if( [o_title isEqualToString: _NS("Normal Size")] )
1230     {
1231         NSMenuItem *item = [[o_mi menu] itemWithTitle:_NS("Teletext")];
1232                 bool b_telx = p_input && var_GetInteger( p_input, "teletext-es" ) >= 0;
1233
1234         [[item submenu] setAutoenablesItems:NO];
1235         for( int k=0; k < [[item submenu] numberOfItems]; k++ )
1236         {
1237             [[[item submenu] itemAtIndex:k] setEnabled: b_telx];
1238         }
1239     }
1240
1241     if( p_input ) vlc_object_release( p_input );
1242
1243     return( bEnabled );
1244 }
1245
1246 @end
1247
1248
1249 /*****************************************************************************
1250  * VLCAutoGeneratedMenuContent implementation
1251  *****************************************************************************
1252  * Object connected to a playlistitem which remembers the data belonging to
1253  * the variable of the autogenerated menu
1254  *****************************************************************************/
1255 @implementation VLCAutoGeneratedMenuContent
1256
1257 -(id) initWithVariableName:(const char *)name ofObject:(vlc_object_t *)object
1258                   andValue:(vlc_value_t)val ofType:(int)type
1259 {
1260     self = [super init];
1261
1262     if( self != nil )
1263     {
1264         _vlc_object = vlc_object_hold( object );
1265         psz_name = strdup( name );
1266         i_type = type;
1267         value = val;
1268         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING )
1269             value.psz_string = strdup( val.psz_string );
1270     }
1271
1272     return( self );
1273 }
1274
1275 - (void)dealloc
1276 {
1277     vlc_object_release( _vlc_object );
1278     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING )
1279         free( value.psz_string );
1280     free( psz_name );
1281     [super dealloc];
1282 }
1283
1284 - (const char *)name
1285 {
1286     return psz_name;
1287 }
1288
1289 - (vlc_value_t)value
1290 {
1291     return value;
1292 }
1293
1294 - (vlc_object_t *)vlcObject
1295 {
1296     return vlc_object_hold( _vlc_object );
1297 }
1298
1299
1300 - (int)type
1301 {
1302     return i_type;
1303 }
1304
1305 @end