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 * extension to NSWindow's interface to fix compilation warnings
41 * and let us access this functions properly
42 * this uses a private Apple-API, but works fine on all current OSX releases
43 * keep checking for compatiblity with future releases though
44 *****************************************************************************/
46 @interface NSWindow (UndocumentedWindowProperties)
47 - (void)setBottomCornerRounded: (BOOL)value;
50 /*****************************************************************************
51 * VLCEmbeddedWindow Implementation
52 *****************************************************************************/
54 @implementation VLCEmbeddedWindow
58 [self setDelegate: self];
59 [self setBottomCornerRounded:NO];
62 [o_btn_backward setToolTip: _NS("Rewind")];
63 [o_btn_forward setToolTip: _NS("Fast Forward")];
64 [o_btn_fullscreen setToolTip: _NS("Fullscreen")];
65 [o_btn_play setToolTip: _NS("Play")];
66 [o_timeslider setToolTip: _NS("Position")];
67 [o_btn_prev setToolTip: _NS("Previous")];
68 [o_btn_stop setToolTip: _NS("Stop")];
69 [o_btn_next setToolTip: _NS("Next")];
70 [o_volumeslider setToolTip: _NS("Volume")];
71 [o_btn_playlist setToolTip: _NS("Playlist")];
72 [self setTitle: _NS("VLC media player")];
74 o_img_play = [NSImage imageNamed: @"play_embedded"];
75 o_img_pause = [NSImage imageNamed: @"pause_embedded"];
77 [self controlTintChanged];
78 [[NSNotificationCenter defaultCenter] addObserver: self
79 selector: @selector( controlTintChanged )
80 name: NSControlTintDidChangeNotification
83 /* Set color of sidebar to Leopard's "Sidebar Blue" */
84 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820
89 [self setMinSize:NSMakeSize([o_sidebar_list convertRect:[o_sidebar_list bounds]
90 toView: nil].size.width + 551., 114.)];
92 /* Useful to save o_view frame in fullscreen mode */
93 o_temp_view = [[NSView alloc] init];
94 [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
96 o_fullscreen_window = nil;
97 o_makekey_anim = o_fullscreen_anim1 = o_fullscreen_anim2 = nil;
99 /* Not fullscreen when we wake up */
100 [o_btn_fullscreen setState: NO];
103 /* Make sure setVisible: returns NO */
104 [self orderOut:self];
105 //b_window_is_invisible = YES;
106 videoRatio = NSMakeSize( 0., 0. );
109 - (void)controlTintChanged
112 if( [o_btn_play alternateImage] == o_img_play_pressed )
115 if( [NSColor currentControlTint] == NSGraphiteControlTint ) {
116 o_img_play_pressed = [NSImage imageNamed: @"play_embedded_graphite"];
117 o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_graphite"];
119 o_img_play_pressed = [NSImage imageNamed:@"play_embedded_blue"];
120 o_img_pause_pressed = [NSImage imageNamed:@"pause_embedded_blue"];
124 [o_btn_play setAlternateImage: o_img_play_pressed];
126 [o_btn_play setAlternateImage: o_img_pause_pressed];
131 [[NSNotificationCenter defaultCenter] removeObserver: self];
132 [o_img_play release];
133 [o_img_play_pressed release];
134 [o_img_pause release];
135 [o_img_pause_pressed release];
140 - (void)setTime:(NSString *)o_arg_time position:(float)f_position
142 [o_time setStringValue: o_arg_time];
143 [o_timeslider setFloatValue: f_position];
146 - (void)playStatusUpdated:(int)i_status
148 if( i_status == PLAYING_S )
150 [o_btn_play setImage: o_img_pause];
151 [o_btn_play setAlternateImage: o_img_pause_pressed];
152 [o_btn_play setToolTip: _NS("Pause")];
156 [o_btn_play setImage: o_img_play];
157 [o_btn_play setAlternateImage: o_img_play_pressed];
158 [o_btn_play setToolTip: _NS("Play")];
162 - (void)setSeekable:(BOOL)b_seekable
164 [o_btn_forward setEnabled: b_seekable];
165 [o_btn_backward setEnabled: b_seekable];
166 [o_timeslider setEnabled: b_seekable];
169 - (void)setScrollString:(NSString *)o_string
171 [o_scrollfield setStringValue: o_string];
182 - (void)setStop:(BOOL)b_input
184 [o_btn_stop setEnabled: b_input];
187 - (void)setNext:(BOOL)b_input
189 [o_btn_next setEnabled: b_input];
192 - (void)setPrev:(BOOL)b_input
194 [o_btn_prev setEnabled: b_input];
197 - (void)setVolumeEnabled:(BOOL)b_input
199 [o_volumeslider setEnabled: b_input];
202 - (void)setVolumeSlider:(float)f_level
204 [o_volumeslider setFloatValue: f_level];
207 - (BOOL)windowShouldZoom:(NSWindow *)sender toFrame:(NSRect)newFrame
209 [self setFrame: newFrame display: YES animate: YES];
213 - (BOOL)windowShouldClose:(id)sender
215 playlist_t * p_playlist = pl_Get( VLCIntf );
217 /* Only want to stop playback if video is playing */
218 if( videoRatio.height != 0. && videoRatio.width != 0. )
219 playlist_Stop( p_playlist );
225 if (o_fullscreen_window)
231 - (void)setVideoRatio:(NSSize)ratio
236 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
238 NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1];
239 NSRect newList = [playlist_area frame];
240 if( newList.size.height < 50 && newList.size.height > 0 ) {
241 [self togglePlaylist:self];
244 /* With no video open or with the playlist open the behavior is odd */
245 if( newList.size.height > 50 )
246 return proposedFrameSize;
248 if( videoRatio.height == 0. || videoRatio.width == 0. )
249 return proposedFrameSize;
251 NSRect viewRect = [o_view convertRect:[o_view bounds] toView: nil];
252 NSRect contentRect = [self contentRectForFrameRect:[self frame]];
253 float marginy = viewRect.origin.y + [self frame].size.height - contentRect.size.height;
254 float marginx = contentRect.size.width - viewRect.size.width;
256 proposedFrameSize.height = (proposedFrameSize.width - marginx) * videoRatio.height / videoRatio.width + marginy;
258 return proposedFrameSize;
261 - (void)becomeMainWindow
263 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820
267 [o_status becomeMainWindow];
268 [super becomeMainWindow];
271 - (void)resignMainWindow
273 [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedWhite:0.91 alpha:1.0]];
274 [o_status resignMainWindow];
275 [super resignMainWindow];
278 - (CGFloat)splitView:(NSSplitView *) splitView constrainSplitPosition:(CGFloat) proposedPosition ofSubviewAt:(NSInteger) index
280 if([splitView isVertical])
281 return proposedPosition;
282 else if ( splitView == o_vertical_split )
283 return proposedPosition ;
285 float bottom = [splitView frame].size.height - [splitView dividerThickness];
286 if(proposedPosition > bottom - 50) {
287 [o_btn_playlist setState: NSOffState];
288 [o_searchfield setHidden:YES];
289 [o_playlist_view setHidden:YES];
293 [o_btn_playlist setState: NSOnState];
294 [o_searchfield setHidden:NO];
295 [o_playlist_view setHidden:NO];
296 [o_playlist swapPlaylists: o_playlist_table];
297 [o_vlc_main togglePlaylist:self];
298 return proposedPosition;
303 - (void)splitViewWillResizeSubviews:(NSNotification *) notification
308 - (CGFloat)splitView:(NSSplitView *) splitView constrainMinCoordinate:(CGFloat) proposedMin ofSubviewAt:(NSInteger) offset
310 if([splitView isVertical])
316 - (CGFloat)splitView:(NSSplitView *) splitView constrainMaxCoordinate:(CGFloat) proposedMax ofSubviewAt:(NSInteger) offset
318 if([splitView isVertical])
319 return MIN([self frame].size.width - 551, 300);
321 return [splitView frame].size.height;
324 - (BOOL)splitView:(NSSplitView *) splitView canCollapseSubview:(NSView *) subview
326 if([splitView isVertical])
332 - (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect
333 ofDividerAtIndex:(NSInteger)dividerIndex
335 if([splitView isVertical]) {
336 drawnRect.origin.x -= 3;
337 drawnRect.size.width += 5;
344 - (IBAction)togglePlaylist:(id)sender
346 NSView *playback_area = [[o_vertical_split subviews] objectAtIndex:0];
347 NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1];
348 NSRect newVid = [playback_area frame];
349 NSRect newList = [playlist_area frame];
350 if(newList.size.height < 50 && sender != self && sender != o_vlc_main) {
351 newList.size.height = newVid.size.height/2;
352 newVid.size.height = newVid.size.height/2;
353 newVid.origin.y = newVid.origin.y + newList.size.height;
354 [o_btn_playlist setState: NSOnState];
355 [o_searchfield setHidden:NO];
356 [o_playlist_view setHidden:NO];
357 [o_playlist swapPlaylists: o_playlist_table];
358 [o_vlc_main togglePlaylist:self];
361 newVid.size.height = newVid.size.height + newList.size.height;
362 newList.size.height = 0;
364 [o_btn_playlist setState: NSOffState];
365 [o_searchfield setHidden:YES];
366 [o_playlist_view setHidden:YES];
368 [playback_area setFrame: newVid];
369 [playlist_area setFrame: newList];
372 /*****************************************************************************
381 - (void)lockFullscreenAnimation
383 [o_animation_lock lock];
386 - (void)unlockFullscreenAnimation
388 [o_animation_lock unlock];
391 - (void)enterFullscreen
393 NSMutableDictionary *dict1, *dict2;
397 vout_thread_t *p_vout = getVout();
398 BOOL blackout_other_displays = config_GetInt( VLCIntf, "macosx-black" );
400 screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_GetInteger( p_vout, "video-device" )];
402 [self lockFullscreenAnimation];
406 msg_Dbg( p_vout, "chosen screen isn't present, using current screen for fullscreen mode" );
407 screen = [self screen];
411 msg_Dbg( p_vout, "Using deepest screen" );
412 screen = [NSScreen deepestScreen];
415 vlc_object_release( p_vout );
417 screen_rect = [screen frame];
419 [o_btn_fullscreen setState: YES];
421 [NSCursor setHiddenUntilMouseMoves: YES];
423 if( blackout_other_displays )
424 [screen blackoutOtherScreens];
426 /* Make sure we don't see the window flashes in float-on-top mode */
427 originalLevel = [self level];
428 [self setLevel:NSNormalWindowLevel];
430 /* Only create the o_fullscreen_window if we are not in the middle of the zooming animation */
431 if (!o_fullscreen_window)
433 /* We can't change the styleMask of an already created NSWindow, so we create an other window, and do eye catching stuff */
435 rect = [[o_view superview] convertRect: [o_view frame] toView: nil]; /* Convert to Window base coord */
436 rect.origin.x += [self frame].origin.x;
437 rect.origin.y += [self frame].origin.y;
438 o_fullscreen_window = [[VLCWindow alloc] initWithContentRect:rect styleMask: NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
439 [o_fullscreen_window setBackgroundColor: [NSColor blackColor]];
440 [o_fullscreen_window setCanBecomeKeyWindow: YES];
442 if (![self isVisible] || [self alphaValue] == 0.0)
444 /* We don't animate if we are not visible, instead we
445 * simply fade the display */
446 CGDisplayFadeReservationToken token;
448 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
449 CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES );
451 if ([screen isMainScreen])
452 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
454 [[o_view superview] replaceSubview:o_view with:o_temp_view];
455 [o_temp_view setFrame:[o_view frame]];
456 [o_fullscreen_window setContentView:o_view];
458 [o_fullscreen_window makeKeyAndOrderFront:self];
460 [o_fullscreen_window makeKeyAndOrderFront:self];
461 [o_fullscreen_window orderFront:self animate:YES];
463 [o_fullscreen_window setFrame:screen_rect display:YES];
465 CGDisplayFade( token, 0.3, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO );
466 CGReleaseDisplayFadeReservation( token);
468 /* Will release the lock */
469 [self hasBecomeFullscreen];
474 /* Make sure we don't see the o_view disappearing of the screen during this operation */
475 NSDisableScreenUpdates();
476 [[o_view superview] replaceSubview:o_view with:o_temp_view];
477 [o_temp_view setFrame:[o_view frame]];
478 [o_fullscreen_window setContentView:o_view];
479 [o_fullscreen_window makeKeyAndOrderFront:self];
480 NSEnableScreenUpdates();
483 /* We are in fullscreen (and no animation is running) */
486 /* Make sure we are hidden */
487 [super orderOut: self];
488 [self unlockFullscreenAnimation];
492 if (o_fullscreen_anim1)
494 [o_fullscreen_anim1 stopAnimation];
495 [o_fullscreen_anim1 release];
497 if (o_fullscreen_anim2)
499 [o_fullscreen_anim2 stopAnimation];
500 [o_fullscreen_anim2 release];
503 if ([screen isMainScreen])
504 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
506 dict1 = [[NSMutableDictionary alloc] initWithCapacity:2];
507 dict2 = [[NSMutableDictionary alloc] initWithCapacity:3];
509 [dict1 setObject:self forKey:NSViewAnimationTargetKey];
510 [dict1 setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
512 [dict2 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
513 [dict2 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
514 [dict2 setObject:[NSValue valueWithRect:screen_rect] forKey:NSViewAnimationEndFrameKey];
516 /* Strategy with NSAnimation allocation:
517 - Keep at most 2 animation at a time
518 - leaveFullscreen/enterFullscreen are the only responsible for releasing and alloc-ing
520 o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict1]];
521 o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict2]];
526 [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
527 [o_fullscreen_anim1 setDuration: 0.3];
528 [o_fullscreen_anim1 setFrameRate: 30];
529 [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
530 [o_fullscreen_anim2 setDuration: 0.2];
531 [o_fullscreen_anim2 setFrameRate: 30];
533 [o_fullscreen_anim2 setDelegate: self];
534 [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
536 [o_fullscreen_anim1 startAnimation];
537 /* fullscreenAnimation will be unlocked when animation ends */
540 - (void)hasBecomeFullscreen
542 [o_fullscreen_window makeFirstResponder: [[[VLCMain sharedInstance] controls] voutView]];
544 [o_fullscreen_window makeKeyWindow];
545 [o_fullscreen_window setAcceptsMouseMovedEvents: TRUE];
547 /* tell the fspanel to move itself to front next time it's triggered */
548 [[[[VLCMain sharedInstance] controls] fspanel] setVoutWasUpdated: (int)[[o_fullscreen_window screen] displayID]];
551 [super orderOut: self];
553 [[[[VLCMain sharedInstance] controls] fspanel] setActive: nil];
556 [self unlockFullscreenAnimation];
559 - (void)leaveFullscreen
561 [self leaveFullscreenAndFadeOut: NO];
564 - (void)leaveFullscreenAndFadeOut: (BOOL)fadeout
566 NSMutableDictionary *dict1, *dict2;
569 [self lockFullscreenAnimation];
572 [o_btn_fullscreen setState: NO];
574 /* We always try to do so */
575 [NSScreen unblackoutScreens];
577 /* Don't do anything if o_fullscreen_window is already closed */
578 if (!o_fullscreen_window)
580 [self unlockFullscreenAnimation];
586 /* We don't animate if we are not visible, instead we
587 * simply fade the display */
588 CGDisplayFadeReservationToken token;
590 CGAcquireDisplayFadeReservation(kCGMaxDisplayReservationInterval, &token);
591 CGDisplayFade( token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES );
593 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
594 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
596 /* Will release the lock */
597 [self hasEndedFullscreen];
599 /* Our window is hidden, and might be faded. We need to workaround that, so note it
601 b_window_is_invisible = YES;
603 CGDisplayFade( token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO );
604 CGReleaseDisplayFadeReservation( token);
608 [self setAlphaValue: 0.0];
609 [self orderFront: self];
611 [[[[VLCMain sharedInstance] controls] fspanel] setNonActive: nil];
612 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
614 if (o_fullscreen_anim1)
616 [o_fullscreen_anim1 stopAnimation];
617 [o_fullscreen_anim1 release];
619 if (o_fullscreen_anim2)
621 [o_fullscreen_anim2 stopAnimation];
622 [o_fullscreen_anim2 release];
625 frame = [[o_temp_view superview] convertRect: [o_temp_view frame] toView: nil]; /* Convert to Window base coord */
626 frame.origin.x += [self frame].origin.x;
627 frame.origin.y += [self frame].origin.y;
629 dict2 = [[NSMutableDictionary alloc] initWithCapacity:2];
630 [dict2 setObject:self forKey:NSViewAnimationTargetKey];
631 [dict2 setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
633 o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict2, nil]];
636 [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
637 [o_fullscreen_anim2 setDuration: 0.3];
638 [o_fullscreen_anim2 setFrameRate: 30];
640 [o_fullscreen_anim2 setDelegate: self];
642 dict1 = [[NSMutableDictionary alloc] initWithCapacity:3];
644 [dict1 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
645 [dict1 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
646 [dict1 setObject:[NSValue valueWithRect:frame] forKey:NSViewAnimationEndFrameKey];
648 o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict1, nil]];
651 [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
652 [o_fullscreen_anim1 setDuration: 0.2];
653 [o_fullscreen_anim1 setFrameRate: 30];
654 [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
656 /* Make sure o_fullscreen_window is the frontmost window */
657 [o_fullscreen_window orderFront: self];
659 [o_fullscreen_anim1 startAnimation];
660 /* fullscreenAnimation will be unlocked when animation ends */
663 - (void)hasEndedFullscreen
665 /* This function is private and should be only triggered at the end of the fullscreen change animation */
666 /* Make sure we don't see the o_view disappearing of the screen during this operation */
667 NSDisableScreenUpdates();
669 [o_view removeFromSuperviewWithoutNeedingDisplay];
670 [[o_temp_view superview] replaceSubview:o_temp_view with:o_view];
672 [o_view setFrame:[o_temp_view frame]];
673 [self makeFirstResponder: o_view];
674 if ([self isVisible])
675 [super makeKeyAndOrderFront:self]; /* our version contains a workaround */
676 [o_fullscreen_window orderOut: self];
677 NSEnableScreenUpdates();
679 [o_fullscreen_window release];
680 o_fullscreen_window = nil;
681 [self setLevel:originalLevel];
683 [self unlockFullscreenAnimation];
686 - (void)animationDidEnd:(NSAnimation*)animation
688 NSArray *viewAnimations;
689 if( o_makekey_anim == animation )
691 [o_makekey_anim release];
694 if ([animation currentValue] < 1.0)
697 /* Fullscreen ended or started (we are a delegate only for leaveFullscreen's/enterFullscren's anim2) */
698 viewAnimations = [o_fullscreen_anim2 viewAnimations];
699 if ([viewAnimations count] >=1 &&
700 [[[viewAnimations objectAtIndex: 0] objectForKey: NSViewAnimationEffectKey] isEqualToString:NSViewAnimationFadeInEffect])
702 /* Fullscreen ended */
703 [self hasEndedFullscreen];
707 /* Fullscreen started */
708 [self hasBecomeFullscreen];
712 - (void)orderOut: (id)sender
714 [super orderOut: sender];
716 /* Make sure we leave fullscreen */
717 [self leaveFullscreenAndFadeOut: YES];
720 - (void)makeKeyAndOrderFront: (id)sender
723 * when we exit fullscreen and fade out, we may endup in
724 * having a window that is faded. We can't have it fade in unless we
727 if(!b_window_is_invisible)
729 /* Make sure we don't do it too much */
730 [super makeKeyAndOrderFront: sender];
734 [super setAlphaValue:0.0f];
735 [super makeKeyAndOrderFront: sender];
737 NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithCapacity:2];
738 [dict setObject:self forKey:NSViewAnimationTargetKey];
739 [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
741 o_makekey_anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
744 [o_makekey_anim setAnimationBlockingMode: NSAnimationNonblocking];
745 [o_makekey_anim setDuration: 0.1];
746 [o_makekey_anim setFrameRate: 30];
747 [o_makekey_anim setDelegate: self];
749 [o_makekey_anim startAnimation];
750 b_window_is_invisible = NO;
752 /* fullscreenAnimation will be unlocked when animation ends */
757 /* Make sure setFrame gets executed on main thread especially if we are animating.
758 * (Thus we won't block the video output thread) */
759 - (void)setFrame:(NSRect)frame display:(BOOL)display animate:(BOOL)animate
761 struct { NSRect frame; BOOL display; BOOL animate;} args;
765 args.display = display;
766 args.animate = animate;
768 packedargs = [NSData dataWithBytes:&args length:sizeof(args)];
770 [self performSelectorOnMainThread:@selector(setFrameOnMainThread:)
771 withObject: packedargs waitUntilDone: YES];
774 - (void)setFrameOnMainThread:(NSData*)packedargs
776 struct args { NSRect frame; BOOL display; BOOL animate; } * args = (struct args*)[packedargs bytes];
780 /* Make sure we don't block too long and set up a non blocking animation */
781 NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:
782 self, NSViewAnimationTargetKey,
783 [NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey,
784 [NSValue valueWithRect:args->frame], NSViewAnimationEndFrameKey, nil];
786 NSViewAnimation * anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
789 [anim setAnimationBlockingMode: NSAnimationNonblocking];
790 [anim setDuration: 0.4];
791 [anim setFrameRate: 30];
792 [anim startAnimation];
795 [super setFrame:args->frame display:args->display animate:args->animate];
801 /*****************************************************************************
803 *****************************************************************************/
806 @implementation embeddedbackground
810 [self unregisterDraggedTypes];
816 [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType,
817 NSFilenamesPboardType, nil]];
818 [self addSubview: o_timeslider];
819 [self addSubview: o_scrollfield];
820 [self addSubview: o_time];
821 [self addSubview: o_main_pgbar];
822 [self addSubview: o_btn_backward];
823 [self addSubview: o_btn_forward];
824 [self addSubview: o_btn_fullscreen];
825 [self addSubview: o_btn_equalizer];
826 [self addSubview: o_btn_playlist];
827 [self addSubview: o_btn_play];
828 [self addSubview: o_btn_prev];
829 [self addSubview: o_btn_stop];
830 [self addSubview: o_btn_next];
831 [self addSubview: o_btn_volume_down];
832 [self addSubview: o_volumeslider];
833 [self addSubview: o_btn_volume_up];
834 [self addSubview: o_searchfield];
837 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
839 if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
840 == NSDragOperationGeneric)
842 return NSDragOperationGeneric;
846 return NSDragOperationNone;
850 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
855 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
857 NSPasteboard *o_paste = [sender draggingPasteboard];
858 NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
859 NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
860 NSData *o_carried_data = [o_paste dataForType:o_desired_type];
861 BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
865 if ([o_desired_type isEqualToString:NSFilenamesPboardType])
868 NSArray *o_array = [NSArray array];
869 NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType]
870 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
872 for( i = 0; i < (int)[o_values count]; i++)
875 o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"];
876 o_array = [o_array arrayByAddingObject: o_dic];
879 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
881 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
885 [self setNeedsDisplay:YES];
889 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
891 [self setNeedsDisplay:YES];
894 - (void)drawRect:(NSRect)rect
896 NSImage *leftImage = [NSImage imageNamed:@"display_left"];
897 NSImage *middleImage = [NSImage imageNamed:@"display_middle"];
898 NSImage *rightImage = [NSImage imageNamed:@"display_right"];
899 [middleImage setSize:NSMakeSize(NSWidth( [self bounds] ) - 134 - [leftImage size].width - [rightImage size].width, [middleImage size].height)];
900 [middleImage setScalesWhenResized:YES];
901 [leftImage compositeToPoint:NSMakePoint( 122., 40. ) operation:NSCompositeSourceOver];
902 [middleImage compositeToPoint:NSMakePoint( 122. + [leftImage size].width, 40. ) operation:NSCompositeSourceOver];
903 [rightImage compositeToPoint:NSMakePoint( NSWidth( [self bounds] ) - 12 - [rightImage size].width, 40. ) operation:NSCompositeSourceOver];
906 - (void)mouseDown:(NSEvent *)event
908 dragStart = [self convertPoint:[event locationInWindow] fromView:nil];
911 - (void)mouseDragged:(NSEvent *)event
913 NSPoint dragLocation = [self convertPoint:[event locationInWindow] fromView:nil];
914 NSPoint winOrigin = [o_window frame].origin;
916 NSPoint newOrigin = NSMakePoint(winOrigin.x + (dragLocation.x - dragStart.x),
917 winOrigin.y + (dragLocation.y - dragStart.y));
918 [o_window setFrameOrigin: newOrigin];
923 /*****************************************************************************
925 *****************************************************************************/
928 @implementation statusbar
931 [self addSubview: o_text];
935 - (void)resignMainWindow
941 - (void)becomeMainWindow
947 - (void)drawRect:(NSRect)rect
950 [[NSColor colorWithCalibratedRed:0.820
955 [[NSColor colorWithCalibratedWhite:0.91 alpha:1.0] set];
957 /*NSRect divider = rect;
958 divider.origin.y += divider.size.height - 1;
959 divider.size.height = 1;
960 [[NSColor colorWithCalibratedWhite:0.65 alpha:1.] set];
961 NSRectFill(divider);*/