]> git.sesse.net Git - vlc/blob - modules/gui/macosx/controls.m
For consistency, remove references to vlc from libvlc
[vlc] / modules / gui / macosx / controls.m
1 /*****************************************************************************
2  * controls.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2002-2005 the VideoLAN team
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  *          Benjamin Pracht <bigben at videolan doit org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <stdlib.h>                                      /* malloc(), free() */
31 #include <sys/param.h>                                    /* for MAXPATHLEN */
32 #include <string.h>
33
34 #include "intf.h"
35 #include "vout.h"
36 #include "open.h"
37 #include "controls.h"
38 #include <vlc_osd.h>
39
40
41 /*****************************************************************************
42  * VLCControls implementation 
43  *****************************************************************************/
44 @implementation VLCControls
45
46 - (id)init
47 {
48     [super init];
49     o_fs_panel = [[VLCFSPanel alloc] init];
50     return self;
51 }
52
53 - (void)awakeFromNib
54 {
55     [o_specificTime_mi setTitle: _NS("Jump To Time")];
56     [o_specificTime_cancel_btn setTitle: _NS("Cancel")];
57     [o_specificTime_ok_btn setTitle: _NS("OK")];
58     [o_specificTime_sec_lbl setStringValue: _NS("sec.")];
59     [o_specificTime_goTo_lbl setStringValue: _NS("Jump to time")];
60 }
61
62 - (IBAction)play:(id)sender
63 {
64     vlc_value_t val;
65     intf_thread_t * p_intf = VLCIntf;
66     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
67                                         FIND_ANYWHERE );
68     if( p_playlist )
69     {
70         vlc_mutex_lock( &p_playlist->object_lock );
71         if( p_playlist->i_size <= 0 )
72         {
73             vlc_mutex_unlock( &p_playlist->object_lock );
74             vlc_object_release( p_playlist );
75             [o_main intfOpenFileGeneric: (id)sender];
76         }
77         else
78         {
79             vlc_mutex_unlock( &p_playlist->object_lock );
80             vlc_object_release( p_playlist );
81         }
82
83     }
84     val.i_int = config_GetInt( p_intf, "key-play-pause" );
85     var_Set( p_intf->p_libvlc, "key-pressed", val );
86 }
87
88 /* Small helper method */
89
90 -(id) getVoutView
91 {
92     id o_window;
93     id o_vout_view = nil;
94     id o_embedded_vout_list = [[VLCMain sharedInstance] getEmbeddedList];
95     NSEnumerator *o_enumerator = [[NSApp orderedWindows] objectEnumerator];
96     while( !o_vout_view && ( o_window = [o_enumerator nextObject] ) )
97     {
98         /* We have an embedded vout */
99         if( [o_embedded_vout_list windowContainsEmbedded: o_window] )
100         {
101             o_vout_view = [o_embedded_vout_list getViewForWindow: o_window];
102         }
103         /* We have a detached vout */
104         else if( [[o_window className] isEqualToString: @"VLCWindow"] )
105         {
106             msg_Dbg( VLCIntf, "detached vout controls.m call getVoutView" );
107             o_vout_view = [o_window getVoutView];
108         }
109     }
110     return o_vout_view;
111 }
112
113
114 - (IBAction)stop:(id)sender
115 {
116     vlc_value_t val;
117     intf_thread_t * p_intf = VLCIntf;
118     val.i_int = config_GetInt( p_intf, "key-stop" );
119     var_Set( p_intf->p_libvlc, "key-pressed", val );
120 }
121
122 - (IBAction)faster:(id)sender
123 {
124     vlc_value_t val;
125     intf_thread_t * p_intf = VLCIntf;
126     val.i_int = config_GetInt( p_intf, "key-faster" );
127     var_Set( p_intf->p_libvlc, "key-pressed", val );
128 }
129
130 - (IBAction)slower:(id)sender
131 {
132     vlc_value_t val;
133     intf_thread_t * p_intf = VLCIntf;
134     val.i_int = config_GetInt( p_intf, "key-slower" );
135     var_Set( p_intf->p_libvlc, "key-pressed", val );
136 }
137
138 - (IBAction)prev:(id)sender
139 {
140     vlc_value_t val;
141     intf_thread_t * p_intf = VLCIntf;
142     val.i_int = config_GetInt( p_intf, "key-prev" );
143     var_Set( p_intf->p_libvlc, "key-pressed", val );
144 }
145
146 - (IBAction)next:(id)sender
147 {
148     vlc_value_t val;
149     intf_thread_t * p_intf = VLCIntf;
150     val.i_int = config_GetInt( p_intf, "key-next" );
151     var_Set( p_intf->p_libvlc, "key-pressed", val );
152 }
153
154 - (IBAction)random:(id)sender
155 {
156     vlc_value_t val;
157     intf_thread_t * p_intf = VLCIntf;
158     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
159                                                        FIND_ANYWHERE );
160     if( p_playlist == NULL )
161     {
162         return;
163     }
164
165     var_Get( p_playlist, "random", &val );
166     val.b_bool = !val.b_bool;
167     var_Set( p_playlist, "random", val );
168     if( val.b_bool )
169     {
170         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Random On" ) );
171         config_PutInt( p_playlist, "random", 1 );
172     }
173     else
174     {
175         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Random Off" ) );
176         config_PutInt( p_playlist, "random", 0 );
177     }
178
179     p_intf->p_sys->b_playmode_update = VLC_TRUE;
180     p_intf->p_sys->b_intf_update = VLC_TRUE;
181     vlc_object_release( p_playlist );
182 }
183
184 - (IBAction)repeat:(id)sender
185 {
186     vlc_value_t val;
187     intf_thread_t * p_intf = VLCIntf;
188     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
189                                                        FIND_ANYWHERE );
190     if( p_playlist == NULL )
191     {
192         return;
193     }
194
195     var_Get( p_playlist, "repeat", &val );
196     if (!val.b_bool)
197     {
198         var_Set( p_playlist, "loop", val );
199     }
200     val.b_bool = !val.b_bool;
201     var_Set( p_playlist, "repeat", val );
202     if( val.b_bool )
203     {
204         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat One" ) );
205         config_PutInt( p_playlist, "repeat", 1 );
206     }
207     else
208     {
209         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat Off" ) );
210         config_PutInt( p_playlist, "repeat", 0 );
211     }
212     
213     p_intf->p_sys->b_playmode_update = VLC_TRUE;
214     p_intf->p_sys->b_intf_update = VLC_TRUE;
215     vlc_object_release( p_playlist );
216 }
217
218 - (IBAction)loop:(id)sender
219 {
220     vlc_value_t val;
221     intf_thread_t * p_intf = VLCIntf;
222     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
223                                                        FIND_ANYWHERE );
224     if( p_playlist == NULL )
225     {
226         return;
227     }
228
229     var_Get( p_playlist, "loop", &val );
230     if (!val.b_bool)
231     {
232         var_Set( p_playlist, "repeat", val );
233     }
234     val.b_bool = !val.b_bool;
235     var_Set( p_playlist, "loop", val );
236     if( val.b_bool )
237     {
238         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat All" ) );
239         config_PutInt( p_playlist, "loop", 1 );
240     }
241     else
242     {
243         vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat Off" ) );
244         config_PutInt( p_playlist, "loop", 0 );
245     }
246
247     p_intf->p_sys->b_playmode_update = VLC_TRUE;
248     p_intf->p_sys->b_intf_update = VLC_TRUE;
249     vlc_object_release( p_playlist );
250 }
251
252 - (IBAction)forward:(id)sender
253 {
254     vlc_value_t val;
255     intf_thread_t * p_intf = VLCIntf;
256     val.i_int = config_GetInt( p_intf, "key-jump+short" );
257     var_Set( p_intf->p_libvlc, "key-pressed", val );
258 }
259
260 - (IBAction)backward:(id)sender
261 {
262     vlc_value_t val;
263     intf_thread_t * p_intf = VLCIntf;
264     val.i_int = config_GetInt( p_intf, "key-jump-short" );
265     var_Set( p_intf->p_libvlc, "key-pressed", val );
266 }
267
268
269 - (IBAction)volumeUp:(id)sender
270 {
271     vlc_value_t val;
272     intf_thread_t * p_intf = VLCIntf;
273     val.i_int = config_GetInt( p_intf, "key-vol-up" );
274     var_Set( p_intf->p_libvlc, "key-pressed", val );
275     /* Manage volume status */
276     [o_main manageVolumeSlider];
277 }
278
279 - (IBAction)volumeDown:(id)sender
280 {
281     vlc_value_t val;
282     intf_thread_t * p_intf = VLCIntf;
283     val.i_int = config_GetInt( p_intf, "key-vol-down" );
284     var_Set( p_intf->p_libvlc, "key-pressed", val );
285     /* Manage volume status */
286     [o_main manageVolumeSlider];
287 }
288
289 - (IBAction)mute:(id)sender
290 {
291     vlc_value_t val;
292     intf_thread_t * p_intf = VLCIntf;
293     val.i_int = config_GetInt( p_intf, "key-vol-mute" );
294     var_Set( p_intf->p_libvlc, "key-pressed", val );
295     /* Manage volume status */
296     [o_main manageVolumeSlider];
297 }
298
299 - (IBAction)volumeSliderUpdated:(id)sender
300 {
301     intf_thread_t * p_intf = VLCIntf;
302     audio_volume_t i_volume = (audio_volume_t)[sender intValue];
303     int i_volume_step = 0;
304     i_volume_step = config_GetInt( p_intf->p_libvlc, "volume-step" );
305     aout_VolumeSet( p_intf, i_volume * i_volume_step );
306     /* Manage volume status */
307     [o_main manageVolumeSlider];
308 }
309
310 - (IBAction)windowAction:(id)sender
311 {
312     NSString *o_title = [sender title];
313
314     vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
315                                               FIND_ANYWHERE );
316     if( p_vout != NULL )
317     {
318         id o_vout_view = [self getVoutView];
319         if( o_vout_view )
320         {
321             if( [o_title isEqualToString: _NS("Half Size") ] )
322                 [o_vout_view scaleWindowWithFactor: 0.5];
323             else if( [o_title isEqualToString: _NS("Normal Size") ] )
324                 [o_vout_view scaleWindowWithFactor: 1.0];
325             else if( [o_title isEqualToString: _NS("Double Size") ] )
326                 [o_vout_view scaleWindowWithFactor: 2.0];
327             else if( [o_title isEqualToString: _NS("Float on Top") ] )
328                 [o_vout_view toggleFloatOnTop];
329             else if( [o_title isEqualToString: _NS("Fit to Screen") ] )
330             {
331                 id o_window = [o_vout_view getWindow];
332                 if( ![o_window isZoomed] )
333                     [o_window performZoom:self];
334             }
335             else if( [o_title isEqualToString: _NS("Snapshot") ] )
336             {
337                 [o_vout_view snapshot];
338             }
339             else
340             {
341                 [o_vout_view toggleFullscreen];
342             }
343         }
344         vlc_object_release( (vlc_object_t *)p_vout );
345     }
346     else
347     {
348         playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST,
349                                               FIND_ANYWHERE );
350
351         if( p_playlist && ( [o_title isEqualToString: _NS("Fullscreen")] ||
352             [sender isKindOfClass:[NSButton class]] ) )
353         {
354             vlc_value_t val;
355             var_Get( p_playlist, "fullscreen", &val );
356             var_Set( p_playlist, "fullscreen", (vlc_value_t)!val.b_bool );
357         }
358         if( p_playlist ) vlc_object_release( (vlc_object_t *)p_playlist );
359     }
360
361 }
362
363 - (BOOL)keyEvent:(NSEvent *)o_event
364 {
365     BOOL eventHandled = NO;
366     unichar key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0];
367
368     if( key )
369     {
370         vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
371                                               FIND_ANYWHERE );
372         if( p_vout != NULL )
373         {
374             /* Escape */
375             if( key == (unichar) 0x1b )
376             {
377                 id o_vout_view = [self getVoutView];
378                 if( o_vout_view && [o_vout_view isFullscreen] )
379                 {
380                     [o_vout_view toggleFullscreen];
381                     eventHandled = YES;
382                 }
383             }
384             else if( key == ' ' )
385             {
386                 [self play:self];
387                 eventHandled = YES;
388             }
389             vlc_object_release( (vlc_object_t *)p_vout );
390         }
391     }
392     return eventHandled;
393 }
394
395 - (void)setupVarMenuItem:(NSMenuItem *)o_mi
396                     target:(vlc_object_t *)p_object
397                     var:(const char *)psz_variable
398                     selector:(SEL)pf_callback
399 {
400     vlc_value_t val, text;
401     int i_type = var_Type( p_object, psz_variable );
402
403     switch( i_type & VLC_VAR_TYPE )
404     {
405     case VLC_VAR_VOID:
406     case VLC_VAR_BOOL:
407     case VLC_VAR_VARIABLE:
408     case VLC_VAR_STRING:
409     case VLC_VAR_INTEGER:
410         break;
411     default:
412         /* Variable doesn't exist or isn't handled */
413         return;
414     }
415     
416     /* Make sure we want to display the variable */
417     if( i_type & VLC_VAR_HASCHOICE )
418     {
419         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
420         if( val.i_int == 0 ) return;
421         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
422             return;
423     }
424     
425     /* Get the descriptive name of the variable */
426     var_Change( p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL );
427     [o_mi setTitle: [[VLCMain sharedInstance] localizedString: text.psz_string ?
428                                         text.psz_string : strdup( psz_variable ) ]];
429
430     var_Get( p_object, psz_variable, &val );
431     if( i_type & VLC_VAR_HASCHOICE )
432     {
433         NSMenu *o_menu = [o_mi submenu];
434
435         [self setupVarMenu: o_menu forMenuItem: o_mi target:p_object
436                         var:psz_variable selector:pf_callback];
437         
438         if( text.psz_string ) free( text.psz_string );
439         return;
440     }
441
442     VLCMenuExt *o_data;
443     switch( i_type & VLC_VAR_TYPE )
444     {
445     case VLC_VAR_VOID:
446         o_data = [[VLCMenuExt alloc] initWithVar: psz_variable Object: p_object->i_object_id
447                 Value: val ofType: i_type];
448         [o_mi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
449         break;
450
451     case VLC_VAR_BOOL:
452         o_data = [[VLCMenuExt alloc] initWithVar: psz_variable Object: p_object->i_object_id
453                 Value: val ofType: i_type];
454         [o_mi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
455         if( !( i_type & VLC_VAR_ISCOMMAND ) )
456             [o_mi setState: val.b_bool ? TRUE : FALSE ];
457         break;
458
459     default:
460         if( text.psz_string ) free( text.psz_string );
461         return;
462     }
463
464     if( ( i_type & VLC_VAR_TYPE ) == VLC_VAR_STRING ) free( val.psz_string );
465     if( text.psz_string ) free( text.psz_string );
466 }
467
468
469 - (void)setupVarMenu:(NSMenu *)o_menu
470                     forMenuItem: (NSMenuItem *)o_parent
471                     target:(vlc_object_t *)p_object
472                     var:(const char *)psz_variable
473                     selector:(SEL)pf_callback
474 {
475     vlc_value_t val, val_list, text_list;
476     int i_type, i, i_nb_items;
477
478     /* remove previous items */
479     i_nb_items = [o_menu numberOfItems];
480     for( i = 0; i < i_nb_items; i++ )
481     {
482         [o_menu removeItemAtIndex: 0];
483     }
484
485     /* Check the type of the object variable */
486     i_type = var_Type( p_object, psz_variable );
487
488     /* Make sure we want to display the variable */
489     if( i_type & VLC_VAR_HASCHOICE )
490     {
491         var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
492         if( val.i_int == 0 ) return;
493         if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
494             return;
495     }
496     else
497     {
498         return;
499     }
500
501     switch( i_type & VLC_VAR_TYPE )
502     {
503     case VLC_VAR_VOID:
504     case VLC_VAR_BOOL:
505     case VLC_VAR_VARIABLE:
506     case VLC_VAR_STRING:
507     case VLC_VAR_INTEGER:
508         break;
509     default:
510         /* Variable doesn't exist or isn't handled */
511         return;
512     }
513
514     if( var_Get( p_object, psz_variable, &val ) < 0 )
515     {
516         return;
517     }
518
519     if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST,
520                     &val_list, &text_list ) < 0 )
521     {
522         if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
523         return;
524     }
525
526     /* make (un)sensitive */
527     [o_parent setEnabled: ( val_list.p_list->i_count > 1 )];
528
529     for( i = 0; i < val_list.p_list->i_count; i++ )
530     {
531         vlc_value_t another_val;
532         NSMenuItem * o_lmi;
533         NSString *o_title = @"";
534         VLCMenuExt *o_data;
535
536         switch( i_type & VLC_VAR_TYPE )
537         {
538         case VLC_VAR_STRING:
539             another_val.psz_string =
540                 strdup(val_list.p_list->p_values[i].psz_string);
541
542             o_title = [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string ?
543                 text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string ];
544
545             o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
546             o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
547                     Value: another_val ofType: i_type];
548             [o_lmi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
549             [o_lmi setTarget: self];
550
551             if( !strcmp( val.psz_string, val_list.p_list->p_values[i].psz_string ) && !( i_type & VLC_VAR_ISCOMMAND ) )
552                 [o_lmi setState: TRUE ];
553
554             break;
555
556         case VLC_VAR_INTEGER:
557
558              o_title = text_list.p_list->p_values[i].psz_string ?
559                                  [[VLCMain sharedInstance] localizedString: strdup( text_list.p_list->p_values[i].psz_string )] :
560                                  [NSString stringWithFormat: @"%d",
561                                  val_list.p_list->p_values[i].i_int];
562
563             o_lmi = [[o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""] retain ];
564             o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
565                     Value: val_list.p_list->p_values[i] ofType: i_type];
566             [o_lmi setRepresentedObject: [NSValue valueWithPointer:[ o_data retain]]];
567             [o_lmi setTarget: self];
568
569             if( val_list.p_list->p_values[i].i_int == val.i_int && !( i_type & VLC_VAR_ISCOMMAND ) )
570                 [o_lmi setState: TRUE ];
571             break;
572
573         default:
574           break;
575         }
576     }
577
578     /* clean up everything */
579     if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
580     var_Change( p_object, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list );
581 }
582
583 - (IBAction)toggleVar:(id)sender
584 {
585     NSMenuItem *o_mi = (NSMenuItem *)sender;
586     VLCMenuExt *o_data = [[o_mi representedObject] pointerValue];
587     [NSThread detachNewThreadSelector: @selector(toggleVarThread:)
588         toTarget: self withObject: o_data];
589
590     return;
591 }
592
593 - (int)toggleVarThread: (id)_o_data
594 {
595     vlc_object_t *p_object;
596     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
597     VLCMenuExt *o_data = (VLCMenuExt *)_o_data;
598
599     vlc_thread_set_priority( VLCIntf , VLC_THREAD_PRIORITY_LOW );
600
601     p_object = (vlc_object_t *)vlc_object_get( VLCIntf,
602                                     [o_data objectID] );
603
604     if( p_object != NULL )
605     {
606         var_Set( p_object, strdup([o_data name]), [o_data value] );
607         vlc_object_release( p_object );
608         [o_pool release];
609         return VLC_TRUE;
610     }
611     [o_pool release];
612     return VLC_EGENERIC;
613 }
614
615 - (IBAction)goToSpecificTime:(id)sender
616 {
617     if( sender == o_specificTime_cancel_btn )
618     {
619         [NSApp endSheet: o_specificTime_win];
620         [o_specificTime_win close];
621     }
622     else if( sender == o_specificTime_ok_btn )
623     {
624         input_thread_t * p_input = (input_thread_t *)vlc_object_find( VLCIntf, \
625             VLC_OBJECT_INPUT, FIND_ANYWHERE );
626         if( p_input )
627         {
628             unsigned int timeInSec = 0;
629             NSString * fieldContent = [o_specificTime_enter_fld stringValue];
630             if( [[fieldContent componentsSeparatedByString: @":"] count] > 1 && 
631                 [[fieldContent componentsSeparatedByString: @":"] count] <= 3 )
632             {
633                 NSArray * ourTempArray = \
634                     [fieldContent componentsSeparatedByString: @":"];
635
636                 if( [[fieldContent componentsSeparatedByString: @":"] count] == 3 )
637                 {
638                     timeInSec += ([[ourTempArray objectAtIndex: 0] intValue] * 3600); //h
639                     timeInSec += ([[ourTempArray objectAtIndex: 1] intValue] * 60); //m
640                     timeInSec += [[ourTempArray objectAtIndex: 2] intValue];        //s
641                 }
642                 else
643                 {
644                     timeInSec += ([[ourTempArray objectAtIndex: 0] intValue] * 60); //m
645                     timeInSec += [[ourTempArray objectAtIndex: 1] intValue]; //s
646                 }
647             }
648             else
649                 timeInSec = [fieldContent intValue];
650
651             input_Control( p_input, INPUT_SET_TIME, (int64_t)(timeInSec * 1000000));
652             vlc_object_release( p_input );
653         }
654     
655         [NSApp endSheet: o_specificTime_win];
656         [o_specificTime_win close];
657     }
658     else
659     {
660         input_thread_t * p_input = (input_thread_t *)vlc_object_find( VLCIntf, \
661             VLC_OBJECT_INPUT, FIND_ANYWHERE );
662         if( p_input )
663         {
664             /* we can obviously only do that if an input is available */
665             vlc_value_t pos, length;
666             var_Get( p_input, "time", &pos );
667             [o_specificTime_enter_fld setIntValue: (pos.i_time / 1000000)];
668             var_Get( p_input, "length", &length );
669             [o_specificTime_stepper setMaxValue: (length.i_time / 1000000)];
670
671             [NSApp beginSheet: o_specificTime_win modalForWindow: \
672                 [NSApp mainWindow] modalDelegate: self didEndSelector: nil \
673                 contextInfo: nil];
674             [o_specificTime_win makeKeyWindow];
675             vlc_object_release( p_input );
676         }
677     }
678 }
679
680 - (id)getFSPanel
681 {
682     if( o_fs_panel )
683         return o_fs_panel;
684     else
685     {
686         msg_Err( VLCIntf, "FSPanel is nil" );
687         return NULL;
688     }
689 }
690
691 @end
692
693 @implementation VLCControls (NSMenuValidation)
694
695 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
696 {
697     BOOL bEnabled = TRUE;
698     vlc_value_t val;
699     intf_thread_t * p_intf = VLCIntf;
700     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
701                                                        FIND_ANYWHERE );
702
703     if( p_playlist != NULL )
704     {
705         vlc_mutex_lock( &p_playlist->object_lock );
706     }
707     else return FALSE;
708
709 #define p_input p_playlist->p_input
710
711     if( [[o_mi title] isEqualToString: _NS("Faster")] ||
712         [[o_mi title] isEqualToString: _NS("Slower")] )
713     {
714         if( p_input != NULL )
715         {
716             bEnabled = p_input->input.b_can_pace_control;
717         }
718         else
719         {
720             bEnabled = FALSE;
721         }
722     }
723     else if( [[o_mi title] isEqualToString: _NS("Stop")] )
724     {
725         if( p_input == NULL )
726         {
727             bEnabled = FALSE;
728         }
729         [o_main setupMenus]; /* Make sure input menu is up to date */
730     }
731     else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
732              [[o_mi title] isEqualToString: _NS("Next")] )
733     {
734             bEnabled = p_playlist->i_size > 1;
735     }
736     else if( [[o_mi title] isEqualToString: _NS("Random")] )
737     {
738         int i_state;
739         var_Get( p_playlist, "random", &val );
740         i_state = val.b_bool ? NSOnState : NSOffState;
741         [o_mi setState: i_state];
742     }
743     else if( [[o_mi title] isEqualToString: _NS("Repeat One")] )
744     {
745         int i_state;
746         var_Get( p_playlist, "repeat", &val );
747         i_state = val.b_bool ? NSOnState : NSOffState;
748         [o_mi setState: i_state];
749     }
750     else if( [[o_mi title] isEqualToString: _NS("Repeat All")] )
751     {
752         int i_state;
753         var_Get( p_playlist, "loop", &val );
754         i_state = val.b_bool ? NSOnState : NSOffState;
755         [o_mi setState: i_state];
756     }
757     else if( [[o_mi title] isEqualToString: _NS("Step Forward")] ||
758              [[o_mi title] isEqualToString: _NS("Step Backward")] ||
759              [[o_mi title] isEqualToString: _NS("Jump To Time")])
760     {
761         if( p_input != NULL )
762         {
763             var_Get( p_input, "seekable", &val);
764             bEnabled = val.b_bool;
765         }
766         else bEnabled = FALSE;
767     }
768     else if( [[o_mi title] isEqualToString: _NS("Mute")] )
769     {
770         [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
771         [o_main setupMenus]; /* Make sure audio menu is up to date */
772     }
773     else if( [[o_mi title] isEqualToString: _NS("Half Size")] ||
774                 [[o_mi title] isEqualToString: _NS("Normal Size")] ||
775                 [[o_mi title] isEqualToString: _NS("Double Size")] ||
776                 [[o_mi title] isEqualToString: _NS("Fit to Screen")] ||
777                 [[o_mi title] isEqualToString: _NS("Snapshot")] ||
778                 [[o_mi title] isEqualToString: _NS("Fullscreen")] ||
779                 [[o_mi title] isEqualToString: _NS("Float on Top")] )
780     {
781         id o_window;
782         NSArray *o_windows = [NSApp orderedWindows];
783         NSEnumerator *o_enumerator = [o_windows objectEnumerator];
784         bEnabled = FALSE;
785         
786         vout_thread_t   *p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
787                                               FIND_ANYWHERE );
788         if( p_vout != NULL )
789         {
790             if( [[o_mi title] isEqualToString: _NS("Float on Top")] )
791             {
792                 var_Get( p_vout, "video-on-top", &val );
793                 [o_mi setState: val.b_bool ?  NSOnState : NSOffState];
794             }
795
796             while( (o_window = [o_enumerator nextObject]))
797             {
798                 if( [[o_window className] isEqualToString: @"VLCWindow"] ||
799                             [[[VLCMain sharedInstance] getEmbeddedList]
800                             windowContainsEmbedded: o_window])
801                 {
802                     bEnabled = TRUE;
803                     break;
804                 }
805             }
806             vlc_object_release( (vlc_object_t *)p_vout );
807         }
808         else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )
809         {
810             var_Get( p_playlist, "fullscreen", &val );
811             [o_mi setState: val.b_bool];
812             bEnabled = TRUE;
813         }
814         [o_main setupMenus]; /* Make sure video menu is up to date */
815     }
816
817     vlc_mutex_unlock( &p_playlist->object_lock );
818     vlc_object_release( p_playlist );
819
820     return( bEnabled );
821 }
822
823 @end
824
825 /*****************************************************************************
826  * VLCMenuExt implementation 
827  *****************************************************************************
828  * Object connected to a playlistitem which remembers the data belonging to
829  * the variable of the autogenerated menu
830  *****************************************************************************/
831 @implementation VLCMenuExt
832
833 - (id)initWithVar: (const char *)_psz_name Object: (int)i_id
834         Value: (vlc_value_t)val ofType: (int)_i_type
835 {
836     self = [super init];
837
838     if( self != nil )
839     {
840         psz_name = strdup( _psz_name );
841         i_object_id = i_id;
842         value = val;
843         i_type = _i_type;
844     }
845
846     return( self );
847 }
848
849 - (void)dealloc
850 {
851     free( psz_name );
852     [super dealloc];
853 }
854
855 - (char *)name
856 {
857     return psz_name;
858 }
859
860 - (int)objectID
861 {
862     return i_object_id;
863 }
864
865 - (vlc_value_t)value
866 {
867     return value;
868 }
869
870 - (int)type
871 {
872     return i_type;
873 }
874
875 @end
876
877
878 /*****************************************************************************
879  * VLCTimeField implementation 
880  *****************************************************************************
881  * we need this to catch our click-event in the controller window
882  *****************************************************************************/
883
884 @implementation VLCTimeField
885 - (void)mouseDown: (NSEvent *)ourEvent
886 {
887     if( [ourEvent clickCount] > 1 )
888         [[[VLCMain sharedInstance] getControls] goToSpecificTime: nil];
889 }
890 @end