1 /*****************************************************************************
2 * embeddedwindow.m: MacOS X interface module
3 *****************************************************************************
4 * Copyright (C) 2005-2008 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 [self controlTintChanged];
82 [[NSNotificationCenter defaultCenter] addObserver: self
83 selector: @selector( controlTintChanged )
84 name: NSControlTintDidChangeNotification
87 /* Set color of sidebar to Leopard's "Sidebar Blue" */
88 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820
93 [self setMinSize:NSMakeSize([o_sidebar_list convertRect:[o_sidebar_list bounds]
94 toView: nil].size.width + 551., 114.)];
96 /* Useful to save o_view frame in fullscreen mode */
97 o_temp_view = [[NSView alloc] init];
98 [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
100 o_fullscreen_window = nil;
101 o_makekey_anim = o_fullscreen_anim1 = o_fullscreen_anim2 = nil;
103 /* Not fullscreen when we wake up */
104 [o_btn_fullscreen setState: NO];
107 [self setMovableByWindowBackground:YES];
109 [self setDelegate:self];
111 /* Make sure setVisible: returns NO */
112 [self orderOut:self];
113 b_window_is_invisible = YES;
114 videoRatio = NSMakeSize( 0., 0. );
117 - (void)controlTintChanged
120 if( [o_btn_play alternateImage] == o_img_play_pressed )
123 if( [NSColor currentControlTint] == NSGraphiteControlTint )
125 o_img_play_pressed = [NSImage imageNamed: @"play_embedded_graphite"];
126 o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_graphite"];
127 [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_embedded_graphite"]];
128 [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_embedded_graphite"]];
129 [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_graphite"]];
131 o_img_play_pressed = [NSImage imageNamed: @"play_embedded_blue"];
132 o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_blue"];
133 [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_embedded_blue"]];
134 [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_embedded_blue"]];
135 [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_blue"]];
139 [o_btn_play setAlternateImage: o_img_play_pressed];
141 [o_btn_play setAlternateImage: o_img_pause_pressed];
146 [[NSNotificationCenter defaultCenter] removeObserver: self];
147 [o_img_play release];
148 [o_img_play_pressed release];
149 [o_img_pause release];
150 [o_img_pause_pressed release];
155 - (void)setTime:(NSString *)o_arg_time position:(float)f_position
157 [o_time setStringValue: o_arg_time];
158 [o_timeslider setFloatValue: f_position];
161 - (void)playStatusUpdated:(int)i_status
163 if( i_status == PLAYING_S )
165 [o_btn_play setImage: o_img_pause];
166 [o_btn_play setAlternateImage: o_img_pause_pressed];
167 [o_btn_play setToolTip: _NS("Pause")];
171 [o_btn_play setImage: o_img_play];
172 [o_btn_play setAlternateImage: o_img_play_pressed];
173 [o_btn_play setToolTip: _NS("Play")];
177 - (void)setSeekable:(BOOL)b_seekable
179 [o_btn_forward setEnabled: b_seekable];
180 [o_btn_backward setEnabled: b_seekable];
181 [o_timeslider setEnabled: b_seekable];
184 - (void)setScrollString:(NSString *)o_string
186 [o_scrollfield setStringValue: o_string];
197 - (void)setStop:(BOOL)b_input
199 [o_btn_stop setEnabled: b_input];
202 - (void)setNext:(BOOL)b_input
204 [o_btn_next setEnabled: b_input];
207 - (void)setPrev:(BOOL)b_input
209 [o_btn_prev setEnabled: b_input];
212 - (void)setVolumeEnabled:(BOOL)b_input
214 [o_volumeslider setEnabled: b_input];
217 - (void)setVolumeSlider:(float)f_level
219 [o_volumeslider setFloatValue: f_level];
222 - (BOOL)windowShouldZoom:(NSWindow *)sender toFrame:(NSRect)newFrame
224 [self setFrame: newFrame display: YES animate: YES];
228 - (BOOL)windowShouldClose:(id)sender
230 playlist_t * p_playlist = pl_Get( VLCIntf );
231 playlist_Stop( p_playlist );
238 if (o_fullscreen_window)
244 - (void)setVideoRatio:(NSSize)ratio
249 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
251 NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1];
252 NSRect newList = [playlist_area frame];
253 if( newList.size.height < 50 && newList.size.height > 0 ) {
254 [self togglePlaylist:self];
257 /* With no video open or with the playlist open the behavior is odd */
258 if( newList.size.height > 50 )
259 return proposedFrameSize;
261 if( videoRatio.height == 0. || videoRatio.width == 0. )
262 return proposedFrameSize;
264 NSRect viewRect = [o_view convertRect:[o_view bounds] toView: nil];
265 NSRect contentRect = [self contentRectForFrameRect:[self frame]];
266 float marginy = viewRect.origin.y + [self frame].size.height - contentRect.size.height;
267 float marginx = contentRect.size.width - viewRect.size.width;
269 proposedFrameSize.height = (proposedFrameSize.width - marginx) * videoRatio.height / videoRatio.width + marginy;
271 return proposedFrameSize;
274 - (void)becomeMainWindow
276 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820
280 [o_status becomeMainWindow];
281 [super becomeMainWindow];
284 - (void)resignMainWindow
286 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedWhite:0.91 alpha:1.0]];
287 [o_status resignMainWindow];
288 [super resignMainWindow];
291 - (CGFloat)splitView:(NSSplitView *) splitView constrainSplitPosition:(CGFloat) proposedPosition ofSubviewAt:(NSInteger) index
293 if([splitView isVertical])
294 return proposedPosition;
295 else if ( splitView == o_vertical_split )
296 return proposedPosition ;
298 float bottom = [splitView frame].size.height - [splitView dividerThickness];
299 if(proposedPosition > bottom - 50) {
300 [o_btn_playlist setState: NSOffState];
301 [o_searchfield setHidden:YES];
302 [o_playlist_view setHidden:YES];
306 [o_btn_playlist setState: NSOnState];
307 [o_searchfield setHidden:NO];
308 [o_playlist_view setHidden:NO];
309 [o_playlist swapPlaylists: o_playlist_table];
310 [o_vlc_main togglePlaylist:self];
311 return proposedPosition;
316 - (void)splitViewWillResizeSubviews:(NSNotification *) notification
321 - (CGFloat)splitView:(NSSplitView *) splitView constrainMinCoordinate:(CGFloat) proposedMin ofSubviewAt:(NSInteger) offset
323 if([splitView isVertical])
329 - (CGFloat)splitView:(NSSplitView *) splitView constrainMaxCoordinate:(CGFloat) proposedMax ofSubviewAt:(NSInteger) offset
331 if([splitView isVertical])
332 return MIN([self frame].size.width - 551, 300);
334 return [splitView frame].size.height;
337 - (BOOL)splitView:(NSSplitView *) splitView canCollapseSubview:(NSView *) subview
339 if([splitView isVertical])
345 - (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect
346 ofDividerAtIndex:(NSInteger)dividerIndex
348 if([splitView isVertical]) {
349 drawnRect.origin.x -= 3;
350 drawnRect.size.width += 5;
357 - (IBAction)togglePlaylist:(id)sender
359 NSView *playback_area = [[o_vertical_split subviews] objectAtIndex:0];
360 NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1];
361 NSRect newVid = [playback_area frame];
362 NSRect newList = [playlist_area frame];
363 if(newList.size.height < 50 && sender != self && sender != o_vlc_main) {
364 newList.size.height = newVid.size.height/2;
365 newVid.size.height = newVid.size.height/2;
366 newVid.origin.y = newVid.origin.y + newList.size.height;
367 [o_btn_playlist setState: NSOnState];
368 [o_searchfield setHidden:NO];
369 [o_playlist_view setHidden:NO];
370 [o_playlist swapPlaylists: o_playlist_table];
371 [o_vlc_main togglePlaylist:self];
374 newVid.size.height = newVid.size.height + newList.size.height;
375 newList.size.height = 0;
377 [o_btn_playlist setState: NSOffState];
378 [o_searchfield setHidden:YES];
379 [o_playlist_view setHidden:YES];
381 [playback_area setFrame: newVid];
382 [playlist_area setFrame: newList];
385 /*****************************************************************************
394 - (void)lockFullscreenAnimation
396 [o_animation_lock lock];
399 - (void)unlockFullscreenAnimation
401 [o_animation_lock unlock];
404 - (void)enterFullscreen
406 NSMutableDictionary *dict1, *dict2;
410 vout_thread_t *p_vout = getVout();
411 BOOL blackout_other_displays = config_GetInt( VLCIntf, "macosx-black" );
413 screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_GetInteger( p_vout, "video-device" )];
415 [self lockFullscreenAnimation];
419 msg_Dbg( p_vout, "chosen screen isn't present, using current screen for fullscreen mode" );
420 screen = [self screen];
424 msg_Dbg( p_vout, "Using deepest screen" );
425 screen = [NSScreen deepestScreen];
428 vlc_object_release( p_vout );
430 screen_rect = [screen frame];
432 [o_btn_fullscreen setState: YES];
434 [NSCursor setHiddenUntilMouseMoves: YES];
436 if( blackout_other_displays )
437 [screen blackoutOtherScreens];
439 /* Make sure we don't see the window flashes in float-on-top mode */
440 originalLevel = [self level];
441 [self setLevel:NSNormalWindowLevel];
443 /* Only create the o_fullscreen_window if we are not in the middle of the zooming animation */
444 if (!o_fullscreen_window)
446 /* We can't change the styleMask of an already created NSWindow, so we create an other window, and do eye catching stuff */
448 rect = [[o_view superview] convertRect: [o_view frame] toView: nil]; /* Convert to Window base coord */
449 rect.origin.x += [self frame].origin.x;
450 rect.origin.y += [self frame].origin.y;
451 o_fullscreen_window = [[VLCWindow alloc] initWithContentRect:rect styleMask: NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
452 [o_fullscreen_window setBackgroundColor: [NSColor blackColor]];
453 [o_fullscreen_window setCanBecomeKeyWindow: YES];
455 if (![self isVisible] || [self alphaValue] == 0.0)
457 /* We don't animate if we are not visible, instead we
458 * simply fade the display */
459 CGDisplayFadeReservationToken token;
461 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
462 CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES );
464 if ([screen isMainScreen])
465 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
467 [[o_view superview] replaceSubview:o_view with:o_temp_view];
468 [o_temp_view setFrame:[o_view frame]];
469 [o_fullscreen_window setContentView:o_view];
471 [o_fullscreen_window makeKeyAndOrderFront:self];
472 [o_fullscreen_window orderFront:self animate:YES];
474 [o_fullscreen_window setFrame:screen_rect display:YES];
476 CGDisplayFade( token, 0.3, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO );
477 CGReleaseDisplayFadeReservation( token);
479 /* Will release the lock */
480 [self hasBecomeFullscreen];
485 /* Make sure we don't see the o_view disappearing of the screen during this operation */
486 NSDisableScreenUpdates();
487 [[o_view superview] replaceSubview:o_view with:o_temp_view];
488 [o_temp_view setFrame:[o_view frame]];
489 [o_fullscreen_window setContentView:o_view];
490 [o_fullscreen_window makeKeyAndOrderFront:self];
491 NSEnableScreenUpdates();
494 /* We are in fullscreen (and no animation is running) */
497 /* Make sure we are hidden */
498 [super orderOut: self];
499 [self unlockFullscreenAnimation];
503 if (o_fullscreen_anim1)
505 [o_fullscreen_anim1 stopAnimation];
506 [o_fullscreen_anim1 release];
508 if (o_fullscreen_anim2)
510 [o_fullscreen_anim2 stopAnimation];
511 [o_fullscreen_anim2 release];
514 if ([screen isMainScreen])
515 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
517 dict1 = [[NSMutableDictionary alloc] initWithCapacity:2];
518 dict2 = [[NSMutableDictionary alloc] initWithCapacity:3];
520 [dict1 setObject:self forKey:NSViewAnimationTargetKey];
521 [dict1 setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
523 [dict2 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
524 [dict2 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
525 [dict2 setObject:[NSValue valueWithRect:screen_rect] forKey:NSViewAnimationEndFrameKey];
527 /* Strategy with NSAnimation allocation:
528 - Keep at most 2 animation at a time
529 - leaveFullscreen/enterFullscreen are the only responsible for releasing and alloc-ing
531 o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict1]];
532 o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict2]];
537 [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
538 [o_fullscreen_anim1 setDuration: 0.3];
539 [o_fullscreen_anim1 setFrameRate: 30];
540 [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
541 [o_fullscreen_anim2 setDuration: 0.2];
542 [o_fullscreen_anim2 setFrameRate: 30];
544 [o_fullscreen_anim2 setDelegate: self];
545 [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
547 [o_fullscreen_anim1 startAnimation];
548 /* fullscreenAnimation will be unlocked when animation ends */
551 - (void)hasBecomeFullscreen
553 [o_fullscreen_window makeFirstResponder: [[[VLCMain sharedInstance] controls] voutView]];
555 [o_fullscreen_window makeKeyWindow];
556 [o_fullscreen_window setAcceptsMouseMovedEvents: TRUE];
558 /* tell the fspanel to move itself to front next time it's triggered */
559 [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: (int)[[o_fullscreen_window screen] displayID]];
562 [super orderOut: self];
564 [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil];
567 [self unlockFullscreenAnimation];
570 - (void)leaveFullscreen
572 [self leaveFullscreenAndFadeOut: NO];
575 - (void)leaveFullscreenAndFadeOut: (BOOL)fadeout
577 NSMutableDictionary *dict1, *dict2;
580 [self lockFullscreenAnimation];
583 [o_btn_fullscreen setState: NO];
585 /* We always try to do so */
586 [NSScreen unblackoutScreens];
588 /* Don't do anything if o_fullscreen_window is already closed */
589 if (!o_fullscreen_window)
591 [self unlockFullscreenAnimation];
597 /* We don't animate if we are not visible, instead we
598 * simply fade the display */
599 CGDisplayFadeReservationToken token;
601 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
602 CGDisplayFade( token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES );
604 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
605 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
607 /* Will release the lock */
608 [self hasEndedFullscreen];
610 /* Our window is hidden, and might be faded. We need to workaround that, so note it
612 b_window_is_invisible = YES;
614 CGDisplayFade( token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO );
615 CGReleaseDisplayFadeReservation( token);
619 [self setAlphaValue: 0.0];
620 [self orderFront: self];
622 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
623 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
625 if (o_fullscreen_anim1)
627 [o_fullscreen_anim1 stopAnimation];
628 [o_fullscreen_anim1 release];
630 if (o_fullscreen_anim2)
632 [o_fullscreen_anim2 stopAnimation];
633 [o_fullscreen_anim2 release];
636 frame = [[o_temp_view superview] convertRect: [o_temp_view frame] toView: nil]; /* Convert to Window base coord */
637 frame.origin.x += [self frame].origin.x;
638 frame.origin.y += [self frame].origin.y;
640 dict2 = [[NSMutableDictionary alloc] initWithCapacity:2];
641 [dict2 setObject:self forKey:NSViewAnimationTargetKey];
642 [dict2 setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
644 o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict2, nil]];
647 [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
648 [o_fullscreen_anim2 setDuration: 0.3];
649 [o_fullscreen_anim2 setFrameRate: 30];
651 [o_fullscreen_anim2 setDelegate: self];
653 dict1 = [[NSMutableDictionary alloc] initWithCapacity:3];
655 [dict1 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
656 [dict1 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
657 [dict1 setObject:[NSValue valueWithRect:frame] forKey:NSViewAnimationEndFrameKey];
659 o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict1, nil]];
662 [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
663 [o_fullscreen_anim1 setDuration: 0.2];
664 [o_fullscreen_anim1 setFrameRate: 30];
665 [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
667 /* Make sure o_fullscreen_window is the frontmost window */
668 [o_fullscreen_window orderFront: self];
670 [o_fullscreen_anim1 startAnimation];
671 /* fullscreenAnimation will be unlocked when animation ends */
674 - (void)hasEndedFullscreen
676 /* This function is private and should be only triggered at the end of the fullscreen change animation */
677 /* Make sure we don't see the o_view disappearing of the screen during this operation */
678 NSDisableScreenUpdates();
680 [o_view removeFromSuperviewWithoutNeedingDisplay];
681 [[o_temp_view superview] replaceSubview:o_temp_view with:o_view];
683 [o_view setFrame:[o_temp_view frame]];
684 [self makeFirstResponder: o_view];
685 if ([self isVisible])
686 [super makeKeyAndOrderFront:self]; /* our version contains a workaround */
687 [o_fullscreen_window orderOut: self];
688 NSEnableScreenUpdates();
690 [o_fullscreen_window release];
691 o_fullscreen_window = nil;
692 [self setLevel:originalLevel];
694 [self unlockFullscreenAnimation];
697 - (void)animationDidEnd:(NSAnimation*)animation
699 NSArray *viewAnimations;
700 if( o_makekey_anim == animation )
702 [o_makekey_anim release];
705 if ([animation currentValue] < 1.0)
708 /* Fullscreen ended or started (we are a delegate only for leaveFullscreen's/enterFullscren's anim2) */
709 viewAnimations = [o_fullscreen_anim2 viewAnimations];
710 if ([viewAnimations count] >=1 &&
711 [[[viewAnimations objectAtIndex: 0] objectForKey: NSViewAnimationEffectKey] isEqualToString:NSViewAnimationFadeInEffect])
713 /* Fullscreen ended */
714 [self hasEndedFullscreen];
718 /* Fullscreen started */
719 [self hasBecomeFullscreen];
723 - (void)orderOut: (id)sender
725 [super orderOut: sender];
727 /* Make sure we leave fullscreen */
728 [self leaveFullscreenAndFadeOut: YES];
731 - (void)makeKeyAndOrderFront: (id)sender
734 * when we exit fullscreen and fade out, we may endup in
735 * having a window that is faded. We can't have it fade in unless we
738 if(!b_window_is_invisible)
740 /* Make sure we don't do it too much */
741 [super makeKeyAndOrderFront: sender];
745 [super setAlphaValue:0.0f];
746 [super makeKeyAndOrderFront: sender];
748 NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithCapacity:2];
749 [dict setObject:self forKey:NSViewAnimationTargetKey];
750 [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
752 o_makekey_anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
755 [o_makekey_anim setAnimationBlockingMode: NSAnimationNonblocking];
756 [o_makekey_anim setDuration: 0.1];
757 [o_makekey_anim setFrameRate: 30];
758 [o_makekey_anim setDelegate: self];
760 [o_makekey_anim startAnimation];
761 b_window_is_invisible = NO;
763 /* fullscreenAnimation will be unlocked when animation ends */
768 /* Make sure setFrame gets executed on main thread especially if we are animating.
769 * (Thus we won't block the video output thread) */
770 - (void)setFrame:(NSRect)frame display:(BOOL)display animate:(BOOL)animate
772 struct { NSRect frame; BOOL display; BOOL animate;} args;
776 args.display = display;
777 args.animate = animate;
779 packedargs = [NSData dataWithBytes:&args length:sizeof(args)];
781 [self performSelectorOnMainThread:@selector(setFrameOnMainThread:)
782 withObject: packedargs waitUntilDone: YES];
785 - (void)setFrameOnMainThread:(NSData*)packedargs
787 struct args { NSRect frame; BOOL display; BOOL animate; } * args = (struct args*)[packedargs bytes];
791 /* Make sure we don't block too long and set up a non blocking animation */
792 NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:
793 self, NSViewAnimationTargetKey,
794 [NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey,
795 [NSValue valueWithRect:args->frame], NSViewAnimationEndFrameKey, nil];
797 NSViewAnimation * anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
800 [anim setAnimationBlockingMode: NSAnimationNonblocking];
801 [anim setDuration: 0.4];
802 [anim setFrameRate: 30];
803 [anim startAnimation];
806 [super setFrame:args->frame display:args->display animate:args->animate];
812 /*****************************************************************************
814 *****************************************************************************/
817 @implementation embeddedbackground
821 [self unregisterDraggedTypes];
827 [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType,
828 NSFilenamesPboardType, nil]];
829 [self addSubview: o_timeslider];
830 [self addSubview: o_scrollfield];
831 [self addSubview: o_time];
832 [self addSubview: o_main_pgbar];
833 [self addSubview: o_btn_backward];
834 [self addSubview: o_btn_forward];
835 [self addSubview: o_btn_fullscreen];
836 [self addSubview: o_btn_equalizer];
837 [self addSubview: o_btn_playlist];
838 [self addSubview: o_btn_play];
839 [self addSubview: o_btn_prev];
840 [self addSubview: o_btn_stop];
841 [self addSubview: o_btn_next];
842 [self addSubview: o_btn_volume_down];
843 [self addSubview: o_volumeslider];
844 [self addSubview: o_btn_volume_up];
845 [self addSubview: o_searchfield];
848 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
850 if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
851 == NSDragOperationGeneric)
853 return NSDragOperationGeneric;
857 return NSDragOperationNone;
861 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
866 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
868 NSPasteboard *o_paste = [sender draggingPasteboard];
869 NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
870 NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
871 NSData *o_carried_data = [o_paste dataForType:o_desired_type];
872 BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
876 if ([o_desired_type isEqualToString:NSFilenamesPboardType])
879 NSArray *o_array = [NSArray array];
880 NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType]
881 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
883 for( i = 0; i < (int)[o_values count]; i++)
886 o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"];
887 o_array = [o_array arrayByAddingObject: o_dic];
890 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
892 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
896 [self setNeedsDisplay:YES];
900 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
902 [self setNeedsDisplay:YES];
905 - (void)drawRect:(NSRect)rect
907 NSImage *leftImage = [NSImage imageNamed:@"display_left"];
908 NSImage *middleImage = [NSImage imageNamed:@"display_middle"];
909 NSImage *rightImage = [NSImage imageNamed:@"display_right"];
910 [middleImage setSize:NSMakeSize(NSWidth( [self bounds] ) - 134 - [leftImage size].width - [rightImage size].width, [middleImage size].height)];
911 [middleImage setScalesWhenResized:YES];
912 [leftImage compositeToPoint:NSMakePoint( 122., 40. ) operation:NSCompositeSourceOver];
913 [middleImage compositeToPoint:NSMakePoint( 122. + [leftImage size].width, 40. ) operation:NSCompositeSourceOver];
914 [rightImage compositeToPoint:NSMakePoint( NSWidth( [self bounds] ) - 12 - [rightImage size].width, 40. ) operation:NSCompositeSourceOver];
917 - (void)mouseDown:(NSEvent *)event
919 dragStart = [self convertPoint:[event locationInWindow] fromView:nil];
922 - (void)mouseDragged:(NSEvent *)event
924 NSPoint dragLocation = [self convertPoint:[event locationInWindow] fromView:nil];
925 NSPoint winOrigin = [o_window frame].origin;
927 NSPoint newOrigin = NSMakePoint(winOrigin.x + (dragLocation.x - dragStart.x),
928 winOrigin.y + (dragLocation.y - dragStart.y));
929 [o_window setFrameOrigin: newOrigin];
934 /*****************************************************************************
936 *****************************************************************************/
939 @implementation statusbar
942 [self addSubview: o_text];
946 - (void)resignMainWindow
952 - (void)becomeMainWindow
958 - (void)drawRect:(NSRect)rect
961 [[NSColor colorWithCalibratedRed:0.820
966 [[NSColor colorWithCalibratedWhite:0.91 alpha:1.0] set];
968 /*NSRect divider = rect;
969 divider.origin.y += divider.size.height - 1;
970 divider.size.height = 1;
971 [[NSColor colorWithCalibratedWhite:0.65 alpha:1.] set];
972 NSRectFill(divider);*/