controls.m 29.4 KB
Newer Older
1
/*****************************************************************************
2
 * controls.m: MacOS X interface module
3
 *****************************************************************************
4
 * Copyright (C) 2002-2006 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
 *          Felix Khne <fkuehne at videolan dot org>
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * 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
25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26
27
28
29
30
31
32
33
34
 *****************************************************************************/

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

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

zorglub's avatar
Ah Ah    
zorglub committed
42
43
44
/* UGLY UGLY UGLY FIXME FIXME FIXME. Need solution for b_can_pace_control.
 * Put it public ? Is it needed here ?*/
#include "../../../src/input/input_internal.h"
45

46
47
48
49
50
/*****************************************************************************
 * VLCControls implementation 
 *****************************************************************************/
@implementation VLCControls

51
52
53
54
55
56
57
- (id)init
{
    [super init];
    o_fs_panel = [[VLCFSPanel alloc] init];
    return self;
}

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

67
68
- (IBAction)play:(id)sender
{
hartman's avatar
hartman committed
69
    vlc_value_t val;
hartman's avatar
hartman committed
70
    intf_thread_t * p_intf = VLCIntf;
71
    playlist_t * p_playlist = pl_Yield( p_intf );
72

73
    vlc_mutex_lock( &p_playlist->object_lock );
zorglub's avatar
zorglub committed
74
    if( playlist_IsEmpty( p_playlist ) )
75
76
77
78
79
80
81
82
83
    {
        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 );
84
    }
85

86
    val.i_int = config_GetInt( p_intf, "key-play-pause" );
87
    var_Set( p_intf->p_libvlc, "key-pressed", val );
88
89
}

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* 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;
}


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

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

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

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

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

hartman's avatar
hartman committed
156
- (IBAction)random:(id)sender
157
{
hartman's avatar
hartman committed
158
    vlc_value_t val;
159
    intf_thread_t * p_intf = VLCIntf;
160
    playlist_t * p_playlist = pl_Yield( p_intf );
hartman's avatar
hartman committed
161
162
163
164

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

176
    p_intf->p_sys->b_playmode_update = VLC_TRUE;
bigben's avatar
bigben committed
177
    p_intf->p_sys->b_intf_update = VLC_TRUE;
hartman's avatar
hartman committed
178
179
    vlc_object_release( p_playlist );
}
180

181
182
183
/* three little ugly helpers */
- (void)repeatOne
{
184
185
    [o_btn_repeat setImage: [NSImage imageNamed:@"repeat_single_embedded_blue"]];
    [o_btn_repeat setAlternateImage: [NSImage imageNamed:@"repeat_embedded_blue"]];
186
187
188
}
- (void)repeatAll
{
189
190
    [o_btn_repeat setImage: [NSImage imageNamed:@"repeat_embedded_blue"]];
    [o_btn_repeat setAlternateImage: [NSImage imageNamed:@"repeat_embedded"]];
191
192
193
}
- (void)repeatOff
{
194
195
    [o_btn_repeat setImage: [NSImage imageNamed:@"repeat_embedded"]];
    [o_btn_repeat setAlternateImage: [NSImage imageNamed:@"repeat_single_embedded_blue"]];
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
}
- (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 );

    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
274
275
276
- (IBAction)repeat:(id)sender
{
    vlc_value_t val;
277
    intf_thread_t * p_intf = VLCIntf;
278
    playlist_t * p_playlist = pl_Yield( p_intf );
279

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

- (IBAction)loop:(id)sender
{
    vlc_value_t val;
306
    intf_thread_t * p_intf = VLCIntf;
307
    playlist_t * p_playlist = pl_Yield( p_intf );
hartman's avatar
hartman committed
308
309

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

327
    p_intf->p_sys->b_playmode_update = VLC_TRUE;
bigben's avatar
bigben committed
328
    p_intf->p_sys->b_intf_update = VLC_TRUE;
329
330
331
    vlc_object_release( p_playlist );
}

332
333
- (IBAction)forward:(id)sender
{
334
    vlc_value_t val;
hartman's avatar
hartman committed
335
    intf_thread_t * p_intf = VLCIntf;
336
    val.i_int = config_GetInt( p_intf, "key-jump+short" );
337
    var_Set( p_intf->p_libvlc, "key-pressed", val );
338
339
}

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

348

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

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

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

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

390
- (IBAction)windowAction:(id)sender
391
{
392
    NSString *o_title = [sender title];
393

394
    vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
395
396
                                              FIND_ANYWHERE );
    if( p_vout != NULL )
397
    {
398
399
        id o_vout_view = [self getVoutView];
        if( o_vout_view )
hartman's avatar
hartman committed
400
        {
401
402
403
404
405
406
407
408
409
            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") ] )
410
            {
411
412
413
                id o_window = [o_vout_view getWindow];
                if( ![o_window isZoomed] )
                    [o_window performZoom:self];
414
            }
415
            else if( [o_title isEqualToString: _NS("Snapshot") ] )
416
            {
417
                [o_vout_view snapshot];
418
            }
419
            else
420
            {
421
                [o_vout_view toggleFullscreen];
422
            }
hartman's avatar
hartman committed
423
        }
424
        vlc_object_release( (vlc_object_t *)p_vout );
hartman's avatar
hartman committed
425
    }
426
    else
bigben's avatar
bigben committed
427
    {
428
        playlist_t * p_playlist = pl_Yield( VLCIntf );
429

430
431
        if( [o_title isEqualToString: _NS("Fullscreen")] ||
            [sender isKindOfClass:[NSButton class]] )
bigben's avatar
bigben committed
432
433
434
435
436
        {
            vlc_value_t val;
            var_Get( p_playlist, "fullscreen", &val );
            var_Set( p_playlist, "fullscreen", (vlc_value_t)!val.b_bool );
        }
437
438

        vlc_object_release( p_playlist );
bigben's avatar
bigben committed
439
440
    }

hartman's avatar
hartman committed
441
442
}

443
444
445
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
- (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
475
476
477
478
- (void)setupVarMenuItem:(NSMenuItem *)o_mi
                    target:(vlc_object_t *)p_object
                    var:(const char *)psz_variable
                    selector:(SEL)pf_callback
479
{
hartman's avatar
* ALL:    
hartman committed
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
    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
507
    [o_mi setTitle: [[VLCMain sharedInstance] localizedString: text.psz_string ?
hartman's avatar
* ALL:    
hartman committed
508
                                        text.psz_string : strdup( psz_variable ) ]];
509

hartman's avatar
* ALL:    
hartman committed
510
511
    var_Get( p_object, psz_variable, &val );
    if( i_type & VLC_VAR_HASCHOICE )
512
    {
hartman's avatar
* ALL:    
hartman committed
513
514
515
516
517
518
519
        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;
520
    }
hartman's avatar
* ALL:    
hartman committed
521
522
523

    VLCMenuExt *o_data;
    switch( i_type & VLC_VAR_TYPE )
524
    {
hartman's avatar
* ALL:    
hartman committed
525
526
527
528
529
530
531
532
533
534
    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]]];
535
536
        if( !( i_type & VLC_VAR_ISCOMMAND ) )
            [o_mi setState: val.b_bool ? TRUE : FALSE ];
hartman's avatar
* ALL:    
hartman committed
537
538
539
540
541
        break;

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

544
    if( ( i_type & VLC_VAR_TYPE ) == VLC_VAR_STRING ) free( val.psz_string );
hartman's avatar
* ALL:    
hartman committed
545
    if( text.psz_string ) free( text.psz_string );
546
}
547

hartman's avatar
* ALL:    
hartman committed
548
549
550
551
552
553

- (void)setupVarMenu:(NSMenu *)o_menu
                    forMenuItem: (NSMenuItem *)o_parent
                    target:(vlc_object_t *)p_object
                    var:(const char *)psz_variable
                    selector:(SEL)pf_callback
554
{
hartman's avatar
* ALL:    
hartman committed
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
    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 )
582
    {
hartman's avatar
* ALL:    
hartman committed
583
584
585
586
587
588
589
590
591
592
    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;
    }
593

hartman's avatar
* ALL:    
hartman committed
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
    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 )
617
        {
hartman's avatar
* ALL:    
hartman committed
618
619
620
621
        case VLC_VAR_STRING:
            another_val.psz_string =
                strdup(val_list.p_list->p_values[i].psz_string);

hartman's avatar
hartman committed
622
            o_title = [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string ?
hartman's avatar
* ALL:    
hartman committed
623
624
625
626
627
628
629
                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];
630

631
            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
632
633
634
635
636
637
638
                [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
639
                                 [[VLCMain sharedInstance] localizedString: strdup( text_list.p_list->p_values[i].psz_string )] :
hartman's avatar
* ALL:    
hartman committed
640
641
642
643
644
645
646
647
648
                                 [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];

649
            if( val_list.p_list->p_values[i].i_int == val.i_int && !( i_type & VLC_VAR_ISCOMMAND ) )
hartman's avatar
* ALL:    
hartman committed
650
651
652
653
654
                [o_lmi setState: TRUE ];
            break;

        default:
          break;
655
656
        }
    }
657

hartman's avatar
* ALL:    
hartman committed
658
    /* clean up everything */
659
    if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
hartman's avatar
* ALL:    
hartman committed
660
661
662
663
664
665
666
    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];
667
668
669
670
671
672
673
674
    [NSThread detachNewThreadSelector: @selector(toggleVarThread:)
        toTarget: self withObject: o_data];

    return;
}

- (int)toggleVarThread: (id)_o_data
{
hartman's avatar
* ALL:    
hartman committed
675
    vlc_object_t *p_object;
676
677
678
    NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
    VLCMenuExt *o_data = (VLCMenuExt *)_o_data;

hartman's avatar
hartman committed
679
    vlc_thread_set_priority( VLCIntf , VLC_THREAD_PRIORITY_LOW );
hartman's avatar
* ALL:    
hartman committed
680

hartman's avatar
hartman committed
681
    p_object = (vlc_object_t *)vlc_object_get( VLCIntf,
hartman's avatar
* ALL:    
hartman committed
682
683
                                    [o_data objectID] );

684
685
686
687
688
689
690
691
692
    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;
693
694
}

695
696
697
698
699
700
701
702
703
704
705
706
707
- (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 )
        {
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
            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));
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
            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 );
        }
    }
}

760
761
762
763
764
765
766
767
768
769
770
- (id)getFSPanel
{
    if( o_fs_panel )
        return o_fs_panel;
    else
    {
        msg_Err( VLCIntf, "FSPanel is nil" );
        return NULL;
    }
}

771
772
773
@end

@implementation VLCControls (NSMenuValidation)
774

775
776
777
- (BOOL)validateMenuItem:(NSMenuItem *)o_mi
{
    BOOL bEnabled = TRUE;
hartman's avatar
hartman committed
778
    vlc_value_t val;
hartman's avatar
hartman committed
779
    intf_thread_t * p_intf = VLCIntf;
780
    playlist_t * p_playlist = pl_Yield( p_intf );
781

782
    vlc_mutex_lock( &p_playlist->object_lock );
783

784
785
#define p_input p_playlist->p_input

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

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

893
894
    vlc_mutex_unlock( &p_playlist->object_lock );
    vlc_object_release( p_playlist );
895

896
897
898
899
    return( bEnabled );
}

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

/*****************************************************************************
 * 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 );
928
    [super dealloc];
hartman's avatar
* ALL:    
hartman committed
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
}

- (char *)name
{
    return psz_name;
}

- (int)objectID
{
    return i_object_id;
}

- (vlc_value_t)value
{
    return value;
}

- (int)type
{
    return i_type;
}

@end
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966


/*****************************************************************************
 * 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