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