MainWindow.m 71.2 KB
Newer Older
1
/*****************************************************************************
Pere Orga's avatar
Pere Orga committed
2
 * MainWindow.m: MacOS X interface module
3
 *****************************************************************************
4
 * Copyright (C) 2002-2012 VLC authors and VideoLAN
5 6 7
 * $Id$
 *
 * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8 9 10
 *          Jon Lech Johansen <jon-vl@nanocrew.net>
 *          Christophe Massiot <massiot@via.ecp.fr>
 *          Derk-Jan Hartman <hartman at videolan.org>
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * 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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

27
#import "CompatibilityFixes.h"
28
#import "MainWindow.h"
29 30 31 32
#import "intf.h"
#import "CoreInteraction.h"
#import "AudioEffects.h"
#import "MainMenu.h"
33
#import "open.h"
34
#import "controls.h" // TODO: remove me
35
#import "playlist.h"
36
#import "SideBarItem.h"
37 38
#import <vlc_playlist.h>
#import <vlc_aout_intf.h>
39 40
#import <vlc_url.h>
#import <vlc_strings.h>
41
#import <vlc_services_discovery.h>
42
#import <vlc_aout_intf.h>
43 44

@implementation VLCMainWindow
45
static VLCMainWindow *_o_sharedInstance = nil;
46

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
+ (VLCMainWindow *)sharedInstance
{
    return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
}

#pragma mark -
#pragma mark Initialization

- (id)init
{
    if( _o_sharedInstance)
    {
        [self dealloc];
        return _o_sharedInstance;
    }
    else
63 64
    {
        o_fspanel = [[VLCFSPanel alloc] init];
65
        _o_sharedInstance = [super init];
66
    }
67 68 69 70 71 72 73

    return _o_sharedInstance;
}

- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask
                  backing:(NSBackingStoreType)backingType defer:(BOOL)flag
{
74
    b_dark_interface = config_GetInt( VLCIntf, "macosx-interfacestyle" );
75

76
    if (b_dark_interface)
77
    {
78
#ifdef MAC_OS_X_VERSION_10_7
79 80 81 82
        if (OSX_LION)
            styleMask = NSBorderlessWindowMask | NSResizableWindowMask;
        else
            styleMask = NSBorderlessWindowMask;
83
#else
84
        styleMask = NSBorderlessWindowMask;
85
#endif
86
    }
87 88 89

    self = [super initWithContentRect:contentRect styleMask:styleMask
                              backing:backingType defer:flag];
90 91 92 93 94 95 96

    [[VLCMain sharedInstance] updateTogglePlaylistState];

    /* we want to be moveable regardless of our style */
    [self setMovableByWindowBackground: YES];

    /* we don't want this window to be restored on relaunch */
Felix Paul Kühne's avatar
Felix Paul Kühne committed
97
    if (OSX_LION)
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
        [self setRestorable:NO];

    return self;
}

- (BOOL)performKeyEquivalent:(NSEvent *)o_event
{
    /* We indeed want to prioritize Cocoa key equivalent against libvlc,
     so we perform the menu equivalent now. */
    if([[NSApp mainMenu] performKeyEquivalent:o_event])
        return TRUE;

    return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event] || [(VLCControls *)[[VLCMain sharedInstance] controls] keyEvent:o_event];
}

- (void)dealloc
{
115 116 117
    if (b_dark_interface)
        [o_color_backdrop release];

118
    [[NSNotificationCenter defaultCenter] removeObserver: self];
119
    [o_sidebaritems release];
120 121 122 123 124
    [super dealloc];
}

- (void)awakeFromNib
{
125
    /* setup the styled interface */
126
    b_nativeFullscreenMode = NO;
127 128 129
#ifdef MAC_OS_X_VERSION_10_7
    if( config_GetInt( VLCIntf, "embedded-video" ))
        b_nativeFullscreenMode = config_GetInt( VLCIntf, "macosx-nativefullscreenmode" );
130
#endif
131
    i_lastShownVolume = -1;
132
    t_hide_mouse_timer = nil;
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147

    [o_play_btn setToolTip: _NS("Play/Pause")];
    [o_bwd_btn setToolTip: _NS("Backward")];
    [o_fwd_btn setToolTip: _NS("Forward")];
    [o_stop_btn setToolTip: _NS("Stop")];
    [o_playlist_btn setToolTip: _NS("Show/Hide Playlist")];
    [o_repeat_btn setToolTip: _NS("Repeat")];
    [o_shuffle_btn setToolTip: _NS("Shuffle")];
    [o_effects_btn setToolTip: _NS("Effects")];
    [o_fullscreen_btn setToolTip: _NS("Toggle Fullscreen mode")];
    [[o_search_fld cell] setPlaceholderString: _NS("Search")];
    [o_volume_sld setToolTip: _NS("Volume")];
    [o_volume_down_btn setToolTip: _NS("Mute")];
    [o_volume_up_btn setToolTip: _NS("Full Volume")];
    [o_time_sld setToolTip: _NS("Position")];
148 149
    [o_dropzone_btn setTitle: _NS("Open media...")];
    [o_dropzone_lbl setStringValue: _NS("Drop media here")];
150

151
    if (!b_dark_interface) {
152
        [o_bottombar_view setImagesLeft: [NSImage imageNamed:@"bottom-background"] middle: [NSImage imageNamed:@"bottom-background"] right: [NSImage imageNamed:@"bottom-background"]];
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
        [o_bwd_btn setImage: [NSImage imageNamed:@"back"]];
        [o_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed"]];
        o_play_img = [[NSImage imageNamed:@"play"] retain];
        o_play_pressed_img = [[NSImage imageNamed:@"play-pressed"] retain];
        o_pause_img = [[NSImage imageNamed:@"pause"] retain];
        o_pause_pressed_img = [[NSImage imageNamed:@"pause-pressed"] retain];
        [o_fwd_btn setImage: [NSImage imageNamed:@"forward"]];
        [o_fwd_btn setAlternateImage: [NSImage imageNamed:@"forward-pressed"]];
        [o_stop_btn setImage: [NSImage imageNamed:@"stop"]];
        [o_stop_btn setAlternateImage: [NSImage imageNamed:@"stop-pressed"]];
        [o_playlist_btn setImage: [NSImage imageNamed:@"playlist"]];
        [o_playlist_btn setAlternateImage: [NSImage imageNamed:@"playlist-pressed"]];
        o_repeat_img = [[NSImage imageNamed:@"repeat"] retain];
        o_repeat_pressed_img = [[NSImage imageNamed:@"repeat-pressed"] retain];
        o_repeat_all_img  = [[NSImage imageNamed:@"repeat-all"] retain];
        o_repeat_all_pressed_img = [[NSImage imageNamed:@"repeat-all-pressed"] retain];
        o_repeat_one_img = [[NSImage imageNamed:@"repeat-one"] retain];
        o_repeat_one_pressed_img = [[NSImage imageNamed:@"repeat-one-pressed"] retain];
        o_shuffle_img = [[NSImage imageNamed:@"shuffle"] retain];
        o_shuffle_pressed_img = [[NSImage imageNamed:@"shuffle-pressed"] retain];
        o_shuffle_on_img = [[NSImage imageNamed:@"shuffle-blue"] retain];
        o_shuffle_on_pressed_img = [[NSImage imageNamed:@"shuffle-blue-pressed"] retain];
175
        [o_time_sld_background setImagesLeft: [NSImage imageNamed:@"progression-track-wrapper-left"] middle: [NSImage imageNamed:@"progression-track-wrapper-middle"] right: [NSImage imageNamed:@"progression-track-wrapper-right"]];
176
        [o_volume_down_btn setImage: [NSImage imageNamed:@"volume-low"]];
177
        [o_volume_track_view setImage: [NSImage imageNamed:@"volume-slider-track"]];
178
        [o_volume_up_btn setImage: [NSImage imageNamed:@"volume-high"]];
179
        if (OSX_LION && b_nativeFullscreenMode)
180 181 182 183 184 185 186 187 188
        {
            [o_effects_btn setImage: [NSImage imageNamed:@"effects-one-button"]];
            [o_effects_btn setAlternateImage: [NSImage imageNamed:@"effects-one-button-blue"]];
        }
        else
        {
            [o_effects_btn setImage: [NSImage imageNamed:@"effects-double-buttons"]];
            [o_effects_btn setAlternateImage: [NSImage imageNamed:@"effects-double-buttons-pressed"]];
        }
189 190
        [o_fullscreen_btn setImage: [NSImage imageNamed:@"fullscreen-double-buttons"]];
        [o_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"fullscreen-double-buttons-pressed"]];
191
        [o_time_sld_fancygradient_view setImagesLeft:[NSImage imageNamed:@"progression-fill-left"] middle:[NSImage imageNamed:@"progression-fill-middle"] right:[NSImage imageNamed:@"progression-fill-right"]];
192 193 194
    }
    else
    {
195
        [o_bottombar_view setImagesLeft: [NSImage imageNamed:@"bottomdark-left"] middle: [NSImage imageNamed:@"bottom-background_dark"] right: [NSImage imageNamed:@"bottomdark-right"]];
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
        [o_bwd_btn setImage: [NSImage imageNamed:@"back_dark"]];
        [o_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed_dark"]];
        o_play_img = [[NSImage imageNamed:@"play_dark"] retain];
        o_play_pressed_img = [[NSImage imageNamed:@"play-pressed_dark"] retain];
        o_pause_img = [[NSImage imageNamed:@"pause_dark"] retain];
        o_pause_pressed_img = [[NSImage imageNamed:@"pause-pressed_dark"] retain];
        [o_fwd_btn setImage: [NSImage imageNamed:@"forward_dark"]];
        [o_fwd_btn setAlternateImage: [NSImage imageNamed:@"forward-pressed_dark"]];
        [o_stop_btn setImage: [NSImage imageNamed:@"stop_dark"]];
        [o_stop_btn setAlternateImage: [NSImage imageNamed:@"stop-pressed_dark"]];
        [o_playlist_btn setImage: [NSImage imageNamed:@"playlist_dark"]];
        [o_playlist_btn setAlternateImage: [NSImage imageNamed:@"playlist-pressed_dark"]];
        o_repeat_img = [[NSImage imageNamed:@"repeat_dark"] retain];
        o_repeat_pressed_img = [[NSImage imageNamed:@"repeat-pressed_dark"] retain];
        o_repeat_all_img  = [[NSImage imageNamed:@"repeat-all-blue_dark"] retain];
        o_repeat_all_pressed_img = [[NSImage imageNamed:@"repeat-all-blue-pressed_dark"] retain];
        o_repeat_one_img = [[NSImage imageNamed:@"repeat-one-blue_dark"] retain];
        o_repeat_one_pressed_img = [[NSImage imageNamed:@"repeat-one-blue-pressed_dark"] retain];
        o_shuffle_img = [[NSImage imageNamed:@"shuffle_dark"] retain];
        o_shuffle_pressed_img = [[NSImage imageNamed:@"shuffle-pressed_dark"] retain];
        o_shuffle_on_img = [[NSImage imageNamed:@"shuffle-blue_dark"] retain];
        o_shuffle_on_pressed_img = [[NSImage imageNamed:@"shuffle-blue-pressed_dark"] retain];
218
        [o_time_sld_background setImagesLeft: [NSImage imageNamed:@"progression-track-wrapper-left_dark"] middle: [NSImage imageNamed:@"progression-track-wrapper-middle_dark"] right: [NSImage imageNamed:@"progression-track-wrapper-right_dark"]];
219 220 221
        [o_volume_down_btn setImage: [NSImage imageNamed:@"volume-low_dark"]];
        [o_volume_track_view setImage: [NSImage imageNamed:@"volume-slider-track_dark"]];
        [o_volume_up_btn setImage: [NSImage imageNamed:@"volume-high_dark"]];
222
        if (OSX_LION && b_nativeFullscreenMode)
223 224 225 226 227 228 229 230 231
        {
            [o_effects_btn setImage: [NSImage imageNamed:@"effects-one-button_dark"]];
            [o_effects_btn setAlternateImage: [NSImage imageNamed:@"effects-one-button-blue_dark"]];
        }
        else
        {
            [o_effects_btn setImage: [NSImage imageNamed:@"effects-double-buttons_dark"]];
            [o_effects_btn setAlternateImage: [NSImage imageNamed:@"effects-double-buttons-pressed_dark"]];            
        }
232
        [o_fullscreen_btn setImage: [NSImage imageNamed:@"fullscreen-double-buttons_dark"]];
233
        [o_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"fullscreen-double-buttons-pressed_dark"]];
234
        [o_time_sld_fancygradient_view setImagesLeft:[NSImage imageNamed:@"progressbar-fill-left_dark"] middle:[NSImage imageNamed:@"progressbar-fill-middle_dark"] right:[NSImage imageNamed:@"progressbar-fill-right_dark"]];
235 236 237 238 239 240 241
    }
    [o_repeat_btn setImage: o_repeat_img];
    [o_repeat_btn setAlternateImage: o_repeat_pressed_img];
    [o_shuffle_btn setImage: o_shuffle_img];
    [o_shuffle_btn setAlternateImage: o_shuffle_pressed_img];
    [o_play_btn setImage: o_play_img];
    [o_play_btn setAlternateImage: o_play_pressed_img];
242 243 244
    BOOL b_mute = ![[VLCCoreInteraction sharedInstance] isMuted];
    [o_volume_sld setEnabled: b_mute];
    [o_volume_up_btn setEnabled: b_mute];
245

246
    /* interface builder action */
247 248
    [self setDelegate: self];
    [self setExcludedFromWindowsMenu: YES];
249
    [self setAcceptsMouseMovedEvents: YES];
250
    // Set that here as IB seems to be buggy
251
    if (b_dark_interface)
252
        [self setContentMinSize:NSMakeSize(604., (288. + [o_titlebar_view frame].size.height))];
253
    else
254
        [self setContentMinSize:NSMakeSize(604., 288.)];
255
    [self setTitle: _NS("VLC media player")];
256 257
    [o_time_fld setAlignment: NSCenterTextAlignment];
    [o_time_fld setNeedsDisplay:YES];
258
    b_dropzone_active = YES;
259 260
    o_temp_view = [[NSView alloc] init];
    [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
261
    [o_dropzone_view setFrame: [o_playlist_table frame]];
262
    [o_left_split_view setFrame: [o_sidebar_view frame]];
263
    if (OSX_LION && b_nativeFullscreenMode)
264 265
    {
        NSRect frame;
266
        [self setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
        float f_width = [o_fullscreen_btn frame].size.width;

        #define moveItem( item ) \
        frame = [item frame]; \
        frame.origin.x = f_width + frame.origin.x; \
        [item setFrame: frame]

        moveItem( o_effects_btn );
        moveItem( o_volume_up_btn );
        moveItem( o_volume_sld );
        moveItem( o_volume_track_view );
        moveItem( o_volume_down_btn );
        moveItem( o_time_fld );
        #undef moveItem

        #define enlargeItem( item ) \
        frame = [item frame]; \
        frame.size.width = f_width + frame.size.width; \
        [item setFrame: frame]

        enlargeItem( o_time_sld );
        enlargeItem( o_progress_bar );
289
        enlargeItem( o_time_sld_background );
290 291 292 293 294
        enlargeItem( o_time_sld_fancygradient_view );
        #undef enlargeItem

        [o_fullscreen_btn removeFromSuperviewWithoutNeedingDisplay];
    }
295 296 297
    else
        [o_titlebar_view setFullscreenButtonHidden: YES];

298 299 300 301 302 303 304 305 306
    if (OSX_LION)
    {
        /* the default small size of the search field is slightly different on Lion, let's work-around that */
        NSRect frame;
        frame = [o_search_fld frame];
        frame.origin.y = frame.origin.y + 2.0;
        frame.size.height = frame.size.height - 1.0;
        [o_search_fld setFrame: frame];
    }
307

308 309 310 311
    /* create the sidebar */
    o_sidebaritems = [[NSMutableArray alloc] init];
    SideBarItem *libraryItem = [SideBarItem itemWithTitle:_NS("LIBRARY") identifier:@"library"];
    SideBarItem *playlistItem = [SideBarItem itemWithTitle:_NS("Playlist") identifier:@"playlist"];
312
    [playlistItem setIcon: [NSImage imageNamed:@"sidebar-playlist"]];
313 314
    SideBarItem *medialibraryItem = [SideBarItem itemWithTitle:_NS("Media Library") identifier:@"medialibrary"];
    [medialibraryItem setIcon: [NSImage imageNamed:@"sidebar-playlist"]];
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
    SideBarItem *mycompItem = [SideBarItem itemWithTitle:_NS("MY COMPUTER") identifier:@"mycomputer"];
    SideBarItem *devicesItem = [SideBarItem itemWithTitle:_NS("DEVICES") identifier:@"devices"];
    SideBarItem *lanItem = [SideBarItem itemWithTitle:_NS("LOCAL NETWORK") identifier:@"localnetwork"];
    SideBarItem *internetItem = [SideBarItem itemWithTitle:_NS("INTERNET") identifier:@"internet"];

    /* SD subnodes, inspired by the Qt4 intf */
    char **ppsz_longnames;
    int *p_categories;
    char **ppsz_names = vlc_sd_GetNames( pl_Get( VLCIntf ), &ppsz_longnames, &p_categories );
    if (!ppsz_names)
        msg_Err( VLCIntf, "no sd item found" ); //TODO
    char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
    int *p_category = p_categories;
    NSMutableArray *internetItems = [[NSMutableArray alloc] init];
    NSMutableArray *devicesItems = [[NSMutableArray alloc] init];
    NSMutableArray *lanItems = [[NSMutableArray alloc] init];
    NSMutableArray *mycompItems = [[NSMutableArray alloc] init];
332
    NSString *o_identifier;
333 334
    for (; *ppsz_name; ppsz_name++, ppsz_longname++, p_category++)
    {
335
        o_identifier = [NSString stringWithCString: *ppsz_name encoding: NSUTF8StringEncoding];
336 337
        switch (*p_category) {
            case SD_CAT_INTERNET:
338
                {
339
                    [internetItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
340
                    if (!strncmp( *ppsz_name, "podcast", 7 ))
341 342
                        [internetItems removeLastObject]; // we don't support podcasts at this point (see #6017)
//                        [[internetItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-podcast"]];
343 344
                    else
                        [[internetItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
345
                    [[internetItems lastObject] setSdtype: SD_CAT_INTERNET];
346
                    [[internetItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
347
                }
348 349
                break;
            case SD_CAT_DEVICES:
350
                {
351
                    [devicesItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
352
                    [[devicesItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
353
                    [[devicesItems lastObject] setSdtype: SD_CAT_DEVICES];
354
                    [[devicesItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
355
                }
356 357
                break;
            case SD_CAT_LAN:
358
                {
359
                    [lanItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
360
                    [[lanItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-local"]];
361
                    [[lanItems lastObject] setSdtype: SD_CAT_LAN];
362
                    [[lanItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
363
                }
364 365
                break;
            case SD_CAT_MYCOMPUTER:
366
                {
367
                    [mycompItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
368
                    if (!strncmp( *ppsz_name, "video_dir", 9 ))
369
                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-movie"]];
370
                    else if (!strncmp( *ppsz_name, "audio_dir", 9 ))
371
                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-music"]];
372
                    else if (!strncmp( *ppsz_name, "picture_dir", 11 ))
373
                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-pictures"]];
374 375
                    else
                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
376
                    [[mycompItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
377
                    [[mycompItems lastObject] setSdtype: SD_CAT_MYCOMPUTER];
378
                }
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
                break;
            default:
                msg_Warn( VLCIntf, "unknown SD type found, skipping (%s)", *ppsz_name );
                break;
        }

        free( *ppsz_name );
        free( *ppsz_longname );
    }
    [mycompItem setChildren: [NSArray arrayWithArray: mycompItems]];
    [devicesItem setChildren: [NSArray arrayWithArray: devicesItems]];
    [lanItem setChildren: [NSArray arrayWithArray: lanItems]];
    [internetItem setChildren: [NSArray arrayWithArray: internetItems]];
    [mycompItems release];
    [devicesItems release];
    [lanItems release];
    [internetItems release];
    free( ppsz_names );
    free( ppsz_longnames );
    free( p_categories );

400
    [libraryItem setChildren: [NSArray arrayWithObjects: playlistItem, medialibraryItem, nil]];
401 402 403 404 405 406 407 408 409 410 411
    [o_sidebaritems addObject: libraryItem];
    if ([mycompItem hasChildren])
        [o_sidebaritems addObject: mycompItem];
    if ([devicesItem hasChildren])
        [o_sidebaritems addObject: devicesItem];
    if ([lanItem hasChildren])
        [o_sidebaritems addObject: lanItem];
    if ([internetItem hasChildren])
        [o_sidebaritems addObject: internetItem];

    [o_sidebar_view reloadData];
412 413 414
    NSUInteger i_sidebaritem_count = [o_sidebaritems count];
    for (NSUInteger x = 0; x < i_sidebaritem_count; x++)
        [o_sidebar_view expandItem: [o_sidebaritems objectAtIndex: x] expandChildren: YES];
415
    [o_sidebar_view selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
416 417 418

    if( b_dark_interface )
    {
419 420 421
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowResizedOrMoved:) name: NSWindowDidResizeNotification object: nil];
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowResizedOrMoved:) name: NSWindowDidMoveNotification object: nil];

422 423
        [self setBackgroundColor: [NSColor clearColor]];
        [self setOpaque: NO];
424
        [self setHasShadow:YES];
425

426
        NSRect winrect = [self frame];
427 428 429 430 431 432
        CGFloat f_titleBarHeight = [o_titlebar_view frame].size.height;

        [o_titlebar_view setFrame: NSMakeRect( 0, winrect.size.height - f_titleBarHeight,
                                              winrect.size.width, f_titleBarHeight )];
        [[self contentView] addSubview: o_titlebar_view];

433 434
        [self setFrame: winrect display:YES animate:YES];
        previousSavedFrame = winrect;
435 436 437 438
        winrect = [o_split_view frame];
        winrect.size.height = winrect.size.height - f_titleBarHeight;
        [o_split_view setFrame: winrect];
        [o_video_view setFrame: winrect];
439

440 441 442
        o_color_backdrop = [[VLCColorView alloc] initWithFrame: [o_split_view frame]];
        [[self contentView] addSubview: o_color_backdrop positioned: NSWindowBelow relativeTo: o_split_view];
        [o_color_backdrop setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
443 444
    }
    else
445
    {
446 447 448 449 450 451
        NSRect frame;
        frame = [o_time_sld_fancygradient_view frame];
        frame.size.height = frame.size.height - 1;
        frame.origin.y = frame.origin.y + 1;
        [o_time_sld_fancygradient_view setFrame: frame];

452
        [o_video_view setFrame: [o_split_view frame]];
453 454 455
        [o_playlist_table setBorderType: NSNoBorder];
        [o_sidebar_scrollview setBorderType: NSNoBorder];
    }
456 457 458 459 460 461

    if (OSX_LION)
        [o_resize_view setImage: NULL];

    if ([self styleMask] & NSResizableWindowMask)
        [o_resize_view removeFromSuperviewWithoutNeedingDisplay];
462 463 464

    if (OSX_LEOPARD)
        [o_time_sld_fancygradient_view removeFromSuperviewWithoutNeedingDisplay];
465 466

    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(someWindowWillClose:) name: NSWindowWillCloseNotification object: nil];
467
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(someWindowWillMiniaturize:) name: NSWindowWillMiniaturizeNotification object:nil];
468
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(applicationWillTerminate:) name: NSApplicationWillTerminateNotification object: nil];
469
    [[VLCMain sharedInstance] playbackModeUpdated];
470 471 472 473 474 475 476 477 478 479
}

#pragma mark -
#pragma mark Button Actions

- (IBAction)play:(id)sender
{
    [[VLCCoreInteraction sharedInstance] play];
}

480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
- (void)resetPreviousButton
{
    if (([NSDate timeIntervalSinceReferenceDate] - last_bwd_event) >= 0.35) {
        // seems like no further event occured, so let's switch the playback item
        [[VLCCoreInteraction sharedInstance] previous];
        just_triggered_previous = NO;
    }
}

- (void)resetBackwardSkip
{
    // the user stopped skipping, so let's allow him to change the item
    if (([NSDate timeIntervalSinceReferenceDate] - last_bwd_event) >= 0.35)
        just_triggered_previous = NO;
}

496 497
- (IBAction)bwd:(id)sender
{
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
    if(!just_triggered_previous)
    {
        just_triggered_previous = YES;
        [self performSelector:@selector(resetPreviousButton)
                   withObject: NULL
                   afterDelay:0.40];
    }
    else
    {
        if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) > 0.12 )
        {
            // we just skipped 3 "continous" events, otherwise we are too fast
            [[VLCCoreInteraction sharedInstance] backward];
            last_bwd_event = [NSDate timeIntervalSinceReferenceDate];
            [self performSelector:@selector(resetBackwardSkip)
                       withObject: NULL
                       afterDelay:0.40];
        }
    }
}

- (void)resetNextButton
{
    if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) >= 0.35) {
        // seems like no further event occured, so let's switch the playback item
        [[VLCCoreInteraction sharedInstance] next];
        just_triggered_next = NO;
    }
}

- (void)resetForwardSkip
{
    // the user stopped skipping, so let's allow him to change the item
    if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) >= 0.35)
        just_triggered_next = NO;
533 534 535 536
}

- (IBAction)fwd:(id)sender
{
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
   if(!just_triggered_next)
    {
        just_triggered_next = YES;
        [self performSelector:@selector(resetNextButton)
                   withObject: NULL
                   afterDelay:0.40];
    }
    else
    {
        if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) > 0.12 )
        {
            // we just skipped 3 "continous" events, otherwise we are too fast
            [[VLCCoreInteraction sharedInstance] forward];
            last_fwd_event = [NSDate timeIntervalSinceReferenceDate];
            [self performSelector:@selector(resetForwardSkip)
                       withObject: NULL
                       afterDelay:0.40];
        }
    }
556 557 558 559 560 561 562 563 564
}

- (IBAction)stop:(id)sender
{
    [[VLCCoreInteraction sharedInstance] stop];
}

- (IBAction)togglePlaylist:(id)sender
{
565
    if (b_dropzone_active && ![[VLCMain sharedInstance] activeVideoPlayback])
566 567 568 569 570
    {
        b_dropzone_active = NO;
        [self hideDropZone];
    }

571 572
    if (!b_nonembedded)
    {
573
        if ([o_video_view isHidden] && [[VLCMain sharedInstance] activeVideoPlayback]) {
574
            [o_split_view setHidden: YES];
575
            [o_video_view setHidden: NO];
576
            [self makeFirstResponder: o_video_view];
577 578 579 580
        }
        else
        {
            [o_video_view setHidden: YES];
581
            [o_split_view setHidden: NO];
582
            [self makeFirstResponder: nil];
583
        }
584 585 586
    }
    else
    {
587
        [o_split_view setHidden: NO];
588
        [o_playlist_table setHidden: NO];
589
        [o_video_view setHidden: ![[VLCMain sharedInstance] activeVideoPlayback]];
590 591 592
    }
}

593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
- (void)setRepeatOne
{
    [o_repeat_btn setImage: o_repeat_one_img];
    [o_repeat_btn setAlternateImage: o_repeat_one_pressed_img];   
}

- (void)setRepeatAll
{
    [o_repeat_btn setImage: o_repeat_all_img];
    [o_repeat_btn setAlternateImage: o_repeat_all_pressed_img];
}

- (void)setRepeatOff
{
    [o_repeat_btn setImage: o_repeat_img];
    [o_repeat_btn setAlternateImage: o_repeat_pressed_img];
}

611 612 613 614 615 616 617 618 619 620 621 622 623
- (IBAction)repeat:(id)sender
{
    vlc_value_t looping,repeating;
    intf_thread_t * p_intf = VLCIntf;
    playlist_t * p_playlist = pl_Get( 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 */
        [[VLCCoreInteraction sharedInstance] repeatOne];
624
        [self setRepeatOne];
625 626 627 628 629
    }
    else if( repeating.b_bool && !looping.b_bool )
    {
        /* was: Repeat One, switching to Repeat All */
        [[VLCCoreInteraction sharedInstance] repeatAll];
630
        [self setRepeatAll];
631 632 633 634 635
    }
    else
    {
        /* was: Repeat All or bug in VLC, switching to Repeat Off */
        [[VLCCoreInteraction sharedInstance] repeatOff];
636
        [self setRepeatOff];
637 638 639
    }
}

640
- (void)setShuffle
641
{
642
    bool b_value;
643
    playlist_t *p_playlist = pl_Get( VLCIntf );
644 645
    b_value = var_GetBool( p_playlist, "random" );
	if(b_value) {
646 647 648 649 650 651 652 653 654 655
        [o_shuffle_btn setImage: o_shuffle_on_img];
        [o_shuffle_btn setAlternateImage: o_shuffle_on_pressed_img];
    }
    else
    {
        [o_shuffle_btn setImage: o_shuffle_img];
        [o_shuffle_btn setAlternateImage: o_shuffle_pressed_img];
    }
}

656 657 658 659 660 661
- (IBAction)shuffle:(id)sender
{
    [[VLCCoreInteraction sharedInstance] shuffle];
    [self setShuffle];
}

662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
- (IBAction)timeSliderAction:(id)sender
{
    float f_updated;
    input_thread_t * p_input;

    switch( [[NSApp currentEvent] type] )
    {
        case NSLeftMouseUp:
        case NSLeftMouseDown:
        case NSLeftMouseDragged:
            f_updated = [sender floatValue];
            break;

        default:
            return;
    }
    p_input = pl_CurrentInput( VLCIntf );
    if( p_input != NULL )
    {
        vlc_value_t time;
        vlc_value_t pos;
        NSString * o_time;
        char psz_time[MSTRTIME_MAX_SIZE];

        pos.f_float = f_updated / 10000.;
        var_Set( p_input, "position", pos );
        [o_time_sld setFloatValue: f_updated];

        var_Get( p_input, "time", &time );

        mtime_t dur = input_item_GetDuration( input_GetItem( p_input ) );
693
        if( [o_time_fld timeRemaining] && dur != -1 )
694 695 696 697 698 699 700
        {
            o_time = [NSString stringWithFormat: @"-%s", secstotimestr( psz_time, ((dur - time.i_time) / 1000000) )];
        }
        else
            o_time = [NSString stringWithUTF8String: secstotimestr( psz_time, (time.i_time / 1000000) )];

        [o_time_fld setStringValue: o_time];
701
        [o_fspanel setStreamPos: f_updated andTime: o_time];
702 703
        vlc_object_release( p_input );
    }
704
    [self drawFancyGradientEffectForTimeSlider];
705 706 707 708 709 710 711
}

- (IBAction)volumeAction:(id)sender
{
    if (sender == o_volume_sld)
        [[VLCCoreInteraction sharedInstance] setVolume: [sender intValue]];
    else if (sender == o_volume_down_btn)
712
    {
713
        [[VLCCoreInteraction sharedInstance] mute];
714 715 716 717 718
        [o_volume_sld setIntValue: 0];
        BOOL b_mute = ![[VLCCoreInteraction sharedInstance] isMuted];
        [o_volume_sld setEnabled: b_mute];
        [o_volume_up_btn setEnabled: b_mute];
    }
719
    else
720
        [[VLCCoreInteraction sharedInstance] setVolume: AOUT_VOLUME_MAX];
721 722 723 724 725 726 727 728 729
}

- (IBAction)effects:(id)sender
{
    [[VLCMainMenu sharedInstance] showAudioEffects: sender];
}

- (IBAction)fullscreen:(id)sender
{
730
    [[VLCCoreInteraction sharedInstance] toggleFullscreen];
731 732
}

733 734 735 736 737
- (IBAction)dropzoneButtonAction:(id)sender
{
    [[[VLCMain sharedInstance] open] openFileGeneric];
}

738 739 740 741 742 743 744
#pragma mark -
#pragma mark overwritten default functionality
- (BOOL)canBecomeKeyWindow
{
    return YES;
}

745 746 747 748 749 750 751 752 753
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
	SEL s_menuAction = [menuItem action];
	if ((s_menuAction == @selector(performClose:)) || (s_menuAction == @selector(performMiniaturize:)) || (s_menuAction == @selector(performZoom:)))
        return YES;

	return [super validateMenuItem:menuItem];
}

754 755 756 757 758
- (BOOL)isMainWindow
{
	return YES;
}

759 760
- (void)setTitle:(NSString *)title
{
761 762
    if (b_dark_interface)
        [o_titlebar_view setWindowTitle: title];
763 764
    if (b_nonembedded && [[VLCMain sharedInstance] activeVideoPlayback])
        [o_nonembedded_window setTitle: title];
765 766 767
    [super setTitle: title];
}

768 769 770
- (void)performClose:(id)sender
{
    if (b_dark_interface)
771
    {
772
        [self orderOut: sender];
773 774
        [[VLCCoreInteraction sharedInstance] stop];
    }
775 776 777 778 779 780 781
    else
        [super performClose: sender];
}

- (void)performMiniaturize:(id)sender
{
    if (b_dark_interface)
782
    {
783
        [self miniaturize: sender];
784 785 786 787 788
        if (config_GetInt( VLCIntf, "macosx-pause-minimized" ))
        {
            if ([[VLCMain sharedInstance] activeVideoPlayback])
                [[VLCCoreInteraction sharedInstance] pause];
        }
789
    }
790 791 792 793
    else
        [super performMiniaturize: sender];
}

794 795
- (void)performZoom:(id)sender
{
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
    if (b_dark_interface)
        [self customZoom: sender];
    else
        [super performZoom: sender];
}

- (void)zoom:(id)sender
{
    if (b_dark_interface)
        [self customZoom: sender];
    else
        [super zoom: sender];
}

/**
 * Given a proposed frame rectangle, return a modified version
 * which will fit inside the screen.
 *
 * This method is based upon NSWindow.m, part of the GNUstep GUI Library, licensed under LGPLv2+.
 *    Authors:  Scott Christley <scottc@net-community.com>, Venkat Ajjanagadde <venkat@ocbi.com>,   
 *              Felipe A. Rodriguez <far@ix.netcom.com>, Richard Frith-Macdonald <richard@brainstorm.co.uk>
 *    Copyright (C) 1996 Free Software Foundation, Inc.
 */
819
- (NSRect) customConstrainFrameRect: (NSRect)frameRect toScreen: (NSScreen*)screen
820 821 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
{
    NSRect screenRect = [screen visibleFrame];
    float difference;

    /* Move top edge of the window inside the screen */
    difference = NSMaxY (frameRect) - NSMaxY (screenRect);
    if (difference > 0)
    {
        frameRect.origin.y -= difference;
    }

    /* If the window is resizable, resize it (if needed) so that the
     bottom edge is on the screen or can be on the screen when the user moves
     the window */
    difference = NSMaxY (screenRect) - NSMaxY (frameRect);
    if (_styleMask & NSResizableWindowMask)
    {
        float difference2;

        difference2 = screenRect.origin.y - frameRect.origin.y;
        difference2 -= difference;
        // Take in account the space between the top of window and the top of the 
        // screen which can be used to move the bottom of the window on the screen
        if (difference2 > 0)
        {
            frameRect.size.height -= difference2;
            frameRect.origin.y += difference2;
        }

        /* Ensure that resizing doesn't makewindow smaller than minimum */
        difference2 = [self minSize].height - frameRect.size.height;
        if (difference2 > 0)
        {
            frameRect.size.height += difference2;
            frameRect.origin.y -= difference2;
        }
    }

    return frameRect;
}

#define DIST 3

/**
 Zooms the receiver.   This method calls the delegate method
 windowShouldZoom:toFrame: to determine if the window should
 be allowed to zoom to full screen.
 *
 * This method is based upon NSWindow.m, part of the GNUstep GUI Library, licensed under LGPLv2+.
 *    Authors:  Scott Christley <scottc@net-community.com>, Venkat Ajjanagadde <venkat@ocbi.com>,   
 *              Felipe A. Rodriguez <far@ix.netcom.com>, Richard Frith-Macdonald <richard@brainstorm.co.uk>
 *    Copyright (C) 1996 Free Software Foundation, Inc.
 */
- (void) customZoom: (id)sender
{
    NSRect maxRect = [[self screen] visibleFrame];
    NSRect currentFrame = [self frame];

    if ([[self delegate] respondsToSelector: @selector(windowWillUseStandardFrame:defaultFrame:)])
    {
        maxRect = [[self delegate] windowWillUseStandardFrame: self defaultFrame: maxRect];
    }

883
    maxRect = [self customConstrainFrameRect: maxRect toScreen: [self screen]];
884 885 886 887 888 889 890 891 892 893

    // Compare the new frame with the current one
    if ((abs(NSMaxX(maxRect) - NSMaxX(currentFrame)) < DIST)
        && (abs(NSMaxY(maxRect) - NSMaxY(currentFrame)) < DIST)
        && (abs(NSMinX(maxRect) - NSMinX(currentFrame)) < DIST)
        && (abs(NSMinY(maxRect) - NSMinY(currentFrame)) < DIST))
    {
        // Already in zoomed mode, reset user frame, if stored
        if ([self frameAutosaveName] != nil)
        {
894
            [self setFrame: previousSavedFrame display: YES animate: YES];
895 896 897 898 899 900 901 902
            [self saveFrameUsingName: [self frameAutosaveName]];
        }
        return;
    }

    if ([self frameAutosaveName] != nil)
    {
        [self saveFrameUsingName: [self frameAutosaveName]];
903
        previousSavedFrame = [self frame];
904 905
    }

906
    [self setFrame: maxRect display: YES animate: YES];
907 908
}

909 910 911 912 913
- (void)windowResizedOrMoved:(NSNotification *)notification
{
    [self saveFrameUsingName: [self frameAutosaveName]];
}

914 915
- (void)applicationWillTerminate:(NSNotification *)notification
{
916 917 918
    if( config_GetInt( VLCIntf, "macosx-autosave-volume" ))
        config_PutInt( VLCIntf->p_libvlc, "volume", i_lastShownVolume );

919 920 921 922 923 924 925 926 927 928 929
    [self saveFrameUsingName: [self frameAutosaveName]];
}

- (void)someWindowWillClose:(NSNotification *)notification
{
    if([notification object] == o_nonembedded_window || [notification object] == self)
        [[VLCCoreInteraction sharedInstance] stop];
}

- (void)someWindowWillMiniaturize:(NSNotification *)notification
{
930
    if (config_GetInt( VLCIntf, "macosx-pause-minimized" ))
931
    {
932 933 934 935 936
        if([notification object] == o_nonembedded_window || [notification object] == self)
        {
            if([[VLCMain sharedInstance] activeVideoPlayback])
                [[VLCCoreInteraction sharedInstance] pause];
        }
937 938 939
    }
}

940 941
#pragma mark -
#pragma mark Update interface and respond to foreign events
942 943
- (void)showDropZone
{
944
    b_dropzone_active = YES;
945
    [o_right_split_view addSubview: o_dropzone_view];
946
    [o_dropzone_view setFrame: [o_playlist_table frame]];
947
    [[o_playlist_table animator] setHidden:YES];
948 949 950 951 952
}

- (void)hideDropZone
{
    [o_dropzone_view removeFromSuperview];
953
    [[o_playlist_table animator] setHidden: NO];
954 955
}

956 957
- (void)updateTimeSlider
{
958 959 960
    input_thread_t * p_input;
    p_input = pl_CurrentInput( VLCIntf );
    if( p_input )
961
    {
962 963 964 965 966 967 968 969 970 971 972 973 974
        vlc_value_t time;
        NSString * o_time;
        vlc_value_t pos;
        char psz_time[MSTRTIME_MAX_SIZE];
        float f_updated;

        var_Get( p_input, "position", &pos );
        f_updated = 10000. * pos.f_float;
        [o_time_sld setFloatValue: f_updated];

        var_Get( p_input, "time", &time );

        mtime_t dur = input_item_GetDuration( input_GetItem( p_input ) );
975
        if( [o_time_fld timeRemaining] && dur != -1 )
976
        {
977
            o_time = [NSString stringWithFormat: @"-%s", secstotimestr( psz_time, ((dur - time.i_time) / 1000000))];
978
        }
979 980 981
        else
            o_time = [NSString stringWithUTF8String: secstotimestr( psz_time, (time.i_time / 1000000) )];

982 983 984 985 986 987 988 989
        if (dur == -1) {
            [o_time_sld setEnabled: NO];
            [o_time_sld setHidden: YES];
        } else {
            [o_time_sld setEnabled: YES];
            [o_time_sld setHidden: NO];
        }

990
        [o_time_fld setStringValue: o_time];
991
        [o_time_fld setNeedsDisplay:YES];
992
        [o_fspanel setStreamPos: f_updated andTime: o_time];
993
        vlc_object_release( p_input );
994
    }
995 996 997 998
    else
    {
        [o_time_sld setFloatValue: 0.0];
        [o_time_fld setStringValue: @"00:00"];
999 1000
        [o_time_sld setEnabled: NO];
        [o_time_sld setHidden: YES];
1001 1002 1003
    }
        
    [self performSelectorOnMainThread:@selector(drawFancyGradientEffectForTimeSlider) withObject:nil waitUntilDone:NO];
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
}

- (void)updateVolumeSlider
{
    audio_volume_t i_volume;
    playlist_t * p_playlist = pl_Get( VLCIntf );

    i_volume = aout_VolumeGet( p_playlist );

    if( i_volume != i_lastShownVolume )
    {
1015
        i_lastShownVolume = i_volume;
1016 1017
        [o_volume_sld setIntValue: i_volume];
        [o_fspanel setVolumeLevel: i_volume];
1018 1019 1020
    }
}

1021
- (void)updateName
1022
{
1023
    NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
1024 1025 1026 1027 1028
    input_thread_t * p_input;
    p_input = pl_CurrentInput( VLCIntf );
    if( p_input )
    {
        NSString *aString;
1029 1030 1031 1032 1033
        char *format = var_InheritString( VLCIntf, "input-title-format" );
        char *formated = str_format_meta( p_input, format );
        free( format );
        aString = [NSString stringWithUTF8String:formated];
        free( formated );
1034

1035
        char *uri = input_item_GetURI( input_GetItem( p_input ) );
1036

1037 1038 1039 1040
        NSURL * o_url = [NSURL URLWithString: [NSString stringWithUTF8String: uri]];
        if ([o_url isFileURL])
            [self setRepresentedURL: o_url];
        else
1041
            [self setRepresentedURL: nil];
1042 1043
        free( uri );

1044
        if ([aString isEqualToString:@""])
1045
        {
1046 1047 1048 1049
            if ([o_url isFileURL])
                aString = [[NSFileManager defaultManager] displayNameAtPath: [o_url path]];
            else
                aString = [o_url absoluteString];
1050
        }
1051 1052

        [self setTitle: aString];
1053
        [o_fspanel setStreamTitle: aString];
1054
        vlc_object_release( p_input );
1055
    }
1056 1057 1058
    else
    {
        [self setTitle: _NS("VLC media player")];
1059
        [self setRepresentedURL: nil];
1060
    }
1061

1062
    [o_pool release];
1063 1064
}

1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
- (void)updateWindow
{
    bool b_input = false;
    bool b_plmul = false;
    bool b_control = false;
    bool b_seekable = false;
    bool b_chapters = false;

    playlist_t * p_playlist = pl_Get( VLCIntf );

    PL_LOCK;
    b_plmul = playlist_CurrentSize( p_playlist ) > 1;
    PL_UNLOCK;

    input_thread_t * p_input = playlist_CurrentInput( p_playlist );

    bool b_buffering = NO;

    if( ( b_input = ( p_input != NULL ) ) )
    {
        /* seekable streams */
        cachedInputState = input_GetState( p_input );
        if ( cachedInputState == INIT_S || cachedInputState == OPENING_S )
            b_buffering = YES;

        /* seekable streams */
        b_seekable = var_GetBool( p_input, "can-seek" );

        /* check whether slow/fast motion is possible */
        b_control = var_GetBool( p_input, "can-rate" );

        /* chapters & titles */
        //FIXME! b_chapters = p_input->stream.i_area_nb > 1;
1098

1099
        if (( cachedInputState == PLAYING_S || b_buffering == YES ) && [[VLCMain sharedInstance] activeVideoPlayback] )
1100 1101
            [[o_video_view window] makeKeyAndOrderFront: nil];

1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
        vlc_object_release( p_input );
    }

    if( b_buffering )
    {
        [o_progress_bar startAnimation:self];
        [o_progress_bar setIndeterminate:YES];
        [o_progress_bar setHidden:NO];
    } else {
        [o_progress_bar stopAnimation:self];
        [o_progress_bar setHidden:YES];
    }

    [o_stop_btn setEnabled: b_input];
    [o_fwd_btn setEnabled: (b_seekable || b_plmul || b_chapters)];
    [o_bwd_btn setEnabled: (b_seekable || b_plmul || b_chapters)];
    [[VLCMainMenu sharedInstance] setRateControlsEnabled: b_control];

    [o_time_sld setEnabled: b_seekable];
1121
    [self updateTimeSlider];
1122
    [o_fspanel setSeekable: b_seekable];
1123 1124

    PL_LOCK;
1125
    if ([[[VLCMain sharedInstance] playlist] currentPlaylistRoot] != p_playlist->p_local_category || p_playlist->p_local_category->i_children > 0)
1126 1127 1128 1129
        [self hideDropZone];
    else
        [self showDropZone];
    PL_UNLOCK;
1130
    [o_sidebar_view setNeedsDisplay:YES];
1131 1132 1133 1134 1135 1136 1137
}

- (void)setPause
{
    [o_play_btn setImage: o_pause_img];
    [o_play_btn setAlternateImage: o_pause_pressed_img];
    [o_play_btn setToolTip: _NS("Pause")];
1138
    [o_fspanel setPause];
1139 1140 1141 1142 1143 1144 1145
}

- (void)setPlay
{
    [o_play_btn setImage: o_play_img];
    [o_play_btn setAlternateImage: o_play_pressed_img];
    [o_play_btn setToolTip: _NS("Play")];
1146
    [o_fspanel setPlay];
1147 1148
}

1149 1150
- (void)drawFancyGradientEffectForTimeSlider
{
1151 1152 1153
    if (OSX_LEOPARD)
        return;

1154
    NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
1155
    CGFloat f_value = [o_time_sld knobPosition];
1156
    if (f_value > 7.5)
1157
    {
1158 1159
        NSRect oldFrame = [o_time_sld_fancygradient_view frame];
        if (f_value != oldFrame.size.width)
1160 1161
        {
            [o_time_sld_fancygradient_view setHidden: NO];
1162
            [o_time_sld_fancygradient_view setFrame: NSMakeRect( oldFrame.origin.x, oldFrame.origin.y, f_value, oldFrame.size.height )];
1163 1164 1165 1166 1167 1168 1169
            [o_time_sld_fancygradient_view setNeedsDisplay:YES];
        }
    }
    else
    {
        [o_time_sld_fancygradient_view setHidden: YES];
    }
1170
    [o_pool release];
1171 1172
}

1173 1174 1175 1176 1177
#pragma mark -
#pragma mark Video Output handling

- (id)videoView
{
1178 1179 1180 1181 1182 1183
    vout_thread_t *p_vout = getVout();
    if (config_GetInt( VLCIntf, "embedded-video" ))
    {
        if ([o_video_view window] != self)
        {
            [o_video_view removeFromSuperviewWithoutNeedingDisplay];
1184
            [o_video_view setFrame: [o_split_view frame]];
1185
            [[self contentView] addSubview:o_video_view positioned:NSWindowAbove relativeTo:nil];
1186 1187 1188 1189 1190
        }
        b_nonembedded = NO;
    }
    else
    {
1191 1192
        if ([o_video_view superview] != NULL)
            [o_video_view removeFromSuperviewWithoutNeedingDisplay];
1193 1194 1195
        if (o_nonembedded_window)
            [o_nonembedded_window release];

1196
        o_nonembedded_window = [[VLCWindow alloc] initWithContentRect:[o_video_view frame] styleMask: NSTitledWindowMask|NSClosableWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:YES];
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
        [o_nonembedded_window setFrame:[o_video_view frame] display:NO];
        [o_nonembedded_window setBackgroundColor: [NSColor blackColor]];
        [o_nonembedded_window setMovableByWindowBackground: YES];
        [o_nonembedded_window setCanBecomeKeyWindow: YES];
        [o_nonembedded_window setHasShadow:YES];
        [o_nonembedded_window setContentView: o_video_view];
        [o_nonembedded_window setLevel:NSNormalWindowLevel];
        [o_nonembedded_window useOptimizedDrawing: YES];
        [o_nonembedded_window center];
        [o_nonembedded_window makeKeyAndOrderFront:self];
        [o_nonembedded_window orderFront:self animate:YES];
        [o_nonembedded_window setReleasedWhenClosed:NO];
        b_nonembedded = YES;
    }

    if (p_vout)
    {
        if( var_GetBool( p_vout, "video-on-top" ) )
            [[o_video_view window] setLevel: NSStatusWindowLevel];
        else
            [[o_video_view window] setLevel: NSNormalWindowLevel];
        vlc_object_release( p_vout );
    }
1220 1221 1222
    return o_video_view;
}

1223
- (void)setVideoplayEnabled
1224
{
1225 1226
    BOOL b_videoPlayback = [[VLCMain sharedInstance] activeVideoPlayback];

1227 1228
    if (!b_videoPlayback)
        [o_nonembedded_window orderOut: nil];
1229
    if( OSX_LION && b_nativeFullscreenMode )
1230
    {
1231
        if( [NSApp presentationOptions] & NSApplicationPresentationFullScreen )
1232 1233 1234
            [o_bottombar_view setHidden: b_videoPlayback];
        else
            [o_bottombar_view setHidden: NO];
1235 1236
        if (!b_videoPlayback)
            [o_fspanel setNonActive: nil];
1237
    }
1238 1239
    if (b_videoPlayback)
        [self makeFirstResponder: o_video_view];
1240 1241
    else
        [self makeFirstResponder: nil];
1242 1243

    if (!b_videoPlayback && b_fullscreen && !b_nativeFullscreenMode)
1244
        [[VLCCoreInteraction sharedInstance] toggleFullscreen];
1245
}
1246

1247 1248
- (void)resizeWindow
{
1249 1250
    if ( b_fullscreen || (OSX_LION && [NSApp presentationOptions] == NSApplicationPresentationFullScreen && b_nativeFullscreenMode) )
        return;
1251

1252 1253
    NSPoint topleftbase = NSMakePoint(0, [self frame].size.height);
    NSPoint topleftscreen = [self convertBaseToScreen: topleftbase];
1254

1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
    /* Calculate the window's new size */
    float w = [self frame].size.width  - [o_video_view frame].size.width
        + nativeVideoSize.width;
    float h = [self frame].size.height - [o_video_view frame].size.height
        + nativeVideoSize.height;

    if (b_dark_interface)
        h += [o_titlebar_view frame].size.height;

    NSRect new_frame = NSMakeRect(topleftscreen.x, topleftscreen.y - h, w, h);

    [[self animator] setFrame:new_frame display:YES];
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277
}

- (void)setNativeVideoSize:(NSSize)size
{
    if (size.width != nativeVideoSize.width || size.height != nativeVideoSize.height )
    {
        nativeVideoSize = size;
        [self resizeWindow];
    }
}

1278 1279 1280
//  Called automatically if window's acceptsMouseMovedEvents property is true
- (void)mouseMoved:(NSEvent *)theEvent
{
1281
    if (b_fullscreen)
1282
        [self recreateHideMouseTimer];
1283