controls.m 29.7 KB
Newer Older
1
/*****************************************************************************
2
 * controls.m: MacOS X interface module
3
 *****************************************************************************
4
 * Copyright (C) 2002-2005 the VideoLAN team
5
 * $Id$
6
7
8
 *
 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
 *          Christophe Massiot <massiot@via.ecp.fr>
hartman's avatar
hartman committed
9
 *          Derk-Jan Hartman <hartman at videolan dot org>
10
 *          Benjamin Pracht <bigben at videolan doit org>
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
24
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25
26
27
28
29
30
31
32
33
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
#include <sys/param.h>                                    /* for MAXPATHLEN */
#include <string.h>

34
35
36
37
38
#import "intf.h"
#import "vout.h"
#import "open.h"
#import "controls.h"
#import "playlist.h"
39
#include <vlc_osd.h>
40

41

42
43
44
45
46
/*****************************************************************************
 * VLCControls implementation 
 *****************************************************************************/
@implementation VLCControls

47
48
49
50
51
52
53
- (id)init
{
    [super init];
    o_fs_panel = [[VLCFSPanel alloc] init];
    return self;
}

54
55
- (void)awakeFromNib
{
56
    [o_specificTime_mi setTitle: _NS("Jump To Time")];
57
58
59
    [o_specificTime_cancel_btn setTitle: _NS("Cancel")];
    [o_specificTime_ok_btn setTitle: _NS("OK")];
    [o_specificTime_sec_lbl setStringValue: _NS("sec.")];
60
    [o_specificTime_goTo_lbl setStringValue: _NS("Jump to time")];
61
62
}

63
64
- (IBAction)play:(id)sender
{
hartman's avatar
hartman committed
65
    vlc_value_t val;
hartman's avatar
hartman committed
66
    intf_thread_t * p_intf = VLCIntf;
67
    playlist_t * p_playlist = pl_Yield( p_intf );
68

69
70
71
72
73
74
75
76
77
78
79
    vlc_mutex_lock( &p_playlist->object_lock );
    if( p_playlist->i_size <= 0 )
    {
        vlc_mutex_unlock( &p_playlist->object_lock );
        vlc_object_release( p_playlist );
        [o_main intfOpenFileGeneric: (id)sender];
    }
    else
    {
        vlc_mutex_unlock( &p_playlist->object_lock );
        vlc_object_release( p_playlist );
80
    }
81

82
    val.i_int = config_GetInt( p_intf, "key-play-pause" );
83
    var_Set( p_intf->p_libvlc, "key-pressed", val );
84
85
}

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* Small helper method */

-(id) getVoutView
{
    id o_window;
    id o_vout_view = nil;
    id o_embedded_vout_list = [[VLCMain sharedInstance] getEmbeddedList];
    NSEnumerator *o_enumerator = [[NSApp orderedWindows] objectEnumerator];
    while( !o_vout_view && ( o_window = [o_enumerator nextObject] ) )
    {
        /* We have an embedded vout */
        if( [o_embedded_vout_list windowContainsEmbedded: o_window] )
        {
            o_vout_view = [o_embedded_vout_list getViewForWindow: o_window];
        }
        /* We have a detached vout */
        else if( [[o_window className] isEqualToString: @"VLCWindow"] )
        {
            msg_Dbg( VLCIntf, "detached vout controls.m call getVoutView" );
            o_vout_view = [o_window getVoutView];
        }
    }
    return o_vout_view;
}


112
113
- (IBAction)stop:(id)sender
{
114
    vlc_value_t val;
hartman's avatar
hartman committed
115
    intf_thread_t * p_intf = VLCIntf;
116
    val.i_int = config_GetInt( p_intf, "key-stop" );
117
    var_Set( p_intf->p_libvlc, "key-pressed", val );
118
119
120
121
}

- (IBAction)faster:(id)sender
{
122
    vlc_value_t val;
hartman's avatar
hartman committed
123
    intf_thread_t * p_intf = VLCIntf;
124
    val.i_int = config_GetInt( p_intf, "key-faster" );
125
    var_Set( p_intf->p_libvlc, "key-pressed", val );
126
127
128
129
}

- (IBAction)slower:(id)sender
{
130
    vlc_value_t val;
hartman's avatar
hartman committed
131
    intf_thread_t * p_intf = VLCIntf;
132
    val.i_int = config_GetInt( p_intf, "key-slower" );
133
    var_Set( p_intf->p_libvlc, "key-pressed", val );
hartman's avatar
hartman committed
134
135
}

136
137
- (IBAction)prev:(id)sender
{
138
    vlc_value_t val;
hartman's avatar
hartman committed
139
    intf_thread_t * p_intf = VLCIntf;
140
    val.i_int = config_GetInt( p_intf, "key-prev" );
141
    var_Set( p_intf->p_libvlc, "key-pressed", val );
142
143
144
145
}

- (IBAction)next:(id)sender
{
146
    vlc_value_t val;
hartman's avatar
hartman committed
147
    intf_thread_t * p_intf = VLCIntf;
148
    val.i_int = config_GetInt( p_intf, "key-next" );
149
    var_Set( p_intf->p_libvlc, "key-pressed", val );
150
151
}

hartman's avatar
hartman committed
152
- (IBAction)random:(id)sender
153
{
hartman's avatar
hartman committed
154
    vlc_value_t val;
155
    intf_thread_t * p_intf = VLCIntf;
156
    playlist_t * p_playlist = pl_Yield( p_intf );
hartman's avatar
hartman committed
157
158
159
160

    var_Get( p_playlist, "random", &val );
    val.b_bool = !val.b_bool;
    var_Set( p_playlist, "random", val );
161
162
    if( val.b_bool )
    {
163
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Random On" ) );
164
        config_PutInt( p_playlist, "random", 1 );
165
166
167
    }
    else
    {
168
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Random Off" ) );
169
        config_PutInt( p_playlist, "random", 0 );
170
    }
hartman's avatar
hartman committed
171

172
    p_intf->p_sys->b_playmode_update = VLC_TRUE;
bigben's avatar
bigben committed
173
    p_intf->p_sys->b_intf_update = VLC_TRUE;
hartman's avatar
hartman committed
174
175
    vlc_object_release( p_playlist );
}
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/* three little ugly helpers */
- (void)repeatOne
{
    [o_btn_repeat setImage: [[NSImage alloc] initWithContentsOfFile:
    [[NSBundle mainBundle] pathForImageResource:@"repeat_single_embedded_blue.png"]]];
    [o_btn_repeat setAlternateImage: [[NSImage alloc] initWithContentsOfFile:
        [[NSBundle mainBundle] pathForImageResource:@"repeat_embedded_blue.png"]]];
}
- (void)repeatAll
{
    [o_btn_repeat setImage: [[NSImage alloc] initWithContentsOfFile:
        [[NSBundle mainBundle] pathForImageResource:@"repeat_embedded_blue.png"]]];
    [o_btn_repeat setAlternateImage: [[NSImage alloc] initWithContentsOfFile:
        [[NSBundle mainBundle] pathForImageResource:@"repeat_embedded.png"]]];
}
- (void)repeatOff
{
    [o_btn_repeat setImage: [[NSImage alloc] initWithContentsOfFile:
        [[NSBundle mainBundle] pathForImageResource:@"repeat_embedded.png"]]];
    [o_btn_repeat setAlternateImage: [[NSImage alloc] initWithContentsOfFile:
    [[NSBundle mainBundle] pathForImageResource:@"repeat_single_embedded_blue.png"]]];
}
- (void)shuffle
{
    vlc_value_t val;
    playlist_t *p_playlist = pl_Yield( VLCIntf );
    var_Get( p_playlist, "random", &val );
    [o_btn_shuffle setState: val.b_bool];
    vlc_object_release( p_playlist );
}

- (IBAction)repeatButtonAction:(id)sender
{
    vlc_value_t looping,repeating;
    intf_thread_t * p_intf = VLCIntf;
    playlist_t * p_playlist = pl_Yield( p_intf );

    var_Get( p_playlist, "repeat", &repeating );
    var_Get( p_playlist, "loop", &looping );

    [[o_btn_repeat image] release];
    [[o_btn_repeat alternateImage] release];

    if( !repeating.b_bool && !looping.b_bool )
    {
        /* was: no repeating at all, switching to Repeat One */
        
        /* set our button's look */
        [self repeatOne];
        
        /* prepare core communication */
        repeating.b_bool = VLC_TRUE;
        looping.b_bool = VLC_FALSE;
        config_PutInt( p_playlist, "repeat", 1 );
        config_PutInt( p_playlist, "loop", 0 ); 
        
        /* show the change */
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat One" ) );
    }
    else if( repeating.b_bool && !looping.b_bool )
    {
        /* was: Repeat One, switching to Repeat All */
        
        /* set our button's look */
        [self repeatAll];
        
        /* prepare core communication */
        repeating.b_bool = VLC_FALSE;
        looping.b_bool = VLC_TRUE;
        config_PutInt( p_playlist, "repeat", 0 ); 
        config_PutInt( p_playlist, "loop", 1 ); 
        
        /* show the change */
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat All" ) );
    }
    else
    {
        /* was: Repeat All or bug in VLC, switching to Repeat Off */
        
        /* set our button's look */
        [self repeatOff];
        
        /* prepare core communication */
        repeating.b_bool = VLC_FALSE;
        looping.b_bool = VLC_FALSE;
        config_PutInt( p_playlist, "repeat", 0 ); 
        config_PutInt( p_playlist, "loop", 0 ); 
        
        /* show the change */
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat Off" ) );
    }

    /* communicate with core and the main intf loop */
    var_Set( p_playlist, "repeat", repeating );
    var_Set( p_playlist, "loop", looping );    
    p_intf->p_sys->b_playmode_update = VLC_TRUE;
    p_intf->p_sys->b_intf_update = VLC_TRUE;

    vlc_object_release( p_playlist );
}


hartman's avatar
hartman committed
279
280
281
- (IBAction)repeat:(id)sender
{
    vlc_value_t val;
282
    intf_thread_t * p_intf = VLCIntf;
283
    playlist_t * p_playlist = pl_Yield( p_intf );
284

hartman's avatar
hartman committed
285
    var_Get( p_playlist, "repeat", &val );
286
    if (!val.b_bool)
287
    {
288
        var_Set( p_playlist, "loop", val );
289
    }
hartman's avatar
hartman committed
290
291
    val.b_bool = !val.b_bool;
    var_Set( p_playlist, "repeat", val );
292
293
    if( val.b_bool )
    {
294
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat One" ) );
295
        config_PutInt( p_playlist, "repeat", 1 );
296
297
298
    }
    else
    {
299
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat Off" ) );
300
        config_PutInt( p_playlist, "repeat", 0 );
bigben's avatar
bigben committed
301
    }
302
    
303
    p_intf->p_sys->b_playmode_update = VLC_TRUE;
bigben's avatar
bigben committed
304
    p_intf->p_sys->b_intf_update = VLC_TRUE;
hartman's avatar
hartman committed
305
306
307
308
309
310
    vlc_object_release( p_playlist );
}

- (IBAction)loop:(id)sender
{
    vlc_value_t val;
311
    intf_thread_t * p_intf = VLCIntf;
312
    playlist_t * p_playlist = pl_Yield( p_intf );
hartman's avatar
hartman committed
313
314

    var_Get( p_playlist, "loop", &val );
315
316
317
318
    if (!val.b_bool)
    {
        var_Set( p_playlist, "repeat", val );
    }
hartman's avatar
hartman committed
319
320
    val.b_bool = !val.b_bool;
    var_Set( p_playlist, "loop", val );
321
322
    if( val.b_bool )
    {
323
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat All" ) );
324
        config_PutInt( p_playlist, "loop", 1 );
325
326
327
    }
    else
    {
328
        vout_OSDMessage( p_intf, DEFAULT_CHAN, _( "Repeat Off" ) );
329
        config_PutInt( p_playlist, "loop", 0 );
330
    }
331

332
    p_intf->p_sys->b_playmode_update = VLC_TRUE;
bigben's avatar
bigben committed
333
    p_intf->p_sys->b_intf_update = VLC_TRUE;
334
335
336
    vlc_object_release( p_playlist );
}

337
338
- (IBAction)forward:(id)sender
{
339
    vlc_value_t val;
hartman's avatar
hartman committed
340
    intf_thread_t * p_intf = VLCIntf;
341
    val.i_int = config_GetInt( p_intf, "key-jump+short" );
342
    var_Set( p_intf->p_libvlc, "key-pressed", val );
343
344
}

345
346
- (IBAction)backward:(id)sender
{
347
    vlc_value_t val;
hartman's avatar
hartman committed
348
    intf_thread_t * p_intf = VLCIntf;
349
    val.i_int = config_GetInt( p_intf, "key-jump-short" );
350
    var_Set( p_intf->p_libvlc, "key-pressed", val );
351
352
}

353

354
355
- (IBAction)volumeUp:(id)sender
{
356
    vlc_value_t val;
hartman's avatar
hartman committed
357
    intf_thread_t * p_intf = VLCIntf;
358
    val.i_int = config_GetInt( p_intf, "key-vol-up" );
359
    var_Set( p_intf->p_libvlc, "key-pressed", val );
360
361
    /* Manage volume status */
    [o_main manageVolumeSlider];
362
363
364
365
}

- (IBAction)volumeDown:(id)sender
{
366
    vlc_value_t val;
hartman's avatar
hartman committed
367
    intf_thread_t * p_intf = VLCIntf;
368
    val.i_int = config_GetInt( p_intf, "key-vol-down" );
369
    var_Set( p_intf->p_libvlc, "key-pressed", val );
370
371
    /* Manage volume status */
    [o_main manageVolumeSlider];
372
373
374
375
}

- (IBAction)mute:(id)sender
{
376
    vlc_value_t val;
hartman's avatar
hartman committed
377
    intf_thread_t * p_intf = VLCIntf;
378
    val.i_int = config_GetInt( p_intf, "key-vol-mute" );
379
    var_Set( p_intf->p_libvlc, "key-pressed", val );
380
381
    /* Manage volume status */
    [o_main manageVolumeSlider];
hartman's avatar
hartman committed
382
383
}

384
- (IBAction)volumeSliderUpdated:(id)sender
hartman's avatar
hartman committed
385
{
hartman's avatar
hartman committed
386
    intf_thread_t * p_intf = VLCIntf;
387
    audio_volume_t i_volume = (audio_volume_t)[sender intValue];
388
    int i_volume_step = 0;
389
    i_volume_step = config_GetInt( p_intf->p_libvlc, "volume-step" );
390
    aout_VolumeSet( p_intf, i_volume * i_volume_step );
391
392
    /* Manage volume status */
    [o_main manageVolumeSlider];
393
394
}

395
- (IBAction)windowAction:(id)sender
396
{
397
    NSString *o_title = [sender title];
398

399
    vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
400
401
                                              FIND_ANYWHERE );
    if( p_vout != NULL )
402
    {
403
404
        id o_vout_view = [self getVoutView];
        if( o_vout_view )
hartman's avatar
hartman committed
405
        {
406
407
408
409
410
411
412
413
414
            if( [o_title isEqualToString: _NS("Half Size") ] )
                [o_vout_view scaleWindowWithFactor: 0.5];
            else if( [o_title isEqualToString: _NS("Normal Size") ] )
                [o_vout_view scaleWindowWithFactor: 1.0];
            else if( [o_title isEqualToString: _NS("Double Size") ] )
                [o_vout_view scaleWindowWithFactor: 2.0];
            else if( [o_title isEqualToString: _NS("Float on Top") ] )
                [o_vout_view toggleFloatOnTop];
            else if( [o_title isEqualToString: _NS("Fit to Screen") ] )
415
            {
416
417
418
                id o_window = [o_vout_view getWindow];
                if( ![o_window isZoomed] )
                    [o_window performZoom:self];
419
            }
420
            else if( [o_title isEqualToString: _NS("Snapshot") ] )
421
            {
422
                [o_vout_view snapshot];
423
            }
424
            else
425
            {
426
                [o_vout_view toggleFullscreen];
427
            }
hartman's avatar
hartman committed
428
        }
429
        vlc_object_release( (vlc_object_t *)p_vout );
hartman's avatar
hartman committed
430
    }
431
    else
bigben's avatar
bigben committed
432
    {
433
        playlist_t * p_playlist = pl_Yield( VLCIntf );
434

435
436
        if( [o_title isEqualToString: _NS("Fullscreen")] ||
            [sender isKindOfClass:[NSButton class]] )
bigben's avatar
bigben committed
437
438
439
440
441
        {
            vlc_value_t val;
            var_Get( p_playlist, "fullscreen", &val );
            var_Set( p_playlist, "fullscreen", (vlc_value_t)!val.b_bool );
        }
442
443

        vlc_object_release( p_playlist );
bigben's avatar
bigben committed
444
445
    }

hartman's avatar
hartman committed
446
447
}

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
- (BOOL)keyEvent:(NSEvent *)o_event
{
    BOOL eventHandled = NO;
    unichar key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0];

    if( key )
    {
        vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
                                              FIND_ANYWHERE );
        if( p_vout != NULL )
        {
            /* Escape */
            if( key == (unichar) 0x1b )
            {
                id o_vout_view = [self getVoutView];
                if( o_vout_view && [o_vout_view isFullscreen] )
                {
                    [o_vout_view toggleFullscreen];
                    eventHandled = YES;
                }
            }
            else if( key == ' ' )
            {
                [self play:self];
                eventHandled = YES;
            }
            vlc_object_release( (vlc_object_t *)p_vout );
        }
    }
    return eventHandled;
}

hartman's avatar
* ALL:    
hartman committed
480
481
482
483
- (void)setupVarMenuItem:(NSMenuItem *)o_mi
                    target:(vlc_object_t *)p_object
                    var:(const char *)psz_variable
                    selector:(SEL)pf_callback
484
{
hartman's avatar
* ALL:    
hartman committed
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
    vlc_value_t val, text;
    int i_type = var_Type( p_object, psz_variable );

    switch( i_type & VLC_VAR_TYPE )
    {
    case VLC_VAR_VOID:
    case VLC_VAR_BOOL:
    case VLC_VAR_VARIABLE:
    case VLC_VAR_STRING:
    case VLC_VAR_INTEGER:
        break;
    default:
        /* Variable doesn't exist or isn't handled */
        return;
    }
    
    /* Make sure we want to display the variable */
    if( i_type & VLC_VAR_HASCHOICE )
    {
        var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
        if( val.i_int == 0 ) return;
        if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
            return;
    }
    
    /* Get the descriptive name of the variable */
    var_Change( p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL );
hartman's avatar
hartman committed
512
    [o_mi setTitle: [[VLCMain sharedInstance] localizedString: text.psz_string ?
hartman's avatar
* ALL:    
hartman committed
513
                                        text.psz_string : strdup( psz_variable ) ]];
514

hartman's avatar
* ALL:    
hartman committed
515
516
    var_Get( p_object, psz_variable, &val );
    if( i_type & VLC_VAR_HASCHOICE )
517
    {
hartman's avatar
* ALL:    
hartman committed
518
519
520
521
522
523
524
        NSMenu *o_menu = [o_mi submenu];

        [self setupVarMenu: o_menu forMenuItem: o_mi target:p_object
                        var:psz_variable selector:pf_callback];
        
        if( text.psz_string ) free( text.psz_string );
        return;
525
    }
hartman's avatar
* ALL:    
hartman committed
526
527
528

    VLCMenuExt *o_data;
    switch( i_type & VLC_VAR_TYPE )
529
    {
hartman's avatar
* ALL:    
hartman committed
530
531
532
533
534
535
536
537
538
539
    case VLC_VAR_VOID:
        o_data = [[VLCMenuExt alloc] initWithVar: psz_variable Object: p_object->i_object_id
                Value: val ofType: i_type];
        [o_mi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
        break;

    case VLC_VAR_BOOL:
        o_data = [[VLCMenuExt alloc] initWithVar: psz_variable Object: p_object->i_object_id
                Value: val ofType: i_type];
        [o_mi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
540
541
        if( !( i_type & VLC_VAR_ISCOMMAND ) )
            [o_mi setState: val.b_bool ? TRUE : FALSE ];
hartman's avatar
* ALL:    
hartman committed
542
543
544
545
546
        break;

    default:
        if( text.psz_string ) free( text.psz_string );
        return;
547
    }
hartman's avatar
* ALL:    
hartman committed
548

549
    if( ( i_type & VLC_VAR_TYPE ) == VLC_VAR_STRING ) free( val.psz_string );
hartman's avatar
* ALL:    
hartman committed
550
    if( text.psz_string ) free( text.psz_string );
551
}
552

hartman's avatar
* ALL:    
hartman committed
553
554
555
556
557
558

- (void)setupVarMenu:(NSMenu *)o_menu
                    forMenuItem: (NSMenuItem *)o_parent
                    target:(vlc_object_t *)p_object
                    var:(const char *)psz_variable
                    selector:(SEL)pf_callback
559
{
hartman's avatar
* ALL:    
hartman committed
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
    vlc_value_t val, val_list, text_list;
    int i_type, i, i_nb_items;

    /* remove previous items */
    i_nb_items = [o_menu numberOfItems];
    for( i = 0; i < i_nb_items; i++ )
    {
        [o_menu removeItemAtIndex: 0];
    }

    /* Check the type of the object variable */
    i_type = var_Type( p_object, psz_variable );

    /* Make sure we want to display the variable */
    if( i_type & VLC_VAR_HASCHOICE )
    {
        var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
        if( val.i_int == 0 ) return;
        if( (i_type & VLC_VAR_TYPE) != VLC_VAR_VARIABLE && val.i_int == 1 )
            return;
    }
    else
    {
        return;
    }

    switch( i_type & VLC_VAR_TYPE )
587
    {
hartman's avatar
* ALL:    
hartman committed
588
589
590
591
592
593
594
595
596
597
    case VLC_VAR_VOID:
    case VLC_VAR_BOOL:
    case VLC_VAR_VARIABLE:
    case VLC_VAR_STRING:
    case VLC_VAR_INTEGER:
        break;
    default:
        /* Variable doesn't exist or isn't handled */
        return;
    }
598

hartman's avatar
* ALL:    
hartman committed
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
    if( var_Get( p_object, psz_variable, &val ) < 0 )
    {
        return;
    }

    if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST,
                    &val_list, &text_list ) < 0 )
    {
        if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
        return;
    }

    /* make (un)sensitive */
    [o_parent setEnabled: ( val_list.p_list->i_count > 1 )];

    for( i = 0; i < val_list.p_list->i_count; i++ )
    {
        vlc_value_t another_val;
        NSMenuItem * o_lmi;
        NSString *o_title = @"";
        VLCMenuExt *o_data;

        switch( i_type & VLC_VAR_TYPE )
622
        {
hartman's avatar
* ALL:    
hartman committed
623
624
625
626
        case VLC_VAR_STRING:
            another_val.psz_string =
                strdup(val_list.p_list->p_values[i].psz_string);

hartman's avatar
hartman committed
627
            o_title = [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string ?
hartman's avatar
* ALL:    
hartman committed
628
629
630
631
632
633
634
                text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string ];

            o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""];
            o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
                    Value: another_val ofType: i_type];
            [o_lmi setRepresentedObject: [NSValue valueWithPointer:[o_data retain]]];
            [o_lmi setTarget: self];
635

636
            if( !strcmp( val.psz_string, val_list.p_list->p_values[i].psz_string ) && !( i_type & VLC_VAR_ISCOMMAND ) )
hartman's avatar
* ALL:    
hartman committed
637
638
639
640
641
642
643
                [o_lmi setState: TRUE ];

            break;

        case VLC_VAR_INTEGER:

             o_title = text_list.p_list->p_values[i].psz_string ?
hartman's avatar
hartman committed
644
                                 [[VLCMain sharedInstance] localizedString: strdup( text_list.p_list->p_values[i].psz_string )] :
hartman's avatar
* ALL:    
hartman committed
645
646
647
648
649
650
651
652
653
                                 [NSString stringWithFormat: @"%d",
                                 val_list.p_list->p_values[i].i_int];

            o_lmi = [[o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""] retain ];
            o_data = [[VLCMenuExt alloc] initWithVar: strdup(psz_variable) Object: p_object->i_object_id
                    Value: val_list.p_list->p_values[i] ofType: i_type];
            [o_lmi setRepresentedObject: [NSValue valueWithPointer:[ o_data retain]]];
            [o_lmi setTarget: self];

654
            if( val_list.p_list->p_values[i].i_int == val.i_int && !( i_type & VLC_VAR_ISCOMMAND ) )
hartman's avatar
* ALL:    
hartman committed
655
656
657
658
659
                [o_lmi setState: TRUE ];
            break;

        default:
          break;
660
661
        }
    }
662

hartman's avatar
* ALL:    
hartman committed
663
    /* clean up everything */
664
    if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
hartman's avatar
* ALL:    
hartman committed
665
666
667
668
669
670
671
    var_Change( p_object, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list );
}

- (IBAction)toggleVar:(id)sender
{
    NSMenuItem *o_mi = (NSMenuItem *)sender;
    VLCMenuExt *o_data = [[o_mi representedObject] pointerValue];
672
673
674
675
676
677
678
679
    [NSThread detachNewThreadSelector: @selector(toggleVarThread:)
        toTarget: self withObject: o_data];

    return;
}

- (int)toggleVarThread: (id)_o_data
{
hartman's avatar
* ALL:    
hartman committed
680
    vlc_object_t *p_object;
681
682
683
    NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
    VLCMenuExt *o_data = (VLCMenuExt *)_o_data;

hartman's avatar
hartman committed
684
    vlc_thread_set_priority( VLCIntf , VLC_THREAD_PRIORITY_LOW );
hartman's avatar
* ALL:    
hartman committed
685

hartman's avatar
hartman committed
686
    p_object = (vlc_object_t *)vlc_object_get( VLCIntf,
hartman's avatar
* ALL:    
hartman committed
687
688
                                    [o_data objectID] );

689
690
691
692
693
694
695
696
697
    if( p_object != NULL )
    {
        var_Set( p_object, strdup([o_data name]), [o_data value] );
        vlc_object_release( p_object );
        [o_pool release];
        return VLC_TRUE;
    }
    [o_pool release];
    return VLC_EGENERIC;
698
699
}

700
701
702
703
704
705
706
707
708
709
710
711
712
- (IBAction)goToSpecificTime:(id)sender
{
    if( sender == o_specificTime_cancel_btn )
    {
        [NSApp endSheet: o_specificTime_win];
        [o_specificTime_win close];
    }
    else if( sender == o_specificTime_ok_btn )
    {
        input_thread_t * p_input = (input_thread_t *)vlc_object_find( VLCIntf, \
            VLC_OBJECT_INPUT, FIND_ANYWHERE );
        if( p_input )
        {
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
            unsigned int timeInSec = 0;
            NSString * fieldContent = [o_specificTime_enter_fld stringValue];
            if( [[fieldContent componentsSeparatedByString: @":"] count] > 1 && 
                [[fieldContent componentsSeparatedByString: @":"] count] <= 3 )
            {
                NSArray * ourTempArray = \
                    [fieldContent componentsSeparatedByString: @":"];

                if( [[fieldContent componentsSeparatedByString: @":"] count] == 3 )
                {
                    timeInSec += ([[ourTempArray objectAtIndex: 0] intValue] * 3600); //h
                    timeInSec += ([[ourTempArray objectAtIndex: 1] intValue] * 60); //m
                    timeInSec += [[ourTempArray objectAtIndex: 2] intValue];        //s
                }
                else
                {
                    timeInSec += ([[ourTempArray objectAtIndex: 0] intValue] * 60); //m
                    timeInSec += [[ourTempArray objectAtIndex: 1] intValue]; //s
                }
            }
            else
                timeInSec = [fieldContent intValue];

            input_Control( p_input, INPUT_SET_TIME, (int64_t)(timeInSec * 1000000));
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
            vlc_object_release( p_input );
        }
    
        [NSApp endSheet: o_specificTime_win];
        [o_specificTime_win close];
    }
    else
    {
        input_thread_t * p_input = (input_thread_t *)vlc_object_find( VLCIntf, \
            VLC_OBJECT_INPUT, FIND_ANYWHERE );
        if( p_input )
        {
            /* we can obviously only do that if an input is available */
            vlc_value_t pos, length;
            var_Get( p_input, "time", &pos );
            [o_specificTime_enter_fld setIntValue: (pos.i_time / 1000000)];
            var_Get( p_input, "length", &length );
            [o_specificTime_stepper setMaxValue: (length.i_time / 1000000)];

            [NSApp beginSheet: o_specificTime_win modalForWindow: \
                [NSApp mainWindow] modalDelegate: self didEndSelector: nil \
                contextInfo: nil];
            [o_specificTime_win makeKeyWindow];
            vlc_object_release( p_input );
        }
    }
}

765
766
767
768
769
770
771
772
773
774
775
- (id)getFSPanel
{
    if( o_fs_panel )
        return o_fs_panel;
    else
    {
        msg_Err( VLCIntf, "FSPanel is nil" );
        return NULL;
    }
}

776
777
778
@end

@implementation VLCControls (NSMenuValidation)
779

780
781
782
- (BOOL)validateMenuItem:(NSMenuItem *)o_mi
{
    BOOL bEnabled = TRUE;
hartman's avatar
hartman committed
783
    vlc_value_t val;
hartman's avatar
hartman committed
784
    intf_thread_t * p_intf = VLCIntf;
785
    playlist_t * p_playlist = pl_Yield( p_intf );
786

787
    vlc_mutex_lock( &p_playlist->object_lock );
788

789
790
#define p_input p_playlist->p_input

hartman's avatar
hartman committed
791
    if( [[o_mi title] isEqualToString: _NS("Faster")] ||
792
793
        [[o_mi title] isEqualToString: _NS("Slower")] )
    {
794
        if( p_input != NULL )
795
        {
796
            bEnabled = p_input->input.b_can_pace_control;
797
798
799
800
801
802
803
804
        }
        else
        {
            bEnabled = FALSE;
        }
    }
    else if( [[o_mi title] isEqualToString: _NS("Stop")] )
    {
805
        if( p_input == NULL )
806
807
808
        {
            bEnabled = FALSE;
        }
809
        [o_main setupMenus]; /* Make sure input menu is up to date */
810
    }
Jon Lech Johansen's avatar
Jon Lech Johansen committed
811
    else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
812
813
814
815
             [[o_mi title] isEqualToString: _NS("Next")] )
    {
            bEnabled = p_playlist->i_size > 1;
    }
816
    else if( [[o_mi title] isEqualToString: _NS("Random")] )
817
    {
hartman's avatar
hartman committed
818
819
820
821
822
        int i_state;
        var_Get( p_playlist, "random", &val );
        i_state = val.b_bool ? NSOnState : NSOffState;
        [o_mi setState: i_state];
    }
823
    else if( [[o_mi title] isEqualToString: _NS("Repeat One")] )
hartman's avatar
hartman committed
824
825
826
827
828
829
    {
        int i_state;
        var_Get( p_playlist, "repeat", &val );
        i_state = val.b_bool ? NSOnState : NSOffState;
        [o_mi setState: i_state];
    }
830
    else if( [[o_mi title] isEqualToString: _NS("Repeat All")] )
hartman's avatar
hartman committed
831
832
833
834
    {
        int i_state;
        var_Get( p_playlist, "loop", &val );
        i_state = val.b_bool ? NSOnState : NSOffState;
835
836
        [o_mi setState: i_state];
    }
837
    else if( [[o_mi title] isEqualToString: _NS("Step Forward")] ||
838
839
             [[o_mi title] isEqualToString: _NS("Step Backward")] ||
             [[o_mi title] isEqualToString: _NS("Jump To Time")])
840
    {
841
        if( p_input != NULL )
842
        {
843
            var_Get( p_input, "seekable", &val);
844
            bEnabled = val.b_bool;
845
        }
846
        else bEnabled = FALSE;
847
    }
848
    else if( [[o_mi title] isEqualToString: _NS("Mute")] )
849
850
    {
        [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
851
        [o_main setupMenus]; /* Make sure audio menu is up to date */
852
    }
bigben's avatar
bigben committed
853
    else if( [[o_mi title] isEqualToString: _NS("Half Size")] ||
854
                [[o_mi title] isEqualToString: _NS("Normal Size")] ||
hartman's avatar
hartman committed
855
                [[o_mi title] isEqualToString: _NS("Double Size")] ||
856
                [[o_mi title] isEqualToString: _NS("Fit to Screen")] ||
857
                [[o_mi title] isEqualToString: _NS("Snapshot")] ||
858
                [[o_mi title] isEqualToString: _NS("Fullscreen")] ||
859
                [[o_mi title] isEqualToString: _NS("Float on Top")] )
860
    {
861
        id o_window;
862
        NSArray *o_windows = [NSApp orderedWindows];
863
864
865
        NSEnumerator *o_enumerator = [o_windows objectEnumerator];
        bEnabled = FALSE;
        
866
867
868
        vout_thread_t   *p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
                                              FIND_ANYWHERE );
        if( p_vout != NULL )
869
        {
870
            if( [[o_mi title] isEqualToString: _NS("Float on Top")] )
871
872
873
874
875
            {
                var_Get( p_vout, "video-on-top", &val );
                [o_mi setState: val.b_bool ?  NSOnState : NSOffState];
            }

876
            while( (o_window = [o_enumerator nextObject]))
877
            {
878
879
880
                if( [[o_window className] isEqualToString: @"VLCWindow"] ||
                            [[[VLCMain sharedInstance] getEmbeddedList]
                            windowContainsEmbedded: o_window])
881
882
883
884
                {
                    bEnabled = TRUE;
                    break;
                }
885
            }
886
            vlc_object_release( (vlc_object_t *)p_vout );
887
        }
888
        else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )
bigben's avatar
bigben committed
889
        {
890
            var_Get( p_playlist, "fullscreen", &val );
bigben's avatar
bigben committed
891
892
893
            [o_mi setState: val.b_bool];
            bEnabled = TRUE;
        }
894
        [o_main setupMenus]; /* Make sure video menu is up to date */
bigben's avatar
bigben committed
895
896
    }

897
898
    vlc_mutex_unlock( &p_playlist->object_lock );
    vlc_object_release( p_playlist );
899

900
901
902
903
    return( bEnabled );
}

@end
hartman's avatar
* ALL:    
hartman committed
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931

/*****************************************************************************
 * VLCMenuExt implementation 
 *****************************************************************************
 * Object connected to a playlistitem which remembers the data belonging to
 * the variable of the autogenerated menu
 *****************************************************************************/
@implementation VLCMenuExt

- (id)initWithVar: (const char *)_psz_name Object: (int)i_id
        Value: (vlc_value_t)val ofType: (int)_i_type
{
    self = [super init];

    if( self != nil )
    {
        psz_name = strdup( _psz_name );
        i_object_id = i_id;
        value = val;
        i_type = _i_type;
    }

    return( self );
}

- (void)dealloc
{
    free( psz_name );
932
    [super dealloc];
hartman's avatar
* ALL:    
hartman committed
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
}

- (char *)name
{
    return psz_name;
}

- (int)objectID
{
    return i_object_id;
}

- (vlc_value_t)value
{
    return value;
}

- (int)type
{
    return i_type;
}

@end
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970


/*****************************************************************************
 * VLCTimeField implementation 
 *****************************************************************************
 * we need this to catch our click-event in the controller window
 *****************************************************************************/

@implementation VLCTimeField
- (void)mouseDown: (NSEvent *)ourEvent
{
    if( [ourEvent clickCount] > 1 )
        [[[VLCMain sharedInstance] getControls] goToSpecificTime: nil];
}
@end