intf.m 87.4 KB
Newer Older
1
/*****************************************************************************
2
 * intf.m: MacOS X interface module
3
 *****************************************************************************
4
 * Copyright (C) 2002-2009 the VideoLAN team
5
 * $Id$
6
7
8
 *
 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
 *          Christophe Massiot <massiot@via.ecp.fr>
9
 *          Derk-Jan Hartman <hartman at videolan.org>
10
 *          Felix Paul Kühne <fkuehne at videolan dot org>
11
12
13
14
15
 *
 * 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.
16
 *
17
18
19
20
21
22
23
 * 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
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
#include <sys/param.h>                                    /* for MAXPATHLEN */
#include <string.h>
33
#include <vlc_keys.h>
34
#include <unistd.h> /* execl() */
35

Rafaël Carré's avatar
Rafaël Carré committed
36
37
38
39
#ifdef HAVE_CONFIG_H
#   include "config.h"
#endif

40
41
42
43
44
#import "intf.h"
#import "fspanel.h"
#import "vout.h"
#import "prefs.h"
#import "playlist.h"
45
#import "playlistinfo.h"
46
47
48
49
50
51
52
53
54
55
#import "controls.h"
#import "about.h"
#import "open.h"
#import "wizard.h"
#import "extended.h"
#import "bookmarks.h"
#import "interaction.h"
#import "embeddedwindow.h"
#import "update.h"
#import "AppleRemote.h"
56
#import "eyetv.h"
57
#import "simple_prefs.h"
58
#import "vlm.h"
59

60
#import <vlc_input.h>
61
#import <vlc_interface.h>
62
#import <AddressBook/AddressBook.h>
63

64
65
66
/*****************************************************************************
 * Local prototypes.
 *****************************************************************************/
67
static void Run ( intf_thread_t *p_intf );
68

69
static void * ManageThread( void *user_data );
70

71
72
static unichar VLCKeyToCocoa( unsigned int i_key );
static unsigned int VLCModifiersToCocoa( unsigned int i_key );
73

74
#pragma mark -
75
#pragma mark VLC Interface Object Callbacks
76

77
78
79
/*****************************************************************************
 * OpenIntf: initialize interface
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
80
int OpenIntf ( vlc_object_t *p_this )
Jérome Decoodt's avatar
Jérome Decoodt committed
81
{
82
83
84
85
86
87
88
89
90
    intf_thread_t *p_intf = (intf_thread_t*) p_this;

    p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
    if( p_intf->p_sys == NULL )
    {
        return( 1 );
    }

    memset( p_intf->p_sys, 0, sizeof( *p_intf->p_sys ) );
Jérome Decoodt's avatar
Jérome Decoodt committed
91

92
    p_intf->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
hartman's avatar
hartman committed
93

94
95
    /* subscribe to LibVLCCore's messages */
    p_intf->p_sys->p_sub = msg_Subscribe( p_intf->p_libvlc, MsgCallback, NULL );
96
    p_intf->pf_run = Run;
97
    p_intf->b_should_run_on_first_thread = true;
98
99
100
101
102
103
104

    return( 0 );
}

/*****************************************************************************
 * CloseIntf: destroy interface
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
105
void CloseIntf ( vlc_object_t *p_this )
106
107
{
    intf_thread_t *p_intf = (intf_thread_t*) p_this;
Jérome Decoodt's avatar
Jérome Decoodt committed
108

109
    [p_intf->p_sys->o_pool release];
Jérome Decoodt's avatar
Jérome Decoodt committed
110

111
112
113
    free( p_intf->p_sys );
}

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
static void MsgCallback( msg_cb_data_t *data, msg_item_t *item, unsigned int i )
{
    int canc = vlc_savecancel();
    NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];

    NSDictionary *o_dict = [NSDictionary dictionaryWithObjects: 
                    [NSArray arrayWithObjects: 
                        [NSString stringWithUTF8String: item->psz_module],
                        [NSString stringWithUTF8String: item->psz_msg],
                        [NSNumber numberWithInt: item->i_type], nil] 
                                         forKeys:
              [NSArray arrayWithObjects: @"Module", @"Message", @"Type", nil]];

    [[NSNotificationCenter defaultCenter] postNotificationName: @"VLCCoreMessageReceived" 
                                                        object: nil 
                                                      userInfo: o_dict];

    [o_pool release];
    vlc_restorecancel( canc );
}

135
136
137
/*****************************************************************************
 * Run: main loop
 *****************************************************************************/
138
139
jmp_buf jmpbuffer;

140
141
static void Run( intf_thread_t *p_intf )
{
142
143
    sigset_t set;

144
145
146
147
    /* Do it again - for some unknown reason, vlc_thread_create() often
     * fails to go to real-time priority with the first launched thread
     * (???) --Meuuh */
    vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW );
148
149
150
151
152
153
154
155
156

    /* Make sure the "force quit" menu item does quit instantly.
     * VLC overrides SIGTERM which is sent by the "force quit"
     * menu item to make sure deamon mode quits gracefully, so
     * we un-override SIGTERM here. */
    sigemptyset( &set );
    sigaddset( &set, SIGTERM );
    pthread_sigmask( SIG_UNBLOCK, &set, NULL );

157
158
159
160
    NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];

    /* Install a jmpbuffer to where we can go back before the NSApp exit
     * see applicationWillTerminate: */
161
    [NSApplication sharedApplication];
162

hartman's avatar
-    
hartman committed
163
    [[VLCMain sharedInstance] setIntf: p_intf];
hartman's avatar
hartman committed
164
    [NSBundle loadNibNamed: @"MainMenu" owner: NSApp];
165
166
167
168
169

    /* Install a jmpbuffer to where we can go back before the NSApp exit
     * see applicationWillTerminate: */
    if(setjmp(jmpbuffer) == 0)
        [NSApp run];
170
    
171
    [o_pool release];
172
173
}

174
175
#pragma mark -
#pragma mark Variables Callback
176

177
178
179
180
/*****************************************************************************
 * playlistChanged: Callback triggered by the intf-change playlist
 * variable, to let the intf update the playlist.
 *****************************************************************************/
181
static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
182
183
                     vlc_value_t old_val, vlc_value_t new_val, void *param )
{
hartman's avatar
hartman committed
184
    intf_thread_t * p_intf = VLCIntf;
185
    p_intf->p_sys->b_intf_update = true;
186
    p_intf->p_sys->b_playlist_update = true;
187
188
    p_intf->p_sys->b_playmode_update = true;
    p_intf->p_sys->b_current_title_update = true;
189
190
191
192
193
194
195
196
197
198
199
200
    return VLC_SUCCESS;
}

/*****************************************************************************
 * ShowController: Callback triggered by the show-intf playlist variable
 * through the ShowIntf-control-intf, to let us show the controller-win;
 * usually when in fullscreen-mode
 *****************************************************************************/
static int ShowController( vlc_object_t *p_this, const char *psz_variable,
                     vlc_value_t old_val, vlc_value_t new_val, void *param )
{
    intf_thread_t * p_intf = VLCIntf;
201
    p_intf->p_sys->b_intf_show = true;
202
203
204
    return VLC_SUCCESS;
}

bigben's avatar
bigben committed
205
206
207
208
/*****************************************************************************
 * FullscreenChanged: Callback triggered by the fullscreen-change playlist
 * variable, to let the intf update the controller.
 *****************************************************************************/
209
static int FullscreenChanged( vlc_object_t *p_this, const char *psz_variable,
bigben's avatar
bigben committed
210
211
212
                     vlc_value_t old_val, vlc_value_t new_val, void *param )
{
    intf_thread_t * p_intf = VLCIntf;
213
    p_intf->p_sys->b_fullscreen_update = true;
bigben's avatar
bigben committed
214
215
216
    return VLC_SUCCESS;
}

217
218
219
220
221
222
223
224
225
226
227
/*****************************************************************************
 * InteractCallback: Callback triggered by the interaction
 * variable, to let the intf display error and interaction dialogs
 *****************************************************************************/
static int InteractCallback( vlc_object_t *p_this, const char *psz_variable,
                     vlc_value_t old_val, vlc_value_t new_val, void *param )
{
    NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
    VLCMain *interface = (VLCMain *)param;
    interaction_dialog_t *p_dialog = (interaction_dialog_t *)(new_val.p_address);
    NSValue *o_value = [NSValue valueWithPointer:p_dialog];
228
 
229
230
    [[NSNotificationCenter defaultCenter] postNotificationName: @"VLCNewInteractionEventNotification" object:[interface getInteractionList]
     userInfo:[NSDictionary dictionaryWithObject:o_value forKey:@"VLCDialogPointer"]];
231
 
232
233
234
    [o_pool release];
    return VLC_SUCCESS;
}
bigben's avatar
bigben committed
235

236
#pragma mark -
237
238
239
240
241
#pragma mark Private

@interface VLCMain ()
- (void)_removeOldPreferences;
@end
242

243
/*****************************************************************************
Jérome Decoodt's avatar
Jérome Decoodt committed
244
 * VLCMain implementation
245
246
247
 *****************************************************************************/
@implementation VLCMain

248
249
250
#pragma mark -
#pragma mark Initialization

hartman's avatar
hartman committed
251
252
253
254
255
256
257
static VLCMain *_o_sharedMainInstance = nil;

+ (VLCMain *)sharedInstance
{
    return _o_sharedMainInstance ? _o_sharedMainInstance : [[self alloc] init];
}

Jérome Decoodt's avatar
Jérome Decoodt committed
258
- (id)init
hartman's avatar
hartman committed
259
{
260
261
    if( _o_sharedMainInstance) 
    {
hartman's avatar
hartman committed
262
        [self dealloc];
263
264
265
        return _o_sharedMainInstance;
    } 
    else
hartman's avatar
hartman committed
266
        _o_sharedMainInstance = [super init];
267

268
269
270
271
272
    o_msg_lock = [[NSLock alloc] init];
    o_msg_arr = [[NSMutableArray arrayWithCapacity: 200] retain];
    /* subscribe to LibVLC's debug messages as early as possible (for us) */
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(libvlcMessageReceived:) name: @"VLCCoreMessageReceived" object: nil];
    
273
    o_about = [[VLAboutBox alloc] init];
274
    o_prefs = nil;
275
    o_open = [[VLCOpen alloc] init];
276
    o_wizard = [[VLCWizard alloc] init];
277
    o_vlm = [[VLCVLMController alloc] init];
278
    o_extended = nil;
279
    o_bookmarks = [[VLCBookmarks alloc] init];
280
    o_embedded_list = [[VLCEmbeddedList alloc] init];
281
    o_interaction_list = [[VLCInteractionList alloc] init];
282
    o_info = [[VLCInfo alloc] init];
283
#ifdef UPDATE_CHECK
Rafaël Carré's avatar
Rafaël Carré committed
284
    o_update = [[VLCUpdate alloc] init];
285
#endif
286
287

    i_lastShownVolume = -1;
288
289

    o_remote = [[AppleRemote alloc] init];
290
    [o_remote setClickCountEnabledButtons: kRemoteButtonPlay];
291
    [o_remote setDelegate: _o_sharedMainInstance];
292

293
294
295
296
297
298
299
300
    o_eyetv = [[VLCEyeTVController alloc] init];

    /* announce our launch to a potential eyetv plugin */
    [[NSDistributedNotificationCenter defaultCenter] postNotificationName: @"VLCOSXGUIInit"
                                                                   object: @"VLCEyeTVSupport"
                                                                 userInfo: NULL
                                                       deliverImmediately: YES];

hartman's avatar
hartman committed
301
302
303
304
305
306
307
308
309
310
311
    return _o_sharedMainInstance;
}

- (void)setIntf: (intf_thread_t *)p_mainintf {
    p_intf = p_mainintf;
}

- (intf_thread_t *)getIntf {
    return p_intf;
}

312
313
- (void)awakeFromNib
{
hartman's avatar
hartman committed
314
    unsigned int i_key = 0;
315
    playlist_t *p_playlist;
316
    vlc_value_t val;
hartman's avatar
hartman committed
317

318
319
320
    /* Check if we already did this once. Opening the other nibs calls it too, because VLCMain is the owner */
    if( nib_main_loaded ) return;

321
    [self initStrings];
322
323
324

    [o_window setExcludedFromWindowsMenu: YES];
    [o_msgs_panel setExcludedFromWindowsMenu: YES];
325
    [o_msgs_panel setDelegate: self];
Jérome Decoodt's avatar
Jérome Decoodt committed
326

327
328
329
330
331
332
333
334
335
    /* In code and not in Nib for 10.4 compat */
    NSToolbar * toolbar = [[[NSToolbar alloc] initWithIdentifier:@"mainControllerToolbar"] autorelease];
    [toolbar setDelegate:self];
    [toolbar setShowsBaselineSeparator:NO];
    [toolbar setAllowsUserCustomization:NO];
    [toolbar setDisplayMode:NSToolbarDisplayModeIconOnly];
    [toolbar setAutosavesConfiguration:YES];
    [o_window setToolbar:toolbar];

336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
    i_key = config_GetInt( p_intf, "key-quit" );
    [o_mi_quit setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_quit setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
    i_key = config_GetInt( p_intf, "key-play-pause" );
    [o_mi_play setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_play setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
    i_key = config_GetInt( p_intf, "key-stop" );
    [o_mi_stop setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_stop setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
    i_key = config_GetInt( p_intf, "key-faster" );
    [o_mi_faster setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_faster setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
    i_key = config_GetInt( p_intf, "key-slower" );
    [o_mi_slower setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_slower setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
    i_key = config_GetInt( p_intf, "key-prev" );
    [o_mi_previous setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_previous setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
    i_key = config_GetInt( p_intf, "key-next" );
    [o_mi_next setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_next setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
357
    i_key = config_GetInt( p_intf, "key-jump+short" );
358
359
    [o_mi_fwd setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_fwd setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
360
    i_key = config_GetInt( p_intf, "key-jump-short" );
361
362
    [o_mi_bwd setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_bwd setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
363
    i_key = config_GetInt( p_intf, "key-jump+medium" );
364
365
    [o_mi_fwd1m setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_fwd1m setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
366
    i_key = config_GetInt( p_intf, "key-jump-medium" );
367
368
    [o_mi_bwd1m setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_bwd1m setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
369
    i_key = config_GetInt( p_intf, "key-jump+long" );
370
371
    [o_mi_fwd5m setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_fwd5m setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
372
    i_key = config_GetInt( p_intf, "key-jump-long" );
373
374
    [o_mi_bwd5m setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_bwd5m setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
375
376
377
378
379
380
    i_key = config_GetInt( p_intf, "key-vol-up" );
    [o_mi_vol_up setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_vol_up setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
    i_key = config_GetInt( p_intf, "key-vol-down" );
    [o_mi_vol_down setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_vol_down setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
hartman's avatar
hartman committed
381
382
383
    i_key = config_GetInt( p_intf, "key-vol-mute" );
    [o_mi_mute setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_mute setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
384
385
386
    i_key = config_GetInt( p_intf, "key-fullscreen" );
    [o_mi_fullscreen setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_fullscreen setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
387
388
389
    i_key = config_GetInt( p_intf, "key-snapshot" );
    [o_mi_snapshot setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
    [o_mi_snapshot setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
390

391
    var_Create( p_intf, "intf-change", VLC_VAR_BOOL );
392

393
    [self setSubmenusEnabled: FALSE];
394
    [o_volumeslider setEnabled: YES];
395
    [self manageVolumeSlider];
hartman's avatar
hartman committed
396
    [o_window setDelegate: self];
397
 
398
    b_restore_size = false;
399
400
401
402
403

    // Set that here as IB seems to be buggy
    [o_window setContentMinSize:NSMakeSize(338., 30.)];

    if( [o_window contentRectForFrameRect:[o_window frame]].size.height <= 169. )
404
405
    {
        b_small_window = YES;
406
407
408
        [o_window setFrame: NSMakeRect( [o_window frame].origin.x,
            [o_window frame].origin.y, [o_window frame].size.width,
            [o_window minSize].height ) display: YES animate:YES];
409
410
411
412
413
        [o_playlist_view setAutoresizesSubviews: NO];
    }
    else
    {
        b_small_window = NO;
414
415
        NSRect contentRect = [o_window contentRectForFrameRect:[o_window frame]];
        [o_playlist_view setFrame: NSMakeRect( 0, 0, contentRect.size.width, contentRect.size.height - [o_window contentMinSize].height )];
416
417
418
419
        [o_playlist_view setNeedsDisplay:YES];
        [o_playlist_view setAutoresizesSubviews: YES];
        [[o_window contentView] addSubview: o_playlist_view];
    }
420

421
    [self updateTogglePlaylistState];
Jérome Decoodt's avatar
Jérome Decoodt committed
422

423
    o_size_with_playlist = [o_window contentRectForFrameRect:[o_window frame]].size;
424

dionoea's avatar
dionoea committed
425
    p_playlist = pl_Hold( p_intf );
hartman's avatar
hartman committed
426

427
    var_Create( p_playlist, "fullscreen", VLC_VAR_BOOL | VLC_VAR_DOINHERIT);
428
    val.b_bool = false;
bigben's avatar
bigben committed
429

430
    var_AddCallback( p_playlist, "fullscreen", FullscreenChanged, self);
431
    var_AddCallback( p_intf->p_libvlc, "intf-show", ShowController, self);
bigben's avatar
bigben committed
432

433
    pl_Release( p_intf );
434
 
435
436
    var_Create( p_intf, "interaction", VLC_VAR_ADDRESS );
    var_AddCallback( p_intf, "interaction", InteractCallback, self );
437
    interaction_Register( p_intf );
438

439
    /* update the playmode stuff */
440
    p_intf->p_sys->b_playmode_update = true;
441

442
443
444
445
    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(refreshVoutDeviceMenu:)
                                                 name: NSApplicationDidChangeScreenParametersNotification
                                               object: nil];
446
447
448
449
450
451
452
453
454
455
456

    o_img_play = [NSImage imageNamed: @"play"];
    o_img_pause = [NSImage imageNamed: @"pause"];    
    
    [self controlTintChanged];

    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector( controlTintChanged )
                                                 name: NSControlTintDidChangeNotification
                                               object: nil];
    
457
    nib_main_loaded = TRUE;
458
459
}

460
- (void)applicationWillFinishLaunching:(NSNotification *)o_notification
461
{
462
463
464
465
    /* FIXME: don't poll */
    interfaceTimer = [[NSTimer scheduledTimerWithTimeInterval: 0.5
                                     target: self selector: @selector(manageIntf:)
                                   userInfo: nil repeats: FALSE] retain];
466

467
468
    /* Note: we use the pthread API to support pre-10.5 */
    pthread_create( &manage_thread, NULL, ManageThread, self );
469

470
471
    [o_controls setupVarMenuItem: o_mi_add_intf target: (vlc_object_t *)p_intf
        var: "intf-add" selector: @selector(toggleVar:)];
472

473
474
    /* check whether the user runs a valid version of OSX; alert is auto-released */
    if( MACOS_VERSION < 10.4f )
475
    {
476
477
478
479
480
481
482
483
484
485
        NSAlert *ourAlert;
        int i_returnValue;
        ourAlert = [NSAlert alertWithMessageText: _NS("Your version of Mac OS X is not supported")
                        defaultButton: _NS("Quit")
                      alternateButton: NULL
                          otherButton: NULL
            informativeTextWithFormat: _NS("VLC media player requires Mac OS X 10.4 or higher.")];
        [ourAlert setAlertStyle: NSCriticalAlertStyle];
        i_returnValue = [ourAlert runModal];
        [NSApp terminate: self];
486
487
    }

488
489
    vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW );
}
490

491
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
492
{
493
494
    [self _removeOldPreferences];

495
496
497
#ifdef UPDATE_CHECK
    /* Check for update silently on startup */
    if( !nib_update_loaded )
Felix Paul Kühne's avatar
Felix Paul Kühne committed
498
        nib_update_loaded = [NSBundle loadNibNamed:@"Update" owner: NSApp];
499
500
501
502
503
504
505
506
507
508

    if([o_update shouldCheckForUpdate])
        [NSThread detachNewThreadSelector:@selector(checkForUpdate) toTarget:o_update withObject:nil];
#endif

    /* Handle sleep notification */
    [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(computerWillSleep:)
           name:NSWorkspaceWillSleepNotification object:nil];

    [NSThread detachNewThreadSelector:@selector(lookForCrashLog) toTarget:self withObject:nil];
509
510
}

hartman's avatar
hartman committed
511
- (void)initStrings
512
{
Felix Paul Kühne's avatar
Felix Paul Kühne committed
513
    [o_window setTitle: _NS("VLC media player")];
514
    [self setScrollField:_NS("VLC media player") stopAfter:-1];
515

Jon Lech Johansen's avatar
Jon Lech Johansen committed
516
517
    /* button controls */
    [o_btn_prev setToolTip: _NS("Previous")];
hartman's avatar
hartman committed
518
    [o_btn_rewind setToolTip: _NS("Rewind")];
Jon Lech Johansen's avatar
Jon Lech Johansen committed
519
520
    [o_btn_play setToolTip: _NS("Play")];
    [o_btn_stop setToolTip: _NS("Stop")];
hartman's avatar
hartman committed
521
    [o_btn_ff setToolTip: _NS("Fast Forward")];
Jon Lech Johansen's avatar
Jon Lech Johansen committed
522
    [o_btn_next setToolTip: _NS("Next")];
hartman's avatar
hartman committed
523
    [o_btn_fullscreen setToolTip: _NS("Fullscreen")];
hartman's avatar
hartman committed
524
525
    [o_volumeslider setToolTip: _NS("Volume")];
    [o_timeslider setToolTip: _NS("Position")];
526
    [o_btn_playlist setToolTip: _NS("Playlist")];
527

Jérome Decoodt's avatar
Jérome Decoodt committed
528
    /* messages panel */
529
    [o_msgs_panel setTitle: _NS("Messages")];
530
    [o_msgs_btn_crashlog setTitle: _NS("Open CrashLog...")];
531

Jon Lech Johansen's avatar
Jon Lech Johansen committed
532
    /* main menu */
533
534
    [o_mi_about setTitle: [_NS("About VLC media player") \
        stringByAppendingString: @"..."]];
535
    [o_mi_checkForUpdate setTitle: _NS("Check for Update...")];
536
    [o_mi_prefs setTitle: _NS("Preferences...")];
hartman's avatar
hartman committed
537
538
    [o_mi_add_intf setTitle: _NS("Add Interface")];
    [o_mu_add_intf setTitle: _NS("Add Interface")];
539
    [o_mi_services setTitle: _NS("Services")];
540
    [o_mi_hide setTitle: _NS("Hide VLC")];
541
542
    [o_mi_hide_others setTitle: _NS("Hide Others")];
    [o_mi_show_all setTitle: _NS("Show All")];
543
    [o_mi_quit setTitle: _NS("Quit VLC")];
544

hartman's avatar
ALL:    
hartman committed
545
    [o_mu_file setTitle: _ANS("1:File")];
546
547
    [o_mi_open_generic setTitle: _NS("Advanced Open File...")];
    [o_mi_open_file setTitle: _NS("Open File...")];
548
549
    [o_mi_open_disc setTitle: _NS("Open Disc...")];
    [o_mi_open_net setTitle: _NS("Open Network...")];
550
    [o_mi_open_capture setTitle: _NS("Open Capture Device...")];
551
552
    [o_mi_open_recent setTitle: _NS("Open Recent")];
    [o_mi_open_recent_cm setTitle: _NS("Clear Menu")];
553
    [o_mi_open_wizard setTitle: _NS("Streaming/Exporting Wizard...")];
554
555
556
557
558
559
560
561

    [o_mu_edit setTitle: _NS("Edit")];
    [o_mi_cut setTitle: _NS("Cut")];
    [o_mi_copy setTitle: _NS("Copy")];
    [o_mi_paste setTitle: _NS("Paste")];
    [o_mi_clear setTitle: _NS("Clear")];
    [o_mi_select_all setTitle: _NS("Select All")];

562
    [o_mu_controls setTitle: _NS("Playback")];
563
    [o_mi_play setTitle: _NS("Play")];
564
565
566
    [o_mi_stop setTitle: _NS("Stop")];
    [o_mi_faster setTitle: _NS("Faster")];
    [o_mi_slower setTitle: _NS("Slower")];
Christophe Massiot's avatar
Christophe Massiot committed
567
    [o_mi_previous setTitle: _NS("Previous")];
568
    [o_mi_next setTitle: _NS("Next")];
569
570
571
    [o_mi_random setTitle: _NS("Random")];
    [o_mi_repeat setTitle: _NS("Repeat One")];
    [o_mi_loop setTitle: _NS("Repeat All")];
572
573
    [o_mi_fwd setTitle: _NS("Step Forward")];
    [o_mi_bwd setTitle: _NS("Step Backward")];
574

hartman's avatar
hartman committed
575
    [o_mi_program setTitle: _NS("Program")];
576
    [o_mu_program setTitle: _NS("Program")];
hartman's avatar
hartman committed
577
    [o_mi_title setTitle: _NS("Title")];
578
    [o_mu_title setTitle: _NS("Title")];
hartman's avatar
hartman committed
579
    [o_mi_chapter setTitle: _NS("Chapter")];
580
    [o_mu_chapter setTitle: _NS("Chapter")];
Jérome Decoodt's avatar
Jérome Decoodt committed
581

hartman's avatar
hartman committed
582
    [o_mu_audio setTitle: _NS("Audio")];
Jon Lech Johansen's avatar
Jon Lech Johansen committed
583
584
    [o_mi_vol_up setTitle: _NS("Volume Up")];
    [o_mi_vol_down setTitle: _NS("Volume Down")];
585
    [o_mi_mute setTitle: _NS("Mute")];
586
587
588
589
590
591
    [o_mi_audiotrack setTitle: _NS("Audio Track")];
    [o_mu_audiotrack setTitle: _NS("Audio Track")];
    [o_mi_channels setTitle: _NS("Audio Channels")];
    [o_mu_channels setTitle: _NS("Audio Channels")];
    [o_mi_device setTitle: _NS("Audio Device")];
    [o_mu_device setTitle: _NS("Audio Device")];
592
593
    [o_mi_visual setTitle: _NS("Visualizations")];
    [o_mu_visual setTitle: _NS("Visualizations")];
Jérome Decoodt's avatar
Jérome Decoodt committed
594

hartman's avatar
hartman committed
595
    [o_mu_video setTitle: _NS("Video")];
596
597
598
    [o_mi_half_window setTitle: _NS("Half Size")];
    [o_mi_normal_window setTitle: _NS("Normal Size")];
    [o_mi_double_window setTitle: _NS("Double Size")];
599
    [o_mi_fittoscreen setTitle: _NS("Fit to Screen")];
600
    [o_mi_fullscreen setTitle: _NS("Fullscreen")];
601
    [o_mi_floatontop setTitle: _NS("Float on Top")];
602
    [o_mi_snapshot setTitle: _NS("Snapshot")];
603
604
    [o_mi_videotrack setTitle: _NS("Video Track")];
    [o_mu_videotrack setTitle: _NS("Video Track")];
605
606
    [o_mi_aspect_ratio setTitle: _NS("Aspect-ratio")];
    [o_mu_aspect_ratio setTitle: _NS("Aspect-ratio")];
bigben's avatar
bigben committed
607
608
    [o_mi_crop setTitle: _NS("Crop")];
    [o_mu_crop setTitle: _NS("Crop")];
609
610
    [o_mi_screen setTitle: _NS("Fullscreen Video Device")];
    [o_mu_screen setTitle: _NS("Fullscreen Video Device")];
611
612
    [o_mi_subtitle setTitle: _NS("Subtitles Track")];
    [o_mu_subtitle setTitle: _NS("Subtitles Track")];
613
    [o_mi_deinterlace setTitle: _NS("Deinterlace")];
614
    [o_mu_deinterlace setTitle: _NS("Deinterlace")];
bigben's avatar
bigben committed
615
616
    [o_mi_ffmpeg_pp setTitle: _NS("Post processing")];
    [o_mu_ffmpeg_pp setTitle: _NS("Post processing")];
hartman's avatar
hartman committed
617
618
619
620
621
622
623
    [o_mi_teletext setTitle: _NS("Teletext")];
    [o_mi_teletext_transparent setTitle: _NS("Transparent")];
    [o_mi_teletext_index setTitle: _NS("Index")];
    [o_mi_teletext_red setTitle: _NS("Red")];
    [o_mi_teletext_green setTitle: _NS("Green")];
    [o_mi_teletext_yellow setTitle: _NS("Yellow")];
    [o_mi_teletext_blue setTitle: _NS("Blue")];
624
625

    [o_mu_window setTitle: _NS("Window")];
626
627
    [o_mi_minimize setTitle: _NS("Minimize Window")];
    [o_mi_close_window setTitle: _NS("Close Window")];
628
629
630
631
632
633
634
635
    [o_mi_controller setTitle: _NS("Controller...")];
    [o_mi_equalizer setTitle: _NS("Equalizer...")];
    [o_mi_extended setTitle: _NS("Extended Controls...")];
    [o_mi_bookmarks setTitle: _NS("Bookmarks...")];
    [o_mi_playlist setTitle: _NS("Playlist...")];
    [o_mi_info setTitle: _NS("Media Information...")];
    [o_mi_messages setTitle: _NS("Messages...")];
    [o_mi_errorsAndWarnings setTitle: _NS("Errors and Warnings...")];
hartman's avatar
hartman committed
636

637
638
    [o_mi_bring_atf setTitle: _NS("Bring All to Front")];

639
    [o_mu_help setTitle: _NS("Help")];
640
    [o_mi_help setTitle: _NS("VLC media player Help...")];
641
    [o_mi_readme setTitle: _NS("ReadMe / FAQ...")];
642
    [o_mi_license setTitle: _NS("License")];
643
644
645
646
    [o_mi_documentation setTitle: _NS("Online Documentation...")];
    [o_mi_website setTitle: _NS("VideoLAN Website...")];
    [o_mi_donation setTitle: _NS("Make a donation...")];
    [o_mi_forum setTitle: _NS("Online Forum...")];
647

648
    /* dock menu */
649
    [o_dmi_play setTitle: _NS("Play")];
650
    [o_dmi_stop setTitle: _NS("Stop")];
651
652
    [o_dmi_next setTitle: _NS("Next")];
    [o_dmi_previous setTitle: _NS("Previous")];
653
    [o_dmi_mute setTitle: _NS("Mute")];
654
 
655
656
657
658
659
660
661
662
663
664
    /* vout menu */
    [o_vmi_play setTitle: _NS("Play")];
    [o_vmi_stop setTitle: _NS("Stop")];
    [o_vmi_prev setTitle: _NS("Previous")];
    [o_vmi_next setTitle: _NS("Next")];
    [o_vmi_volup setTitle: _NS("Volume Up")];
    [o_vmi_voldown setTitle: _NS("Volume Down")];
    [o_vmi_mute setTitle: _NS("Mute")];
    [o_vmi_fullscreen setTitle: _NS("Fullscreen")];
    [o_vmi_snapshot setTitle: _NS("Snapshot")];
665
666
667
668
669
670
671

    /* crash reporter panel */
    [o_crashrep_send_btn setTitle: _NS("Send")];
    [o_crashrep_dontSend_btn setTitle: _NS("Don't Send")];
    [o_crashrep_title_txt setStringValue: _NS("VLC crashed previously")];
    [o_crashrep_win setTitle: _NS("VLC crashed previously")];
    [o_crashrep_desc_txt setStringValue: _NS("Do you want to send details on the crash to VLC's development team?\n\nIf you want, you can enter a few lines on what you did before VLC crashed along with other helpful information: a link to download a sample file, a URL of a network stream, ...")];
672
673
    [o_crashrep_includeEmail_ckb setTitle: _NS("I agree to be possibly contacted about this bugreport.")];
    [o_crashrep_includeEmail_txt setStringValue: _NS("Only your default E-Mail address will be submitted, including no further information.")];
674
675
}

676
677
678
679
#pragma mark -
#pragma mark Termination

- (void)applicationWillTerminate:(NSNotification *)notification
680
{
681
682
683
684
685
    playlist_t * p_playlist;
    vout_thread_t * p_vout;
    int returnedValue = 0;
 
    msg_Dbg( p_intf, "Terminating" );
686

687
688
    /* Make sure the manage_thread won't call -terminate: again */
    pthread_cancel( manage_thread );
689

690
691
    /* Make sure the intf object is getting killed */
    vlc_object_kill( p_intf );
Jérome Decoodt's avatar
Jérome Decoodt committed
692

693
694
    /* Make sure our manage_thread ends */
    pthread_join( manage_thread, NULL );
695

696
697
698
699
700
701
702
703
704
705
    /* Make sure the interfaceTimer is destroyed */
    [interfaceTimer invalidate];
    [interfaceTimer release];
    interfaceTimer = nil;

    /* make sure that the current volume is saved */
    config_PutInt( p_intf->p_libvlc, "volume", i_lastShownVolume );

    /* save the prefs if they were changed in the extended panel */
    if(o_extended && [o_extended getConfigChanged])
706
    {
707
        [o_extended savePrefs];
708
    }
709
 
710
    interaction_Unregister( p_intf );
711
    var_DelCallback( p_intf, "interaction", InteractCallback, self );
712

713
714
    /* remove global observer watching for vout device changes correctly */
    [[NSNotificationCenter defaultCenter] removeObserver: self];
Jérome Decoodt's avatar
Jérome Decoodt committed
715

716
717
    [o_update end];

718
719
    /* release some other objects here, because it isn't sure whether dealloc
     * will be called later on */
hartman's avatar
-    
hartman committed
720

721
722
    if( nib_about_loaded )
        [o_about release];
hartman's avatar
hartman committed
723

724
    if( nib_prefs_loaded )
hartman's avatar
hartman committed
725
    {
726
727
728
        [o_sprefs release];
        [o_prefs release];
    }
729

730
731
732
733
734
735
    if( nib_open_loaded )
        [o_open release];

    if( nib_extended_loaded )
    {
        [o_extended release];
hartman's avatar
hartman committed
736
    }
737
738
739
740
741

    if( nib_bookmarks_loaded )
        [o_bookmarks release];

    if( o_info )
hartman's avatar
hartman committed
742
    {
743
744
        [o_info stopTimers];
        [o_info release];
hartman's avatar
hartman committed
745
746
    }

747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
    if( nib_wizard_loaded )
        [o_wizard release];

    [crashLogURLConnection cancel];
    [crashLogURLConnection release];
 
    [o_embedded_list release];
    [o_interaction_list release];
    [o_eyetv release];

    [o_img_pause_pressed release];
    [o_img_play_pressed release];
    [o_img_pause release];
    [o_img_play release];

762
763
764
    /* unsubscribe from libvlc's debug messages */
    msg_Unsubscribe( p_intf->p_sys->p_sub );

765
766
767
768
769
770
771
772
773
774
    [o_msg_arr removeAllObjects];
    [o_msg_arr release];

    [o_msg_lock release];

    /* write cached user defaults to disk */
    [[NSUserDefaults standardUserDefaults] synchronize];

    /* Kill the playlist, so that it doesn't accept new request
     * such as the play request from vlc.c (we are a blocking interface). */
dionoea's avatar
dionoea committed
775
    p_playlist = pl_Hold( p_intf );
776
777
778
    vlc_object_kill( p_playlist );
    pl_Release( p_intf );

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
779
    libvlc_Quit( p_intf->p_libvlc );
780

781
782
    [self setIntf:nil];

783
784
785
786
    /* Go back to Run() and make libvlc exit properly */
    if( jmpbuffer )
        longjmp( jmpbuffer, 1 );
    /* not reached */
hartman's avatar
hartman committed
787
788
}

789
790
#pragma mark -
#pragma mark Toolbar delegate
791

792
793
794
795
796
797
798
799
800
801
802
803
/* Our item identifiers */
static NSString * VLCToolbarMediaControl     = @"VLCToolbarMediaControl";

- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
{
    return [NSArray arrayWithObjects:
//                        NSToolbarCustomizeToolbarItemIdentifier,
//                        NSToolbarFlexibleSpaceItemIdentifier,
//                        NSToolbarSpaceItemIdentifier,
//                        NSToolbarSeparatorItemIdentifier,
                        VLCToolbarMediaControl,
                        nil ];
804
805
}

806
- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
807
{
808
809
810
811
    return [NSArray arrayWithObjects:
                        VLCToolbarMediaControl,
                        nil ];
}
812

813
814
815
- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
    NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
816

817
818
819
820
821
 
    if( [itemIdentifier isEqual: VLCToolbarMediaControl] )
    {
        [toolbarItem setLabel:@"Media Controls"];
        [toolbarItem setPaletteLabel:@"Media Controls"];
822

823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
        NSSize size = toolbarMediaControl.frame.size;
        [toolbarItem setView:toolbarMediaControl];
        [toolbarItem setMinSize:size];
        size.width += 1000.;
        [toolbarItem setMaxSize:size];

        // Hack: For some reason we need to make sure
        // that the those element are on top
        // Add them again will put them frontmost
        [toolbarMediaControl addSubview:o_scrollfield];
        [toolbarMediaControl addSubview:o_timeslider];
        [toolbarMediaControl addSubview:o_timefield];
        [toolbarMediaControl addSubview:o_main_pgbar];

        /* TODO: setup a menu */
    }
    else
    {
        /* itemIdentifier referred to a toolbar item that is not
         * provided or supported by us or Cocoa
         * Returning nil will inform the toolbar
         * that this kind of item is not supported */
        toolbarItem = nil;
    }
    return toolbarItem;
}

#pragma mark -
#pragma mark Other notification

- (void)controlTintChanged
{
    BOOL b_playing = NO;
    
    if( [o_btn_play alternateImage] == o_img_play_pressed )
        b_playing = YES;
    
    if( [NSColor currentControlTint] == NSGraphiteControlTint )
    {
        o_img_play_pressed = [NSImage imageNamed: @"play_graphite"];
        o_img_pause_pressed = [NSImage imageNamed: @"pause_graphite"];
        
        [o_btn_prev setAlternateImage: [NSImage imageNamed: @"previous_graphite"]];
        [o_btn_rewind setAlternateImage: [NSImage imageNamed: @"skip_previous_graphite"]];
        [o_btn_stop setAlternateImage: [NSImage imageNamed: @"stop_graphite"]];
        [o_btn_ff setAlternateImage: [NSImage imageNamed: @"skip_forward_graphite"]];
        [o_btn_next setAlternateImage: [NSImage imageNamed: @"next_graphite"]];
        [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_graphite"]];
        [o_btn_playlist setAlternateImage: [NSImage imageNamed: @"playlistdrawer_graphite"]];
        [o_btn_equalizer setAlternateImage: [NSImage imageNamed: @"equalizerdrawer_graphite"]];
    }
    else
    {
        o_img_play_pressed = [NSImage imageNamed: @"play_blue"];
        o_img_pause_pressed = [NSImage imageNamed: @"pause_blue"];
        
        [o_btn_prev setAlternateImage: [NSImage imageNamed: @"previous_blue"]];
        [o_btn_rewind setAlternateImage: [NSImage imageNamed: @"skip_previous_blue"]];
        [o_btn_stop setAlternateImage: [NSImage imageNamed: @"stop_blue"]];
        [o_btn_ff setAlternateImage: [NSImage imageNamed: @"skip_forward_blue"]];
        [o_btn_next setAlternateImage: [NSImage imageNamed: @"next_blue"]];
        [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_blue"]];
        [o_btn_playlist setAlternateImage: [NSImage imageNamed: @"playlistdrawer_blue"]];
        [o_btn_equalizer setAlternateImage: [NSImage imageNamed: @"equalizerdrawer_blue"]];
    }
    
    if( b_playing )
        [o_btn_play setAlternateImage: o_img_play_pressed];
    else
        [o_btn_play setAlternateImage: o_img_pause_pressed];
893
894
}

895
896
897
898
899
900
901
902
903
904
905
/* Listen to the remote in exclusive mode, only when VLC is the active
   application */
- (void)applicationDidBecomeActive:(NSNotification *)aNotification
{
    [o_remote startListening: self];
}
- (void)applicationDidResignActive:(NSNotification *)aNotification
{
    [o_remote stopListening: self];
}

906
907
908
909
/* Triggered when the computer goes to sleep */
- (void)computerWillSleep: (NSNotification *)notification
{
    /* Pause */
910
    if( p_intf->p_sys->i_play_status == PLAYING_S )
911
912
913
914
915
916
917
    {
        vlc_value_t val;
        val.i_int = config_GetInt( p_intf, "key-play-pause" );
        var_Set( p_intf->p_libvlc, "key-pressed", val );
    }
}

918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
#pragma mark -
#pragma mark File opening

- (BOOL)application:(NSApplication *)o_app openFile:(NSString *)o_filename
{
    BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
    NSDictionary *o_dic = [NSDictionary dictionaryWithObjectsAndKeys: o_filename, @"ITEM_URL", nil];
    if( b_autoplay )
        [o_playlist appendArray: [NSArray arrayWithObject: o_dic] atPos: -1 enqueue: NO];
    else
        [o_playlist appendArray: [NSArray arrayWithObject: o_dic] atPos: -1 enqueue: YES];

    return( TRUE );
}

/* When user click in the Dock icon our double click in the finder */
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)hasVisibleWindows
{    
    if(!hasVisibleWindows)
        [o_window makeKeyAndOrderFront:self];

    return YES;
}

#pragma mark -
#pragma mark Apple Remote Control

945
946
/* Helper method for the remote control interface in order to trigger forward/backward and volume
   increase/decrease as long as the user holds the left/right, plus/minus button */
947
- (void) executeHoldActionForRemoteButton: (NSNumber*) buttonIdentifierNumber
948
{
949
    if(b_remote_button_hold)
950
    {
951
        switch([buttonIdentifierNumber intValue])
952
        {
953
            case kRemoteButtonRight_Hold:
954
                  [o_controls forward: self];
955
956
            break;
            case kRemoteButtonLeft_Hold:
957
958
959
960
961
962
963
                  [o_controls backward: self];
            break;
            case kRemoteButtonVolume_Plus_Hold:
                [o_controls volumeUp: self];
            break;
            case kRemoteButtonVolume_Minus_Hold:
                [o_controls volumeDown: self];
964
            break;
965
        }
966
        if(b_remote_button_hold)
967
        {
968
            /* trigger event */
969
            [self performSelector:@selector(executeHoldActionForRemoteButton:)
970
                         withObject:buttonIdentifierNumber
971
                         afterDelay:0.25];
972
973
974
975
        }
    }
}

976
/* Apple Remote callback */
977
978
979
- (void) appleRemoteButton: (AppleRemoteEventIdentifier)buttonIdentifier
               pressedDown: (BOOL) pressedDown
                clickCount: (unsigned int) count
980
981
982
983
{
    switch( buttonIdentifier )
    {
        case kRemoteButtonPlay:
984
            if(count >= 2) {
985
986
987
                [o_controls toogleFullscreen:self];
            } else {
                [o_controls play: self];
988
            }
989
            break;
Eric Petit's avatar
Eric Petit committed
990
        case kRemoteButtonVolume_Plus:
991
            [o_controls volumeUp: self];
Eric Petit's avatar
Eric Petit committed
992
993
            break;
        case kRemoteButtonVolume_Minus:
994
            [o_controls volumeDown: self];
Eric Petit's avatar
Eric Petit committed
995
            break;
996
997
998
999
1000
1001
1002
1003
        case kRemoteButtonRight:
            [o_controls next: self];
            break;
        case kRemoteButtonLeft:
            [o_controls prev: self];
            break;
        case kRemoteButtonRight_Hold:
        case kRemoteButtonLeft_Hold:
1004
1005
        case kRemoteButtonVolume_Plus_Hold:
        case kRemoteButtonVolume_Minus_Hold:
1006
            /* simulate an event as long as the user holds the button */
1007
            b_remote_button_hold = pressedDown;
1008
            if( pressedDown )
Rafaël Carré's avatar