/*****************************************************************************
* MainWindow.m: MacOS X interface module
*****************************************************************************
- * Copyright (C) 2002-2012 VLC authors and VideoLAN
+ * Copyright (C) 2002-2013 VLC authors and VideoLAN
* $Id$
*
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
* Jon Lech Johansen <jon-vl@nanocrew.net>
* Christophe Massiot <massiot@via.ecp.fr>
* Derk-Jan Hartman <hartman at videolan.org>
+ * David Fuhrmann <david dot fuhrmann at googlemail dot com>
*
* 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
#import "SideBarItem.h"
#import <math.h>
#import <vlc_playlist.h>
-#import <vlc_aout_intf.h>
#import <vlc_url.h>
#import <vlc_strings.h>
#import <vlc_services_discovery.h>
-#import <vlc_aout_intf.h>
#import "ControlsBar.h"
#import "VideoView.h"
#import "VLCVoutWindowController.h"
-@interface VLCMainWindow ()
+@interface VLCMainWindow (Internal)
- (void)resizePlaylistAfterCollapse;
- (void)makeSplitViewVisible;
- (void)makeSplitViewHidden;
-
+- (void)showPodcastControls;
+- (void)hidePodcastControls;
@end
@implementation VLCMainWindow
-@synthesize fullscreen=b_fullscreen;
@synthesize nativeFullscreenMode=b_nativeFullscreenMode;
+@synthesize nonembedded=b_nonembedded;
@synthesize fsPanel=o_fspanel;
static VLCMainWindow *_o_sharedInstance = nil;
// 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"]) {
+ ![self isEvent: o_event forKey: "key-vol-mute"] &&
+ ![self isEvent: o_event forKey: "key-prev"] &&
+ ![self isEvent: o_event forKey: "key-next"] &&
+ ![self isEvent: o_event forKey: "key-jump+short"] &&
+ ![self isEvent: o_event forKey: "key-jump-short"]) {
/* We indeed want to prioritize some Cocoa key equivalent against libvlc,
so we perform the menu equivalent now. */
if ([[NSApp mainMenu] performKeyEquivalent:o_event])
[[NSNotificationCenter defaultCenter] removeObserver: self];
[o_sidebaritems release];
+ [o_fspanel release];
[super dealloc];
}
- (void)awakeFromNib
{
+ // sets lion fullscreen behaviour
+ [super awakeFromNib];
+
BOOL b_splitviewShouldBeHidden = NO;
/* setup the styled interface */
if (!OSX_SNOW_LEOPARD)
b_nativeFullscreenMode = var_InheritBool(VLCIntf, "macosx-nativefullscreenmode");
#endif
- t_hide_mouse_timer = nil;
[self useOptimizedDrawing: YES];
-
+
[[o_search_fld cell] setPlaceholderString: _NS("Search")];
[[o_search_fld cell] accessibilitySetOverrideValue:_NS("Enter a term to search the playlist. Results will be selected in the table.") forAttribute:NSAccessibilityDescriptionAttribute];
[o_podcast_unsubscribe_cancel_btn setTitle: _NS("Cancel")];
/* interface builder action */
- float f_threshold_height = f_min_video_height + [[o_controls_bar bottomBarView] frame].size.height;
+ float f_threshold_height = f_min_video_height + [o_controls_bar height];
if (b_dark_interface)
f_threshold_height += [o_titlebar_view frame].size.height;
if ([[self contentView] frame].size.height < f_threshold_height)
[self setExcludedFromWindowsMenu: YES];
[self setAcceptsMouseMovedEvents: YES];
// Set that here as IB seems to be buggy
- if (b_dark_interface) {
+ if (b_dark_interface)
[self setContentMinSize:NSMakeSize(604., 288. + [o_titlebar_view frame].size.height)];
- } else {
+ else
[self setContentMinSize:NSMakeSize(604., 288.)];
- }
[self setTitle: _NS("VLC media player")];
b_dropzone_active = YES;
[o_dropzone_view setFrame: [o_playlist_table frame]];
[o_left_split_view setFrame: [o_sidebar_view frame]];
-
- if (b_nativeFullscreenMode) {
- [self setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
- } else {
- [o_titlebar_view setFullscreenButtonHidden: YES];
- }
if (!OSX_SNOW_LEOPARD) {
/* the default small size of the search field is slightly different on Lion, let's work-around that */
SideBarItem *internetItem = [SideBarItem itemWithTitle:_NS("INTERNET") identifier:@"internet"];
/* SD subnodes, inspired by the Qt4 intf */
- char **ppsz_longnames;
- int *p_categories;
+ char **ppsz_longnames = NULL;
+ int *p_categories = NULL;
char **ppsz_names = vlc_sd_GetNames(pl_Get(VLCIntf), &ppsz_longnames, &p_categories);
if (!ppsz_names)
msg_Err(VLCIntf, "no sd item found"); //TODO
NSMutableArray *lanItems = [[NSMutableArray alloc] init];
NSMutableArray *mycompItems = [[NSMutableArray alloc] init];
NSString *o_identifier;
- for (; *ppsz_name; ppsz_name++, ppsz_longname++, p_category++) {
+ for (; ppsz_name && *ppsz_name; ppsz_name++, ppsz_longname++, p_category++) {
o_identifier = [NSString stringWithCString: *ppsz_name encoding: NSUTF8StringEncoding];
switch (*p_category) {
case SD_CAT_INTERNET:
else
[[internetItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
[[internetItems lastObject] setSdtype: SD_CAT_INTERNET];
- [[internetItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
+ [[internetItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String:*ppsz_longname]];
break;
case SD_CAT_DEVICES:
[devicesItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
[[devicesItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
[[devicesItems lastObject] setSdtype: SD_CAT_DEVICES];
- [[devicesItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
+ [[devicesItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String:*ppsz_longname]];
break;
case SD_CAT_LAN:
[lanItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
[[lanItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-local"]];
[[lanItems lastObject] setSdtype: SD_CAT_LAN];
- [[lanItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
+ [[lanItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String:*ppsz_longname]];
break;
case SD_CAT_MYCOMPUTER:
[mycompItems addObject: [SideBarItem itemWithTitle: _NS(*ppsz_longname) identifier: o_identifier]];
[[mycompItems lastObject] setIcon: [NSImage imageNamed:@"sidebar-pictures"]];
else
[[mycompItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
- [[mycompItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String: *ppsz_longname]];
+ [[mycompItems lastObject] setUntranslatedTitle: [NSString stringWithUTF8String:*ppsz_longname]];
[[mycompItems lastObject] setSdtype: SD_CAT_MYCOMPUTER];
break;
default:
free(ppsz_longnames);
free(p_categories);
- [libraryItem setChildren: [NSArray arrayWithObjects: playlistItem, medialibraryItem, nil]];
+ [libraryItem setChildren: [NSArray arrayWithObjects:playlistItem, medialibraryItem, nil]];
[o_sidebaritems addObject: libraryItem];
if ([mycompItem hasChildren])
[o_sidebaritems addObject: mycompItem];
[o_sidebaritems addObject: internetItem];
[o_sidebar_view reloadData];
- [o_sidebar_view selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
[o_sidebar_view setDropItem:playlistItem dropChildIndex:NSOutlineViewDropOnItemIndex];
- [o_sidebar_view registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, @"VLCPlaylistItemPboardType", nil]];
+ [o_sidebar_view registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, @"VLCPlaylistItemPboardType", nil]];
[o_sidebar_view setAutosaveName:@"mainwindow-sidebar"];
[(PXSourceList *)o_sidebar_view setDataSource:self];
[o_sidebar_view expandItem: libraryItem expandChildren: YES];
+ o_fspanel = [[VLCFSPanel alloc] initWithContentRect:NSMakeRect(110.,267.,549.,87.)
+ styleMask:NSTexturedBackgroundWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
+
/* make sure we display the desired default appearance when VLC launches for the first time */
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:@"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];
+ [o_sidebar_view expandItem: [o_sidebaritems objectAtIndex:x] expandChildren: YES];
+
+ [o_fspanel center];
}
+ // select playlist item by default
+ [o_sidebar_view selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
+
if (b_dark_interface) {
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowResizedOrMoved:) name: NSWindowDidResizeNotification object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(windowResizedOrMoved:) name: NSWindowDidMoveNotification object: nil];
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];
-
} else {
[o_video_view setFrame: [o_split_view frame]];
[o_playlist_table setBorderType: NSNoBorder];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(someWindowWillClose:) name: NSWindowWillCloseNotification object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(someWindowWillMiniaturize:) name: NSWindowWillMiniaturizeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(applicationWillTerminate:) name: NSApplicationWillTerminateNotification object: nil];
+ [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(mainSplitViewDidResizeSubviews:) name: NSSplitViewDidResizeSubviewsNotification object:o_split_view];
- [o_split_view setAutosaveName:@"10thanniversary-splitview"];
if (b_splitviewShouldBeHidden) {
- [self hideSplitView];
+ [self hideSplitView: YES];
i_lastSplitViewHeight = 300;
}
nativeVideoSize = screenSize;
[self resizeWindow];
}
+
+ /* update fs button to reflect state for next startup */
+ if (var_InheritBool(pl_Get(VLCIntf), "fullscreen"))
+ [o_controls_bar setFullscreenState:YES];
+
+ /* restore split view */
+ i_lastLeftSplitViewWidth = 200;
+ /* trick NSSplitView implementation, which pretends to know better than us */
+ if (!config_GetInt(VLCIntf, "macosx-show-sidebar"))
+ [self performSelector:@selector(toggleLeftSubSplitView) withObject:nil afterDelay:0.05];
}
#pragma mark -
+#pragma mark appearance management
- (VLCMainWindowControlsBar *)controlsBar;
{
- (void)resizePlaylistAfterCollapse
{
+ // no animation here since we might be in the middle of another resize animation
NSRect plrect;
plrect = [o_playlist_table frame];
- plrect.size.height = i_lastSplitViewHeight - 20.0; // actual pl top bar height, which differs from its frame
- [[o_playlist_table animator] setFrame: plrect];
+ plrect.size.height = [o_split_view frame].size.height - 20.0; // actual pl top bar height, which differs from its frame
+ [o_playlist_table setFrame: plrect];
+ [o_playlist_table setNeedsDisplay: YES];
NSRect rightSplitRect;
rightSplitRect = [o_right_split_view frame];
plrect = [o_dropzone_box 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];
+ [o_dropzone_view setFrame: [o_playlist_table frame]];
+ [o_dropzone_box setFrame: plrect];
+ [o_dropzone_view setNeedsDisplay: YES];
}
- (void)makeSplitViewVisible
[o_video_view setHidden: YES];
[o_split_view setHidden: NO];
- [self makeFirstResponder: nil];
+ if ([self fullscreen]) {
+ [[o_controls_bar bottomBarView] setHidden: NO];
+ [o_fspanel setNonActive:nil];
+ }
+ [self makeFirstResponder: o_playlist_table];
}
- (void)makeSplitViewHidden
[o_split_view setHidden: YES];
[o_video_view setHidden: NO];
+ if ([self fullscreen]) {
+ [[o_controls_bar bottomBarView] setHidden: YES];
+ [o_fspanel setActive:nil];
+ }
if ([[o_video_view subviews] count] > 0)
[self makeFirstResponder: [[o_video_view subviews] objectAtIndex:0]];
}
-// only exception for an controls bar button action
-- (IBAction)togglePlaylist:(id)sender
+
+- (void)changePlaylistState:(VLCPlaylistStateEvent)event
{
- if (![self isVisible] && sender != nil) {
- [self makeKeyAndOrderFront: sender];
+ // Beware, this code is really ugly
+
+ msg_Dbg(VLCIntf, "toggle playlist from state: removed splitview %i, minimized view %i. Event %i", b_splitview_removed, b_minimized_view, event);
+ if (![self isVisible] && event == psUserMenuEvent) {
+ [self makeKeyAndOrderFront: nil];
return;
}
BOOL b_activeVideo = [[VLCMain sharedInstance] activeVideoPlayback];
BOOL b_restored = NO;
- // 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;
+ // ignore alt if triggered through main menu shortcut
+ BOOL b_have_alt_key = ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) != 0;
+ if (event == psUserMenuEvent)
+ b_have_alt_key = NO;
+
+ // eUserMenuEvent is now handled same as eUserEvent
+ if(event == psUserMenuEvent)
+ event = psUserEvent;
- if (b_dropzone_active && ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) != 0) {
+ if (b_dropzone_active && b_have_alt_key) {
[self hideDropZone];
return;
}
- if (!(b_nativeFullscreenMode && b_fullscreen) && !b_splitview_removed && ((([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) != 0 && b_activeVideo)
- || (b_nonembedded && sender != nil)
- || (!b_activeVideo && sender != nil)
- || b_minimized_view))
- [self hideSplitView];
- else {
+ if (!(b_nativeFullscreenMode && b_fullscreen) && !b_splitview_removed && ((b_have_alt_key && b_activeVideo)
+ || (b_nonembedded && event == psUserEvent)
+ || (!b_activeVideo && event == psUserEvent)
+ || (b_minimized_view && event == psVideoStartedOrStoppedEvent))) {
+ // for starting playback, window is resized through resized events
+ // for stopping playback, resize through reset to previous frame
+ [self hideSplitView: event != psVideoStartedOrStoppedEvent];
+ b_minimized_view = NO;
+ } else {
if (b_splitview_removed) {
- if (!b_nonembedded || (sender != nil && b_nonembedded))
- [self showSplitView];
+ if (!b_nonembedded || (event == psUserEvent && b_nonembedded))
+ [self showSplitView: event != psVideoStartedOrStoppedEvent];
- if (sender == nil)
+ if (event != psUserEvent)
b_minimized_view = YES;
else
b_minimized_view = NO;
}
if (!b_nonembedded) {
- if (([o_video_view isHidden] && b_activeVideo) || b_restored || (b_activeVideo && sender == nil))
+ if (([o_video_view isHidden] && b_activeVideo) || b_restored || (b_activeVideo && event != psUserEvent))
[self makeSplitViewHidden];
else
[self makeSplitViewVisible];
} else {
[o_split_view setHidden: NO];
[o_playlist_table setHidden: NO];
- [o_video_view setHidden: !b_activeVideo];
- if (b_activeVideo && [[o_video_view subviews] count] > 0)
- [[o_video_view window] makeFirstResponder: [[o_video_view subviews] objectAtIndex:0]];
+ [o_video_view setHidden: YES];
}
}
+
+ msg_Dbg(VLCIntf, "toggle playlist to state: removed splitview %i, minimized view %i", b_splitview_removed, b_minimized_view);
}
- (IBAction)dropzoneButtonAction:(id)sender
- (void)applicationWillTerminate:(NSNotification *)notification
{
+ config_PutInt(VLCIntf, "macosx-show-sidebar", ![o_split_view isSubviewCollapsed:o_left_split_view]);
+
[self saveFrameUsingName: [self frameAutosaveName]];
}
- (void)someWindowWillClose:(NSNotification *)notification
{
id obj = [notification object];
-
- if ([obj class] == [VLCVideoWindowCommon class] || [obj class] == [VLCDetachedVideoWindow class] || ([obj class] == [VLCMainWindow class] && !b_nonembedded)) {
+
+ // hasActiveVideo is defined for VLCVideoWindowCommon and subclasses
+ if ([obj respondsToSelector:@selector(hasActiveVideo)] && [obj hasActiveVideo]) {
if ([[VLCMain sharedInstance] activeVideoPlayback])
[[VLCCoreInteraction sharedInstance] stop];
}
[[o_playlist_table animator] setHidden: NO];
}
-- (void)hideSplitView
+- (void)hideSplitView:(BOOL)b_with_resize
{
- NSRect winrect = [self frame];
- i_lastSplitViewHeight = [o_split_view frame].size.height;
- winrect.size.height = winrect.size.height - i_lastSplitViewHeight;
- winrect.origin.y = winrect.origin.y + i_lastSplitViewHeight;
- [self setFrame: winrect display: YES animate: YES];
+ if (b_with_resize) {
+ NSRect winrect = [self frame];
+ i_lastSplitViewHeight = [o_split_view frame].size.height;
+ winrect.size.height = winrect.size.height - i_lastSplitViewHeight;
+ winrect.origin.y = winrect.origin.y + i_lastSplitViewHeight;
+ [self setFrame: winrect display: YES animate: YES];
+ }
+
[self performSelector:@selector(hideDropZone) withObject:nil afterDelay:0.1];
if (b_dark_interface) {
- [self setContentMinSize: NSMakeSize(604., [[o_controls_bar bottomBarView] frame].size.height + [o_titlebar_view frame].size.height)];
- [self setContentMaxSize: NSMakeSize(FLT_MAX, [[o_controls_bar bottomBarView] frame].size.height + [o_titlebar_view frame].size.height)];
+ [self setContentMinSize: NSMakeSize(604., [o_controls_bar height] + [o_titlebar_view frame].size.height)];
+ [self setContentMaxSize: NSMakeSize(FLT_MAX, [o_controls_bar height] + [o_titlebar_view frame].size.height)];
} else {
- [self setContentMinSize: NSMakeSize(604., [[o_controls_bar bottomBarView] frame].size.height)];
- [self setContentMaxSize: NSMakeSize(FLT_MAX, [[o_controls_bar bottomBarView] frame].size.height)];
+ [self setContentMinSize: NSMakeSize(604., [o_controls_bar height])];
+ [self setContentMaxSize: NSMakeSize(FLT_MAX, [o_controls_bar height])];
}
b_splitview_removed = YES;
}
-- (void)showSplitView
+- (void)showSplitView:(BOOL)b_with_resize
{
[self updateWindow];
if (b_dark_interface)
[self setContentMinSize:NSMakeSize(604., 288.)];
[self setContentMaxSize: NSMakeSize(FLT_MAX, FLT_MAX)];
- NSRect winrect;
- winrect = [self frame];
- winrect.size.height = winrect.size.height + i_lastSplitViewHeight;
- winrect.origin.y = winrect.origin.y - i_lastSplitViewHeight;
- [self setFrame: winrect display: YES animate: YES];
+ if (b_with_resize) {
+ NSRect winrect;
+ winrect = [self frame];
+ winrect.size.height = winrect.size.height + i_lastSplitViewHeight;
+ winrect.origin.y = winrect.origin.y - i_lastSplitViewHeight;
+ [self setFrame: winrect display: YES animate: YES];
+ }
[self performSelector:@selector(resizePlaylistAfterCollapse) withObject: nil afterDelay:0.75];
- (void)updateTimeSlider
{
[o_controls_bar updateTimeSlider];
- [[self controlsBar] updatePosAndTimeInFSPanel:o_fspanel];
+ [o_fspanel updatePositionAndTime];
[[[VLCMain sharedInstance] voutController] updateWindowsControlsBarWithSelector:@selector(updateTimeSlider)];
}
p_input = pl_CurrentInput(VLCIntf);
if (p_input) {
NSString *aString;
- char *format = var_InheritString(VLCIntf, "input-title-format");
- char *formated = str_format_meta(pl_Get(VLCIntf), format);
- free(format);
- aString = [NSString stringWithUTF8String:formated];
- free(formated);
+
+ if (!config_GetPsz(VLCIntf, "video-title")) {
+ char *format = var_InheritString(VLCIntf, "input-title-format");
+ char *formated = str_format_meta(p_input, format);
+ free(format);
+ aString = [NSString stringWithUTF8String:formated];
+ free(formated);
+ } else
+ aString = [NSString stringWithUTF8String:config_GetPsz(VLCIntf, "video-title")];
char *uri = input_item_GetURI(input_GetItem(p_input));
- NSURL * o_url = [NSURL URLWithString: [NSString stringWithUTF8String: uri]];
+ NSURL * o_url = [NSURL URLWithString:[NSString stringWithUTF8String:uri]];
if ([o_url isFileURL]) {
[self setRepresentedURL: o_url];
[[[VLCMain sharedInstance] voutController] updateWindowsUsingBlock:^(VLCVideoWindowCommon *o_window) {
aString = [o_url absoluteString];
}
- [self setTitle: aString];
- [[[VLCMain sharedInstance] voutController] updateWindowsUsingBlock:^(VLCVideoWindowCommon *o_window) {
- [o_window setTitle:aString];
- }];
+ if ([aString length] > 0) {
+ [self setTitle: aString];
+ [[[VLCMain sharedInstance] voutController] updateWindowsUsingBlock:^(VLCVideoWindowCommon *o_window) {
+ [o_window setTitle:aString];
+ }];
+
+ [o_fspanel setStreamTitle: aString];
+ } else {
+ [self setTitle: _NS("VLC media player")];
+ [self setRepresentedURL: nil];
+ }
- [o_fspanel setStreamTitle: aString];
vlc_object_release(p_input);
} else {
[self setTitle: _NS("VLC media player")];
[o_fspanel setPlay];
[[[VLCMain sharedInstance] voutController] updateWindowsControlsBarWithSelector:@selector(setPlay)];
-
}
- (void)updateVolumeSlider
#pragma mark -
#pragma mark Video Output handling
-- (VLCVoutView *)setupVout:(vout_window_t *)p_wnd
+- (void)videoplayWillBeStarted
{
- BOOL b_video_deco = var_InheritBool(VLCIntf, "video-deco");
- BOOL b_video_wallpaper = var_InheritBool(VLCIntf, "video-wallpaper");
- VLCVoutView *o_vout_view;
- VLCVideoWindowCommon *o_new_video_window;
-
- // TODO: make lion fullscreen compatible with video-wallpaper and !embedded-video
- if ((b_video_wallpaper || !b_video_deco) && !b_nativeFullscreenMode) {
- // b_video_wallpaper is priorized over !b_video_deco
-
- msg_Dbg(VLCIntf, "Creating background / blank window");
- NSScreen *screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_InheritInteger(VLCIntf, "macosx-vdev")];
- if (!screen)
- screen = [self screen];
-
- NSRect window_rect;
- if (b_video_wallpaper)
- window_rect = [screen frame];
- else
- window_rect = [self frame];
-
- NSUInteger mask = NSBorderlessWindowMask;
- if (!OSX_SNOW_LEOPARD && !b_video_deco)
- mask |= NSResizableWindowMask;
-
- BOOL b_no_video_deco_only = !b_video_wallpaper;
- o_new_video_window = [[VLCVideoWindowCommon alloc] initWithContentRect:window_rect styleMask:mask backing:NSBackingStoreBuffered defer:YES];
- [o_new_video_window setDelegate:o_new_video_window];
-
- if (b_video_wallpaper)
- [o_new_video_window setLevel:CGWindowLevelForKey(kCGDesktopWindowLevelKey) + 1];
-
- [o_new_video_window setBackgroundColor: [NSColor blackColor]];
- [o_new_video_window setCanBecomeKeyWindow: !b_video_wallpaper];
- [o_new_video_window setCanBecomeMainWindow: !b_video_wallpaper];
- [o_new_video_window setAcceptsMouseMovedEvents: !b_video_wallpaper];
- [o_new_video_window setMovableByWindowBackground: !b_video_wallpaper];
- [o_new_video_window useOptimizedDrawing: YES];
-
- o_vout_view = [[VLCVoutView alloc] initWithFrame:[[o_new_video_window contentView] bounds]];
- [o_vout_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- [[o_new_video_window contentView] addSubview:o_vout_view positioned:NSWindowAbove relativeTo:nil];
- [o_new_video_window setVideoView:o_vout_view];
-
-
- if (b_video_wallpaper)
- [o_new_video_window orderBack:nil];
- else {
- [o_new_video_window center];
- [o_new_video_window setFrameAutosaveName:@"extra-videowindow"];
- [o_new_video_window setContentMinSize: NSMakeSize(f_min_video_height, f_min_video_height)];
- }
-
- b_nonembedded = YES;
- } else {
- if (var_InheritBool(VLCIntf, "embedded-video") || b_nativeFullscreenMode) {
- o_vout_view = [o_video_view retain];
- o_new_video_window = [self retain];
- b_nonembedded = NO;
- } else {
- NSWindowController *o_controller = [[NSWindowController alloc] initWithWindowNibName:@"DetachedVideoWindow"];
- [o_controller loadWindow];
- o_new_video_window = [(VLCDetachedVideoWindow *)[o_controller window] retain];
- [o_controller release];
-
- [o_new_video_window setDelegate: o_new_video_window];
- [o_new_video_window setLevel:NSNormalWindowLevel];
- [o_new_video_window useOptimizedDrawing: YES];
- o_vout_view = [[o_new_video_window videoView] retain];
- b_nonembedded = YES;
- }
- }
-
- if (!b_video_wallpaper) {
- [o_new_video_window makeKeyAndOrderFront: self];
-
- vout_thread_t *p_vout = getVout();
- if (p_vout) {
- if (var_GetBool(p_vout, "video-on-top"))
- [o_new_video_window setLevel: NSStatusWindowLevel];
- else
- [o_new_video_window setLevel: NSNormalWindowLevel];
- vlc_object_release(p_vout);
- }
- }
-
- [o_new_video_window setAlphaValue: config_GetFloat(VLCIntf, "macosx-opaqueness")];
- [[[VLCMain sharedInstance] voutController] addVout:[o_new_video_window autorelease] forDisplay:p_wnd];
-
- if(b_nonembedded) {
- // event occurs before window is created, so call again
- [[VLCMain sharedInstance] playbackStatusUpdated];
- }
-
- return [o_vout_view autorelease];
+ if (!b_fullscreen)
+ frameBeforePlayback = [self frame];
}
- (void)setVideoplayEnabled
{
BOOL b_videoPlayback = [[VLCMain sharedInstance] activeVideoPlayback];
+
+ if (!b_videoPlayback) {
+ if (!b_nonembedded && (!b_nativeFullscreenMode || (b_nativeFullscreenMode && !b_fullscreen)) && frameBeforePlayback.size.width > 0 && frameBeforePlayback.size.height > 0) {
- if (b_videoPlayback) {
- if (!b_fullscreen)
- frameBeforePlayback = [self frame];
- } else {
- if (!b_nonembedded && !b_fullscreen && frameBeforePlayback.size.width > 0 && frameBeforePlayback.size.height > 0)
- [[self animator] setFrame:frameBeforePlayback display:YES];
+ // only resize back to minimum view of this is still desired final state
+ float f_threshold_height = f_min_video_height + [o_controls_bar height];
+ if(frameBeforePlayback.size.height > f_threshold_height || b_minimized_view)
+ [[self animator] setFrame:frameBeforePlayback display:YES];
+ }
- [self makeFirstResponder: nil];
+ frameBeforePlayback = NSMakeRect(0, 0, 0, 0);
- if ([self level] != NSNormalWindowLevel)
- [self setLevel: NSNormalWindowLevel];
+ // update fs button to reflect state for next startup
+ if (var_InheritBool(VLCIntf, "fullscreen") || var_GetBool(pl_Get(VLCIntf), "fullscreen")) {
+ [o_controls_bar setFullscreenState:YES];
+ }
+
+ [self makeFirstResponder: o_playlist_table];
+ [[[VLCMain sharedInstance] voutController] updateWindowLevelForHelperWindows: NSNormalWindowLevel];
// restore alpha value to 1 for the case that macosx-opaqueness is set to < 1
[self setAlphaValue:1.0];
}
if (b_nativeFullscreenMode) {
- if ([NSApp presentationOptions] & NSApplicationPresentationFullScreen)
+ if ([self hasActiveVideo] && [self fullscreen]) {
[[o_controls_bar bottomBarView] setHidden: b_videoPlayback];
- else
- [[o_controls_bar bottomBarView] setHidden: NO];
- if (b_videoPlayback && b_fullscreen)
[o_fspanel setActive: nil];
- if (!b_videoPlayback)
+ } else {
+ [[o_controls_bar bottomBarView] setHidden: NO];
[o_fspanel setNonActive: nil];
+ }
}
-}
-
-// Called automatically if window's acceptsMouseMovedEvents property is true
-- (void)mouseMoved:(NSEvent *)theEvent
-{
- if (b_fullscreen)
- [self recreateHideMouseTimer];
-
- [super mouseMoved: theEvent];
-}
-
-- (void)recreateHideMouseTimer
-{
- if (t_hide_mouse_timer != nil) {
- [t_hide_mouse_timer invalidate];
- [t_hide_mouse_timer release];
- }
-
- t_hide_mouse_timer = [NSTimer scheduledTimerWithTimeInterval:2
- target:self
- selector:@selector(hideMouseCursor:)
- userInfo:nil
- repeats:NO];
- [t_hide_mouse_timer retain];
-}
-
-// NSTimer selectors require this function signature as per Apple's docs
-- (void)hideMouseCursor:(NSTimer *)timer
-{
- [NSCursor setHiddenUntilMouseMoves: YES];
-}
-
-
-#pragma mark -
-#pragma mark Fullscreen support
-
-- (void)showFullscreenController
-{
- if (b_fullscreen && [[VLCMain sharedInstance] activeVideoPlayback])
- [o_fspanel fadeIn];
-}
-
-- (void)makeKeyAndOrderFront: (id)sender
-{
- /* Hack
- * when we exit fullscreen and fade out, we may endup in
- * having a window that is faded. We can't have it fade in unless we
- * animate again. */
-
- if (!b_window_is_invisible) {
- /* Make sure we don't do it too much */
- [super makeKeyAndOrderFront: sender];
- return;
- }
-
- [super setAlphaValue:0.0f];
- [super makeKeyAndOrderFront: sender];
-
- NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithCapacity:2];
- [dict setObject:self forKey:NSViewAnimationTargetKey];
- [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
- o_makekey_anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
- [dict release];
-
- [o_makekey_anim setAnimationBlockingMode: NSAnimationNonblocking];
- [o_makekey_anim setDuration: 0.1];
- [o_makekey_anim setFrameRate: 30];
- [o_makekey_anim setDelegate: self];
-
- [o_makekey_anim startAnimation];
- b_window_is_invisible = NO;
-
- /* fullscreenAnimation will be unlocked when animation ends */
+ [self changePlaylistState: psVideoStartedOrStoppedEvent];
}
#pragma mark -
#pragma mark Lion native fullscreen handling
- (void)windowWillEnterFullScreen:(NSNotification *)notification
{
- // workaround, see #6668
- [NSApp setPresentationOptions:(NSApplicationPresentationFullScreen | NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
-
- var_SetBool(pl_Get(VLCIntf), "fullscreen", true);
-
- vout_thread_t *p_vout = getVout();
- if (p_vout) {
- var_SetBool(p_vout, "fullscreen", true);
- vlc_object_release(p_vout);
- }
-
- [o_video_view setFrame: [[self contentView] frame]];
- b_fullscreen = YES;
-
- [self recreateHideMouseTimer];
- i_originalLevel = [self level];
- [self setLevel:NSNormalWindowLevel];
+ [super windowWillEnterFullScreen:notification];
+ // update split view frame after removing title bar
if (b_dark_interface) {
- [o_titlebar_view removeFromSuperviewWithoutNeedingDisplay];
-
- NSRect winrect;
- CGFloat f_titleBarHeight = [o_titlebar_view frame].size.height;
- winrect = [self frame];
-
- winrect.size.height = winrect.size.height - f_titleBarHeight;
- [self setFrame: winrect display:NO animate:NO];
- winrect = [o_split_view frame];
- winrect.size.height = winrect.size.height + f_titleBarHeight;
- [o_split_view setFrame: winrect];
+ NSRect frame = [[self contentView] frame];
+ frame.origin.y += [o_controls_bar height];
+ frame.size.height -= [o_controls_bar height];
+ [o_split_view setFrame:frame];
}
-
- if ([[VLCMain sharedInstance] activeVideoPlayback])
- [[o_controls_bar bottomBarView] setHidden: YES];
-
- [self setMovableByWindowBackground: NO];
-}
-
-- (void)windowDidEnterFullScreen:(NSNotification *)notification
-{
- // Indeed, we somehow can have an "inactive" fullscreen (but a visible window!).
- // But this creates some problems when leaving fs over remote intfs, so activate app here.
- [NSApp activateIgnoringOtherApps:YES];
-
- [o_fspanel setVoutWasUpdated: self];
- [o_fspanel setActive: nil];
}
- (void)windowWillExitFullScreen:(NSNotification *)notification
{
+ [super windowWillExitFullScreen: notification];
- var_SetBool(pl_Get(VLCIntf), "fullscreen", false);
-
- vout_thread_t *p_vout = getVout();
- if (p_vout) {
- var_SetBool(p_vout, "fullscreen", false);
- vlc_object_release(p_vout);
- }
-
- [o_video_view setFrame: [o_split_view frame]];
- [NSCursor setHiddenUntilMouseMoves: NO];
- [o_fspanel setNonActive: nil];
- [self setLevel:i_originalLevel];
- b_fullscreen = NO;
-
+ // update split view frame after readding title bar
if (b_dark_interface) {
- NSRect winrect;
- CGFloat f_titleBarHeight = [o_titlebar_view frame].size.height;
- winrect = [self frame];
+ NSRect frame = [o_split_view frame];
+ frame.size.height -= [o_titlebar_view frame].size.height;
+ [o_split_view setFrame:frame];
+ }
+}
+#pragma mark -
+#pragma mark Fullscreen support
- [o_titlebar_view setFrame: NSMakeRect(0, winrect.size.height - f_titleBarHeight,
- winrect.size.width, f_titleBarHeight)];
- [[self contentView] addSubview: o_titlebar_view];
+- (void)showFullscreenController
+{
+ id currentWindow = [NSApp keyWindow];
+ if ([currentWindow respondsToSelector:@selector(hasActiveVideo)] && [currentWindow hasActiveVideo]) {
+ if ([currentWindow respondsToSelector:@selector(fullscreen)] && [currentWindow fullscreen] && ![[currentWindow videoView] isHidden]) {
- winrect.size.height = winrect.size.height + f_titleBarHeight;
- [self setFrame: winrect display:NO animate:NO];
- winrect = [o_split_view frame];
- winrect.size.height = winrect.size.height - f_titleBarHeight;
- [o_split_view setFrame: winrect];
- [o_video_view setFrame: winrect];
+ if ([[VLCMain sharedInstance] activeVideoPlayback])
+ [o_fspanel fadeIn];
+ }
}
- if ([[VLCMain sharedInstance] activeVideoPlayback])
- [[o_controls_bar bottomBarView] setHidden: NO];
-
- [self setMovableByWindowBackground: YES];
}
#pragma mark -
return YES;
}
+- (void)mainSplitViewDidResizeSubviews:(id)object
+{
+ i_lastLeftSplitViewWidth = [o_left_split_view frame].size.width;
+ config_PutInt(VLCIntf, "macosx-show-sidebar", ![o_split_view isSubviewCollapsed:o_left_split_view]);
+ [[[VLCMain sharedInstance] mainMenu] updateSidebarMenuItem];
+}
+
+- (void)toggleLeftSubSplitView
+{
+ [o_split_view adjustSubviews];
+ if ([o_split_view isSubviewCollapsed:o_left_split_view])
+ [o_split_view setPosition:i_lastLeftSplitViewWidth ofDividerAtIndex:0];
+ else
+ [o_split_view setPosition:[o_split_view minPossiblePositionOfDividerAtIndex:0] ofDividerAtIndex:0];
+ [[[VLCMain sharedInstance] mainMenu] updateSidebarMenuItem];
+}
+
#pragma mark -
#pragma mark Side Bar Data handling
/* taken under BSD-new from the PXSourceList sample project, adapted for VLC */
- (NSInteger)sourceList:(PXSourceList*)aSourceList badgeValueForItem:(id)item
{
playlist_t * p_playlist = pl_Get(VLCIntf);
- NSInteger i_playlist_size;
+ NSInteger i_playlist_size = 0;
if ([[item identifier] isEqualToString: @"playlist"]) {
PL_LOCK;
}
if ([[item identifier] isEqualToString: @"medialibrary"]) {
PL_LOCK;
- i_playlist_size = p_playlist->p_ml_category->i_children;
+ if (p_playlist->p_ml_category)
+ i_playlist_size = p_playlist->p_ml_category->i_children;
PL_UNLOCK;
return i_playlist_size;
if ([[item identifier] isEqualToString:@"playlist"]) {
[[[VLCMain sharedInstance] playlist] setPlaylistRoot:p_playlist->p_local_category];
} else if ([[item identifier] isEqualToString:@"medialibrary"]) {
- [[[VLCMain sharedInstance] playlist] setPlaylistRoot:p_playlist->p_ml_category];
+ if (p_playlist->p_ml_category)
+ [[[VLCMain sharedInstance] playlist] setPlaylistRoot:p_playlist->p_ml_category];
} else {
playlist_item_t * pl_item;
PL_LOCK;
[self showPodcastControls];
else
[self hidePodcastControls];
+
+ [[NSNotificationCenter defaultCenter] postNotificationName: @"VLCMediaKeySupportSettingChanged"
+ object: nil
+ userInfo: nil];
}
- (NSDragOperation)sourceList:(PXSourceList *)aSourceList validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
return nil;
for (NSUInteger x = 0; x < count; x++) {
- id item = [array objectAtIndex: x]; // save one objc selector call
+ id item = [array objectAtIndex:x]; // save one objc selector call
if ([[item identifier] isEqualToString:object])
return item;
}
[podcastConf appendString: [o_podcast_subscribe_url_fld stringValue]];
config_PutPsz(VLCIntf, "podcast-urls", [podcastConf UTF8String]);
-
- vlc_object_t *p_obj = (vlc_object_t*)vlc_object_find_name(VLCIntf->p_libvlc, "podcast");
- if (p_obj) {
- var_SetString(p_obj, "podcast-urls", [podcastConf UTF8String]);
- vlc_object_release(p_obj);
- }
+ var_SetString(pl_Get(VLCIntf), "podcast-urls", [podcastConf UTF8String]);
[podcastConf release];
}
}
NSMutableArray * urls = [[NSMutableArray alloc] initWithArray:[[NSString stringWithUTF8String:config_GetPsz(VLCIntf, "podcast-urls")] componentsSeparatedByString:@"|"]];
[urls removeObjectAtIndex: [o_podcast_unsubscribe_pop indexOfSelectedItem]];
config_PutPsz(VLCIntf, "podcast-urls", [[urls componentsJoinedByString:@"|"] UTF8String]);
+ var_SetString(pl_Get(VLCIntf), "podcast-urls", config_GetPsz(VLCIntf, "podcast-urls"));
[urls release];
- vlc_object_t *p_obj = (vlc_object_t*)vlc_object_find_name(VLCIntf->p_libvlc, "podcast");
- if (p_obj) {
- var_SetString(p_obj, "podcast-urls", config_GetPsz(VLCIntf, "podcast-urls"));
- vlc_object_release(p_obj);
- }
-
/* reload the podcast module, since it won't update its list when removing podcasts */
playlist_t * p_playlist = pl_Get(VLCIntf);
if (playlist_IsServicesDiscoveryLoaded(p_playlist, "podcast{longname=\"Podcasts\"}")) {
playlist_ServicesDiscoveryRemove(p_playlist, "podcast{longname=\"Podcasts\"}");
playlist_ServicesDiscoveryAdd(p_playlist, "podcast{longname=\"Podcasts\"}");
- [o_playlist_table reloadData];
+ [[[VLCMain sharedInstance] playlist] playlistUpdated];
}
-
}
}
- (void)awakeFromNib
{
+ // sets lion fullscreen behaviour
+ [super awakeFromNib];
[self setAcceptsMouseMovedEvents: YES];
if (b_dark_interface) {
[o_titlebar_view setFrame: NSMakeRect(0, winrect.size.height - f_titleBarHeight, winrect.size.width, f_titleBarHeight)];
[[self contentView] addSubview: o_titlebar_view positioned: NSWindowAbove relativeTo: nil];
- // native fs not supported with detached view yet
- [o_titlebar_view setFullscreenButtonHidden: YES];
} else {
[self setBackgroundColor: [NSColor blackColor]];
}
NSRect videoViewRect = [[self contentView] bounds];
if (b_dark_interface)
videoViewRect.size.height -= [o_titlebar_view frame].size.height;
- CGFloat f_bottomBarHeight = [[[self controlsBar] bottomBarView] frame].size.height;
+ CGFloat f_bottomBarHeight = [[self controlsBar] height];
videoViewRect.size.height -= f_bottomBarHeight;
videoViewRect.origin.y = f_bottomBarHeight;
[o_video_view setFrame: videoViewRect];
[[self contentView] addSubview: o_color_backdrop positioned: NSWindowBelow relativeTo: o_video_view];
[o_color_backdrop setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
- [self setContentMinSize: NSMakeSize(363., f_min_video_height + [[[self controlsBar] bottomBarView] frame].size.height + [o_titlebar_view frame].size.height)];
+ [self setContentMinSize: NSMakeSize(363., f_min_video_height + [[self controlsBar] height] + [o_titlebar_view frame].size.height)];
} else {
- [self setContentMinSize: NSMakeSize(363., f_min_video_height + [[[self controlsBar] bottomBarView] frame].size.height)];
+ [self setContentMinSize: NSMakeSize(363., f_min_video_height + [[self controlsBar] height])];
}
}