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