1 /*****************************************************************************
2 * embeddedwindow.m: MacOS X interface module
3 *****************************************************************************
4 * Copyright (C) 2005-2011 the VideoLAN team
7 * Authors: Benjamin Pracht <bigben at videolan dot org>
8 * Felix Paul Kühne <fkuehne at videolan dot org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #import "embeddedwindow.h"
36 /* SetSystemUIMode, ... */
37 #import <Carbon/Carbon.h>
39 /*****************************************************************************
40 * VLCEmbeddedWindow Implementation
41 *****************************************************************************/
43 @implementation VLCEmbeddedWindow
45 - (id)initWithContentRect:(NSRect)contentRect styleMask: (NSUInteger)windowStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation
47 BOOL b_useTextured = YES;
48 if( [[NSWindow class] instancesRespondToSelector:@selector(setContentBorderThickness:forEdge:)] )
51 windowStyle ^= NSTexturedBackgroundWindowMask;
53 self = [super initWithContentRect:contentRect styleMask:windowStyle backing:bufferingType defer:deferCreation];
56 [self setContentBorderThickness:28.0 forEdge:NSMinYEdge];
63 [self setDelegate: self];
66 [o_btn_backward setToolTip: _NS("Rewind")];
67 [o_btn_forward setToolTip: _NS("Fast Forward")];
68 [o_btn_fullscreen setToolTip: _NS("Fullscreen")];
69 [o_btn_play setToolTip: _NS("Play")];
70 [o_timeslider setToolTip: _NS("Position")];
71 [o_btn_prev setToolTip: _NS("Previous")];
72 [o_btn_stop setToolTip: _NS("Stop")];
73 [o_btn_next setToolTip: _NS("Next")];
74 [o_volumeslider setToolTip: _NS("Volume")];
75 [o_btn_playlist setToolTip: _NS("Playlist")];
76 [self setTitle: _NS("VLC media player")];
78 o_img_play = [NSImage imageNamed: @"play_embedded"];
79 o_img_pause = [NSImage imageNamed: @"pause_embedded"];
81 /* Set color of sidebar to Leopard's "Sidebar Blue" */
82 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820
87 [self setMinSize:NSMakeSize([o_sidebar_list convertRect:[o_sidebar_list bounds]
88 toView: nil].size.width + 551., 114.)];
90 /* Useful to save o_view frame in fullscreen mode */
91 o_temp_view = [[NSView alloc] init];
92 [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
94 o_fullscreen_window = nil;
95 o_makekey_anim = o_fullscreen_anim1 = o_fullscreen_anim2 = nil;
97 /* Not fullscreen when we wake up */
98 [o_btn_fullscreen setState: NO];
101 [self setMovableByWindowBackground:YES];
103 [self setDelegate:self];
105 /* Make sure setVisible: returns NO */
106 [self orderOut:self];
107 b_window_is_invisible = YES;
108 videoRatio = NSMakeSize( 0., 0. );
110 /* enlarge the time slider and move items around in case we have no window resize control */
111 if ([self showsResizeIndicator] == NO) {
113 view_rect = [o_backgroundimg_right frame];
115 [o_backgroundimg_right setFrame: NSMakeRect( view_rect.origin.x+15,
117 view_rect.size.width,
118 view_rect.size.height )];
120 view_rect = [o_backgroundimg_middle frame];
121 [o_backgroundimg_middle setFrame: NSMakeRect( view_rect.origin.x,
123 view_rect.size.width+15,
124 view_rect.size.height )];
126 view_rect = [o_timeslider frame];
127 [o_timeslider setFrame: NSMakeRect( view_rect.origin.x,
129 view_rect.size.width+15,
130 view_rect.size.height )];
132 view_rect = [o_time frame];
133 [o_time setFrame: NSMakeRect( view_rect.origin.x+15,
135 view_rect.size.width,
136 view_rect.size.height )];
140 - (void)controlTintChanged
143 if( [o_btn_play alternateImage] == o_img_play_pressed )
146 if( [NSColor currentControlTint] == NSGraphiteControlTint )
148 o_img_play_pressed = [NSImage imageNamed: @"play_embedded_graphite"];
149 o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_graphite"];
150 [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_embedded_graphite"]];
151 [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_embedded_graphite"]];
152 [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_graphite"]];
154 o_img_play_pressed = [NSImage imageNamed: @"play_embedded_blue"];
155 o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_blue"];
156 [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_embedded_blue"]];
157 [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_embedded_blue"]];
158 [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_blue"]];
162 [o_btn_play setAlternateImage: o_img_play_pressed];
164 [o_btn_play setAlternateImage: o_img_pause_pressed];
169 [[NSNotificationCenter defaultCenter] removeObserver: self];
170 [o_img_play release];
171 [o_img_play_pressed release];
172 [o_img_pause release];
173 [o_img_pause_pressed release];
178 - (void)setTime:(NSString *)o_arg_time position:(float)f_position
180 [o_time setStringValue: o_arg_time];
181 [o_timeslider setFloatValue: f_position];
184 - (void)playStatusUpdated:(int)i_status
186 if( i_status == PLAYING_S )
188 [o_btn_play setImage: o_img_pause];
189 [o_btn_play setAlternateImage: o_img_pause_pressed];
190 [o_btn_play setToolTip: _NS("Pause")];
194 [o_btn_play setImage: o_img_play];
195 [o_btn_play setAlternateImage: o_img_play_pressed];
196 [o_btn_play setToolTip: _NS("Play")];
200 - (void)setSeekable:(BOOL)b_seekable
202 [o_btn_forward setEnabled: b_seekable];
203 [o_btn_backward setEnabled: b_seekable];
204 [o_timeslider setEnabled: b_seekable];
207 - (void)setScrollString:(NSString *)o_string
209 [o_scrollfield setStringValue: o_string];
220 - (void)setStop:(BOOL)b_input
222 [o_btn_stop setEnabled: b_input];
225 - (void)setNext:(BOOL)b_input
227 [o_btn_next setEnabled: b_input];
230 - (void)setPrev:(BOOL)b_input
232 [o_btn_prev setEnabled: b_input];
235 - (void)setVolumeEnabled:(BOOL)b_input
237 [o_volumeslider setEnabled: b_input];
240 - (void)setVolumeSlider:(float)f_level
242 [o_volumeslider setFloatValue: f_level];
245 - (BOOL)windowShouldZoom:(NSWindow *)sender toFrame:(NSRect)newFrame
247 [self setFrame: newFrame display: YES animate: YES];
251 - (BOOL)windowShouldClose:(id)sender
253 playlist_t * p_playlist = pl_Get( VLCIntf );
254 playlist_Stop( p_playlist );
261 if (o_fullscreen_window)
267 - (void)setVideoRatio:(NSSize)ratio
272 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
274 if( videoRatio.height == 0. || videoRatio.width == 0. )
275 return proposedFrameSize;
277 if( [[[VLCMain sharedInstance] controls] aspectRatioIsLocked] )
279 NSRect viewRect = [o_view convertRect:[o_view bounds] toView: nil];
280 NSRect contentRect = [self contentRectForFrameRect:[self frame]];
281 float marginy = viewRect.origin.y + [self frame].size.height - contentRect.size.height;
282 float marginx = contentRect.size.width - viewRect.size.width;
283 proposedFrameSize.height = (proposedFrameSize.width - marginx) * videoRatio.height / videoRatio.width + marginy;
286 return proposedFrameSize;
289 - (void)becomeMainWindow
291 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820
295 [o_status becomeMainWindow];
296 [super becomeMainWindow];
299 - (void)resignMainWindow
301 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedWhite:0.91 alpha:1.0]];
302 [o_status resignMainWindow];
303 [super resignMainWindow];
306 - (CGFloat)splitView:(NSSplitView *) splitView constrainSplitPosition:(CGFloat) proposedPosition ofSubviewAt:(NSInteger) index
308 if([splitView isVertical])
309 return proposedPosition;
310 else if ( splitView == o_vertical_split )
311 return proposedPosition ;
313 float bottom = [splitView frame].size.height - [splitView dividerThickness];
314 if(proposedPosition > bottom - 50) {
315 [o_btn_playlist setState: NSOffState];
316 [o_searchfield setHidden:YES];
317 [o_playlist_view setHidden:YES];
321 [o_btn_playlist setState: NSOnState];
322 [o_searchfield setHidden:NO];
323 [o_playlist_view setHidden:NO];
324 [o_playlist swapPlaylists: o_playlist_table];
325 [o_vlc_main togglePlaylist:self];
326 return proposedPosition;
331 - (void)splitViewWillResizeSubviews:(NSNotification *) notification
336 - (CGFloat)splitView:(NSSplitView *) splitView constrainMinCoordinate:(CGFloat) proposedMin ofSubviewAt:(NSInteger) offset
338 if([splitView isVertical])
344 - (CGFloat)splitView:(NSSplitView *) splitView constrainMaxCoordinate:(CGFloat) proposedMax ofSubviewAt:(NSInteger) offset
346 if([splitView isVertical])
347 return MIN([self frame].size.width - 551, 300);
349 return [splitView frame].size.height;
352 - (BOOL)splitView:(NSSplitView *) splitView canCollapseSubview:(NSView *) subview
354 if([splitView isVertical])
360 - (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect
361 ofDividerAtIndex:(NSInteger)dividerIndex
363 if([splitView isVertical]) {
364 drawnRect.origin.x -= 3;
365 drawnRect.size.width += 5;
372 - (IBAction)togglePlaylist:(id)sender
374 NSView *playback_area = [[o_vertical_split subviews] objectAtIndex:0];
375 NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1];
376 NSRect newVid = [playback_area frame];
377 NSRect newList = [playlist_area frame];
378 if(newList.size.height < 50 && sender != self && sender != o_vlc_main) {
379 newList.size.height = newVid.size.height/2;
380 newVid.size.height = newVid.size.height/2;
381 newVid.origin.y = newVid.origin.y + newList.size.height;
382 [o_btn_playlist setState: NSOnState];
383 [o_searchfield setHidden:NO];
384 [o_playlist_view setHidden:NO];
385 [o_playlist swapPlaylists: o_playlist_table];
386 [o_vlc_main togglePlaylist:self];
389 newVid.size.height = newVid.size.height + newList.size.height;
390 newList.size.height = 0;
392 [o_btn_playlist setState: NSOffState];
393 [o_searchfield setHidden:YES];
394 [o_playlist_view setHidden:YES];
396 [playback_area setFrame: newVid];
397 [playlist_area setFrame: newList];
400 /*****************************************************************************
409 - (void)lockFullscreenAnimation
411 [o_animation_lock lock];
414 - (void)unlockFullscreenAnimation
416 [o_animation_lock unlock];
419 - (void)enterFullscreen
421 NSMutableDictionary *dict1, *dict2;
425 vout_thread_t *p_vout = getVout();
426 BOOL blackout_other_displays = config_GetInt( VLCIntf, "macosx-black" );
429 screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_GetInteger( p_vout, "video-device" )];
431 [self lockFullscreenAnimation];
435 msg_Dbg( VLCIntf, "chosen screen isn't present, using current screen for fullscreen mode" );
436 screen = [self screen];
440 msg_Dbg( VLCIntf, "Using deepest screen" );
441 screen = [NSScreen deepestScreen];
445 vlc_object_release( p_vout );
447 screen_rect = [screen frame];
449 [o_btn_fullscreen setState: YES];
451 [NSCursor setHiddenUntilMouseMoves: YES];
453 if( blackout_other_displays )
454 [screen blackoutOtherScreens];
456 /* Make sure we don't see the window flashes in float-on-top mode */
457 originalLevel = [self level];
458 [self setLevel:NSNormalWindowLevel];
460 /* Only create the o_fullscreen_window if we are not in the middle of the zooming animation */
461 if (!o_fullscreen_window)
463 /* We can't change the styleMask of an already created NSWindow, so we create another window, and do eye catching stuff */
465 rect = [[o_view superview] convertRect: [o_view frame] toView: nil]; /* Convert to Window base coord */
466 rect.origin.x += [self frame].origin.x;
467 rect.origin.y += [self frame].origin.y;
468 o_fullscreen_window = [[VLCWindow alloc] initWithContentRect:rect styleMask: NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
469 [o_fullscreen_window setBackgroundColor: [NSColor blackColor]];
470 [o_fullscreen_window setCanBecomeKeyWindow: YES];
472 if (![self isVisible] || [self alphaValue] == 0.0)
474 /* We don't animate if we are not visible, instead we
475 * simply fade the display */
476 CGDisplayFadeReservationToken token;
478 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
479 CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES );
481 if ([screen isMainScreen])
482 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
484 [[o_view superview] replaceSubview:o_view with:o_temp_view];
485 [o_temp_view setFrame:[o_view frame]];
486 [o_fullscreen_window setContentView:o_view];
488 [o_fullscreen_window makeKeyAndOrderFront:self];
489 [o_fullscreen_window orderFront:self animate:YES];
491 [o_fullscreen_window setFrame:screen_rect display:YES];
493 CGDisplayFade( token, 0.3, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO );
494 CGReleaseDisplayFadeReservation( token);
496 /* Will release the lock */
497 [self hasBecomeFullscreen];
502 /* Make sure we don't see the o_view disappearing of the screen during this operation */
503 NSDisableScreenUpdates();
504 [[o_view superview] replaceSubview:o_view with:o_temp_view];
505 [o_temp_view setFrame:[o_view frame]];
506 [o_fullscreen_window setContentView:o_view];
507 [o_fullscreen_window makeKeyAndOrderFront:self];
508 NSEnableScreenUpdates();
511 /* We are in fullscreen (and no animation is running) */
514 /* Make sure we are hidden */
515 [super orderOut: self];
516 [self unlockFullscreenAnimation];
520 if (o_fullscreen_anim1)
522 [o_fullscreen_anim1 stopAnimation];
523 [o_fullscreen_anim1 release];
525 if (o_fullscreen_anim2)
527 [o_fullscreen_anim2 stopAnimation];
528 [o_fullscreen_anim2 release];
531 if ([screen isMainScreen])
532 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
534 dict1 = [[NSMutableDictionary alloc] initWithCapacity:2];
535 dict2 = [[NSMutableDictionary alloc] initWithCapacity:3];
537 [dict1 setObject:self forKey:NSViewAnimationTargetKey];
538 [dict1 setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
540 [dict2 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
541 [dict2 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
542 [dict2 setObject:[NSValue valueWithRect:screen_rect] forKey:NSViewAnimationEndFrameKey];
544 /* Strategy with NSAnimation allocation:
545 - Keep at most 2 animation at a time
546 - leaveFullscreen/enterFullscreen are the only responsible for releasing and alloc-ing
548 o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict1]];
549 o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict2]];
554 [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
555 [o_fullscreen_anim1 setDuration: 0.3];
556 [o_fullscreen_anim1 setFrameRate: 30];
557 [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
558 [o_fullscreen_anim2 setDuration: 0.2];
559 [o_fullscreen_anim2 setFrameRate: 30];
561 [o_fullscreen_anim2 setDelegate: self];
562 [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
564 [o_fullscreen_anim1 startAnimation];
565 /* fullscreenAnimation will be unlocked when animation ends */
568 - (void)hasBecomeFullscreen
570 [o_fullscreen_window makeFirstResponder: [[[VLCMain sharedInstance] controls] voutView]];
572 [o_fullscreen_window makeKeyWindow];
573 [o_fullscreen_window setAcceptsMouseMovedEvents: TRUE];
575 /* tell the fspanel to move itself to front next time it's triggered */
576 [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: (int)[[o_fullscreen_window screen] displayID]];
579 [super orderOut: self];
581 [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil];
584 [self unlockFullscreenAnimation];
587 - (void)leaveFullscreen
589 [self leaveFullscreenAndFadeOut: NO];
592 - (void)leaveFullscreenAndFadeOut: (BOOL)fadeout
594 NSMutableDictionary *dict1, *dict2;
597 [self lockFullscreenAnimation];
600 [o_btn_fullscreen setState: NO];
602 /* We always try to do so */
603 [NSScreen unblackoutScreens];
605 /* Don't do anything if o_fullscreen_window is already closed */
606 if (!o_fullscreen_window)
608 [self unlockFullscreenAnimation];
614 /* We don't animate if we are not visible, instead we
615 * simply fade the display */
616 CGDisplayFadeReservationToken token;
618 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
619 CGDisplayFade( token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES );
621 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
622 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
624 /* Will release the lock */
625 [self hasEndedFullscreen];
627 /* Our window is hidden, and might be faded. We need to workaround that, so note it
629 b_window_is_invisible = YES;
631 CGDisplayFade( token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO );
632 CGReleaseDisplayFadeReservation( token);
636 [self setAlphaValue: 0.0];
637 [self orderFront: self];
639 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
640 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
642 if (o_fullscreen_anim1)
644 [o_fullscreen_anim1 stopAnimation];
645 [o_fullscreen_anim1 release];
647 if (o_fullscreen_anim2)
649 [o_fullscreen_anim2 stopAnimation];
650 [o_fullscreen_anim2 release];
653 frame = [[o_temp_view superview] convertRect: [o_temp_view frame] toView: nil]; /* Convert to Window base coord */
654 frame.origin.x += [self frame].origin.x;
655 frame.origin.y += [self frame].origin.y;
657 dict2 = [[NSMutableDictionary alloc] initWithCapacity:2];
658 [dict2 setObject:self forKey:NSViewAnimationTargetKey];
659 [dict2 setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
661 o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict2, nil]];
664 [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
665 [o_fullscreen_anim2 setDuration: 0.3];
666 [o_fullscreen_anim2 setFrameRate: 30];
668 [o_fullscreen_anim2 setDelegate: self];
670 dict1 = [[NSMutableDictionary alloc] initWithCapacity:3];
672 [dict1 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
673 [dict1 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
674 [dict1 setObject:[NSValue valueWithRect:frame] forKey:NSViewAnimationEndFrameKey];
676 o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict1, nil]];
679 [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
680 [o_fullscreen_anim1 setDuration: 0.2];
681 [o_fullscreen_anim1 setFrameRate: 30];
682 [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
684 /* Make sure o_fullscreen_window is the frontmost window */
685 [o_fullscreen_window orderFront: self];
687 [o_fullscreen_anim1 startAnimation];
688 /* fullscreenAnimation will be unlocked when animation ends */
691 - (void)hasEndedFullscreen
693 /* This function is private and should be only triggered at the end of the fullscreen change animation */
694 /* Make sure we don't see the o_view disappearing of the screen during this operation */
695 NSDisableScreenUpdates();
697 [o_view removeFromSuperviewWithoutNeedingDisplay];
698 [[o_temp_view superview] replaceSubview:o_temp_view with:o_view];
700 [o_view setFrame:[o_temp_view frame]];
701 [self makeFirstResponder: o_view];
702 if ([self isVisible])
703 [super makeKeyAndOrderFront:self]; /* our version contains a workaround */
704 [o_fullscreen_window orderOut: self];
705 NSEnableScreenUpdates();
707 [o_fullscreen_window release];
708 o_fullscreen_window = nil;
709 [self setLevel:originalLevel];
711 [self unlockFullscreenAnimation];
714 - (void)animationDidEnd:(NSAnimation*)animation
716 NSArray *viewAnimations;
717 if( o_makekey_anim == animation )
719 [o_makekey_anim release];
722 if ([animation currentValue] < 1.0)
725 /* Fullscreen ended or started (we are a delegate only for leaveFullscreen's/enterFullscren's anim2) */
726 viewAnimations = [o_fullscreen_anim2 viewAnimations];
727 if ([viewAnimations count] >=1 &&
728 [[[viewAnimations objectAtIndex: 0] objectForKey: NSViewAnimationEffectKey] isEqualToString:NSViewAnimationFadeInEffect])
730 /* Fullscreen ended */
731 [self hasEndedFullscreen];
735 /* Fullscreen started */
736 [self hasBecomeFullscreen];
740 - (void)orderOut: (id)sender
742 [super orderOut: sender];
744 /* Make sure we leave fullscreen */
745 [self leaveFullscreenAndFadeOut: YES];
748 - (void)makeKeyAndOrderFront: (id)sender
751 * when we exit fullscreen and fade out, we may endup in
752 * having a window that is faded. We can't have it fade in unless we
755 if(!b_window_is_invisible)
757 /* Make sure we don't do it too much */
758 [super makeKeyAndOrderFront: sender];
762 [super setAlphaValue:0.0f];
763 [super makeKeyAndOrderFront: sender];
765 NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithCapacity:2];
766 [dict setObject:self forKey:NSViewAnimationTargetKey];
767 [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
769 o_makekey_anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
772 [o_makekey_anim setAnimationBlockingMode: NSAnimationNonblocking];
773 [o_makekey_anim setDuration: 0.1];
774 [o_makekey_anim setFrameRate: 30];
775 [o_makekey_anim setDelegate: self];
777 [o_makekey_anim startAnimation];
778 b_window_is_invisible = NO;
780 /* fullscreenAnimation will be unlocked when animation ends */
785 /* Make sure setFrame gets executed on main thread especially if we are animating.
786 * (Thus we won't block the video output thread) */
787 - (void)setFrame:(NSRect)frame display:(BOOL)display animate:(BOOL)animate
789 struct { NSRect frame; BOOL display; BOOL animate;} args;
793 args.display = display;
794 args.animate = animate;
796 packedargs = [NSData dataWithBytes:&args length:sizeof(args)];
798 [self performSelectorOnMainThread:@selector(setFrameOnMainThread:)
799 withObject: packedargs waitUntilDone: YES];
802 - (void)setFrameOnMainThread:(NSData*)packedargs
804 struct args { NSRect frame; BOOL display; BOOL animate; } * args = (struct args*)[packedargs bytes];
808 /* Make sure we don't block too long and set up a non blocking animation */
809 NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:
810 self, NSViewAnimationTargetKey,
811 [NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey,
812 [NSValue valueWithRect:args->frame], NSViewAnimationEndFrameKey, nil];
814 NSViewAnimation * anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
817 [anim setAnimationBlockingMode: NSAnimationNonblocking];
818 [anim setDuration: 0.4];
819 [anim setFrameRate: 30];
820 [anim startAnimation];
823 [super setFrame:args->frame display:args->display animate:args->animate];
829 /*****************************************************************************
831 *****************************************************************************/
834 @implementation embeddedbackground
838 [self unregisterDraggedTypes];
844 [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType,
845 NSFilenamesPboardType, nil]];
846 [self addSubview: o_timeslider];
847 [self addSubview: o_scrollfield];
848 [self addSubview: o_time];
849 [self addSubview: o_main_pgbar];
850 [self addSubview: o_btn_backward];
851 [self addSubview: o_btn_forward];
852 [self addSubview: o_btn_fullscreen];
853 [self addSubview: o_btn_equalizer];
854 [self addSubview: o_btn_playlist];
855 [self addSubview: o_btn_play];
856 [self addSubview: o_btn_prev];
857 [self addSubview: o_btn_stop];
858 [self addSubview: o_btn_next];
859 [self addSubview: o_btn_volume_down];
860 [self addSubview: o_volumeslider];
861 [self addSubview: o_btn_volume_up];
862 [self addSubview: o_searchfield];
865 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
867 if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
868 == NSDragOperationGeneric)
870 return NSDragOperationGeneric;
874 return NSDragOperationNone;
878 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
883 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
885 NSPasteboard *o_paste = [sender draggingPasteboard];
886 NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
887 NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
888 NSData *o_carried_data = [o_paste dataForType:o_desired_type];
889 BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
893 if ([o_desired_type isEqualToString:NSFilenamesPboardType])
896 NSArray *o_array = [NSArray array];
897 NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType]
898 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
900 for( i = 0; i < (int)[o_values count]; i++)
903 o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"];
904 o_array = [o_array arrayByAddingObject: o_dic];
907 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
909 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
913 [self setNeedsDisplay:YES];
917 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
919 [self setNeedsDisplay:YES];
922 - (void)drawRect:(NSRect)rect
924 NSImage *leftImage = [NSImage imageNamed:@"display_left"];
925 NSImage *middleImage = [NSImage imageNamed:@"display_middle"];
926 NSImage *rightImage = [NSImage imageNamed:@"display_right"];
927 [middleImage setSize:NSMakeSize(NSWidth( [self bounds] ) - 134 - [leftImage size].width - [rightImage size].width, [middleImage size].height)];
928 [middleImage setScalesWhenResized:YES];
929 [leftImage compositeToPoint:NSMakePoint( 122., 40. ) operation:NSCompositeSourceOver];
930 [middleImage compositeToPoint:NSMakePoint( 122. + [leftImage size].width, 40. ) operation:NSCompositeSourceOver];
931 [rightImage compositeToPoint:NSMakePoint( NSWidth( [self bounds] ) - 12 - [rightImage size].width, 40. ) operation:NSCompositeSourceOver];
934 - (void)mouseDown:(NSEvent *)event
936 dragStart = [self convertPoint:[event locationInWindow] fromView:nil];
939 - (void)mouseDragged:(NSEvent *)event
941 NSPoint dragLocation = [self convertPoint:[event locationInWindow] fromView:nil];
942 NSPoint winOrigin = [o_window frame].origin;
944 NSPoint newOrigin = NSMakePoint(winOrigin.x + (dragLocation.x - dragStart.x),
945 winOrigin.y + (dragLocation.y - dragStart.y));
946 [o_window setFrameOrigin: newOrigin];
951 /*****************************************************************************
953 *****************************************************************************/
956 @implementation statusbar
959 [self addSubview: o_text];
963 - (void)resignMainWindow
969 - (void)becomeMainWindow
975 - (void)drawRect:(NSRect)rect
978 [[NSColor colorWithCalibratedRed:0.820
983 [[NSColor colorWithCalibratedWhite:0.91 alpha:1.0] set];
985 /*NSRect divider = rect;
986 divider.origin.y += divider.size.height - 1;
987 divider.size.height = 1;
988 [[NSColor colorWithCalibratedWhite:0.65 alpha:1.] set];
989 NSRectFill(divider);*/