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