]> git.sesse.net Git - vlc/blob - modules/gui/macosx/controls.m
* Fix the state of the playlist and fullscreen button.
[vlc] / modules / gui / macosx / controls.m
1 /*****************************************************************************
2  * controls.m: MacOS X interface plugin
3  *****************************************************************************
4  * Copyright (C) 2002-2003 VideoLAN
5  * $Id: controls.m,v 1.58 2003/12/11 19:34:47 hartman Exp $
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *          Derk-Jan Hartman <thedj@users.sourceforge.net>
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     playlist_t * p_playlist;
48     intf_thread_t * p_intf = [NSApp getIntf];
49     input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
50                                                        FIND_ANYWHERE );
51
52     val.i_int = PLAYING_S;
53     if( p_input )
54     {
55         var_Get( p_input, "state", &val );
56     }
57     if( p_input && val.i_int != PAUSE_S )
58     {
59         vout_OSDMessage( VLC_OBJECT(p_intf), _( "Pause" ) );
60         val.i_int = PAUSE_S;
61         var_Set( p_input, "state", val );
62     }
63     else
64     {
65         p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
66                                         FIND_ANYWHERE );
67         if( p_playlist )
68         {
69             vlc_mutex_lock( &p_playlist->object_lock );
70             if( p_playlist->i_size )
71             {
72                 vlc_mutex_unlock( &p_playlist->object_lock );
73                 vout_OSDMessage( VLC_OBJECT(p_intf), _( "Play" ) );
74                 playlist_Play( p_playlist );
75                 vlc_object_release( p_playlist );
76             }
77             else
78             {
79                 vlc_mutex_unlock( &p_playlist->object_lock );
80                 vlc_object_release( p_playlist );
81                 [o_open openFileGeneric: nil];
82             }
83         }
84     }
85     if( p_input ) vlc_object_release( p_input );
86 }
87
88 - (IBAction)stop:(id)sender
89 {
90     intf_thread_t * p_intf = [NSApp getIntf];
91     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
92                                                        FIND_ANYWHERE );
93     if( p_playlist != NULL )
94     {
95         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Stop" ) );
96         playlist_Stop( p_playlist );
97         vlc_object_release( p_playlist );
98     }
99 }
100
101 - (IBAction)faster:(id)sender
102 {
103     intf_thread_t * p_intf = [NSApp getIntf];
104     input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
105                                                        FIND_ANYWHERE );
106     if( p_input != NULL )
107     {
108         vlc_value_t val; val.b_bool = VLC_TRUE;
109
110         var_Set( p_input, "rate-faster", val );
111         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Faster" ) );
112         vlc_object_release( p_input );
113     }
114 }
115
116 - (IBAction)slower:(id)sender
117 {
118     intf_thread_t * p_intf = [NSApp getIntf];
119     input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
120                                                        FIND_ANYWHERE );
121     if( p_input != NULL )
122     {
123         vlc_value_t val; val.b_bool = VLC_TRUE;
124
125         var_Set( p_input, "rate-slower", val );
126         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Slower" ) );
127         vlc_object_release( p_input );
128     }
129 }
130
131 - (IBAction)prev:(id)sender
132 {
133     intf_thread_t * p_intf = [NSApp getIntf];
134     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
135                                                        FIND_ANYWHERE );
136     if( p_playlist )
137     {
138         playlist_Prev( p_playlist );
139         vlc_object_release( p_playlist );
140         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Previous" ) );
141     }
142 }
143
144 - (IBAction)next:(id)sender
145 {
146     intf_thread_t * p_intf = [NSApp getIntf];
147     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
148                                                        FIND_ANYWHERE );
149     if( p_playlist )
150     {
151         playlist_Next( p_playlist );
152         vlc_object_release( p_playlist );
153         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Next" ) );
154     }
155 }
156
157 - (IBAction)random:(id)sender
158 {
159     intf_thread_t * p_intf = [NSApp getIntf];
160     vlc_value_t val;
161     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
162                                                        FIND_ANYWHERE );
163     if( p_playlist == NULL )
164     {
165         return;
166     }
167
168     var_Get( p_playlist, "random", &val );
169     val.b_bool = !val.b_bool;
170     var_Set( p_playlist, "random", val );
171     if( val.b_bool )
172     {
173         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Shuffle On" ) );
174     }
175     else
176     {
177         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Shuffle Off" ) );
178     }    
179
180     p_intf->p_sys->b_playlist_update = VLC_TRUE;
181     p_intf->p_sys->b_intf_update = VLC_TRUE;
182     vlc_object_release( p_playlist );
183 }
184
185 - (IBAction)repeat:(id)sender
186 {
187     intf_thread_t * p_intf = [NSApp getIntf];
188     vlc_value_t val;
189     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
190                                                        FIND_ANYWHERE );
191     if( p_playlist == NULL )
192     {
193         return;
194     }
195
196     var_Get( p_playlist, "repeat", &val );
197     val.b_bool = !val.b_bool;
198     var_Set( p_playlist, "repeat", val );
199     if( val.b_bool )
200     {
201         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Repeat On" ) );
202     }
203     else
204     {
205         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Repeat Off" ) );
206     }
207
208     p_intf->p_sys->b_playlist_update = VLC_TRUE;    
209     p_intf->p_sys->b_intf_update = VLC_TRUE;
210     vlc_object_release( p_playlist );
211 }
212
213 - (IBAction)loop:(id)sender
214 {
215     intf_thread_t * p_intf = [NSApp getIntf];
216     vlc_value_t val;
217     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
218                                                        FIND_ANYWHERE );
219     if( p_playlist == NULL )
220     {
221         return;
222     }
223
224     var_Get( p_playlist, "loop", &val );
225     val.b_bool = !val.b_bool;
226     var_Set( p_playlist, "loop", val );
227     if( val.b_bool )
228     {
229         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Loop On" ) );
230     }
231     else
232     {
233         vout_OSDMessage( (vlc_object_t *)p_intf, _( "Loop Off" ) );
234     }    
235
236     p_intf->p_sys->b_playlist_update = VLC_TRUE;
237     p_intf->p_sys->b_intf_update = VLC_TRUE;
238     vlc_object_release( p_playlist );
239 }
240
241 - (IBAction)forward:(id)sender
242 {
243     intf_thread_t * p_intf = [NSApp getIntf];
244     input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
245                                                        FIND_ANYWHERE );
246     if( p_input != NULL )
247     {
248         vlc_value_t time;
249         time.i_time = 10 * 1000000;
250         var_Set( p_input, "time-offset", time );
251         vlc_object_release( p_input );
252     }
253 }
254
255 - (IBAction)backward:(id)sender
256 {
257     intf_thread_t * p_intf = [NSApp getIntf];
258     input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
259                                                        FIND_ANYWHERE );
260     if( p_input != NULL )
261     {
262         vlc_value_t time;
263         time.i_time = -10 * 1000000;
264         var_Set( p_input, "time-offset", time );
265         vlc_object_release( p_input );
266     }
267 }
268
269 - (IBAction)volumeUp:(id)sender
270 {
271     intf_thread_t * p_intf = [NSApp getIntf];
272
273     if( p_intf->p_sys->b_mute )
274     {
275         [self mute: nil];
276     }
277
278     aout_VolumeUp( p_intf, 1, NULL );
279
280     [self updateVolumeSlider];
281 }
282
283 - (IBAction)volumeDown:(id)sender
284 {
285     intf_thread_t * p_intf = [NSApp getIntf];
286
287     if( p_intf->p_sys->b_mute )
288     {
289         [self mute: nil];
290     }
291     
292     aout_VolumeDown( p_intf, 1, NULL );
293
294     [self updateVolumeSlider];
295 }
296
297 - (IBAction)mute:(id)sender
298 {
299     intf_thread_t * p_intf = [NSApp getIntf];
300     audio_volume_t i_volume;
301
302     aout_VolumeMute( p_intf, &i_volume );
303     p_intf->p_sys->b_mute = ( i_volume == 0 );
304
305     [self updateVolumeSlider];
306 }
307
308 - (IBAction)volumeSliderUpdated:(id)sender
309 {
310     intf_thread_t * p_intf = [NSApp getIntf];
311     audio_volume_t i_volume = (audio_volume_t)[sender intValue];
312
313     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_STEP );
314 }
315
316 - (void)updateVolumeSlider
317 {
318     intf_thread_t * p_intf = [NSApp getIntf];
319     audio_volume_t i_volume;
320     char string[9];
321
322     aout_VolumeGet( p_intf, &i_volume );
323
324     [o_volumeslider setFloatValue: (float)(i_volume / AOUT_VOLUME_STEP)];
325
326     sprintf( string, "Vol %d%%", i_volume*100/AOUT_VOLUME_MAX );
327     vout_OSDMessage( (vlc_object_t *)p_intf, string );
328 }
329
330 - (IBAction)windowAction:(id)sender
331 {
332     id o_window = [NSApp keyWindow];
333     NSString *o_title = [sender title];
334     NSArray *o_windows = [NSApp orderedWindows];
335     NSEnumerator *o_enumerator = [o_windows objectEnumerator];
336     vout_thread_t   *p_vout = vlc_object_find( [NSApp getIntf], VLC_OBJECT_VOUT,
337                                               FIND_ANYWHERE );
338
339     if( p_vout != NULL )
340     {
341         while ((o_window = [o_enumerator nextObject]))
342         {
343             if( [[o_window className] isEqualToString: @"VLCWindow"] )
344             {
345                 if( [o_title isEqualToString: _NS("Half Size") ] )
346                     [o_window scaleWindowWithFactor: 0.5];
347                 else if( [o_title isEqualToString: _NS("Normal Size") ] )
348                     [o_window scaleWindowWithFactor: 1.0];
349                 else if( [o_title isEqualToString: _NS("Double Size") ] )
350                     [o_window scaleWindowWithFactor: 2.0];
351                 else if( [o_title isEqualToString: _NS("Float On Top") ] )
352                     [o_window toggleFloatOnTop];
353                 else if( [o_title isEqualToString: _NS("Fit To Screen") ] )
354                 {
355                     if( ![o_window isZoomed] )
356                         [o_window performZoom:self];
357                 }
358                 else
359                 {
360                     [o_btn_fullscreen setState: ![o_window isFullscreen]];
361                     [o_window toggleFullscreen];
362                 }
363                 break;
364             }
365         }
366         vlc_object_release( (vlc_object_t *)p_vout );
367     }
368 }
369
370 - (void)setupVarMenuItem:(NSMenuItem *)o_mi
371                     target:(vlc_object_t *)p_object
372                     var:(const char *)psz_variable
373                     selector:(SEL)pf_callback
374 {
375     vlc_value_t val, text;
376     int i_type = var_Type( p_object, psz_variable );
377
378     switch( i_type & VLC_VAR_TYPE )
379     {
380     case VLC_VAR_VOID:
381     case VLC_VAR_BOOL:
382     case VLC_VAR_VARIABLE:
383     case VLC_VAR_STRING:
384     case VLC_VAR_INTEGER:
385         break;
386     default:
387         /* Variable doesn't exist or isn't handled */
388         return;
389     }
390     
391     /* Make sure we want to display the variable */
392     if( i_type & VLC_VAR_HASCHOICE )
393     {
394         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
395         if( val.i_int == 0 ) return;
396         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
397             return;
398     }
399     
400     /* Get the descriptive name of the variable */
401     var_Change( p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL );
402     [o_mi setTitle: [NSApp localizedString: text.psz_string ?
403                                         text.psz_string : strdup( psz_variable ) ]];
404
405     var_Get( p_object, psz_variable, &val );
406     if( i_type & VLC_VAR_HASCHOICE )
407     {
408         NSMenu *o_menu = [o_mi submenu];
409
410         [self setupVarMenu: o_menu forMenuItem: o_mi target:p_object
411                         var:psz_variable selector:pf_callback];
412         
413         if( text.psz_string ) free( text.psz_string );
414         return;
415     }
416
417     VLCMenuExt *o_data;
418     switch( i_type & VLC_VAR_TYPE )
419     {
420     case VLC_VAR_VOID:
421         o_data = [[VLCMenuExt alloc] initWithVar: psz_variable Object: p_object->i_object_id
422                 Value: val ofType: i_type];
423         [o_mi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
424         break;
425
426     case VLC_VAR_BOOL:
427         o_data = [[VLCMenuExt alloc] initWithVar: psz_variable Object: p_object->i_object_id
428                 Value: val ofType: i_type];
429         [o_mi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
430         [o_mi setState: val.b_bool ? TRUE : FALSE ];
431         break;
432
433     default:
434         if( text.psz_string ) free( text.psz_string );
435         return;
436     }
437
438     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
439     if( text.psz_string ) free( text.psz_string );
440 }
441
442
443 - (void)setupVarMenu:(NSMenu *)o_menu
444                     forMenuItem: (NSMenuItem *)o_parent
445                     target:(vlc_object_t *)p_object
446                     var:(const char *)psz_variable
447                     selector:(SEL)pf_callback
448 {
449     vlc_value_t val, val_list, text_list;
450     int i_type, i, i_nb_items;
451
452     /* remove previous items */
453     i_nb_items = [o_menu numberOfItems];
454     for( i = 0; i < i_nb_items; i++ )
455     {
456         [o_menu removeItemAtIndex: 0];
457     }
458
459     /* Check the type of the object variable */
460     i_type = var_Type( p_object, psz_variable );
461
462     /* Make sure we want to display the variable */
463     if( i_type & VLC_VAR_HASCHOICE )
464     {
465         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
466         if( val.i_int == 0 ) return;
467         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
468             return;
469     }
470     else
471     {
472         return;
473     }
474
475     switch( i_type & VLC_VAR_TYPE )
476     {
477     case VLC_VAR_VOID:
478     case VLC_VAR_BOOL:
479     case VLC_VAR_VARIABLE:
480     case VLC_VAR_STRING:
481     case VLC_VAR_INTEGER:
482         break;
483     default:
484         /* Variable doesn't exist or isn't handled */
485         return;
486     }
487
488     if( var_Get( p_object, psz_variable, &val ) < 0 )
489     {
490         return;
491     }
492
493     if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST,
494                     &val_list, &text_list ) < 0 )
495     {
496         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
497         return;
498     }
499
500     /* make (un)sensitive */
501     [o_parent setEnabled: ( val_list.p_list->i_count > 1 )];
502
503     for( i = 0; i < val_list.p_list->i_count; i++ )
504     {
505         vlc_value_t another_val;
506         NSMenuItem * o_lmi;
507         NSString *o_title = @"";
508         VLCMenuExt *o_data;
509
510         switch( i_type & VLC_VAR_TYPE )
511         {
512         case VLC_VAR_VARIABLE:
513
514             /* This is causing crashes for the moment.
515             o_title = [NSApp localizedString: text_list.p_list->p_values[i].psz_string ?
516                 text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string ];
517             
518             o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
519                 Value: val ofType: i_type];
520             [o_lmi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
521
522             // Create a submenu
523             NSMenu *o_menu = [o_lmi submenu];
524
525             [self setupVarMenu: o_menu forMenuItem: o_lmi target:p_object
526                             var:psz_variable selector:pf_callback];
527 */
528             return;
529
530         case VLC_VAR_STRING:
531             another_val.psz_string =
532                 strdup(val_list.p_list->p_values[i].psz_string);
533
534             o_title = [NSApp localizedString: text_list.p_list->p_values[i].psz_string ?
535                 text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string ];
536
537             o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
538             o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
539                     Value: another_val ofType: i_type];
540             [o_lmi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
541             [o_lmi setTarget: self];
542             
543             if( !strcmp( val.psz_string, val_list.p_list->p_values[i].psz_string ) )
544                 [o_lmi setState: TRUE ];
545
546             break;
547
548         case VLC_VAR_INTEGER:
549
550              o_title = text_list.p_list->p_values[i].psz_string ?
551                                  [NSApp localizedString: strdup( text_list.p_list->p_values[i].psz_string )] :
552                                  [NSString stringWithFormat: @"%d",
553                                  val_list.p_list->p_values[i].i_int];
554
555             o_lmi = [[o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""] retain ];
556             o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
557                     Value: val_list.p_list->p_values[i] ofType: i_type];
558             [o_lmi setRepresentedObject: [NSValue valueWithPointer:[ o_data retain]]];
559             [o_lmi setTarget: self];
560
561             if( val_list.p_list->p_values[i].i_int == val.i_int )
562                 [o_lmi setState: TRUE ];
563             break;
564
565         default:
566           break;
567         }
568     }
569     
570     /* clean up everything */
571     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
572     var_Change( p_object, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list );
573 }
574
575 - (IBAction)toggleVar:(id)sender
576 {
577     NSMenuItem *o_mi = (NSMenuItem *)sender;
578     VLCMenuExt *o_data = [[o_mi representedObject] pointerValue];
579     [NSThread detachNewThreadSelector: @selector(toggleVarThread:)
580         toTarget: self withObject: o_data];
581
582     return;
583 }
584
585 - (int)toggleVarThread: (id)_o_data
586 {
587     vlc_object_t *p_object;
588     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
589     VLCMenuExt *o_data = (VLCMenuExt *)_o_data;
590
591     vlc_thread_set_priority( [NSApp getIntf] , VLC_THREAD_PRIORITY_LOW );
592
593     p_object = (vlc_object_t *)vlc_object_get( [NSApp getIntf],
594                                     [o_data objectID] );
595
596     if( p_object != NULL )
597     {
598         var_Set( p_object, strdup([o_data name]), [o_data value] );
599         vlc_object_release( p_object );
600         [o_pool release];
601         return VLC_TRUE;
602     }
603     [o_pool release];
604     return VLC_EGENERIC;
605 }
606
607 @end
608
609 @implementation VLCControls (NSMenuValidation)
610  
611 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
612 {
613     BOOL bEnabled = TRUE;
614     vlc_value_t val;
615     intf_thread_t * p_intf = [NSApp getIntf];
616     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
617                                                        FIND_ANYWHERE );
618
619     if( p_playlist != NULL )
620     {
621         vlc_mutex_lock( &p_playlist->object_lock );
622     }
623
624 #define p_input p_playlist->p_input
625
626     if( [[o_mi title] isEqualToString: _NS("Faster")] ||
627         [[o_mi title] isEqualToString: _NS("Slower")] )
628     {
629         if( p_playlist != NULL && p_input != NULL )
630         {
631             vlc_mutex_lock( &p_input->stream.stream_lock );
632             bEnabled = p_input->stream.b_pace_control;
633             vlc_mutex_unlock( &p_input->stream.stream_lock );
634         }
635         else
636         {
637             bEnabled = FALSE;
638         }
639     }
640     else if( [[o_mi title] isEqualToString: _NS("Stop")] )
641     {
642         if( p_playlist == NULL || p_input == NULL )
643         {
644             bEnabled = FALSE;
645         }
646     }
647     else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
648              [[o_mi title] isEqualToString: _NS("Next")] )
649     {
650         if( p_playlist == NULL )
651         {
652             bEnabled = FALSE;
653         }
654         else
655         {
656             bEnabled = p_playlist->i_size > 1;
657
658             if( p_input != NULL )
659             {
660                 vlc_mutex_lock( &p_input->stream.stream_lock );
661                 bEnabled |= p_input->stream.i_area_nb > 1;
662                 vlc_mutex_unlock( &p_input->stream.stream_lock );
663             }
664         }
665     }
666     else if( [[o_mi title] isEqualToString: _NS("Shuffle")] )
667     {
668         int i_state;
669         var_Get( p_playlist, "random", &val );
670         i_state = val.b_bool ? NSOnState : NSOffState;
671         [o_mi setState: i_state];
672     }
673     else if( [[o_mi title] isEqualToString: _NS("Repeat Item")] )
674     {
675         int i_state;
676         var_Get( p_playlist, "repeat", &val );
677         i_state = val.b_bool ? NSOnState : NSOffState;
678         [o_mi setState: i_state];
679     }
680     else if( [[o_mi title] isEqualToString: _NS("Repeat Playlist")] )
681     {
682         int i_state;
683         var_Get( p_playlist, "loop", &val );
684         i_state = val.b_bool ? NSOnState : NSOffState;
685         [o_mi setState: i_state];
686     }
687     else if( [[o_mi title] isEqualToString: _NS("Step Forward")] ||
688              [[o_mi title] isEqualToString: _NS("Step Backward")] )
689     {
690         if( p_playlist != NULL && p_input != NULL )
691         {
692             vlc_mutex_lock( &p_input->stream.stream_lock );
693             bEnabled = p_input->stream.b_seekable;
694             vlc_mutex_unlock( &p_input->stream.stream_lock );
695         }
696         else
697         {
698             bEnabled = FALSE;
699         }
700     }
701     else if( [[o_mi title] isEqualToString: _NS("Mute")] ) 
702     {
703         [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
704     }
705     else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] ||
706                 [[o_mi title] isEqualToString: _NS("Half Size")] ||
707                 [[o_mi title] isEqualToString: _NS("Normal Size")] ||
708                 [[o_mi title] isEqualToString: _NS("Double Size")] ||
709                 [[o_mi title] isEqualToString: _NS("Fit To Screen")] ||
710                 [[o_mi title] isEqualToString: _NS("Float On Top")] )
711     {
712         id o_window;
713         NSArray *o_windows = [NSApp orderedWindows];
714         NSEnumerator *o_enumerator = [o_windows objectEnumerator];
715         bEnabled = FALSE;
716         
717         if ( [[o_mi title] isEqualToString: _NS("Float On Top")] )
718         {
719             int i_state = config_GetInt( p_playlist, "video-on-top" ) ?
720                       NSOnState : NSOffState;
721             [o_mi setState: i_state];
722         }
723         
724         vout_thread_t   *p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
725                                               FIND_ANYWHERE );
726         if( p_vout != NULL )
727         {
728             while ((o_window = [o_enumerator nextObject]))
729             {
730                 if( [[o_window className] isEqualToString: @"VLCWindow"] )
731                 {
732                     bEnabled = TRUE;
733                     break;
734                 }
735             }
736             vlc_object_release( (vlc_object_t *)p_vout );
737         }
738     }
739
740     if( p_playlist != NULL )
741     {
742         vlc_mutex_unlock( &p_playlist->object_lock );
743         vlc_object_release( p_playlist );
744     }
745
746     return( bEnabled );
747 }
748
749 @end
750
751 /*****************************************************************************
752  * VLCMenuExt implementation 
753  *****************************************************************************
754  * Object connected to a playlistitem which remembers the data belonging to
755  * the variable of the autogenerated menu
756  *****************************************************************************/
757 @implementation VLCMenuExt
758
759 - (id)initWithVar: (const char *)_psz_name Object: (int)i_id
760         Value: (vlc_value_t)val ofType: (int)_i_type
761 {
762     self = [super init];
763
764     if( self != nil )
765     {
766         psz_name = strdup( _psz_name );
767         i_object_id = i_id;
768         value = val;
769         i_type = _i_type;
770     }
771
772     return( self );
773 }
774
775 - (void)dealloc
776 {
777     free( psz_name );
778 }
779
780 - (char *)name
781 {
782     return psz_name;
783 }
784
785 - (int)objectID
786 {
787     return i_object_id;
788 }
789
790 - (vlc_value_t)value
791 {
792     return value;
793 }
794
795 - (int)type
796 {
797     return i_type;
798 }
799
800 @end