]> git.sesse.net Git - vlc/blob - modules/gui/macosx/controls.m
Update the info displayed in the playlist when you change the play mode in the menu...
[vlc] / modules / gui / macosx / controls.m
1 /*****************************************************************************
2  * controls.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2002-2005 VideoLAN
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *          Derk-Jan Hartman <hartman at videolan dot org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>                                      /* malloc(), free() */
30 #include <sys/param.h>                                    /* for MAXPATHLEN */
31 #include <string.h>
32
33 #include "intf.h"
34 #include "vout.h"
35 #include "open.h"
36 #include "controls.h"
37 #include <osd.h>
38
39 /*****************************************************************************
40  * VLCControls implementation 
41  *****************************************************************************/
42 @implementation VLCControls
43
44 - (IBAction)play:(id)sender
45 {
46     vlc_value_t val;
47     intf_thread_t * p_intf = VLCIntf;
48     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
49                                         FIND_ANYWHERE );
50     if( p_playlist )
51     {
52         vlc_mutex_lock( &p_playlist->object_lock );
53         if( p_playlist->i_size <= 0 )
54         {
55             vlc_mutex_unlock( &p_playlist->object_lock );
56             vlc_object_release( p_playlist );
57             [o_main intfOpenFileGeneric: (id)sender];
58         }
59         else
60         {
61             vlc_mutex_unlock( &p_playlist->object_lock );
62             vlc_object_release( p_playlist );
63         }
64
65     }
66     val.i_int = config_GetInt( p_intf, "key-play-pause" );
67     var_Set( p_intf->p_vlc, "key-pressed", val );
68 }
69
70 - (IBAction)stop:(id)sender
71 {
72     vlc_value_t val;
73     intf_thread_t * p_intf = VLCIntf;
74     val.i_int = config_GetInt( p_intf, "key-stop" );
75     var_Set( p_intf->p_vlc, "key-pressed", val );
76 }
77
78 - (IBAction)faster:(id)sender
79 {
80     vlc_value_t val;
81     intf_thread_t * p_intf = VLCIntf;
82     val.i_int = config_GetInt( p_intf, "key-faster" );
83     var_Set( p_intf->p_vlc, "key-pressed", val );
84 }
85
86 - (IBAction)slower:(id)sender
87 {
88     vlc_value_t val;
89     intf_thread_t * p_intf = VLCIntf;
90     val.i_int = config_GetInt( p_intf, "key-slower" );
91     var_Set( p_intf->p_vlc, "key-pressed", val );
92 }
93
94 - (IBAction)prev:(id)sender
95 {
96     vlc_value_t val;
97     intf_thread_t * p_intf = VLCIntf;
98     val.i_int = config_GetInt( p_intf, "key-prev" );
99     var_Set( p_intf->p_vlc, "key-pressed", val );
100 }
101
102 - (IBAction)next:(id)sender
103 {
104     vlc_value_t val;
105     intf_thread_t * p_intf = VLCIntf;
106     val.i_int = config_GetInt( p_intf, "key-next" );
107     var_Set( p_intf->p_vlc, "key-pressed", val );
108 }
109
110 - (IBAction)random:(id)sender
111 {
112     vlc_value_t val;
113     intf_thread_t * p_intf = VLCIntf;
114     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
115                                                        FIND_ANYWHERE );
116     if( p_playlist == NULL )
117     {
118         return;
119     }
120
121     var_Get( p_playlist, "random", &val );
122     val.b_bool = !val.b_bool;
123     var_Set( p_playlist, "random", val );
124     if( val.b_bool )
125     {
126         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Random On" ) );
127     }
128     else
129     {
130         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Random Off" ) );
131     }
132
133     p_intf->p_sys->b_playmode_update = VLC_TRUE;
134     p_intf->p_sys->b_intf_update = VLC_TRUE;
135     vlc_object_release( p_playlist );
136 }
137
138 - (IBAction)repeat:(id)sender
139 {
140     vlc_value_t val;
141     intf_thread_t * p_intf = VLCIntf;
142     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
143                                                        FIND_ANYWHERE );
144     if( p_playlist == NULL )
145     {
146         return;
147     }
148
149     var_Get( p_playlist, "repeat", &val );
150     if (!val.b_bool)
151     {
152         var_Set( p_playlist, "loop", val );
153     }
154     val.b_bool = !val.b_bool;
155     var_Set( p_playlist, "repeat", val );
156     if( val.b_bool )
157     {
158         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat All" ) );
159     }
160     else
161     {
162         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat Off" ) );
163     }
164
165     p_intf->p_sys->b_playmode_update = VLC_TRUE;
166     p_intf->p_sys->b_intf_update = VLC_TRUE;
167     vlc_object_release( p_playlist );
168 }
169
170 - (IBAction)loop:(id)sender
171 {
172     vlc_value_t val;
173     intf_thread_t * p_intf = VLCIntf;
174     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
175                                                        FIND_ANYWHERE );
176     if( p_playlist == NULL )
177     {
178         return;
179     }
180
181     var_Get( p_playlist, "loop", &val );
182     if (!val.b_bool)
183     {
184         var_Set( p_playlist, "repeat", val );
185     }
186     val.b_bool = !val.b_bool;
187     var_Set( p_playlist, "loop", val );
188     if( val.b_bool )
189     {
190         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat One" ) );
191     }
192     else
193     {
194         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat Off" ) );
195     }
196
197     p_intf->p_sys->b_playmode_update = VLC_TRUE;
198     p_intf->p_sys->b_intf_update = VLC_TRUE;
199     vlc_object_release( p_playlist );
200 }
201
202 - (IBAction)forward:(id)sender
203 {
204     vlc_value_t val;
205     intf_thread_t * p_intf = VLCIntf;
206     val.i_int = config_GetInt( p_intf, "key-jump+10sec" );
207     var_Set( p_intf->p_vlc, "key-pressed", val );
208 }
209
210 - (IBAction)backward:(id)sender
211 {
212     vlc_value_t val;
213     intf_thread_t * p_intf = VLCIntf;
214     val.i_int = config_GetInt( p_intf, "key-jump-10sec" );
215     var_Set( p_intf->p_vlc, "key-pressed", val );
216 }
217
218
219 - (IBAction)volumeUp:(id)sender
220 {
221     vlc_value_t val;
222     intf_thread_t * p_intf = VLCIntf;
223     val.i_int = config_GetInt( p_intf, "key-vol-up" );
224     var_Set( p_intf->p_vlc, "key-pressed", val );
225     [self updateVolumeSlider];
226 }
227
228 - (IBAction)volumeDown:(id)sender
229 {
230     vlc_value_t val;
231     intf_thread_t * p_intf = VLCIntf;
232     val.i_int = config_GetInt( p_intf, "key-vol-down" );
233     var_Set( p_intf->p_vlc, "key-pressed", val );
234     [self updateVolumeSlider];
235 }
236
237 - (IBAction)mute:(id)sender
238 {
239     vlc_value_t val;
240     intf_thread_t * p_intf = VLCIntf;
241     val.i_int = config_GetInt( p_intf, "key-vol-mute" );
242     var_Set( p_intf->p_vlc, "key-pressed", val );
243     [self updateVolumeSlider];
244 }
245
246 - (IBAction)volumeSliderUpdated:(id)sender
247 {
248     intf_thread_t * p_intf = VLCIntf;
249     audio_volume_t i_volume = (audio_volume_t)[sender intValue];
250     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_STEP );
251     [self updateVolumeSlider];
252 }
253
254 - (void)updateVolumeSlider
255 {
256     NSString * o_text;
257     intf_thread_t * p_intf = VLCIntf;
258     audio_volume_t i_volume;
259
260     aout_VolumeGet( p_intf, &i_volume );
261
262     o_text = [NSString stringWithFormat: @"Volume: %d", i_volume * 200 / AOUT_VOLUME_MAX];
263     [o_main setScrollField:o_text stopAfter:1000000];
264     
265     [o_volumeslider setFloatValue: (float)(i_volume / AOUT_VOLUME_STEP)];
266 }
267
268 - (IBAction)windowAction:(id)sender
269 {
270     id o_window = [NSApp keyWindow];
271     NSString *o_title = [sender title];
272     NSArray *o_windows = [NSApp orderedWindows];
273     NSEnumerator *o_enumerator = [o_windows objectEnumerator];
274     vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
275                                               FIND_ANYWHERE );
276
277     if( p_vout != NULL )
278     {
279         while ((o_window = [o_enumerator nextObject]))
280         {
281             if( [[o_window className] isEqualToString: @"VLCWindow"] )
282             {
283                 if( [o_title isEqualToString: _NS("Half Size") ] )
284                     [o_window scaleWindowWithFactor: 0.5];
285                 else if( [o_title isEqualToString: _NS("Normal Size") ] )
286                     [o_window scaleWindowWithFactor: 1.0];
287                 else if( [o_title isEqualToString: _NS("Double Size") ] )
288                     [o_window scaleWindowWithFactor: 2.0];
289                 else if( [o_title isEqualToString: _NS("Float on Top") ] )
290                     [o_window toggleFloatOnTop];
291                 else if( [o_title isEqualToString: _NS("Fit to Screen") ] )
292                 {
293                     if( ![o_window isZoomed] )
294                         [o_window performZoom:self];
295                 }
296                 else if( [o_title isEqualToString: _NS("Snapshot") ] )
297                 {
298                     [o_window snapshot];
299                 }
300                 else
301                 {
302                     [o_window toggleFullscreen];
303                 }
304                 break;
305             }
306         }
307         vlc_object_release( (vlc_object_t *)p_vout );
308     }
309     else
310     {
311         playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST,
312                                               FIND_ANYWHERE );
313
314         if( p_playlist && ( [o_title isEqualToString: _NS("Fullscreen")] ||
315             [sender isKindOfClass:[NSButton class]] ) )
316         {
317             vlc_value_t val;
318             var_Get( p_playlist, "fullscreen", &val );
319             var_Set( p_playlist, "fullscreen", (vlc_value_t)!val.b_bool );
320         }
321         if( p_playlist ) vlc_object_release( (vlc_object_t *)p_playlist );
322     }
323
324 }
325
326 - (void)setupVarMenuItem:(NSMenuItem *)o_mi
327                     target:(vlc_object_t *)p_object
328                     var:(const char *)psz_variable
329                     selector:(SEL)pf_callback
330 {
331     vlc_value_t val, text;
332     int i_type = var_Type( p_object, psz_variable );
333
334     switch( i_type & VLC_VAR_TYPE )
335     {
336     case VLC_VAR_VOID:
337     case VLC_VAR_BOOL:
338     case VLC_VAR_VARIABLE:
339     case VLC_VAR_STRING:
340     case VLC_VAR_INTEGER:
341         break;
342     default:
343         /* Variable doesn't exist or isn't handled */
344         return;
345     }
346     
347     /* Make sure we want to display the variable */
348     if( i_type & VLC_VAR_HASCHOICE )
349     {
350         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
351         if( val.i_int == 0 ) return;
352         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
353             return;
354     }
355     
356     /* Get the descriptive name of the variable */
357     var_Change( p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL );
358     [o_mi setTitle: [[VLCMain sharedInstance] localizedString: text.psz_string ?
359                                         text.psz_string : strdup( psz_variable ) ]];
360
361     var_Get( p_object, psz_variable, &val );
362     if( i_type & VLC_VAR_HASCHOICE )
363     {
364         NSMenu *o_menu = [o_mi submenu];
365
366         [self setupVarMenu: o_menu forMenuItem: o_mi target:p_object
367                         var:psz_variable selector:pf_callback];
368         
369         if( text.psz_string ) free( text.psz_string );
370         return;
371     }
372
373     VLCMenuExt *o_data;
374     switch( i_type & VLC_VAR_TYPE )
375     {
376     case VLC_VAR_VOID:
377         o_data = [[VLCMenuExt alloc] initWithVar: psz_variable Object: p_object->i_object_id
378                 Value: val ofType: i_type];
379         [o_mi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
380         break;
381
382     case VLC_VAR_BOOL:
383         o_data = [[VLCMenuExt alloc] initWithVar: psz_variable Object: p_object->i_object_id
384                 Value: val ofType: i_type];
385         [o_mi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
386         if( !( i_type & VLC_VAR_ISCOMMAND ) )
387             [o_mi setState: val.b_bool ? TRUE : FALSE ];
388         break;
389
390     default:
391         if( text.psz_string ) free( text.psz_string );
392         return;
393     }
394
395     if( ( i_type & VLC_VAR_TYPE ) == VLC_VAR_STRING ) free( val.psz_string );
396     if( text.psz_string ) free( text.psz_string );
397 }
398
399
400 - (void)setupVarMenu:(NSMenu *)o_menu
401                     forMenuItem: (NSMenuItem *)o_parent
402                     target:(vlc_object_t *)p_object
403                     var:(const char *)psz_variable
404                     selector:(SEL)pf_callback
405 {
406     vlc_value_t val, val_list, text_list;
407     int i_type, i, i_nb_items;
408
409     /* remove previous items */
410     i_nb_items = [o_menu numberOfItems];
411     for( i = 0; i < i_nb_items; i++ )
412     {
413         [o_menu removeItemAtIndex: 0];
414     }
415
416     /* Check the type of the object variable */
417     i_type = var_Type( p_object, psz_variable );
418
419     /* Make sure we want to display the variable */
420     if( i_type & VLC_VAR_HASCHOICE )
421     {
422         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
423         if( val.i_int == 0 ) return;
424         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
425             return;
426     }
427     else
428     {
429         return;
430     }
431
432     switch( i_type & VLC_VAR_TYPE )
433     {
434     case VLC_VAR_VOID:
435     case VLC_VAR_BOOL:
436     case VLC_VAR_VARIABLE:
437     case VLC_VAR_STRING:
438     case VLC_VAR_INTEGER:
439         break;
440     default:
441         /* Variable doesn't exist or isn't handled */
442         return;
443     }
444
445     if( var_Get( p_object, psz_variable, &val ) < 0 )
446     {
447         return;
448     }
449
450     if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST,
451                     &val_list, &text_list ) < 0 )
452     {
453         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
454         return;
455     }
456
457     /* make (un)sensitive */
458     [o_parent setEnabled: ( val_list.p_list->i_count > 1 )];
459
460     for( i = 0; i < val_list.p_list->i_count; i++ )
461     {
462         vlc_value_t another_val;
463         NSMenuItem * o_lmi;
464         NSString *o_title = @"";
465         VLCMenuExt *o_data;
466
467         switch( i_type & VLC_VAR_TYPE )
468         {
469         case VLC_VAR_STRING:
470             another_val.psz_string =
471                 strdup(val_list.p_list->p_values[i].psz_string);
472
473             o_title = [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string ?
474                 text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string ];
475
476             o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
477             o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
478                     Value: another_val ofType: i_type];
479             [o_lmi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
480             [o_lmi setTarget: self];
481             
482             if( !strcmp( val.psz_string, val_list.p_list->p_values[i].psz_string ) && !( i_type & VLC_VAR_ISCOMMAND ) )
483                 [o_lmi setState: TRUE ];
484
485             break;
486
487         case VLC_VAR_INTEGER:
488
489              o_title = text_list.p_list->p_values[i].psz_string ?
490                                  [[VLCMain sharedInstance] localizedString: strdup( text_list.p_list->p_values[i].psz_string )] :
491                                  [NSString stringWithFormat: @"%d",
492                                  val_list.p_list->p_values[i].i_int];
493
494             o_lmi = [[o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""] retain ];
495             o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
496                     Value: val_list.p_list->p_values[i] ofType: i_type];
497             [o_lmi setRepresentedObject: [NSValue valueWithPointer:[ o_data retain]]];
498             [o_lmi setTarget: self];
499
500             if( val_list.p_list->p_values[i].i_int == val.i_int && !( i_type & VLC_VAR_ISCOMMAND ) )
501                 [o_lmi setState: TRUE ];
502             break;
503
504         default:
505           break;
506         }
507     }
508     
509     /* clean up everything */
510     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
511     var_Change( p_object, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list );
512 }
513
514 - (IBAction)toggleVar:(id)sender
515 {
516     NSMenuItem *o_mi = (NSMenuItem *)sender;
517     VLCMenuExt *o_data = [[o_mi representedObject] pointerValue];
518     [NSThread detachNewThreadSelector: @selector(toggleVarThread:)
519         toTarget: self withObject: o_data];
520
521     return;
522 }
523
524 - (int)toggleVarThread: (id)_o_data
525 {
526     vlc_object_t *p_object;
527     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
528     VLCMenuExt *o_data = (VLCMenuExt *)_o_data;
529
530     vlc_thread_set_priority( VLCIntf , VLC_THREAD_PRIORITY_LOW );
531
532     p_object = (vlc_object_t *)vlc_object_get( VLCIntf,
533                                     [o_data objectID] );
534
535     if( p_object != NULL )
536     {
537         var_Set( p_object, strdup([o_data name]), [o_data value] );
538         vlc_object_release( p_object );
539         [o_pool release];
540         return VLC_TRUE;
541     }
542     [o_pool release];
543     return VLC_EGENERIC;
544 }
545
546 @end
547
548 @implementation VLCControls (NSMenuValidation)
549  
550 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
551 {
552     BOOL bEnabled = TRUE;
553     vlc_value_t val;
554     intf_thread_t * p_intf = VLCIntf;
555     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
556                                                        FIND_ANYWHERE );
557
558     if( p_playlist != NULL )
559     {
560         vlc_mutex_lock( &p_playlist->object_lock );
561     }
562     else return FALSE;
563
564 #define p_input p_playlist->p_input
565
566     if( [[o_mi title] isEqualToString: _NS("Faster")] ||
567         [[o_mi title] isEqualToString: _NS("Slower")] )
568     {
569         if( p_input != NULL )
570         {
571             bEnabled = p_input->input.b_can_pace_control;
572         }
573         else
574         {
575             bEnabled = FALSE;
576         }
577     }
578     else if( [[o_mi title] isEqualToString: _NS("Stop")] )
579     {
580         if( p_input == NULL )
581         {
582             bEnabled = FALSE;
583         }
584                 [o_main setupMenus]; /* Make sure input menu is up to date */
585     }
586     else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
587              [[o_mi title] isEqualToString: _NS("Next")] )
588     {
589             bEnabled = p_playlist->i_size > 1;
590     }
591     else if( [[o_mi title] isEqualToString: _NS("Random")] )
592     {
593         int i_state;
594         var_Get( p_playlist, "random", &val );
595         i_state = val.b_bool ? NSOnState : NSOffState;
596         [o_mi setState: i_state];
597     }
598     else if( [[o_mi title] isEqualToString: _NS("Repeat One")] )
599     {
600         int i_state;
601         var_Get( p_playlist, "repeat", &val );
602         i_state = val.b_bool ? NSOnState : NSOffState;
603         [o_mi setState: i_state];
604     }
605     else if( [[o_mi title] isEqualToString: _NS("Repeat All")] )
606     {
607         int i_state;
608         var_Get( p_playlist, "loop", &val );
609         i_state = val.b_bool ? NSOnState : NSOffState;
610         [o_mi setState: i_state];
611     }
612     else if( [[o_mi title] isEqualToString: _NS("Step Forward")] ||
613              [[o_mi title] isEqualToString: _NS("Step Backward")] )
614     {
615         if( p_input != NULL )
616         {
617             var_Get( p_input, "seekable", &val);
618             bEnabled = val.b_bool;
619         }
620     }
621     else if( [[o_mi title] isEqualToString: _NS("Mute")] ) 
622     {
623         [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
624                 [o_main setupMenus]; /* Make sure audio menu is up to date */
625     }
626     else if( [[o_mi title] isEqualToString: _NS("Half Size")] ||
627                 [[o_mi title] isEqualToString: _NS("Normal Size")] ||
628                 [[o_mi title] isEqualToString: _NS("Double Size")] ||
629                 [[o_mi title] isEqualToString: _NS("Fit to Screen")] ||
630                 [[o_mi title] isEqualToString: _NS("Snapshot")] ||
631                 [[o_mi title] isEqualToString: _NS("Fullscreen")] ||
632                 [[o_mi title] isEqualToString: _NS("Float on Top")] )
633     {
634         id o_window;
635         NSArray *o_windows = [NSApp orderedWindows];
636         NSEnumerator *o_enumerator = [o_windows objectEnumerator];
637         bEnabled = FALSE;
638         
639         vout_thread_t   *p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
640                                               FIND_ANYWHERE );
641         if( p_vout != NULL )
642         {
643             if( [[o_mi title] isEqualToString: _NS("Float on Top")] )
644             {
645                 var_Get( p_vout, "video-on-top", &val );
646                 [o_mi setState: val.b_bool ?  NSOnState : NSOffState];
647             }
648
649             while( (o_window = [o_enumerator nextObject]))
650             {
651                 if( [[o_window className] isEqualToString: @"VLCWindow"] )
652                 {
653                     bEnabled = TRUE;
654                     break;
655                 }
656             }
657             vlc_object_release( (vlc_object_t *)p_vout );
658         }
659         else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )
660         {
661             var_Get( p_playlist, "fullscreen", &val );
662             [o_mi setState: val.b_bool];
663             bEnabled = TRUE;
664         }
665                 [o_main setupMenus]; /* Make sure video menu is up to date */
666     }
667
668     vlc_mutex_unlock( &p_playlist->object_lock );
669     vlc_object_release( p_playlist );
670
671     return( bEnabled );
672 }
673
674 @end
675
676 /*****************************************************************************
677  * VLCMenuExt implementation 
678  *****************************************************************************
679  * Object connected to a playlistitem which remembers the data belonging to
680  * the variable of the autogenerated menu
681  *****************************************************************************/
682 @implementation VLCMenuExt
683
684 - (id)initWithVar: (const char *)_psz_name Object: (int)i_id
685         Value: (vlc_value_t)val ofType: (int)_i_type
686 {
687     self = [super init];
688
689     if( self != nil )
690     {
691         psz_name = strdup( _psz_name );
692         i_object_id = i_id;
693         value = val;
694         i_type = _i_type;
695     }
696
697     return( self );
698 }
699
700 - (void)dealloc
701 {
702     free( psz_name );
703 }
704
705 - (char *)name
706 {
707     return psz_name;
708 }
709
710 - (int)objectID
711 {
712     return i_object_id;
713 }
714
715 - (vlc_value_t)value
716 {
717     return value;
718 }
719
720 - (int)type
721 {
722     return i_type;
723 }
724
725 @end