]> git.sesse.net Git - vlc/blob - modules/gui/macosx/MainMenu.m
macosx: fix main menu initialization order on startup
[vlc] / modules / gui / macosx / MainMenu.m
1 /*****************************************************************************
2  * MainMenu.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2011-2014 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 "intf.h"
26
27 #import <vlc_common.h>
28 #import <vlc_playlist.h>
29 #import <vlc_input.h>
30
31 #import "open.h"
32 #import "wizard.h"
33 #import "about.h"
34 #import "AudioEffects.h"
35 #import "TrackSynchronization.h"
36 #import "VideoEffects.h"
37 #import "bookmarks.h"
38 #import "simple_prefs.h"
39 #import "coredialogs.h"
40 #import "controls.h"
41 #import "playlist.h"
42 #import "playlistinfo.h"
43 #import "VideoView.h"
44 #import "CoreInteraction.h"
45 #import "MainWindow.h"
46 #import "ControlsBar.h"
47 #import "ExtensionsManager.h"
48 #import "ConvertAndSave.h"
49 #import "DebugMessageVisualizer.h"
50 #import "AddonManager.h"
51
52 @implementation VLCMainMenu
53 static VLCMainMenu *_o_sharedInstance = nil;
54
55 + (VLCMainMenu *)sharedInstance
56 {
57     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
58 }
59
60 #pragma mark - Initialization
61
62 - (id)init
63 {
64     if (_o_sharedInstance) {
65         [self dealloc];
66         return _o_sharedInstance;
67     } else {
68         _o_sharedInstance = [super init];
69
70         o_ptc_translation_dict = [[NSDictionary alloc] initWithObjectsAndKeys:
71                       _NS("Track Number"),  TRACKNUM_COLUMN,
72                       _NS("Title"),         TITLE_COLUMN,
73                       _NS("Author"),        ARTIST_COLUMN,
74                       _NS("Duration"),      DURATION_COLUMN,
75                       _NS("Genre"),         GENRE_COLUMN,
76                       _NS("Album"),         ALBUM_COLUMN,
77                       _NS("Description"),   DESCRIPTION_COLUMN,
78                       _NS("Date"),          DATE_COLUMN,
79                       _NS("Language"),      LANGUAGE_COLUMN,
80                       _NS("URI"),           URI_COLUMN,
81                       _NS("File Size"),     FILESIZE_COLUMN,
82                       nil];
83         // this array also assigns tags (index) to type of menu item
84         o_ptc_menuorder = [[NSArray alloc] initWithObjects: TRACKNUM_COLUMN, TITLE_COLUMN,
85                            ARTIST_COLUMN, DURATION_COLUMN, GENRE_COLUMN, ALBUM_COLUMN,
86                            DESCRIPTION_COLUMN, DATE_COLUMN, LANGUAGE_COLUMN, URI_COLUMN,
87                            FILESIZE_COLUMN,nil];
88     }
89
90     return _o_sharedInstance;
91 }
92
93 - (void)dealloc
94 {
95     [[NSNotificationCenter defaultCenter] removeObserver: self];
96
97     if (b_nib_about_loaded)
98         [o_about release];
99
100     if (b_nib_videoeffects_loaded)
101         [o_videoeffects release];
102
103     if (b_nib_audioeffects_loaded)
104         [o_audioeffects release];
105
106     if (b_nib_tracksynchro_loaded)
107         [o_trackSynchronization release];
108
109     if (b_nib_convertandsave_loaded)
110         [o_convertandsave release];
111
112     [o_extMgr release];
113
114     if (o_mu_playlistTableColumnsContextMenu)
115         [o_mu_playlistTableColumnsContextMenu release];
116
117     [self releaseRepresentedObjects:[NSApp mainMenu]];
118
119     [o_ptc_translation_dict release];
120     [o_ptc_menuorder release];
121
122     [super dealloc];
123 }
124
125 - (void)awakeFromNib
126 {
127     [[NSNotificationCenter defaultCenter] addObserver: self
128                                              selector: @selector(applicationWillFinishLaunching:)
129                                                  name: NSApplicationWillFinishLaunchingNotification
130                                                object: nil];
131
132     /* check whether the user runs OSX with a RTL language */
133     NSArray* languages = [NSLocale preferredLanguages];
134     NSString* preferredLanguage = [languages objectAtIndex:0];
135
136     if ([NSLocale characterDirectionForLanguage:preferredLanguage] == NSLocaleLanguageDirectionRightToLeft) {
137         msg_Dbg(VLCIntf, "adapting interface since '%s' is a RTL language", [preferredLanguage UTF8String]);
138         [o_mi_rate_fld setAlignment: NSLeftTextAlignment];
139     }
140
141     [self setRateControlsEnabled:NO];
142
143     p_intf = VLCIntf;
144 }
145
146 - (void)applicationWillFinishLaunching:(NSNotification *)o_notification
147 {
148     NSString* o_key;
149     playlist_t *p_playlist;
150     vlc_value_t val;
151     id o_vlcstringutility = [VLCStringUtility sharedInstance];
152     char * key;
153
154     /* Check if we already did this once. Opening the other nibs calls it too,
155      because VLCMain is the owner */
156     if (b_mainMenu_setup)
157         return;
158
159     /* Get ExtensionsManager */
160     o_extMgr = [ExtensionsManager getInstance:p_intf];
161     [o_extMgr retain];
162
163     [self initStrings];
164
165     key = config_GetPsz(p_intf, "key-quit");
166     o_key = [NSString stringWithFormat:@"%s", key];
167     [o_mi_quit setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
168     [o_mi_quit setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
169     FREENULL(key);
170
171     // do not assign play/pause key
172
173     key = config_GetPsz(p_intf, "key-stop");
174     o_key = [NSString stringWithFormat:@"%s", key];
175     [o_mi_stop setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
176     [o_mi_stop setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
177     FREENULL(key);
178
179     key = config_GetPsz(p_intf, "key-prev");
180     o_key = [NSString stringWithFormat:@"%s", key];
181     [o_mi_previous setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
182     [o_mi_previous setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
183     FREENULL(key);
184
185     key = config_GetPsz(p_intf, "key-next");
186     o_key = [NSString stringWithFormat:@"%s", key];
187     [o_mi_next setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
188     [o_mi_next setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
189     FREENULL(key);
190
191     key = config_GetPsz(p_intf, "key-jump+short");
192     o_key = [NSString stringWithFormat:@"%s", key];
193     [o_mi_fwd setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
194     [o_mi_fwd setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
195     FREENULL(key);
196
197     key = config_GetPsz(p_intf, "key-jump-short");
198     o_key = [NSString stringWithFormat:@"%s", key];
199     [o_mi_bwd setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
200     [o_mi_bwd setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
201     FREENULL(key);
202
203     key = config_GetPsz(p_intf, "key-vol-up");
204     o_key = [NSString stringWithFormat:@"%s", key];
205     [o_mi_vol_up setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
206     [o_mi_vol_up setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
207     FREENULL(key);
208
209     key = config_GetPsz(p_intf, "key-vol-down");
210     o_key = [NSString stringWithFormat:@"%s", key];
211     [o_mi_vol_down setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
212     [o_mi_vol_down setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
213     FREENULL(key);
214
215     key = config_GetPsz(p_intf, "key-vol-mute");
216     o_key = [NSString stringWithFormat:@"%s", key];
217     [o_mi_mute setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
218     [o_mi_mute setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
219     FREENULL(key);
220
221     key = config_GetPsz(p_intf, "key-toggle-fullscreen");
222     o_key = [NSString stringWithFormat:@"%s", key];
223     [o_mi_fullscreen setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
224     [o_mi_fullscreen setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
225     FREENULL(key);
226
227     key = config_GetPsz(p_intf, "key-snapshot");
228     o_key = [NSString stringWithFormat:@"%s", key];
229     [o_mi_snapshot setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
230     [o_mi_snapshot setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
231     FREENULL(key);
232
233     key = config_GetPsz(p_intf, "key-random");
234     o_key = [NSString stringWithFormat:@"%s", key];
235     [o_mi_random setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
236     [o_mi_random setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
237     FREENULL(key);
238
239     key = config_GetPsz(p_intf, "key-zoom-half");
240     o_key = [NSString stringWithFormat:@"%s", key];
241     [o_mi_half_window setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
242     [o_mi_half_window setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
243     FREENULL(key);
244
245     key = config_GetPsz(p_intf, "key-zoom-original");
246     o_key = [NSString stringWithFormat:@"%s", key];
247     [o_mi_normal_window setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
248     [o_mi_normal_window setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
249     FREENULL(key);
250
251     key = config_GetPsz(p_intf, "key-zoom-double");
252     o_key = [NSString stringWithFormat:@"%s", key];
253     [o_mi_double_window setKeyEquivalent: [o_vlcstringutility VLCKeyToString: o_key]];
254     [o_mi_double_window setKeyEquivalentModifierMask: [o_vlcstringutility VLCModifiersToCocoa:o_key]];
255     FREENULL(key);
256
257     [self setSubmenusEnabled: FALSE];
258
259     [[NSNotificationCenter defaultCenter] addObserver: self
260                                              selector: @selector(refreshVoutDeviceMenu:)
261                                                  name: NSApplicationDidChangeScreenParametersNotification
262                                                object: nil];
263
264     /* we're done */
265     b_mainMenu_setup = YES;
266
267     [self setupVarMenuItem: o_mi_add_intf target: (vlc_object_t *)p_intf
268                              var: "intf-add" selector: @selector(toggleVar:)];
269
270     /* setup extensions menu */
271     // FIXME: Implement preference for autoloading extensions on mac
272     if (![o_extMgr isLoaded] && ![o_extMgr cannotLoad])
273         [o_extMgr loadExtensions];
274
275     /* Let the ExtensionsManager itself build the menu */
276     [o_extMgr buildMenu:o_mu_extensions];
277     [o_mi_extensions setEnabled: ([o_mu_extensions numberOfItems] > 0)];
278
279     /* setup post-proc menu */
280     NSUInteger count = (NSUInteger) [o_mu_ffmpeg_pp numberOfItems];
281     if (count > 0)
282         [o_mu_ffmpeg_pp removeAllItems];
283
284     NSMenuItem * o_mitem;
285     [o_mu_ffmpeg_pp setAutoenablesItems: YES];
286     [o_mu_ffmpeg_pp addItemWithTitle: _NS("Disable") action:@selector(togglePostProcessing:) keyEquivalent:@""];
287     o_mitem = [o_mu_ffmpeg_pp itemAtIndex: 0];
288     [o_mitem setTag: -1];
289     [o_mitem setEnabled: YES];
290     [o_mitem setTarget: self];
291     for (NSUInteger x = 1; x < 7; x++) {
292         [o_mu_ffmpeg_pp addItemWithTitle:[NSString stringWithFormat:_NS("Level %i"), x]
293                                                action:@selector(togglePostProcessing:)
294                                         keyEquivalent:@""];
295         o_mitem = [o_mu_ffmpeg_pp itemAtIndex:x];
296         [o_mitem setEnabled:YES];
297         [o_mitem setTag:x];
298         [o_mitem setTarget:self];
299     }
300     char *psz_config = config_GetPsz(p_intf, "video-filter");
301     if (psz_config) {
302         if (!strstr(psz_config, "postproc"))
303             [[o_mu_ffmpeg_pp itemAtIndex:0] setState:NSOnState];
304         else
305             [[o_mu_ffmpeg_pp itemWithTag:config_GetInt(p_intf, "postproc-q")] setState:NSOnState];
306         free(psz_config);
307     } else
308         [[o_mu_ffmpeg_pp itemAtIndex:0] setState:NSOnState];
309     [o_mi_ffmpeg_pp setEnabled: NO];
310
311     [self refreshAudioDeviceList];
312
313     /* setup subtitles menu */
314     [self setupMenu: o_mu_subtitle_size withIntList:"freetype-rel-fontsize" andSelector:@selector(switchSubtitleOption:)];
315     [self setupMenu: o_mu_subtitle_textcolor withIntList:"freetype-color" andSelector:@selector(switchSubtitleOption:)];
316     [o_mi_subtitle_bgopacity_sld setIntValue: config_GetInt(VLC_OBJECT(p_intf), "freetype-background-opacity")];
317     [self setupMenu: o_mu_subtitle_bgcolor withIntList:"freetype-background-color" andSelector:@selector(switchSubtitleOption:)];
318     [self setupMenu: o_mu_subtitle_outlinethickness withIntList:"freetype-outline-thickness" andSelector:@selector(switchSubtitleOption:)];
319 }
320
321 - (void)setupMenu: (NSMenu*)menu withIntList: (char *)psz_name andSelector:(SEL)selector
322 {
323     module_config_t *p_item;
324
325     [menu removeAllItems];
326     p_item = config_FindConfig(VLC_OBJECT(p_intf), psz_name);
327
328     /* serious problem, if no item found */
329     assert(p_item);
330
331     for (int i = 0; i < p_item->list_count; i++) {
332         NSMenuItem *mi;
333         if (p_item->list_text != NULL)
334             mi = [[NSMenuItem alloc] initWithTitle: _NS(p_item->list_text[i]) action:NULL keyEquivalent: @""];
335         else if (p_item->list.i[i])
336             mi = [[NSMenuItem alloc] initWithTitle: [NSString stringWithFormat: @"%d", p_item->list.i[i]] action:NULL keyEquivalent: @""];
337         else {
338             msg_Err(p_intf, "item %d of pref %s failed to be created", i, psz_name);
339             continue;
340         }
341
342         [mi setTarget:self];
343         [mi setAction:selector];
344         [mi setTag:p_item->list.i[i]];
345         [mi setRepresentedObject:[NSString stringWithUTF8String:psz_name]];
346         [menu addItem: [mi autorelease]];
347         if (p_item->value.i == p_item->list.i[i])
348             [mi setState:NSOnState];
349     }
350 }
351
352 - (void)initStrings
353 {
354     /* main menu */
355     [o_mi_about setTitle: [_NS("About VLC media player") \
356                            stringByAppendingString: @"..."]];
357     [o_mi_checkForUpdate setTitle: _NS("Check for Update...")];
358     [o_mi_prefs setTitle: _NS("Preferences...")];
359     [o_mi_extensions setTitle: _NS("Extensions")];
360     [o_mu_extensions setTitle: _NS("Extensions")];
361     [o_mi_addonManager setTitle: _NS("Addons Manager")];
362     [o_mi_add_intf setTitle: _NS("Add Interface")];
363     [o_mu_add_intf setTitle: _NS("Add Interface")];
364     [o_mi_services setTitle: _NS("Services")];
365     [o_mi_hide setTitle: _NS("Hide VLC")];
366     [o_mi_hide_others setTitle: _NS("Hide Others")];
367     [o_mi_show_all setTitle: _NS("Show All")];
368     [o_mi_quit setTitle: _NS("Quit VLC")];
369
370     [o_mu_file setTitle: _ANS("1:File")];
371     [o_mi_open_generic setTitle: _NS("Advanced Open File...")];
372     [o_mi_open_file setTitle: _NS("Open File...")];
373     [o_mi_open_disc setTitle: _NS("Open Disc...")];
374     [o_mi_open_net setTitle: _NS("Open Network...")];
375     [o_mi_open_capture setTitle: _NS("Open Capture Device...")];
376     [o_mi_open_recent setTitle: _NS("Open Recent")];
377     [o_mi_close_window setTitle: _NS("Close Window")];
378     [o_mi_open_wizard setTitle: _NS("Streaming/Exporting Wizard...")];
379     [o_mi_convertandsave setTitle: _NS("Convert / Stream...")];
380     [o_mi_save_playlist setTitle: _NS("Save Playlist...")];
381     [o_mi_revealInFinder setTitle: _NS("Reveal in Finder")];
382
383     [o_mu_edit setTitle: _NS("Edit")];
384     [o_mi_cut setTitle: _NS("Cut")];
385     [o_mi_copy setTitle: _NS("Copy")];
386     [o_mi_paste setTitle: _NS("Paste")];
387     [o_mi_clear setTitle: _NS("Clear")];
388     [o_mi_select_all setTitle: _NS("Select All")];
389
390     [o_mu_view setTitle: _NS("View")];
391     [o_mi_toggleJumpButtons setTitle: _NS("Show Previous & Next Buttons")];
392     [o_mi_toggleJumpButtons setState: config_GetInt(VLCIntf, "macosx-show-playback-buttons")];
393     [o_mi_togglePlaymodeButtons setTitle: _NS("Show Shuffle & Repeat Buttons")];
394     [o_mi_togglePlaymodeButtons setState: config_GetInt(VLCIntf, "macosx-show-playmode-buttons")];
395     [o_mi_toggleEffectsButton setTitle: _NS("Show Audio Effects Button")];
396     [o_mi_toggleEffectsButton setState: config_GetInt(VLCIntf, "macosx-show-effects-button")];
397     [o_mi_toggleSidebar setTitle: _NS("Show Sidebar")];
398     [o_mi_toggleSidebar setState: config_GetInt(VLCIntf, "macosx-show-sidebar")];
399     [o_mu_playlistTableColumns setTitle: _NS("Playlist Table Columns")];
400     [o_mi_playlistTableColumns setTitle: _NS("Playlist Table Columns")];
401
402     [o_mu_controls setTitle: _NS("Playback")];
403     [o_mi_play setTitle: _NS("Play")];
404     [o_mi_stop setTitle: _NS("Stop")];
405     [o_mi_record setTitle: _NS("Record")];
406     [o_mi_rate setView: o_mi_rate_view];
407     [o_mi_rate_lbl setStringValue: _NS("Playback Speed")];
408     [o_mi_rate_slower_lbl setStringValue: _NS("Slower")];
409     [o_mi_rate_normal_lbl setStringValue: _NS("Normal")];
410     [o_mi_rate_faster_lbl setStringValue: _NS("Faster")];
411     [o_mi_trackSynchronization setTitle: _NS("Track Synchronization")];
412     [o_mi_previous setTitle: _NS("Previous")];
413     [o_mi_next setTitle: _NS("Next")];
414     [o_mi_random setTitle: _NS("Random")];
415     [o_mi_repeat setTitle: _NS("Repeat One")];
416     [o_mi_loop setTitle: _NS("Repeat All")];
417     [o_mi_AtoBloop setTitle: _NS("A→B Loop")];
418     [o_mi_quitAfterPB setTitle: _NS("Quit after Playback")];
419     [o_mi_fwd setTitle: _NS("Step Forward")];
420     [o_mi_bwd setTitle: _NS("Step Backward")];
421
422     [o_mi_program setTitle: _NS("Program")];
423     [o_mu_program setTitle: _NS("Program")];
424     [o_mi_title setTitle: _NS("Title")];
425     [o_mu_title setTitle: _NS("Title")];
426     [o_mi_chapter setTitle: _NS("Chapter")];
427     [o_mu_chapter setTitle: _NS("Chapter")];
428
429     [o_mu_audio setTitle: _NS("Audio")];
430     [o_mi_vol_up setTitle: _NS("Increase Volume")];
431     [o_mi_vol_down setTitle: _NS("Decrease Volume")];
432     [o_mi_mute setTitle: _NS("Mute")];
433     [o_mi_audiotrack setTitle: _NS("Audio Track")];
434     [o_mu_audiotrack setTitle: _NS("Audio Track")];
435     [o_mi_channels setTitle: _NS("Stereo audio mode")];
436     [o_mu_channels setTitle: _NS("Stereo audio mode")];
437     [o_mi_device setTitle: _NS("Audio Device")];
438     [o_mu_device setTitle: _NS("Audio Device")];
439     [o_mi_visual setTitle: _NS("Visualizations")];
440     [o_mu_visual setTitle: _NS("Visualizations")];
441
442     [o_mu_video setTitle: _NS("Video")];
443     [o_mi_half_window setTitle: _NS("Half Size")];
444     [o_mi_normal_window setTitle: _NS("Normal Size")];
445     [o_mi_double_window setTitle: _NS("Double Size")];
446     [o_mi_fittoscreen setTitle: _NS("Fit to Screen")];
447     [o_mi_fullscreen setTitle: _NS("Fullscreen")];
448     [o_mi_floatontop setTitle: _NS("Float on Top")];
449     [o_mi_snapshot setTitle: _NS("Snapshot")];
450     [o_mi_videotrack setTitle: _NS("Video Track")];
451     [o_mu_videotrack setTitle: _NS("Video Track")];
452     [o_mi_aspect_ratio setTitle: _NS("Aspect ratio")];
453     [o_mu_aspect_ratio setTitle: _NS("Aspect ratio")];
454     [o_mi_crop setTitle: _NS("Crop")];
455     [o_mu_crop setTitle: _NS("Crop")];
456     [o_mi_screen setTitle: _NS("Fullscreen Video Device")];
457     [o_mu_screen setTitle: _NS("Fullscreen Video Device")];
458     [o_mi_deinterlace setTitle: _NS("Deinterlace")];
459     [o_mu_deinterlace setTitle: _NS("Deinterlace")];
460     [o_mi_deinterlace_mode setTitle: _NS("Deinterlace mode")];
461     [o_mu_deinterlace_mode setTitle: _NS("Deinterlace mode")];
462     [o_mi_ffmpeg_pp setTitle: _NS("Post processing")];
463     [o_mu_ffmpeg_pp setTitle: _NS("Post processing")];
464
465     [o_mu_subtitles setTitle:_NS("Subtitles")];
466     [o_mi_openSubtitleFile setTitle: _NS("Add Subtitle File...")];
467     [o_mi_subtitle_track setTitle: _NS("Subtitles Track")];
468     [o_mu_subtitle_tracks setTitle: _NS("Subtitles Track")];
469     [o_mi_subtitle_size setTitle: _NS("Text Size")];
470     [o_mi_subtitle_textcolor setTitle: _NS("Text Color")];
471     [o_mi_subtitle_outlinethickness setTitle: _NS("Outline Thickness")];
472     [o_mi_subtitle_bgopacity setView: o_mi_subtitle_bgopacity_view];
473     [o_mi_subtitle_bgopacity_lbl setStringValue: _NS("Background Opacity")];
474     [o_mi_subtitle_bgopacity_lbl_gray setStringValue: _NS("Background Opacity")];
475     [o_mi_subtitle_bgcolor setTitle: _NS("Background Color")];
476     [o_mi_teletext setTitle: _NS("Teletext")];
477     [o_mi_teletext_transparent setTitle: _NS("Transparent")];
478     [o_mi_teletext_index setTitle: _NS("Index")];
479     [o_mi_teletext_red setTitle: _NS("Red")];
480     [o_mi_teletext_green setTitle: _NS("Green")];
481     [o_mi_teletext_yellow setTitle: _NS("Yellow")];
482     [o_mi_teletext_blue setTitle: _NS("Blue")];
483
484     [o_mu_window setTitle: _NS("Window")];
485     [o_mi_minimize setTitle: _NS("Minimize")];
486     [o_mi_zoom_window setTitle: _NS("Zoom")];
487     [o_mi_player setTitle: _NS("Player...")];
488     [o_mi_controller setTitle: _NS("Main Window...")];
489     [o_mi_audioeffects setTitle: _NS("Audio Effects...")];
490     [o_mi_videoeffects setTitle: _NS("Video Effects...")];
491     [o_mi_bookmarks setTitle: _NS("Bookmarks...")];
492     [o_mi_playlist setTitle: _NS("Playlist...")];
493     [o_mi_info setTitle: _NS("Media Information...")];
494     [o_mi_messages setTitle: _NS("Messages...")];
495     [o_mi_errorsAndWarnings setTitle: _NS("Errors and Warnings...")];
496
497     [o_mi_bring_atf setTitle: _NS("Bring All to Front")];
498
499     [o_mu_help setTitle: _NS("Help")];
500     [o_mi_help setTitle: _NS("VLC media player Help...")];
501     [o_mi_readme setTitle: _NS("ReadMe / FAQ...")];
502     [o_mi_license setTitle: _NS("License")];
503     [o_mi_documentation setTitle: _NS("Online Documentation...")];
504     [o_mi_website setTitle: _NS("VideoLAN Website...")];
505     [o_mi_donation setTitle: _NS("Make a donation...")];
506     [o_mi_forum setTitle: _NS("Online Forum...")];
507
508     /* dock menu */
509     [o_dmi_play setTitle: _NS("Play")];
510     [o_dmi_stop setTitle: _NS("Stop")];
511     [o_dmi_next setTitle: _NS("Next")];
512     [o_dmi_previous setTitle: _NS("Previous")];
513     [o_dmi_mute setTitle: _NS("Mute")];
514
515     /* vout menu */
516     [o_vmi_play setTitle: _NS("Play")];
517     [o_vmi_stop setTitle: _NS("Stop")];
518     [o_vmi_prev setTitle: _NS("Previous")];
519     [o_vmi_next setTitle: _NS("Next")];
520     [o_vmi_volup setTitle: _NS("Volume Up")];
521     [o_vmi_voldown setTitle: _NS("Volume Down")];
522     [o_vmi_mute setTitle: _NS("Mute")];
523     [o_vmi_fullscreen setTitle: _NS("Fullscreen")];
524     [o_vmi_snapshot setTitle: _NS("Snapshot")];
525 }
526
527 - (NSMenu *)setupPlaylistTableColumnsMenu
528 {
529     NSMenu *o_context_menu = [[NSMenu alloc] init];
530
531     NSMenuItem *o_mi_tmp;
532     NSUInteger count = [o_ptc_menuorder count];
533     for (NSUInteger i = 0; i < count; i++) {
534         NSString *o_title = [o_ptc_translation_dict objectForKey:[o_ptc_menuorder objectAtIndex:i]];
535         o_mi_tmp = [o_mu_playlistTableColumns addItemWithTitle:o_title
536                                                         action:@selector(togglePlaylistColumnTable:)
537                                                  keyEquivalent:@""];
538         /* don't set a valid target for the title column selector, since we want it to be disabled */
539         if (![[o_ptc_menuorder objectAtIndex:i] isEqualToString: TITLE_COLUMN])
540             [o_mi_tmp setTarget:self];
541         [o_mi_tmp setTag:i];
542
543         o_mi_tmp = [o_context_menu addItemWithTitle:o_title
544                                              action:@selector(togglePlaylistColumnTable:)
545                                       keyEquivalent:@""];
546         /* don't set a valid target for the title column selector, since we want it to be disabled */
547         if (![[o_ptc_menuorder objectAtIndex:i] isEqualToString: TITLE_COLUMN])
548             [o_mi_tmp setTarget:self];
549         [o_mi_tmp setTag:i];
550     }
551     if (!o_mu_playlistTableColumnsContextMenu)
552         o_mu_playlistTableColumnsContextMenu = [o_context_menu retain];
553     return [o_context_menu autorelease];
554 }
555
556 #pragma mark - Termination
557
558 - (void)releaseRepresentedObjects:(NSMenu *)the_menu
559 {
560     if (!p_intf) return;
561
562     NSArray *menuitems_array = [the_menu itemArray];
563     NSUInteger menuItemCount = [menuitems_array count];
564     for (NSUInteger i=0; i < menuItemCount; i++) {
565         NSMenuItem *one_item = [menuitems_array objectAtIndex:i];
566         if ([one_item hasSubmenu])
567             [self releaseRepresentedObjects: [one_item submenu]];
568
569         [one_item setRepresentedObject:NULL];
570     }
571 }
572
573 #pragma mark - Interface update
574
575 - (void)setupMenus
576 {
577     playlist_t * p_playlist = pl_Get(p_intf);
578     input_thread_t * p_input = playlist_CurrentInput(p_playlist);
579     if (p_input != NULL) {
580         [self setupVarMenuItem: o_mi_program target: (vlc_object_t *)p_input
581                                  var: "program" selector: @selector(toggleVar:)];
582
583         [self setupVarMenuItem: o_mi_title target: (vlc_object_t *)p_input
584                                  var: "title" selector: @selector(toggleVar:)];
585
586         [self setupVarMenuItem: o_mi_chapter target: (vlc_object_t *)p_input
587                                  var: "chapter" selector: @selector(toggleVar:)];
588
589         [self setupVarMenuItem: o_mi_audiotrack target: (vlc_object_t *)p_input
590                                  var: "audio-es" selector: @selector(toggleVar:)];
591
592         [self setupVarMenuItem: o_mi_videotrack target: (vlc_object_t *)p_input
593                                  var: "video-es" selector: @selector(toggleVar:)];
594
595         [self setupVarMenuItem: o_mi_subtitle_track target: (vlc_object_t *)p_input
596                                  var: "spu-es" selector: @selector(toggleVar:)];
597
598         audio_output_t * p_aout = playlist_GetAout(p_playlist);
599         if (p_aout != NULL) {
600             [self setupVarMenuItem: o_mi_channels target: (vlc_object_t *)p_aout
601                                      var: "stereo-mode" selector: @selector(toggleVar:)];
602
603             [self setupVarMenuItem: o_mi_visual target: (vlc_object_t *)p_aout
604                                      var: "visual" selector: @selector(toggleVar:)];
605             vlc_object_release(p_aout);
606         }
607
608         vout_thread_t * p_vout = getVoutForActiveWindow();
609
610         if (p_vout != NULL) {
611             [self setupVarMenuItem: o_mi_aspect_ratio target: (vlc_object_t *)p_vout
612                                      var: "aspect-ratio" selector: @selector(toggleVar:)];
613
614             [self setupVarMenuItem: o_mi_crop target: (vlc_object_t *) p_vout
615                                      var: "crop" selector: @selector(toggleVar:)];
616
617             [self setupVarMenuItem: o_mi_deinterlace target: (vlc_object_t *)p_vout
618                                      var: "deinterlace" selector: @selector(toggleVar:)];
619
620             [self setupVarMenuItem: o_mi_deinterlace_mode target: (vlc_object_t *)p_vout
621                                      var: "deinterlace-mode" selector: @selector(toggleVar:)];
622
623             vlc_object_release(p_vout);
624
625             [self refreshVoutDeviceMenu:nil];
626         }
627         [o_mi_ffmpeg_pp setEnabled:YES];
628         vlc_object_release(p_input);
629     } else {
630         [o_mi_ffmpeg_pp setEnabled:NO];
631     }
632 }
633
634 - (void)refreshVoutDeviceMenu:(NSNotification *)o_notification
635 {
636     NSUInteger count = (NSUInteger) [o_mu_screen numberOfItems];
637     NSMenu * o_submenu = o_mu_screen;
638     if (count > 0)
639         [o_submenu removeAllItems];
640
641     NSArray * o_screens = [NSScreen screens];
642     NSMenuItem * o_mitem;
643     count = [o_screens count];
644     [o_mi_screen setEnabled: YES];
645     [o_submenu addItemWithTitle: _NS("Default") action:@selector(toggleFullscreenDevice:) keyEquivalent:@""];
646     o_mitem = [o_submenu itemAtIndex: 0];
647     [o_mitem setTag: 0];
648     [o_mitem setEnabled: YES];
649     [o_mitem setTarget: self];
650     NSRect s_rect;
651     for (NSUInteger i = 0; i < count; i++) {
652         s_rect = [[o_screens objectAtIndex:i] frame];
653         [o_submenu addItemWithTitle: [NSString stringWithFormat: @"%@ %li (%ix%i)", _NS("Screen"), i+1,
654                                       (int)s_rect.size.width, (int)s_rect.size.height] action:@selector(toggleFullscreenDevice:) keyEquivalent:@""];
655         o_mitem = [o_submenu itemAtIndex:i+1];
656         [o_mitem setTag: (int)[[o_screens objectAtIndex:i] displayID]];
657         [o_mitem setEnabled: YES];
658         [o_mitem setTarget: self];
659     }
660     [[o_submenu itemWithTag: var_InheritInteger(VLCIntf, "macosx-vdev")] setState: NSOnState];
661 }
662
663 - (void)setSubmenusEnabled:(BOOL)b_enabled
664 {
665     [o_mi_program setEnabled: b_enabled];
666     [o_mi_title setEnabled: b_enabled];
667     [o_mi_chapter setEnabled: b_enabled];
668     [o_mi_audiotrack setEnabled: b_enabled];
669     [o_mi_visual setEnabled: b_enabled];
670     [o_mi_videotrack setEnabled: b_enabled];
671     [o_mi_subtitle_track setEnabled: b_enabled];
672     [o_mi_channels setEnabled: b_enabled];
673     [o_mi_deinterlace setEnabled: b_enabled];
674     [o_mi_deinterlace_mode setEnabled: b_enabled];
675     [o_mi_screen setEnabled: b_enabled];
676     [o_mi_aspect_ratio setEnabled: b_enabled];
677     [o_mi_crop setEnabled: b_enabled];
678 }
679
680 - (void)setSubtitleMenuEnabled:(BOOL)b_enabled
681 {
682     [o_mi_openSubtitleFile setEnabled: b_enabled];
683     if (b_enabled) {
684         [o_mi_subtitle_bgopacity_lbl_gray setHidden: YES];
685         [o_mi_subtitle_bgopacity_lbl setHidden: NO];
686     } else {
687         [o_mi_subtitle_bgopacity_lbl_gray setHidden: NO];
688         [o_mi_subtitle_bgopacity_lbl setHidden: YES];
689     }
690     [o_mi_subtitle_bgopacity_sld setEnabled: b_enabled];
691     [o_mi_teletext setEnabled: b_enabled];
692 }
693
694 - (void)setRateControlsEnabled:(BOOL)b_enabled
695 {
696     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
697     [o_mi_rate_sld setEnabled: b_enabled];
698     [o_mi_rate_sld setIntValue: [[VLCCoreInteraction sharedInstance] playbackRate]];
699     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
700     double speed =  pow(2, (double)i / 17);
701     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%.2fx", speed]];
702
703     NSColor *o_color = b_enabled ? [NSColor controlTextColor] : [NSColor disabledControlTextColor];
704
705     [o_mi_rate_lbl setTextColor:o_color];
706     [o_mi_rate_slower_lbl setTextColor:o_color];
707     [o_mi_rate_normal_lbl setTextColor:o_color];
708     [o_mi_rate_faster_lbl setTextColor:o_color];
709     [o_mi_rate_fld setTextColor:o_color];
710
711     [self setSubtitleMenuEnabled: b_enabled];
712     [o_pool release];
713 }
714
715 #pragma mark - View
716
717 - (IBAction)toggleEffectsButton:(id)sender
718 {
719     BOOL b_value = !config_GetInt(VLCIntf, "macosx-show-effects-button");
720     config_PutInt(VLCIntf, "macosx-show-effects-button", b_value);
721     [[[[VLCMain sharedInstance] mainWindow] controlsBar] toggleEffectsButton];
722     [o_mi_toggleEffectsButton setState: b_value];
723 }
724
725 - (IBAction)toggleJumpButtons:(id)sender
726 {
727     BOOL b_value = !config_GetInt(VLCIntf, "macosx-show-playback-buttons");
728     config_PutInt(VLCIntf, "macosx-show-playback-buttons", b_value);
729
730     [[[[VLCMain sharedInstance] mainWindow] controlsBar] toggleJumpButtons];
731     [[[VLCMain sharedInstance] voutController] updateWindowsUsingBlock:^(VLCVideoWindowCommon *o_window) {
732         [[o_window controlsBar] toggleForwardBackwardMode: b_value];
733     }];
734
735     [o_mi_toggleJumpButtons setState: b_value];
736 }
737
738 - (IBAction)togglePlaymodeButtons:(id)sender
739 {
740     BOOL b_value = !config_GetInt(VLCIntf, "macosx-show-playmode-buttons");
741     config_PutInt(VLCIntf, "macosx-show-playmode-buttons", b_value);
742     [[[[VLCMain sharedInstance] mainWindow] controlsBar] togglePlaymodeButtons];
743     [o_mi_togglePlaymodeButtons setState: b_value];
744 }
745
746 - (IBAction)toggleSidebar:(id)sender
747 {
748     [[[VLCMain sharedInstance] mainWindow] toggleLeftSubSplitView];
749 }
750
751 - (void)updateSidebarMenuItem
752 {
753     [o_mi_toggleSidebar setState: config_GetInt(VLCIntf, "macosx-show-sidebar")];
754 }
755
756 - (IBAction)togglePlaylistColumnTable:(id)sender
757 {
758     NSInteger i_new_state = ![sender state];
759     NSInteger i_tag = [sender tag];
760     [[o_mu_playlistTableColumns            itemWithTag: i_tag] setState: i_new_state];
761     [[o_mu_playlistTableColumnsContextMenu itemWithTag: i_tag] setState: i_new_state];
762
763     NSString *o_column = [o_ptc_menuorder objectAtIndex:i_tag];
764     [[[VLCMain sharedInstance] playlist] setColumn: o_column state: i_new_state translationDict: o_ptc_translation_dict];
765 }
766
767 - (BOOL)setPlaylistColumnTableState:(NSInteger)i_state forColumn:(NSString *)o_column
768 {
769     NSUInteger i_tag = [o_ptc_menuorder indexOfObject: o_column];
770     // prevent setting unknown columns
771     if(i_tag == NSNotFound)
772         return NO;
773
774     [[o_mu_playlistTableColumns            itemWithTag: i_tag] setState: i_state];
775     [[o_mu_playlistTableColumnsContextMenu itemWithTag: i_tag] setState: i_state];
776     [[[VLCMain sharedInstance] playlist] setColumn: o_column state: i_state translationDict: o_ptc_translation_dict];
777
778     return YES;
779 }
780
781 #pragma mark - Playback
782
783 - (IBAction)quitAfterPlayback:(id)sender
784 {
785     playlist_t *p_playlist = pl_Get(VLCIntf);
786     bool b_value = !var_CreateGetBool(p_playlist, "play-and-exit");
787     var_SetBool(p_playlist, "play-and-exit", b_value);
788     config_PutInt(p_intf, "play-and-exit", b_value);
789 }
790
791 - (IBAction)toggleRecord:(id)sender
792 {
793     [[VLCCoreInteraction sharedInstance] toggleRecord];
794 }
795
796 - (void)updateRecordState:(BOOL)b_value
797 {
798     [o_mi_record setState:b_value];
799 }
800
801 - (IBAction)setPlaybackRate:(id)sender
802 {
803     [[VLCCoreInteraction sharedInstance] setPlaybackRate: [o_mi_rate_sld intValue]];
804     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
805     double speed =  pow(2, (double)i / 17);
806     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%.2fx", speed]];
807 }
808
809 - (void)updatePlaybackRate
810 {
811     int i = [[VLCCoreInteraction sharedInstance] playbackRate];
812     double speed =  pow(2, (double)i / 17);
813     [o_mi_rate_fld setStringValue: [NSString stringWithFormat:@"%.2fx", speed]];
814     [o_mi_rate_sld setIntValue: i];
815 }
816
817 - (IBAction)toggleAtoBloop:(id)sender
818 {
819     [[VLCCoreInteraction sharedInstance] setAtoB];
820 }
821
822 #pragma mark - audio menu
823
824 - (void)refreshAudioDeviceList
825 {
826     char **ids, **names;
827     char *currentDevice;
828
829     [o_mu_device removeAllItems];
830
831     audio_output_t * p_aout = getAout();
832     if (!p_aout)
833         return;
834
835     int n = aout_DevicesList(p_aout, &ids, &names);
836     if (n == -1) {
837         vlc_object_release(p_aout);
838         return;
839     }
840
841     currentDevice = aout_DeviceGet(p_aout);
842     NSMenuItem * o_mi_tmp;
843
844     for (NSUInteger x = 0; x < n; x++) {
845         o_mi_tmp = [o_mu_device addItemWithTitle:toNSStr(names[x]) action:@selector(toggleAudioDevice:) keyEquivalent:@""];
846         [o_mi_tmp setTarget:self];
847         [o_mi_tmp setTag:[[NSString stringWithFormat:@"%s", ids[x]] intValue]];
848     }
849     vlc_object_release(p_aout);
850
851     [[o_mu_device itemWithTag:[[NSString stringWithFormat:@"%s", currentDevice] intValue]] setState:NSOnState];
852
853     free(currentDevice);
854
855     for (NSUInteger x = 0; x < n; x++) {
856         free(ids[x]);
857         free(names[x]);
858     }
859     free(ids);
860     free(names);
861
862     [o_mu_device setAutoenablesItems:YES];
863     [o_mi_device setEnabled:YES];
864 }
865
866 - (IBAction)toggleAudioDevice:(id)sender
867 {
868     audio_output_t * p_aout = getAout();
869     if (!p_aout)
870         return;
871
872     int returnValue = 0;
873
874     if ([sender tag] > 0)
875         returnValue = aout_DeviceSet(p_aout, [[NSString stringWithFormat:@"%li", [sender tag]] UTF8String]);
876     else
877         returnValue = aout_DeviceSet(p_aout, NULL);
878
879     if (returnValue != 0)
880         msg_Warn(VLCIntf, "failed to set audio device %li", [sender tag]);
881
882     vlc_object_release(p_aout);
883     [self refreshAudioDeviceList];
884 }
885
886 #pragma mark - video menu
887
888 - (IBAction)toggleFullscreen:(id)sender
889 {
890     [[VLCCoreInteraction sharedInstance] toggleFullscreen];
891 }
892
893 - (IBAction)resizeVideoWindow:(id)sender
894 {
895     input_thread_t *p_input = pl_CurrentInput(VLCIntf);
896     if (p_input) {
897         vout_thread_t *p_vout = getVoutForActiveWindow();
898         if (p_vout) {
899             if (sender == o_mi_half_window)
900                 var_SetFloat(p_vout, "zoom", 0.5);
901             else if (sender == o_mi_normal_window)
902                 var_SetFloat(p_vout, "zoom", 1.0);
903             else if (sender == o_mi_double_window)
904                 var_SetFloat(p_vout, "zoom", 2.0);
905             else
906             {
907                 [[NSApp keyWindow] performZoom:sender];
908             }
909             vlc_object_release(p_vout);
910         }
911         vlc_object_release(p_input);
912     }
913 }
914
915 - (IBAction)floatOnTop:(id)sender
916 {
917     input_thread_t *p_input = pl_CurrentInput(VLCIntf);
918     if (p_input) {
919         vout_thread_t *p_vout = getVoutForActiveWindow();
920         if (p_vout) {
921             BOOL b_fs = var_ToggleBool(p_vout, "video-on-top");
922             var_SetBool(pl_Get(p_intf), "video-on-top", b_fs);
923
924             vlc_object_release(p_vout);
925         }
926         vlc_object_release(p_input);
927     }
928 }
929
930 - (IBAction)createVideoSnapshot:(id)sender
931 {
932     input_thread_t *p_input = pl_CurrentInput(VLCIntf);
933     if (p_input) {
934         vout_thread_t *p_vout = getVoutForActiveWindow();
935         if (p_vout) {
936             var_TriggerCallback(p_vout, "video-snapshot");
937             vlc_object_release(p_vout);
938         }
939         vlc_object_release(p_input);
940     }
941 }
942
943 - (void)_disablePostProcessing
944 {
945     [[VLCCoreInteraction sharedInstance] setVideoFilter:"postproc" on:false];
946 }
947
948 - (void)_enablePostProcessing
949 {
950     [[VLCCoreInteraction sharedInstance] setVideoFilter:"postproc" on:true];
951 }
952
953 - (IBAction)togglePostProcessing:(id)sender
954 {
955     char *psz_name = "postproc";
956     NSInteger count = [o_mu_ffmpeg_pp numberOfItems];
957     for (NSUInteger x = 0; x < count; x++)
958         [[o_mu_ffmpeg_pp itemAtIndex:x] setState:NSOffState];
959
960     if ([sender tag] == -1) {
961         [self _disablePostProcessing];
962         [sender setState:NSOnState];
963     } else {
964         [self _enablePostProcessing];
965         [sender setState:NSOnState];
966
967         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty:"postproc-q" forFilter:"postproc" integer:[sender tag]];
968     }
969 }
970
971 - (IBAction)toggleFullscreenDevice:(id)sender
972 {
973     config_PutInt(VLCIntf, "macosx-vdev", [sender tag]);
974     [self refreshVoutDeviceMenu: nil];
975 }
976
977 - (id)voutMenu
978 {
979     return o_vout_menu;
980 }
981
982 #pragma mark - Subtitles Menu
983
984 - (IBAction)addSubtitleFile:(id)sender
985 {
986     NSInteger i_returnValue = 0;
987     input_thread_t * p_input = pl_CurrentInput(VLCIntf);
988     if (!p_input)
989         return;
990
991     input_item_t *p_item = input_GetItem(p_input);
992     if (!p_item) {
993         vlc_object_release(p_input);
994         return;
995     }
996
997     char *path = input_item_GetURI(p_item);
998
999     if (!path)
1000         path = strdup("");
1001
1002     NSOpenPanel * openPanel = [NSOpenPanel openPanel];
1003     [openPanel setCanChooseFiles: YES];
1004     [openPanel setCanChooseDirectories: NO];
1005     [openPanel setAllowsMultipleSelection: YES];
1006
1007     [openPanel setAllowedFileTypes: [NSArray arrayWithObjects:@"cdg",@"idx",@"srt",@"sub",@"utf",@"ass",@"ssa",@"aqt",@"jss",@"psb",@"rt",@"smi",@"txt",@"smil",nil]];
1008
1009     NSURL *o_url = [NSURL URLWithString:[[NSString stringWithUTF8String:path] stringByExpandingTildeInPath]];
1010     o_url = [o_url URLByDeletingLastPathComponent];
1011     [openPanel setDirectoryURL: o_url];
1012     free(path);
1013     vlc_object_release(p_input);
1014
1015     i_returnValue = [openPanel runModal];
1016
1017     if (i_returnValue == NSOKButton)
1018         [[VLCCoreInteraction sharedInstance] addSubtitlesToCurrentInput:[openPanel URLs]];
1019 }
1020
1021 - (IBAction)switchSubtitleOption:(id)sender
1022 {
1023     int intValue = [sender tag];
1024     NSString *representedObject = [sender representedObject];
1025
1026     config_PutInt(p_intf, [representedObject UTF8String], intValue);
1027
1028     NSMenu *menu = [sender menu];
1029     NSUInteger count = (NSUInteger) [menu numberOfItems];
1030     for (NSUInteger x = 0; x < count; x++)
1031         [[menu itemAtIndex:x] setState:NSOffState];
1032     [[menu itemWithTag:intValue] setState:NSOnState];
1033 }
1034
1035 - (IBAction)switchSubtitleBackgroundOpacity:(id)sender
1036 {
1037     config_PutInt(p_intf, "freetype-background-opacity", [sender intValue]);
1038 }
1039
1040 - (IBAction)telxTransparent:(id)sender
1041 {
1042     vlc_object_t *p_vbi;
1043     p_vbi = (vlc_object_t *) vlc_object_find_name(pl_Get(VLCIntf), "zvbi");
1044     if (p_vbi) {
1045         var_SetBool(p_vbi, "vbi-opaque", [sender state]);
1046         [sender setState: ![sender state]];
1047         vlc_object_release(p_vbi);
1048     }
1049 }
1050
1051 - (IBAction)telxNavLink:(id)sender
1052 {
1053     vlc_object_t *p_vbi;
1054     int i_page = 0;
1055
1056     if ([[sender title] isEqualToString: _NS("Index")])
1057         i_page = 'i' << 16;
1058     else if ([[sender title] isEqualToString: _NS("Red")])
1059         i_page = 'r' << 16;
1060     else if ([[sender title] isEqualToString: _NS("Green")])
1061         i_page = 'g' << 16;
1062     else if ([[sender title] isEqualToString: _NS("Yellow")])
1063         i_page = 'y' << 16;
1064     else if ([[sender title] isEqualToString: _NS("Blue")])
1065         i_page = 'b' << 16;
1066     if (i_page == 0) return;
1067
1068     p_vbi = (vlc_object_t *) vlc_object_find_name(pl_Get(VLCIntf), "zvbi");
1069     if (p_vbi) {
1070         var_SetInteger(p_vbi, "vbi-page", i_page);
1071         vlc_object_release(p_vbi);
1072     }
1073 }
1074
1075 #pragma mark - Panels
1076
1077 - (IBAction)intfOpenFile:(id)sender
1078 {
1079     [[[VLCMain sharedInstance] open] openFile];
1080 }
1081
1082 - (IBAction)intfOpenFileGeneric:(id)sender
1083 {
1084     [[[VLCMain sharedInstance] open] openFileGeneric];
1085 }
1086
1087 - (IBAction)intfOpenDisc:(id)sender
1088 {
1089     [[[VLCMain sharedInstance] open] openDisc];
1090 }
1091
1092 - (IBAction)intfOpenNet:(id)sender
1093 {
1094     [[[VLCMain sharedInstance] open] openNet];
1095 }
1096
1097 - (IBAction)intfOpenCapture:(id)sender
1098 {
1099     [[[VLCMain sharedInstance] open] openCapture];
1100 }
1101
1102 - (IBAction)showWizard:(id)sender
1103 {
1104     [[[VLCMain sharedInstance] wizard] resetWizard];
1105     [[[VLCMain sharedInstance] wizard] showWizard];
1106 }
1107
1108 - (IBAction)savePlaylist:(id)sender
1109 {
1110     [[[VLCMain sharedInstance] playlist] savePlaylist:sender];
1111 }
1112
1113 - (IBAction)revealItemInFinder:(id)sender
1114 {
1115     [[[VLCMain sharedInstance] playlist] revealItemInFinder:sender];
1116 }
1117
1118 - (IBAction)showConvertAndSave:(id)sender
1119 {
1120     if (o_convertandsave == nil)
1121         o_convertandsave = [[VLCConvertAndSave alloc] init];
1122
1123     if (!b_nib_convertandsave_loaded)
1124         b_nib_convertandsave_loaded = [NSBundle loadNibNamed:@"ConvertAndSave" owner: NSApp];
1125
1126     [o_convertandsave toggleWindow];
1127 }
1128
1129 - (IBAction)showVideoEffects:(id)sender
1130 {
1131     if (o_videoeffects == nil)
1132         o_videoeffects = [[VLCVideoEffects alloc] init];
1133
1134     if (!b_nib_videoeffects_loaded)
1135         b_nib_videoeffects_loaded = [NSBundle loadNibNamed:@"VideoEffects" owner: NSApp];
1136
1137     [o_videoeffects toggleWindow:sender];
1138 }
1139
1140 - (IBAction)showTrackSynchronization:(id)sender
1141 {
1142     if (!o_trackSynchronization)
1143         o_trackSynchronization = [[VLCTrackSynchronization alloc] init];
1144
1145     if (!b_nib_tracksynchro_loaded)
1146         b_nib_tracksynchro_loaded = [NSBundle loadNibNamed:@"SyncTracks" owner:NSApp];
1147
1148     [o_trackSynchronization toggleWindow:sender];
1149 }
1150
1151 - (IBAction)showAudioEffects:(id)sender
1152 {
1153     if (!o_audioeffects)
1154         o_audioeffects = [[VLCAudioEffects alloc] init];
1155
1156     if (!b_nib_audioeffects_loaded)
1157         b_nib_audioeffects_loaded = [NSBundle loadNibNamed:@"AudioEffects" owner:NSApp];
1158
1159     [o_audioeffects toggleWindow:sender];
1160 }
1161
1162 - (IBAction)showBookmarks:(id)sender
1163 {
1164     [[[VLCMain sharedInstance] bookmarks] showBookmarks];
1165 }
1166
1167 - (IBAction)viewPreferences:(id)sender
1168 {
1169     NSInteger i_level = [[[VLCMain sharedInstance] voutController] currentStatusWindowLevel];
1170     [[[VLCMain sharedInstance] simplePreferences] showSimplePrefsWithLevel:i_level];
1171 }
1172
1173 - (IBAction)openAddonManager:(id)sender
1174 {
1175     if (!o_addonManager)
1176         o_addonManager = [[VLCAddonManager alloc] init];
1177
1178     if (!b_nib_addonmanager_loaded)
1179         b_nib_addonmanager_loaded = [NSBundle loadNibNamed:@"AddonManager" owner:NSApp];
1180
1181     [o_addonManager showWindow];
1182 }
1183
1184 - (IBAction)showMessagesPanel:(id)showMessagesPanel
1185 {
1186     [[VLCDebugMessageVisualizer sharedInstance] showPanel];
1187 }
1188
1189 - (IBAction)showMainWindow:(id)sender
1190 {
1191     [[VLCMainWindow sharedInstance] makeKeyAndOrderFront:sender];
1192 }
1193
1194 - (IBAction)showPlaylist:(id)sender
1195 {
1196     [[VLCMainWindow sharedInstance] changePlaylistState: psUserMenuEvent];
1197 }
1198
1199 #pragma mark - Help and Docs
1200
1201 - (void)initAbout
1202 {
1203     if (! o_about)
1204         o_about = [[VLAboutBox alloc] init];
1205
1206     if (!b_nib_about_loaded)
1207         b_nib_about_loaded = [NSBundle loadNibNamed:@"About" owner: NSApp];
1208 }
1209
1210 - (IBAction)viewAbout:(id)sender
1211 {
1212     [self initAbout];
1213     [o_about showAbout];
1214 }
1215
1216 - (IBAction)showLicense:(id)sender
1217 {
1218     [self initAbout];
1219     [o_about showGPL];
1220 }
1221
1222 - (IBAction)viewHelp:(id)sender
1223 {
1224     [self initAbout];
1225     [o_about showHelp];
1226 }
1227
1228 - (IBAction)openReadMe:(id)sender
1229 {
1230     NSString * o_path = [[NSBundle mainBundle] pathForResource: @"README.MacOSX" ofType: @"rtf"];
1231
1232     [[NSWorkspace sharedWorkspace] openFile: o_path withApplication: @"TextEdit"];
1233 }
1234
1235 - (IBAction)openDocumentation:(id)sender
1236 {
1237     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/doc/"];
1238
1239     [[NSWorkspace sharedWorkspace] openURL: o_url];
1240 }
1241
1242 - (IBAction)openWebsite:(id)sender
1243 {
1244     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/"];
1245
1246     [[NSWorkspace sharedWorkspace] openURL: o_url];
1247 }
1248
1249 - (IBAction)openForum:(id)sender
1250 {
1251     NSURL * o_url = [NSURL URLWithString: @"http://forum.videolan.org/"];
1252
1253     [[NSWorkspace sharedWorkspace] openURL: o_url];
1254 }
1255
1256 - (IBAction)openDonate:(id)sender
1257 {
1258     NSURL * o_url = [NSURL URLWithString: @"http://www.videolan.org/contribute.html#paypal"];
1259
1260     [[NSWorkspace sharedWorkspace] openURL: o_url];
1261 }
1262
1263 #pragma mark - Errors, warnings and messages
1264
1265 - (IBAction)viewErrorsAndWarnings:(id)sender
1266 {
1267     [[[[VLCMain sharedInstance] coreDialogProvider] errorPanel] showPanel];
1268 }
1269
1270 - (IBAction)showInformationPanel:(id)sender
1271 {
1272     [[[VLCMain sharedInstance] info] initPanel];
1273 }
1274
1275 #pragma mark - convinience stuff for other objects
1276
1277 - (void)setPlay
1278 {
1279     [o_mi_play setTitle: _NS("Play")];
1280     [o_dmi_play setTitle: _NS("Play")];
1281     [o_vmi_play setTitle: _NS("Play")];
1282 }
1283
1284 - (void)setPause
1285 {
1286     [o_mi_play setTitle: _NS("Pause")];
1287     [o_dmi_play setTitle: _NS("Pause")];
1288     [o_vmi_play setTitle: _NS("Pause")];
1289 }
1290
1291 - (void)setRepeatOne
1292 {
1293     [o_mi_repeat setState: NSOnState];
1294     [o_mi_loop setState: NSOffState];
1295 }
1296
1297 - (void)setRepeatAll
1298 {
1299     [o_mi_repeat setState: NSOffState];
1300     [o_mi_loop setState: NSOnState];
1301 }
1302
1303 - (void)setRepeatOff
1304 {
1305     [o_mi_repeat setState: NSOffState];
1306     [o_mi_loop setState: NSOffState];
1307 }
1308
1309 - (void)setShuffle
1310 {
1311     bool b_value;
1312     playlist_t *p_playlist = pl_Get(VLCIntf);
1313     b_value = var_GetBool(p_playlist, "random");
1314
1315     [o_mi_random setState: b_value];
1316 }
1317
1318 #pragma mark - Dynamic menu creation and validation
1319
1320 - (void)setupVarMenuItem:(NSMenuItem *)o_mi
1321                   target:(vlc_object_t *)p_object
1322                      var:(const char *)psz_variable
1323                 selector:(SEL)pf_callback
1324 {
1325     vlc_value_t val, text;
1326     int i_type = var_Type(p_object, psz_variable);
1327
1328     switch(i_type & VLC_VAR_TYPE) {
1329         case VLC_VAR_VOID:
1330         case VLC_VAR_BOOL:
1331         case VLC_VAR_VARIABLE:
1332         case VLC_VAR_STRING:
1333         case VLC_VAR_INTEGER:
1334             break;
1335         default:
1336             /* Variable doesn't exist or isn't handled */
1337             msg_Warn(p_object, "variable %s doesn't exist or isn't handled", psz_variable);
1338             return;
1339     }
1340
1341     /* Get the descriptive name of the variable */
1342     var_Change(p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL);
1343     [o_mi setTitle: _NS(text.psz_string ? text.psz_string : psz_variable)];
1344
1345     if (i_type & VLC_VAR_HASCHOICE) {
1346         NSMenu *o_menu = [o_mi submenu];
1347
1348         [self setupVarMenu: o_menu forMenuItem: o_mi target:p_object
1349                        var:psz_variable selector:pf_callback];
1350
1351         free(text.psz_string);
1352         return;
1353     }
1354
1355     if (var_Get(p_object, psz_variable, &val) < 0)
1356         return;
1357
1358     VLCAutoGeneratedMenuContent *o_data;
1359     switch(i_type & VLC_VAR_TYPE) {
1360         case VLC_VAR_VOID:
1361             o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
1362                                                                       andValue: val ofType: i_type];
1363             [o_mi setRepresentedObject: [o_data autorelease]];
1364             break;
1365
1366         case VLC_VAR_BOOL:
1367             o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
1368                                                                       andValue: val ofType: i_type];
1369             [o_mi setRepresentedObject: [o_data autorelease]];
1370             if (!(i_type & VLC_VAR_ISCOMMAND))
1371                 [o_mi setState: val.b_bool ? TRUE : FALSE ];
1372             break;
1373
1374         default:
1375             break;
1376     }
1377
1378     if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) free(val.psz_string);
1379     free(text.psz_string);
1380 }
1381
1382
1383 - (void)setupVarMenu:(NSMenu *)o_menu
1384          forMenuItem: (NSMenuItem *)o_parent
1385               target:(vlc_object_t *)p_object
1386                  var:(const char *)psz_variable
1387             selector:(SEL)pf_callback
1388 {
1389     vlc_value_t val, val_list, text_list;
1390     int i_type, i;
1391
1392     /* remove previous items */
1393     [o_menu removeAllItems];
1394
1395     /* we disable everything here, and enable it again when needed, below */
1396     [o_parent setEnabled:NO];
1397
1398     /* Aspect Ratio */
1399     if ([[o_parent title] isEqualToString: _NS("Aspect ratio")] == YES) {
1400         NSMenuItem *o_lmi_tmp2;
1401         o_lmi_tmp2 = [o_menu addItemWithTitle: _NS("Lock Aspect Ratio") action: @selector(lockVideosAspectRatio:) keyEquivalent: @""];
1402         [o_lmi_tmp2 setTarget: [[VLCMain sharedInstance] controls]];
1403         [o_lmi_tmp2 setEnabled: YES];
1404         [o_lmi_tmp2 setState: [[VLCCoreInteraction sharedInstance] aspectRatioIsLocked]];
1405         [o_parent setEnabled: YES];
1406         [o_menu addItem: [NSMenuItem separatorItem]];
1407     }
1408
1409     /* Check the type of the object variable */
1410     i_type = var_Type(p_object, psz_variable);
1411
1412     /* Make sure we want to display the variable */
1413     if (i_type & VLC_VAR_HASCHOICE) {
1414         var_Change(p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL);
1415         if (val.i_int == 0)
1416             return;
1417         if ((i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1)
1418             return;
1419     }
1420     else
1421         return;
1422
1423     switch(i_type & VLC_VAR_TYPE) {
1424         case VLC_VAR_VOID:
1425         case VLC_VAR_BOOL:
1426         case VLC_VAR_VARIABLE:
1427         case VLC_VAR_STRING:
1428         case VLC_VAR_INTEGER:
1429             break;
1430         default:
1431             /* Variable doesn't exist or isn't handled */
1432             return;
1433     }
1434
1435     if (var_Get(p_object, psz_variable, &val) < 0) {
1436         return;
1437     }
1438
1439     if (var_Change(p_object, psz_variable, VLC_VAR_GETCHOICES,
1440                    &val_list, &text_list) < 0) {
1441         if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) free(val.psz_string);
1442         return;
1443     }
1444
1445     /* make (un)sensitive */
1446     [o_parent setEnabled: (val_list.p_list->i_count > 1)];
1447
1448     for (i = 0; i < val_list.p_list->i_count; i++) {
1449         NSMenuItem * o_lmi;
1450         NSString *o_title = @"";
1451         VLCAutoGeneratedMenuContent *o_data;
1452
1453         switch(i_type & VLC_VAR_TYPE) {
1454             case VLC_VAR_STRING:
1455
1456                 o_title = _NS(text_list.p_list->p_values[i].psz_string ? text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string);
1457
1458                 o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
1459                 o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
1460                                                                           andValue: val_list.p_list->p_values[i] ofType: i_type];
1461                 [o_lmi setRepresentedObject: [o_data autorelease]];
1462                 [o_lmi setTarget: self];
1463
1464                 if (!strcmp(val.psz_string, val_list.p_list->p_values[i].psz_string) && !(i_type & VLC_VAR_ISCOMMAND))
1465                     [o_lmi setState: TRUE ];
1466
1467                 break;
1468
1469             case VLC_VAR_INTEGER:
1470
1471                 o_title = text_list.p_list->p_values[i].psz_string ?
1472                 _NS(text_list.p_list->p_values[i].psz_string) : [NSString stringWithFormat: @"%"PRId64, val_list.p_list->p_values[i].i_int];
1473
1474                 o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
1475                 o_data = [[VLCAutoGeneratedMenuContent alloc] initWithVariableName: psz_variable ofObject: p_object
1476                                                                           andValue: val_list.p_list->p_values[i] ofType: i_type];
1477                 [o_lmi setRepresentedObject: [o_data autorelease]];
1478                 [o_lmi setTarget: self];
1479
1480                 if (val_list.p_list->p_values[i].i_int == val.i_int && !(i_type & VLC_VAR_ISCOMMAND))
1481                     [o_lmi setState: TRUE ];
1482                 break;
1483
1484             default:
1485                 break;
1486         }
1487     }
1488
1489     /* clean up everything */
1490     if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING) free(val.psz_string);
1491     var_FreeList(&val_list, &text_list);
1492 }
1493
1494 - (IBAction)toggleVar:(id)sender
1495 {
1496     NSMenuItem *o_mi = (NSMenuItem *)sender;
1497     VLCAutoGeneratedMenuContent *o_data = [o_mi representedObject];
1498     [NSThread detachNewThreadSelector: @selector(toggleVarThread:)
1499                              toTarget: self withObject: o_data];
1500
1501     return;
1502 }
1503
1504 - (int)toggleVarThread: (id)data
1505 {
1506     vlc_object_t *p_object;
1507     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
1508
1509     assert([data isKindOfClass:[VLCAutoGeneratedMenuContent class]]);
1510     VLCAutoGeneratedMenuContent *menuContent = (VLCAutoGeneratedMenuContent *)data;
1511
1512     p_object = [menuContent vlcObject];
1513
1514     if (p_object != NULL) {
1515         var_Set(p_object, [menuContent name], [menuContent value]);
1516         vlc_object_release(p_object);
1517         [o_pool release];
1518         return true;
1519     }
1520     [o_pool release];
1521     return VLC_EGENERIC;
1522 }
1523
1524 @end
1525
1526 @implementation VLCMainMenu (NSMenuValidation)
1527
1528 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
1529 {
1530     NSString *o_title = [o_mi title];
1531     BOOL bEnabled = TRUE;
1532     vlc_value_t val;
1533     playlist_t * p_playlist = pl_Get(p_intf);
1534     input_thread_t * p_input = playlist_CurrentInput(p_playlist);
1535
1536     if ([o_title isEqualToString: _NS("Stop")]) {
1537         if (!p_input)
1538             bEnabled = FALSE;
1539         [self setupMenus]; /* Make sure input menu is up to date */
1540     } else if ([o_title isEqualToString: _NS("Record")]) {
1541         bEnabled = FALSE;
1542         if (p_input)
1543             bEnabled = var_GetBool(p_input, "can-record");
1544     } else if ([o_title isEqualToString: _NS("Previous")] ||
1545             [o_title isEqualToString: _NS("Next")]) {
1546         PL_LOCK;
1547         bEnabled = playlist_CurrentSize(p_playlist) > 1;
1548         PL_UNLOCK;
1549     } else if ([o_title isEqualToString: _NS("Random")]) {
1550         int i_state;
1551         var_Get(p_playlist, "random", &val);
1552         i_state = val.b_bool ? NSOnState : NSOffState;
1553         [o_mi setState: i_state];
1554     } else if ([o_title isEqualToString: _NS("Repeat One")]) {
1555         int i_state;
1556         var_Get(p_playlist, "repeat", &val);
1557         i_state = val.b_bool ? NSOnState : NSOffState;
1558         [o_mi setState: i_state];
1559     } else if ([o_title isEqualToString: _NS("Repeat All")]) {
1560         int i_state;
1561         var_Get(p_playlist, "loop", &val);
1562         i_state = val.b_bool ? NSOnState : NSOffState;
1563         [o_mi setState: i_state];
1564     } else if ([o_title isEqualToString: _NS("Quit after Playback")]) {
1565         int i_state;
1566         bool b_value = var_InheritBool(p_playlist, "play-and-exit");
1567         i_state = b_value ? NSOnState : NSOffState;
1568         [o_mi setState: i_state];
1569     } else if ([o_title isEqualToString: _NS("Step Forward")] ||
1570                [o_title isEqualToString: _NS("Step Backward")] ||
1571                [o_title isEqualToString: _NS("Jump to Time")]) {
1572         if (p_input != NULL) {
1573             var_Get(p_input, "can-seek", &val);
1574             bEnabled = val.b_bool;
1575         }
1576         else bEnabled = FALSE;
1577     } else if ([o_title isEqualToString: _NS("Mute")]) {
1578         [o_mi setState: [[VLCCoreInteraction sharedInstance] mute] ? NSOnState : NSOffState];
1579         [self setupMenus]; /* Make sure audio menu is up to date */
1580         [self refreshAudioDeviceList];
1581     } else if ([o_title isEqualToString: _NS("Half Size")] ||
1582                [o_title isEqualToString: _NS("Normal Size")] ||
1583                [o_title isEqualToString: _NS("Double Size")] ||
1584                [o_title isEqualToString: _NS("Fit to Screen")] ||
1585                [o_title isEqualToString: _NS("Snapshot")] ||
1586                [o_title isEqualToString: _NS("Fullscreen")] ||
1587                [o_title isEqualToString: _NS("Float on Top")]) {
1588         bEnabled = FALSE;
1589
1590         if (p_input != NULL) {
1591             vout_thread_t *p_vout = getVoutForActiveWindow();
1592             if (p_vout != NULL) {
1593                 if ([o_title isEqualToString: _NS("Float on Top")])
1594                     [o_mi setState: var_GetBool(p_vout, "video-on-top")];
1595
1596                 if ([o_title isEqualToString: _NS("Fullscreen")])
1597                     [o_mi setState: var_GetBool(p_vout, "fullscreen")];
1598
1599                 bEnabled = TRUE;
1600                 vlc_object_release(p_vout);
1601             }
1602         }
1603
1604         [self setupMenus]; /* Make sure video menu is up to date */
1605
1606     } else if ([o_title isEqualToString: _NS("Add Subtitle File...")]) {
1607         bEnabled = [o_mi isEnabled];
1608         [self setupMenus]; /* Make sure subtitles menu is up to date */
1609     } else {
1610         NSMenuItem *o_mi_parent = [o_mi parentItem];
1611         if (o_mi_parent == o_mi_subtitle_size || o_mi == o_mi_subtitle_size ||
1612             o_mi_parent == o_mi_subtitle_textcolor || o_mi == o_mi_subtitle_textcolor ||
1613             o_mi_parent == o_mi_subtitle_bgcolor || o_mi == o_mi_subtitle_bgcolor ||
1614             o_mi_parent == o_mi_subtitle_bgopacity || o_mi == o_mi_subtitle_bgopacity ||
1615             o_mi_parent == o_mi_subtitle_outlinethickness || o_mi == o_mi_subtitle_outlinethickness ||
1616             o_mi_parent == o_mi_teletext || o_mi == o_mi_teletext)
1617             bEnabled = o_mi_openSubtitleFile.isEnabled;
1618     }
1619
1620     /* Special case for telx menu */
1621     if ([o_title isEqualToString: _NS("Normal Size")]) {
1622         NSMenuItem *item = [[o_mi menu] itemWithTitle:_NS("Teletext")];
1623         bool b_telx = p_input && var_GetInteger(p_input, "teletext-es") >= 0;
1624
1625         [[item submenu] setAutoenablesItems:NO];
1626
1627         for (int k=0; k < [[item submenu] numberOfItems]; k++)
1628             [[[item submenu] itemAtIndex:k] setEnabled: b_telx];
1629     }
1630
1631     if (p_input)
1632         vlc_object_release(p_input);
1633
1634     return bEnabled;
1635 }
1636
1637 @end
1638
1639
1640 /*****************************************************************************
1641  * VLCAutoGeneratedMenuContent implementation
1642  *****************************************************************************
1643  * Object connected to a playlistitem which remembers the data belonging to
1644  * the variable of the autogenerated menu
1645  *****************************************************************************/
1646 @implementation VLCAutoGeneratedMenuContent
1647
1648 -(id) initWithVariableName:(const char *)name ofObject:(vlc_object_t *)object
1649                   andValue:(vlc_value_t)val ofType:(int)type
1650 {
1651     self = [super init];
1652
1653     if (self != nil) {
1654         _vlc_object = vlc_object_hold(object);
1655         psz_name = strdup(name);
1656         i_type = type;
1657         value = val;
1658         if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
1659             value.psz_string = strdup(val.psz_string);
1660     }
1661
1662     return(self);
1663 }
1664
1665 - (void)dealloc
1666 {
1667     if (_vlc_object)
1668         vlc_object_release(_vlc_object);
1669     if ((i_type & VLC_VAR_TYPE) == VLC_VAR_STRING)
1670         free(value.psz_string);
1671     free(psz_name);
1672     [super dealloc];
1673 }
1674
1675 - (const char *)name
1676 {
1677     return psz_name;
1678 }
1679
1680 - (vlc_value_t)value
1681 {
1682     return value;
1683 }
1684
1685 - (vlc_object_t *)vlcObject
1686 {
1687     return vlc_object_hold(_vlc_object);
1688 }
1689
1690
1691 - (int)type
1692 {
1693     return i_type;
1694 }
1695
1696 @end