MainWindow.m 102 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 46
static const float f_min_video_height = 70.0;

47
static VLCMainWindow *_o_sharedInstance = nil;
48

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

#pragma mark -
#pragma mark Initialization

- (id)init
{
59
    if( _o_sharedInstance )
60 61 62 63 64
    {
        [self dealloc];
        return _o_sharedInstance;
    }
    else
65
    {
66
        _o_sharedInstance = [super init];
67
    }
68 69 70 71 72 73 74

    return _o_sharedInstance;
}

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

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

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

    [[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
99
    if (OSX_LION)
100 101 102 103 104
        [self setRestorable:NO];

    return self;
}

105 106 107 108 109 110 111 112 113 114 115
- (BOOL)isEvent:(NSEvent *)o_event forKey:(const char *)keyString
{
    char *key;
    NSString *o_key;

    key = config_GetPsz( VLCIntf, keyString );
    o_key = [NSString stringWithFormat:@"%s", key];
    FREENULL( key );

    unsigned int i_keyModifiers = [[VLCMain sharedInstance] VLCModifiersToCocoa:o_key];

116 117 118 119
    return [[[o_event charactersIgnoringModifiers] lowercaseString] isEqualToString: [[VLCMain sharedInstance] VLCKeyToString: o_key]] &&
            (i_keyModifiers & NSShiftKeyMask)     == ([o_event modifierFlags] & NSShiftKeyMask) &&
            (i_keyModifiers & NSControlKeyMask)   == ([o_event modifierFlags] & NSControlKeyMask) &&
            (i_keyModifiers & NSAlternateKeyMask) == ([o_event modifierFlags] & NSAlternateKeyMask) &&
120 121 122
            (i_keyModifiers & NSCommandKeyMask)   == ([o_event modifierFlags] & NSCommandKeyMask);
}

123 124
- (BOOL)performKeyEquivalent:(NSEvent *)o_event
{
125 126 127 128 129 130 131 132 133 134
    // these are key events which should be handled by vlc core, but are attached to a main menu item
    if( ![self isEvent: o_event forKey: "key-vol-up"] &&
        ![self isEvent: o_event forKey: "key-vol-down"] &&
        ![self isEvent: o_event forKey: "key-vol-mute"] )
    {
        /* We indeed want to prioritize some Cocoa key equivalent against libvlc,
         so we perform the menu equivalent now. */
        if([[NSApp mainMenu] performKeyEquivalent:o_event])
            return TRUE;
    }
135

136 137
    return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event] ||
           [(VLCControls *)[[VLCMain sharedInstance] controls] keyEvent:o_event];
138 139 140 141
}

- (void)dealloc
{
142 143 144
    if (b_dark_interface)
        [o_color_backdrop release];

145
    [[NSNotificationCenter defaultCenter] removeObserver: self];
146
    [o_sidebaritems release];
147 148 149 150 151
    [super dealloc];
}

- (void)awakeFromNib
{
152
    BOOL b_splitviewShouldBeHidden = NO;
153

154
    /* setup the styled interface */
155
    b_video_deco = config_GetInt( VLCIntf, "video-deco" );
156
    b_nativeFullscreenMode = NO;
157
#ifdef MAC_OS_X_VERSION_10_7
158
    if( OSX_LION && b_video_deco )
159
        b_nativeFullscreenMode = config_GetInt( VLCIntf, "macosx-nativefullscreenmode" );
160
#endif
161
    t_hide_mouse_timer = nil;
162
    [o_detached_video_window setDelegate: self];
163
    [self useOptimizedDrawing: YES];
164 165

    [o_play_btn setToolTip: _NS("Play/Pause")];
166
    [o_detached_play_btn setToolTip: [o_play_btn toolTip]];
167
    [o_bwd_btn setToolTip: _NS("Backward")];
168
    [o_detached_bwd_btn setToolTip: [o_bwd_btn toolTip]];
169
    [o_fwd_btn setToolTip: _NS("Forward")];
170
    [o_detached_fwd_btn setToolTip: [o_fwd_btn toolTip]];
171 172 173 174 175 176
    [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")];
177
    [o_detached_fullscreen_btn setToolTip: [o_fullscreen_btn toolTip]];
178 179 180 181 182
    [[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")];
183
    [o_detached_time_sld setToolTip: [o_time_sld toolTip]];
184 185
    [o_dropzone_btn setTitle: _NS("Open media...")];
    [o_dropzone_lbl setStringValue: _NS("Drop media here")];
186

187
    if (!b_dark_interface) {
188
        [o_bottombar_view setImagesLeft: [NSImage imageNamed:@"bottom-background"] middle: [NSImage imageNamed:@"bottom-background"] right: [NSImage imageNamed:@"bottom-background"]];
189
        [o_detached_bottombar_view setImagesLeft: [NSImage imageNamed:@"bottom-background"] middle: [NSImage imageNamed:@"bottom-background"] right: [NSImage imageNamed:@"bottom-background"]];
190 191
        [o_bwd_btn setImage: [NSImage imageNamed:@"back"]];
        [o_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed"]];
192 193
        [o_detached_bwd_btn setImage: [NSImage imageNamed:@"back"]];
        [o_detached_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed"]];
194 195 196 197 198 199
        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"]];
200 201
        [o_detached_fwd_btn setImage: [NSImage imageNamed:@"forward"]];
        [o_detached_fwd_btn setAlternateImage: [NSImage imageNamed:@"forward-pressed"]];
202 203 204 205 206 207 208 209 210 211 212 213 214 215
        [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];
216
        [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"]];
217
        [o_detached_time_sld_background setImagesLeft: [NSImage imageNamed:@"progression-track-wrapper-left"] middle: [NSImage imageNamed:@"progression-track-wrapper-middle"] right: [NSImage imageNamed:@"progression-track-wrapper-right"]];
218
        [o_volume_down_btn setImage: [NSImage imageNamed:@"volume-low"]];
219
        [o_volume_track_view setImage: [NSImage imageNamed:@"volume-slider-track"]];
220
        [o_volume_up_btn setImage: [NSImage imageNamed:@"volume-high"]];
221
        if (b_nativeFullscreenMode)
222 223 224 225 226 227 228 229 230
        {
            [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"]];
        }
231 232
        [o_fullscreen_btn setImage: [NSImage imageNamed:@"fullscreen-double-buttons"]];
        [o_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"fullscreen-double-buttons-pressed"]];
233 234
        [o_detached_fullscreen_btn setImage: [NSImage imageNamed:@"fullscreen-one-button"]];
        [o_detached_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"fullscreen-one-button-pressed"]];
235
        [o_time_sld_fancygradient_view setImagesLeft:[NSImage imageNamed:@"progression-fill-left"] middle:[NSImage imageNamed:@"progression-fill-middle"] right:[NSImage imageNamed:@"progression-fill-right"]];
236
        [o_detached_time_sld_fancygradient_view setImagesLeft:[NSImage imageNamed:@"progression-fill-left"] middle:[NSImage imageNamed:@"progression-fill-middle"] right:[NSImage imageNamed:@"progression-fill-right"]];
237 238 239
    }
    else
    {
240
        [o_bottombar_view setImagesLeft: [NSImage imageNamed:@"bottomdark-left"] middle: [NSImage imageNamed:@"bottom-background_dark"] right: [NSImage imageNamed:@"bottomdark-right"]];
241
        [o_detached_bottombar_view setImagesLeft: [NSImage imageNamed:@"bottomdark-left"] middle: [NSImage imageNamed:@"bottom-background_dark"] right: [NSImage imageNamed:@"bottomdark-right"]];
242 243
        [o_bwd_btn setImage: [NSImage imageNamed:@"back_dark"]];
        [o_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed_dark"]];
244 245
        [o_detached_bwd_btn setImage: [NSImage imageNamed:@"back_dark"]];
        [o_detached_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed_dark"]];
246 247 248 249 250 251
        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"]];
252 253
        [o_detached_fwd_btn setImage: [NSImage imageNamed:@"forward_dark"]];
        [o_detached_fwd_btn setAlternateImage: [NSImage imageNamed:@"forward-pressed_dark"]];
254 255 256 257 258 259 260 261 262 263 264 265 266 267
        [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];
268
        [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"]];
269
        [o_detached_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"]];
270 271 272
        [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"]];
273
        if (b_nativeFullscreenMode)
274 275 276 277 278 279 280
        {
            [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"]];
281
            [o_effects_btn setAlternateImage: [NSImage imageNamed:@"effects-double-buttons-pressed_dark"]];
282
        }
283
        [o_fullscreen_btn setImage: [NSImage imageNamed:@"fullscreen-double-buttons_dark"]];
284
        [o_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"fullscreen-double-buttons-pressed_dark"]];
285 286
        [o_detached_fullscreen_btn setImage: [NSImage imageNamed:@"fullscreen-one-button_dark"]];
        [o_detached_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"fullscreen-one-button-pressed_dark"]];
287
        [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"]];
288
        [o_detached_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"]];
289 290 291 292 293 294 295
    }
    [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];
296 297
    [o_detached_play_btn setImage: o_play_img];
    [o_detached_play_btn setAlternateImage: o_play_pressed_img];
298 299 300
    BOOL b_mute = ![[VLCCoreInteraction sharedInstance] isMuted];
    [o_volume_sld setEnabled: b_mute];
    [o_volume_up_btn setEnabled: b_mute];
301

302 303 304 305
    b_show_jump_buttons = config_GetInt( VLCIntf, "macosx-show-playback-buttons" );
    if (b_show_jump_buttons)
        [self addJumpButtons];

306
    /* interface builder action */
307 308 309 310
    float f_threshold_height = f_min_video_height + [o_bottombar_view frame].size.height;
    if( b_dark_interface )
        f_threshold_height += [o_titlebar_view frame].size.height;
    if( [[self contentView] frame].size.height < f_threshold_height )
311
        b_splitviewShouldBeHidden = YES;
312

313 314
    [self setDelegate: self];
    [self setExcludedFromWindowsMenu: YES];
315
    [self setAcceptsMouseMovedEvents: YES];
316
    // Set that here as IB seems to be buggy
317
    if (b_dark_interface && b_video_deco)
318 319 320 321
    {
        [self setContentMinSize:NSMakeSize(604., 288. + [o_titlebar_view frame].size.height)];
        [o_detached_video_window setContentMinSize: NSMakeSize( 363., f_min_video_height + [o_detached_bottombar_view frame].size.height + [o_detached_titlebar_view frame].size.height )];
    }
322
    else if( b_video_deco )
323
    {
324
        [self setContentMinSize:NSMakeSize(604., 288.)];
325 326
        [o_detached_video_window setContentMinSize: NSMakeSize( 363., f_min_video_height + [o_detached_bottombar_view frame].size.height )];
    }
327
    else
328
    {   // !b_video_deco:
329 330 331 332 333 334
        if (b_dark_interface)
            [self setContentMinSize:NSMakeSize(604., 288. + [o_titlebar_view frame].size.height)];
        else
            [self setContentMinSize:NSMakeSize(604., 288.)];

        [o_detached_bottombar_view setHidden:YES];
335
        [o_detached_video_window setContentMinSize: NSMakeSize( f_min_video_height, f_min_video_height )];
336
    }
337

338
    [self setTitle: _NS("VLC media player")];
339 340
    [o_time_fld setAlignment: NSCenterTextAlignment];
    [o_time_fld setNeedsDisplay:YES];
341
    b_dropzone_active = YES;
342 343
    o_temp_view = [[NSView alloc] init];
    [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
344
    [o_dropzone_view setFrame: [o_playlist_table frame]];
345
    [o_left_split_view setFrame: [o_sidebar_view frame]];
346
    if (b_nativeFullscreenMode)
347 348
    {
        NSRect frame;
349
        [self setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
        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 );
372
        enlargeItem( o_time_sld_background );
373 374 375 376 377
        enlargeItem( o_time_sld_fancygradient_view );
        #undef enlargeItem

        [o_fullscreen_btn removeFromSuperviewWithoutNeedingDisplay];
    }
378
    else
379
    {
380
        [o_titlebar_view setFullscreenButtonHidden: YES];
381 382
        if (b_video_deco)
            [o_detached_titlebar_view setFullscreenButtonHidden: YES];
383
    }
384

385 386 387 388 389 390 391 392 393
    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];
    }
394

395 396 397 398
    /* create the sidebar */
    o_sidebaritems = [[NSMutableArray alloc] init];
    SideBarItem *libraryItem = [SideBarItem itemWithTitle:_NS("LIBRARY") identifier:@"library"];
    SideBarItem *playlistItem = [SideBarItem itemWithTitle:_NS("Playlist") identifier:@"playlist"];
399
    [playlistItem setIcon: [NSImage imageNamed:@"sidebar-playlist"]];
400 401
    SideBarItem *medialibraryItem = [SideBarItem itemWithTitle:_NS("Media Library") identifier:@"medialibrary"];
    [medialibraryItem setIcon: [NSImage imageNamed:@"sidebar-playlist"]];
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
    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];
419
    NSString *o_identifier;
420 421
    for (; *ppsz_name; ppsz_name++, ppsz_longname++, p_category++)
    {
422
        o_identifier = [NSString stringWithCString: *ppsz_name encoding: NSUTF8StringEncoding];
423 424
        switch (*p_category) {
            case SD_CAT_INTERNET:
425
                {
426
                    [internetItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
427
                    if (!strncmp( *ppsz_name, "podcast", 7 ))
428 429
                        [internetItems removeLastObject]; // we don't support podcasts at this point (see #6017)
//                        [[internetItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-podcast"]];
430 431
                    else
                        [[internetItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
432
                    [[internetItems lastObject] setSdtype: SD_CAT_INTERNET];
433
                    [[internetItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
434
                }
435 436
                break;
            case SD_CAT_DEVICES:
437
                {
438
                    [devicesItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
439
                    [[devicesItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
440
                    [[devicesItems lastObject] setSdtype: SD_CAT_DEVICES];
441
                    [[devicesItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
442
                }
443 444
                break;
            case SD_CAT_LAN:
445
                {
446
                    [lanItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
447
                    [[lanItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-local"]];
448
                    [[lanItems lastObject] setSdtype: SD_CAT_LAN];
449
                    [[lanItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
450
                }
451 452
                break;
            case SD_CAT_MYCOMPUTER:
453
                {
454
                    [mycompItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
455
                    if (!strncmp( *ppsz_name, "video_dir", 9 ))
456
                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-movie"]];
457
                    else if (!strncmp( *ppsz_name, "audio_dir", 9 ))
458
                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-music"]];
459
                    else if (!strncmp( *ppsz_name, "picture_dir", 11 ))
460
                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-pictures"]];
461 462
                    else
                        [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
463
                    [[mycompItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
464
                    [[mycompItems lastObject] setSdtype: SD_CAT_MYCOMPUTER];
465
                }
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
                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 );

487
    [libraryItem setChildren: [NSArray arrayWithObjects: playlistItem, medialibraryItem, nil]];
488 489 490 491 492 493 494 495 496 497 498
    [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];
499
    [o_sidebar_view selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
500 501
    [o_sidebar_view setDropItem:playlistItem dropChildIndex:NSOutlineViewDropOnItemIndex];
    [o_sidebar_view registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, @"VLCPlaylistItemPboardType", nil]];
502

503 504 505 506 507
    [o_sidebar_view setAutosaveName:@"mainwindow-sidebar"];
    [(PXSourceList *)o_sidebar_view setDataSource:self];
    [o_sidebar_view setDelegate:self];
    [o_sidebar_view setAutosaveExpandedItems:YES];

508 509 510 511 512 513 514 515 516 517 518 519 520
    [o_sidebar_view expandItem: libraryItem expandChildren: YES];

    /* make sure we display the desired default appearance when VLC launches for the first time */
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if (![defaults objectForKey:@"VLCFirstRun"])
    {
        [defaults setObject:[NSDate date] forKey:@"VLCFirstRun"];

        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];
    }

521 522
    if( b_dark_interface )
    {
523 524 525
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowResizedOrMoved:) name: NSWindowDidResizeNotification object: nil];
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowResizedOrMoved:) name: NSWindowDidMoveNotification object: nil];

526 527
        [self setBackgroundColor: [NSColor clearColor]];
        [self setOpaque: NO];
528 529
        [self display];
        [self setHasShadow:NO];
530
        [self setHasShadow:YES];
531

532
        NSRect winrect = [self frame];
533 534 535 536
        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 )];
537 538 539 540 541 542 543
        [[self contentView] addSubview: o_titlebar_view positioned: NSWindowAbove relativeTo: o_split_view];

        if (winrect.size.height > 100)
        {
            [self setFrame: winrect display:YES animate:YES];
            previousSavedFrame = winrect;
        }
544 545 546 547 548

        winrect = [o_split_view frame];
        winrect.size.height = winrect.size.height - f_titleBarHeight;
        [o_split_view setFrame: winrect];
        [o_video_view setFrame: winrect];
549

550 551
        /* detached video window */
        winrect = [o_detached_video_window frame];
552 553 554 555 556
        if (b_video_deco)
        {
            [o_detached_titlebar_view setFrame: NSMakeRect( 0, winrect.size.height - f_titleBarHeight, winrect.size.width, f_titleBarHeight )];
            [[o_detached_video_window contentView] addSubview: o_detached_titlebar_view positioned: NSWindowAbove relativeTo: nil];
        }
557

558 559 560
        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];
561 562
    }
    else
563
    {
564 565 566 567 568 569
        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];

570 571 572 573 574
        frame = [o_detached_time_sld_fancygradient_view frame];
        frame.size.height = frame.size.height - 1;
        frame.origin.y = frame.origin.y + 1;
        [o_detached_time_sld_fancygradient_view setFrame: frame];

575
        [o_video_view setFrame: [o_split_view frame]];
576 577 578
        [o_playlist_table setBorderType: NSNoBorder];
        [o_sidebar_scrollview setBorderType: NSNoBorder];
    }
579

580 581 582 583 584
    NSRect frame;
    frame = [o_time_sld_fancygradient_view frame];
    frame.size.width = 0;
    [o_time_sld_fancygradient_view setFrame: frame];

585 586 587 588
    frame = [o_detached_time_sld_fancygradient_view frame];
    frame.size.width = 0;
    [o_detached_time_sld_fancygradient_view setFrame: frame];

589
    if (OSX_LION)
590
    {
591
        [o_resize_view setImage: NULL];
592 593
        [o_detached_resize_view setImage: NULL];
    }
594 595

    if ([self styleMask] & NSResizableWindowMask)
596
    {
597
        [o_resize_view removeFromSuperviewWithoutNeedingDisplay];
598 599
        [o_detached_resize_view removeFromSuperviewWithoutNeedingDisplay];
    }
600

601
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(someWindowWillClose:) name: NSWindowWillCloseNotification object: nil];
602
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(someWindowWillMiniaturize:) name: NSWindowWillMiniaturizeNotification object:nil];
603
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(applicationWillTerminate:) name: NSApplicationWillTerminateNotification object: nil];
604
    [[VLCMain sharedInstance] playbackModeUpdated];
605

606
    [o_split_view setAutosaveName:@"10thanniversary-splitview"];
607 608 609
    if (b_splitviewShouldBeHidden)
    {
        [self hideSplitView];
610
        i_lastSplitViewHeight = 300;
611
    }
612 613
}

614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
#pragma mark -
#pragma mark interface customization
- (void)toggleJumpButtons
{
    b_show_jump_buttons = config_GetInt( VLCIntf, "macosx-show-playback-buttons" );

    if (b_show_jump_buttons)
        [self addJumpButtons];
    else
        [self removeJumpButtons];
}

- (void)addJumpButtons
{
    NSRect preliminaryFrame = [o_bwd_btn frame];
    BOOL b_enabled = [o_bwd_btn isEnabled];
    preliminaryFrame.size.width = 26.;
    o_prev_btn = [[NSButton alloc] initWithFrame:preliminaryFrame];
    [o_prev_btn setButtonType: NSMomentaryChangeButton];
    [o_prev_btn setImage: [NSImage imageNamed:@"back-single"]];
    [o_prev_btn setAlternateImage: [NSImage imageNamed:@"back-pressed-single"]];
    [o_prev_btn setBezelStyle:NSRegularSquareBezelStyle];
    [o_prev_btn setBordered:NO];
    [o_prev_btn setTarget:self];
    [o_prev_btn setAction:@selector(prev:)];
    [o_prev_btn setToolTip: _NS("Previous")];
    [o_prev_btn setEnabled: b_enabled];

    o_next_btn = [[NSButton alloc] initWithFrame:preliminaryFrame];
    [o_next_btn setButtonType: NSMomentaryChangeButton];
    [o_next_btn setImage: [NSImage imageNamed:@"forward-single"]];
    [o_next_btn setAlternateImage: [NSImage imageNamed:@"forward-pressed-single"]];
    [o_next_btn setBezelStyle:NSRegularSquareBezelStyle];
    [o_next_btn setBordered:NO];
    [o_next_btn setTarget:self];
    [o_next_btn setAction:@selector(next:)];
    [o_next_btn setToolTip: _NS("Next")];
    [o_next_btn setEnabled: b_enabled];

    NSRect frame;
    float f_space = 32.;
    #define moveItem( item ) \
    frame = [item frame]; \
    frame.origin.x = frame.origin.x + f_space; \
658
    [[item animator] setFrame: frame]
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673

    moveItem( o_bwd_btn );
    moveItem( o_play_btn );
    moveItem( o_fwd_btn );
    f_space = 62.;
    moveItem( o_stop_btn );
    moveItem( o_playlist_btn );
    moveItem( o_repeat_btn );
    moveItem( o_shuffle_btn );
    #undef moveItem

    #define resizeItem( item ) \
    frame = [item frame]; \
    frame.size.width = frame.size.width - f_space; \
    frame.origin.x = frame.origin.x + f_space; \
674
    [[item animator] setFrame: frame]
675 676 677 678 679 680 681

    resizeItem( o_time_sld );
    resizeItem( o_progress_bar );
    resizeItem( o_time_sld_background );
    resizeItem( o_time_sld_fancygradient_view );
    #undef resizeItem

682
    preliminaryFrame.origin.x = [o_next_btn frame].origin.x + 80. + [o_fwd_btn frame].size.width;
683
    [o_next_btn setFrame: preliminaryFrame];
684 685 686 687

    // wait until the animation is done
    [[self contentView] performSelector:@selector(addSubview:) withObject:o_prev_btn afterDelay:.2];
    [[self contentView] performSelector:@selector(addSubview:) withObject:o_next_btn afterDelay:.2];
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709

    [o_fwd_btn setAction:@selector(forward:)];
    [o_bwd_btn setAction:@selector(backward:)];
}

- (void)removeJumpButtons
{
    if (!o_prev_btn || !o_next_btn )
        return;

    [[o_prev_btn animator] setHidden: YES];
    [[o_next_btn animator] setHidden: YES];
    [o_prev_btn removeFromSuperviewWithoutNeedingDisplay];
    [o_next_btn removeFromSuperviewWithoutNeedingDisplay];
    [o_prev_btn release];
    [o_next_btn release];

    NSRect frame;
    float f_space = 32.;
    #define moveItem( item ) \
    frame = [item frame]; \
    frame.origin.x = frame.origin.x - f_space; \
710
    [[item animator] setFrame: frame]
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725

    moveItem( o_bwd_btn );
    moveItem( o_play_btn );
    moveItem( o_fwd_btn );
    f_space = 62.;
    moveItem( o_stop_btn );
    moveItem( o_playlist_btn );
    moveItem( o_repeat_btn );
    moveItem( o_shuffle_btn );
    #undef moveItem

    #define resizeItem( item ) \
    frame = [item frame]; \
    frame.size.width = frame.size.width + f_space; \
    frame.origin.x = frame.origin.x - f_space; \
726
    [[item animator] setFrame: frame]
727 728 729 730 731 732 733 734 735 736 737 738 739

    resizeItem( o_time_sld );
    resizeItem( o_progress_bar );
    resizeItem( o_time_sld_background );
    resizeItem( o_time_sld_fancygradient_view );
    #undef resizeItem

    [o_bottombar_view setNeedsDisplay:YES];

    [o_fwd_btn setAction:@selector(fwd:)];
    [o_bwd_btn setAction:@selector(bwd:)];
}

740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
- (void)togglePlaymodeButtons
{
    b_show_playmode_buttons = config_GetInt( VLCIntf, "macosx-show-playmode-buttons" );

    if (b_show_playmode_buttons)
        [self addPlaymodeButtons];
    else
        [self removePlaymodeButtons];
}

- (void)addPlaymodeButtons
{
    NSRect frame;
    float f_space = [o_repeat_btn frame].size.width + [o_shuffle_btn frame].size.width - 6.;

    // FIXME: switch o_playlist_btn artwork

    #define resizeItem( item ) \
    frame = [item frame]; \
    frame.size.width = frame.size.width - f_space; \
    frame.origin.x = frame.origin.x + f_space; \
    [[item animator] setFrame: frame]

    resizeItem( o_time_sld );
    resizeItem( o_progress_bar );
    resizeItem( o_time_sld_background );
    resizeItem( o_time_sld_fancygradient_view );
    #undef resizeItem

    [[o_repeat_btn animator] setHidden: NO];
    [[o_shuffle_btn animator] setHidden: NO];
}

- (void)removePlaymodeButtons
{
    NSRect frame;
    float f_space = [o_repeat_btn frame].size.width + [o_shuffle_btn frame].size.width - 6.;
    [o_repeat_btn setHidden: YES];
    [o_shuffle_btn setHidden: YES];

    // FIXME: switch o_playlist_btn artwork

    #define resizeItem( item ) \
    frame = [item frame]; \
    frame.size.width = frame.size.width + f_space; \
    frame.origin.x = frame.origin.x - f_space; \
    [[item animator] setFrame: frame]

    resizeItem( o_time_sld );
    resizeItem( o_progress_bar );
    resizeItem( o_time_sld_background );
    resizeItem( o_time_sld_fancygradient_view );
    #undef resizeItem
}

795 796 797 798 799 800 801 802
#pragma mark -
#pragma mark Button Actions

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

803 804 805
- (void)resetPreviousButton
{
    if (([NSDate timeIntervalSinceReferenceDate] - last_bwd_event) >= 0.35) {
Konstantin Pavlov's avatar
Konstantin Pavlov committed
806
        // seems like no further event occurred, so let's switch the playback item
807 808 809 810 811 812 813 814 815 816 817 818
        [[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;
}

819 820 821 822 823
- (IBAction)prev:(id)sender
{
    [[VLCCoreInteraction sharedInstance] previous];
}

824 825
- (IBAction)bwd:(id)sender
{
826 827 828 829 830 831 832 833 834
    if(!just_triggered_previous)
    {
        just_triggered_previous = YES;
        [self performSelector:@selector(resetPreviousButton)
                   withObject: NULL
                   afterDelay:0.40];
    }
    else
    {
835
        if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) > 0.16 )
836
        {
837 838
            // we just skipped 4 "continous" events, otherwise we are too fast
            [[VLCCoreInteraction sharedInstance] backwardExtraShort];
839 840 841 842 843 844 845 846
            last_bwd_event = [NSDate timeIntervalSinceReferenceDate];
            [self performSelector:@selector(resetBackwardSkip)
                       withObject: NULL
                       afterDelay:0.40];
        }
    }
}

847 848 849 850 851
- (IBAction)backward:(id)sender
{
    [[VLCCoreInteraction sharedInstance] backwardShort];
}

852 853 854
- (void)resetNextButton
{
    if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) >= 0.35) {
Konstantin Pavlov's avatar
Konstantin Pavlov committed
855
        // seems like no further event occurred, so let's switch the playback item
856 857 858 859 860 861 862 863 864 865
        [[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;
866 867
}

868 869 870 871 872 873 874 875 876 877
- (IBAction)next:(id)sender
{
    [[VLCCoreInteraction sharedInstance] next];
}

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

878 879
- (IBAction)fwd:(id)sender
{
880 881 882 883 884 885 886 887 888
   if(!just_triggered_next)
    {
        just_triggered_next = YES;
        [self performSelector:@selector(resetNextButton)
                   withObject: NULL
                   afterDelay:0.40];
    }
    else
    {
889
        if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) > 0.16 )
890
        {
891 892
            // we just skipped 4 "continous" events, otherwise we are too fast
            [[VLCCoreInteraction sharedInstance] forwardExtraShort];
893 894 895 896 897 898
            last_fwd_event = [NSDate timeIntervalSinceReferenceDate];
            [self performSelector:@selector(resetForwardSkip)
                       withObject: NULL
                       afterDelay:0.40];
        }
    }
899 900 901 902 903 904 905
}

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

906 907 908 909
- (void)resizePlaylistAfterCollapse
{
    NSRect plrect;
    plrect = [[o_playlist_table animator] frame];
910
    plrect.size.height = i_lastSplitViewHeight - 19.0; // actual pl top bar height, which differs from its frame
911
    [[o_playlist_table animator] setFrame: plrect];
912 913 914 915 916 917 918

    NSRect rightSplitRect;
    rightSplitRect = [o_right_split_view frame];
    plrect = [[o_dropzone_box animator] frame];
    plrect.origin.x = (rightSplitRect.size.width - plrect.size.width) / 2;
    plrect.origin.y = (rightSplitRect.size.height - plrect.size.height) / 2;
    [[o_dropzone_box animator] setFrame: plrect];
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 945 946 947 948 949 950 951 952 953
- (void)makeSplitViewVisible
{
    if( b_dark_interface )
        [self setContentMinSize: NSMakeSize( 604., 288. + [o_titlebar_view frame].size.height )];
    else
        [self setContentMinSize: NSMakeSize( 604., 288. )];

    NSRect old_frame = [self frame];
    float newHeight = [self minSize].height;
    if( old_frame.size.height < newHeight )
    {
        NSRect new_frame = old_frame;
        new_frame.origin.y = old_frame.origin.y + old_frame.size.height - newHeight;
        new_frame.size.height = newHeight;

        [[self animator] setFrame: new_frame display: YES animate: YES];
    }

    [o_video_view setHidden: YES];
    [o_split_view setHidden: NO];
    [self makeFirstResponder: nil];

}

- (void)makeSplitViewHidden
{
    if( b_dark_interface )
        [self setContentMinSize: NSMakeSize( 604., f_min_video_height + [o_titlebar_view frame].size.height )];
    else
        [self setContentMinSize: NSMakeSize( 604., f_min_video_height )];

    [o_split_view setHidden: YES];
    [o_video_view setHidden: NO];
954

955 956
    if( [[o_video_view subviews] count] > 0 )
        [self makeFirstResponder: [[o_video_view subviews] objectAtIndex:0]];
957 958
}

959 960
- (IBAction)togglePlaylist:(id)sender
{
961
    if (![self isVisible] && sender != nil)
962 963
    {
        [self makeKeyAndOrderFront: sender];
964
        return;
965 966
    }

967
    BOOL b_activeVideo = [[VLCMain sharedInstance] activeVideoPlayback];
968
    BOOL b_restored = NO;
969

970 971 972 973 974
    // TODO: implement toggle playlist in this situation (triggerd via menu item).
    // but for now we block this case, to avoid displaying only the half
    if( b_nativeFullscreenMode && b_fullscreen && b_activeVideo && sender != nil )
        return;

975
    if (b_dropzone_active && ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) != 0)
976 977 978 979 980
    {
        [self hideDropZone];
        return;
    }

981
    if ( !(b_nativeFullscreenMode && b_fullscreen) && !b_splitview_removed && ( (([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) != 0 && b_activeVideo)
982 983 984
                                  || (b_nonembedded && sender != nil)
                                  || (!b_activeVideo && sender != nil)
                                  || b_minimized_view ) )
985
    {
986
        [self hideSplitView];
987
    }
988
    else
989
    {
990 991
        if (b_splitview_removed)
        {
992
            if( !b_nonembedded || ( sender != nil && b_nonembedded))
993
                [self showSplitView];
994 995 996 997 998 999 1000 1001

            if (sender == nil)
                b_minimized_view = YES;
            else
                b_minimized_view = NO;

            if (b_activeVideo)
                b_restored = YES;
1002 1003 1004 1005
        }

        if (!b_nonembedded)
        {
1006
            if (([o_video_view isHidden] && b_activeVideo) || b_restored || (b_activeVideo && sender == nil) )
1007
                [self makeSplitViewHidden];
1008
            else
1009
                [self makeSplitViewVisible];
1010 1011 1012
        }
        else
        {
1013
            [o_split_view setHidden: NO];
1014
            [o_playlist_table setHidden: NO];
1015
            [o_video_view setHidden: !b_activeVideo];
1016 1017
            if( b_activeVideo && [[o_video_view subviews] count] > 0 )
                [o_detached_video_window makeFirstResponder: [[o_video_view subviews] objectAtIndex:0]];
1018
        }
1019 1020 1021
    }
}

1022 1023 1024
- (void)setRepeatOne
{
    [o_repeat_btn setImage: o_repeat_one_img];
1025
    [o_repeat_btn setAlternateImage: o_repeat_one_pressed_img];
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
}

- (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];
}

1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
- (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];
1053
        [self setRepeatOne];
1054 1055 1056 1057 1058
    }
    else if( repeating.b_bool && !looping.b_bool )
    {
        /* was: Repeat One, switching to Repeat All */
        [[VLCCoreInteraction sharedInstance] repeatAll];
1059
        [self setRepeatAll];
1060 1061 1062 1063 1064
    }
    else
    {
        /* was: Repeat All or bug in VLC, switching to Repeat Off */
        [[VLCCoreInteraction sharedInstance] repeatOff];
1065
        [self setRepeatOff];
1066 1067 1068
    }
}

1069
- (void)setShuffle
1070
{
1071
    bool b_value;
1072
    playlist_t *p_playlist = pl_Get( VLCIntf );
1073
    b_value = var_GetBool( p_playlist, "random" );
1074 1075

    if(b_value) {
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
        [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];
    }
}

1086 1087 1088 1089 1090 1091
- (IBAction)shuffle:(id)sender
{
    [[VLCCoreInteraction sharedInstance] shuffle];
    [self setShuffle];
}

1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
- (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 pos;
        NSString * o_time;

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

1118
        o_time = [self getCurrentTimeAsString: p_input];
1119
        [o_time_fld setStringValue: o_time];
1120
        [o_fspanel setStreamPos: f_updated andTime: o_time];
1121 1122 1123 1124 1125 1126 1127 1128 1129
        vlc_object_release( p_input );
    }
}

- (IBAction)volumeAction:(id)sender
{
    if (sender == o_volume_sld)
        [[VLCCoreInteraction sharedInstance] setVolume: [sender intValue]];
    else if (sender == o_volume_down_btn)
1130
    {
1131
        [[VLCCoreInteraction sharedInstance] mute];
1132
    }
1133
    else
1134
        [[VLCCoreInteraction sharedInstance] setVolume: AOUT_VOLUME_MAX];
1135 1136 1137 1138 1139 1140 1141 1142 1143
}

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

- (IBAction)fullscreen:(id)sender
{
1144
    [[VLCCoreInteraction sharedInstance] toggleFullscreen];
1145 1146
}

1147 1148 1149 1150 1151
- (IBAction)dropzoneButtonAction:(id)sender
{
    [[[VLCMain sharedInstance] open] openFileGeneric];
}

1152 1153 1154 1155 1156 1157 1158
#pragma mark -
#pragma mark overwritten default functionality
- (BOOL)canBecomeKeyWindow
{
    return YES;
}

1159 1160
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
1161
    SEL s_menuAction = [menuItem action];
1162

1163 1164 1165 1166
    if ((s_menuAction == @selector(performClose:)) || (s_menuAction == @selector(performMiniaturize:)) || (s_menuAction == @selector(performZoom:)))
            return YES;

    return [super validateMenuItem:menuItem];
1167 1168
}

1169 1170
- (void)setTitle:(NSString *)title
{
1171
    if (b_dark_interface)
1172
    {
1173
        [o_titlebar_view setWindowTitle: title];
1174 1175
        if (b_video_deco)
            [o_detached_titlebar_view setWindowTitle: title];
1176
    }
1177
    if (b_nonembedded && [[VLCMain sharedInstance] activeVideoPlayback])
1178
        [o_detached_video_window setTitle: title];
1179 1180 1181
    [super setTitle: title];
}

1182 1183
- (void)performClose:(id)sender
{
1184 1185
    NSWindow *o_key_window = [NSApp keyWindow];

1186
    if (b_dark_interface || !b_video_deco)
1187
    {
1188 1189
        [o_key_window orderOut: sender];
        if ( [[VLCMain sharedInstance] activeVideoPlayback] && ( !b_nonembedded || o_key_window != self ))
1190
            [[VLCCoreInteraction sharedInstance] stop];
1191
    }
1192
    else
1193 1194
    {
        if( b_nonembedded && o_key_window != self )
1195
            [o_detached_video_window performClose: sender];
1196