1 /*****************************************************************************
2 * misc.m: code not specific to vlc
3 *****************************************************************************
4 * Copyright (C) 2003-2012 VLC authors and VideoLAN
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
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 *****************************************************************************/
26 #import "intf.h" /* VLCApplication */
27 #import "MainWindow.h"
29 #import "CoreInteraction.h"
30 #import <CoreAudio/CoreAudio.h>
34 /*****************************************************************************
35 * NSSound (VLCAdditions)
37 * added code to change the system volume, needed for the apple remote code
38 * this is simplified code, which won't let you set the exact volume
39 * (that's what the audio output is for after all), but just the system volume
40 * in steps of 1/16 (matching the default AR or volume key implementation).
41 *****************************************************************************/
43 @implementation NSSound (VLCAdditions)
45 + (float)systemVolumeForChannel:(int)channel
47 AudioDeviceID i_device;
52 i_size = sizeof( i_device );
53 AudioObjectPropertyAddress deviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
54 err = AudioObjectGetPropertyData( kAudioObjectSystemObject, &deviceAddress, 0, NULL, &i_size, &i_device );
56 msg_Warn( VLCIntf, "couldn't get main audio output device" );
60 AudioObjectPropertyAddress propertyAddress = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, channel };
61 i_size = sizeof( f_volume );
62 err = AudioObjectGetPropertyData(i_device, &propertyAddress, 0, NULL, &i_size, &f_volume);
64 msg_Warn( VLCIntf, "couldn't get volume value" );
71 + (bool)setSystemVolume:(float)f_volume forChannel:(int)i_channel
73 /* the following code will fail on S/PDIF devices. there is an easy work-around, but we'd like to match the OS behavior */
75 AudioDeviceID i_device;
80 i_size = sizeof( i_device );
81 AudioObjectPropertyAddress deviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
82 err = AudioObjectGetPropertyData( kAudioObjectSystemObject, &deviceAddress, 0, NULL, &i_size, &i_device );
84 msg_Warn( VLCIntf, "couldn't get main audio output device" );
88 AudioObjectPropertyAddress propertyAddress = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, i_channel };
89 i_size = sizeof( f_volume );
90 err = AudioObjectIsPropertySettable( i_device, &propertyAddress, &b_writeable );
91 if (err != noErr || !b_writeable ) {
92 msg_Warn( VLCIntf, "we can't set the main audio devices' volume" );
95 err = AudioObjectSetPropertyData(i_device, &propertyAddress, 0, NULL, i_size, &f_volume);
100 + (void)increaseSystemVolume
102 float f_volume = [NSSound systemVolumeForChannel:1]; // we trust that mono is always available and that all channels got the same volume
103 f_volume += .0625; // 1/16 to match the OS
104 bool b_returned = YES;
106 /* since core audio doesn't provide a reasonable way to see how many channels we got, let's see how long we can do this */
107 for (NSUInteger x = 1; b_returned ; x++)
108 b_returned = [NSSound setSystemVolume: f_volume forChannel:x];
111 + (void)decreaseSystemVolume
113 float f_volume = [NSSound systemVolumeForChannel:1]; // we trust that mono is always available and that all channels got the same volume
114 f_volume -= .0625; // 1/16 to match the OS
115 bool b_returned = YES;
117 /* since core audio doesn't provide a reasonable way to see how many channels we got, let's see how long we can do this */
118 for (NSUInteger x = 1; b_returned ; x++)
119 b_returned = [NSSound setSystemVolume: f_volume forChannel:x];
124 /*****************************************************************************
125 * NSAnimation (VLCAdditions)
127 * Missing extension to NSAnimation
128 *****************************************************************************/
130 @implementation NSAnimation (VLCAdditions)
131 /* fake class attributes */
132 static NSMapTable *VLCAdditions_userInfo = NULL;
136 /* init our fake object attribute */
137 VLCAdditions_userInfo = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 16);
142 NSMapRemove(VLCAdditions_userInfo, self);
146 - (void)setUserInfo: (void *)userInfo
148 NSMapInsert(VLCAdditions_userInfo, self, (void*)userInfo);
153 return NSMapGet(VLCAdditions_userInfo, self);
157 /*****************************************************************************
158 * NSScreen (VLCAdditions)
160 * Missing extension to NSScreen
161 *****************************************************************************/
163 @implementation NSScreen (VLCAdditions)
165 static NSMutableArray *blackoutWindows = NULL;
169 /* init our fake object attribute */
170 blackoutWindows = [[NSMutableArray alloc] initWithCapacity:1];
173 + (NSScreen *)screenWithDisplayID: (CGDirectDisplayID)displayID
175 NSUInteger count = [[NSScreen screens] count];
177 for ( NSUInteger i = 0; i < count; i++ ) {
178 NSScreen *screen = [[NSScreen screens] objectAtIndex: i];
179 if ([screen displayID] == displayID)
187 return ([self displayID] == [[[NSScreen screens] objectAtIndex:0] displayID]);
190 - (BOOL)isScreen: (NSScreen*)screen
192 return ([self displayID] == [screen displayID]);
195 - (CGDirectDisplayID)displayID
197 return (CGDirectDisplayID)[[[self deviceDescription] objectForKey: @"NSScreenNumber"] intValue];
200 - (void)blackoutOtherScreens
202 /* Free our previous blackout window (follow blackoutWindow alloc strategy) */
203 [blackoutWindows makeObjectsPerformSelector:@selector(close)];
204 [blackoutWindows removeAllObjects];
206 NSUInteger screenCount = [[NSScreen screens] count];
207 for (NSUInteger i = 0; i < screenCount; i++) {
208 NSScreen *screen = [[NSScreen screens] objectAtIndex: i];
209 VLCWindow *blackoutWindow;
212 if ([self isScreen: screen])
215 screen_rect = [screen frame];
216 screen_rect.origin.x = screen_rect.origin.y = 0;
218 /* blackoutWindow alloc strategy
219 - The NSMutableArray blackoutWindows has the blackoutWindow references
220 - blackoutOtherDisplays is responsible for alloc/releasing its Windows
222 blackoutWindow = [[VLCWindow alloc] initWithContentRect: screen_rect styleMask: NSBorderlessWindowMask
223 backing: NSBackingStoreBuffered defer: NO screen: screen];
224 [blackoutWindow setBackgroundColor:[NSColor blackColor]];
225 [blackoutWindow setLevel: NSFloatingWindowLevel]; /* Disappear when Expose is triggered */
227 [blackoutWindow displayIfNeeded];
228 [blackoutWindow orderFront: self animate: YES];
230 [blackoutWindows addObject: blackoutWindow];
231 [blackoutWindow release];
233 if ( [screen mainScreen] )
234 [NSApp setPresentationOptions:(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
238 + (void)unblackoutScreens
240 NSUInteger blackoutWindowCount = [blackoutWindows count];
242 for (NSUInteger i = 0; i < blackoutWindowCount; i++) {
243 VLCWindow *blackoutWindow = [blackoutWindows objectAtIndex: i];
244 [blackoutWindow closeAndAnimate: YES];
247 [NSApp setPresentationOptions:(NSApplicationPresentationDefault)];
252 /*****************************************************************************
255 * Missing extension to NSWindow
256 *****************************************************************************/
258 @implementation VLCWindow
259 - (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask
260 backing:(NSBackingStoreType)backingType defer:(BOOL)flag
262 self = [super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag];
264 b_isset_canBecomeKeyWindow = NO;
265 /* we don't want this window to be restored on relaunch */
266 if (!OSX_SNOW_LEOPARD)
267 [self setRestorable:NO];
272 - (void)setCanBecomeKeyWindow: (BOOL)canBecomeKey
274 b_isset_canBecomeKeyWindow = YES;
275 b_canBecomeKeyWindow = canBecomeKey;
278 - (BOOL)canBecomeKeyWindow
280 if (b_isset_canBecomeKeyWindow)
281 return b_canBecomeKeyWindow;
283 return [super canBecomeKeyWindow];
286 - (void)setCanBecomeMainWindow: (BOOL)canBecomeMain
288 b_isset_canBecomeMainWindow = YES;
289 b_canBecomeMainWindow = canBecomeMain;
292 - (BOOL)canBecomeMainWindow
294 if (b_isset_canBecomeMainWindow)
295 return b_canBecomeMainWindow;
297 return [super canBecomeMainWindow];
300 - (void)closeAndAnimate: (BOOL)animate
309 invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(close)]];
310 [invoc setTarget: self];
312 if (![self isVisible] || [self alphaValue] == 0.0) {
317 [self orderOut: self animate: YES callback: invoc];
320 - (void)orderOut: (id)sender animate: (BOOL)animate
322 NSInvocation *invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(orderOut:)]];
323 [invoc setTarget: self];
324 [invoc setArgument: sender atIndex: 0];
325 [self orderOut: sender animate: animate callback: invoc];
328 - (void)orderOut: (id)sender animate: (BOOL)animate callback:(NSInvocation *)callback
330 NSViewAnimation *anim;
331 NSViewAnimation *current_anim;
332 NSMutableDictionary *dict;
335 [self orderOut: sender];
339 dict = [[NSMutableDictionary alloc] initWithCapacity:2];
341 [dict setObject:self forKey:NSViewAnimationTargetKey];
343 [dict setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
344 anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]];
347 [anim setAnimationBlockingMode:NSAnimationNonblocking];
348 [anim setDuration:0.9];
349 [anim setFrameRate:30];
350 [anim setUserInfo: callback];
352 @synchronized(self) {
353 current_anim = self->animation;
355 if ([[[current_anim viewAnimations] objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] == NSViewAnimationFadeOutEffect && [current_anim isAnimating]) {
359 [current_anim stopAnimation];
360 [anim setCurrentProgress:1.0-[current_anim currentProgress]];
361 [current_anim release];
364 [anim setCurrentProgress:1.0 - [self alphaValue]];
365 self->animation = anim;
366 [self setDelegate: self];
367 [anim startAnimation];
372 - (void)orderFront: (id)sender animate: (BOOL)animate
374 NSViewAnimation *anim;
375 NSViewAnimation *current_anim;
376 NSMutableDictionary *dict;
379 [super orderFront: sender];
380 [self setAlphaValue: 1.0];
384 if (![self isVisible]) {
385 [self setAlphaValue: 0.0];
386 [super orderFront: sender];
388 else if ([self alphaValue] == 1.0) {
389 [super orderFront: self];
393 dict = [[NSMutableDictionary alloc] initWithCapacity:2];
395 [dict setObject:self forKey:NSViewAnimationTargetKey];
397 [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
398 anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]];
401 [anim setAnimationBlockingMode:NSAnimationNonblocking];
402 [anim setDuration:0.5];
403 [anim setFrameRate:30];
405 @synchronized(self) {
406 current_anim = self->animation;
408 if ([[[current_anim viewAnimations] objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] == NSViewAnimationFadeInEffect && [current_anim isAnimating]) {
412 [current_anim stopAnimation];
413 [anim setCurrentProgress:1.0 - [current_anim currentProgress]];
414 [current_anim release];
417 [anim setCurrentProgress:[self alphaValue]];
418 self->animation = anim;
419 [self setDelegate: self];
420 [self orderFront: sender];
421 [anim startAnimation];
426 - (void)animationDidEnd:(NSAnimation*)anim
428 if ([self alphaValue] <= 0.0) {
429 NSInvocation * invoc;
430 [super orderOut: nil];
431 [self setAlphaValue: 1.0];
432 if ((invoc = [anim userInfo]))
437 - (IBAction)fullscreen:(id)sender
439 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
444 /*****************************************************************************
445 * VLBrushedMetalImageView
446 *****************************************************************************/
448 @implementation VLBrushedMetalImageView
450 - (BOOL)mouseDownCanMoveWindow
457 [self unregisterDraggedTypes];
463 [self registerForDraggedTypes:[NSArray arrayWithObject: NSFilenamesPboardType]];
464 [self setImageScaling: NSScaleToFit];
465 [self setImageFrameStyle: NSImageFrameNone];
466 [self setImageAlignment: NSImageAlignCenter];
469 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
471 if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric)
472 return NSDragOperationGeneric;
474 return NSDragOperationNone;
477 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
482 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
485 b_returned = [[VLCCoreInteraction sharedInstance] performDragOperation: sender];
487 [self setNeedsDisplay:YES];
491 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
493 [self setNeedsDisplay:YES];
499 /*****************************************************************************
501 *****************************************************************************/
502 @implementation MPSlider
504 void _drawKnobInRect(NSRect knobRect)
506 // Center knob in given rect
507 knobRect.origin.x += (int)((float)(knobRect.size.width - 7)/2.0);
508 knobRect.origin.y += (int)((float)(knobRect.size.height - 7)/2.0);
511 NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 6, 1, 1), NSCompositeSourceOver);
512 NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 5, 3, 1), NSCompositeSourceOver);
513 NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 4, 5, 1), NSCompositeSourceOver);
514 NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 0, knobRect.origin.y + 3, 7, 1), NSCompositeSourceOver);
515 NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 2, 5, 1), NSCompositeSourceOver);
516 NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 1, 3, 1), NSCompositeSourceOver);
517 NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 0, 1, 1), NSCompositeSourceOver);
520 void _drawFrameInRect(NSRect frameRect)
523 NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, 1), NSCompositeSourceOver);
524 NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y + frameRect.size.height-1, frameRect.size.width, 1), NSCompositeSourceOver);
525 NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
526 NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x+frameRect.size.width-1, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
529 - (void)drawRect:(NSRect)rect
531 // Draw default to make sure the slider behaves correctly
532 [[NSGraphicsContext currentContext] saveGraphicsState];
533 NSRectClip(NSZeroRect);
534 [super drawRect:rect];
535 [[NSGraphicsContext currentContext] restoreGraphicsState];
538 rect = [self bounds];
539 int diff = (int)(([[self cell] knobThickness] - 7.0)/2.0) - 1;
540 rect.origin.x += diff-1;
541 rect.origin.y += diff;
542 rect.size.width -= 2*diff-2;
543 rect.size.height -= 2*diff;
546 NSRect knobRect = [[self cell] knobRectFlipped:NO];
547 [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];
548 _drawFrameInRect(rect);
549 _drawKnobInRect(knobRect);
552 [[[NSColor blackColor] colorWithAlphaComponent:0.1] set];
557 _drawFrameInRect(rect);
558 _drawKnobInRect(knobRect);
563 /*****************************************************************************
565 *****************************************************************************/
567 @implementation VLCProgressView : NSView
569 - (void)scrollWheel:(NSEvent *)o_event
571 intf_thread_t * p_intf = VLCIntf;
572 CGFloat f_deltaY = [o_event deltaY];
573 CGFloat f_deltaX = [o_event deltaX];
575 if (!OSX_SNOW_LEOPARD && [o_event isDirectionInvertedFromDevice])
576 f_deltaX = -f_deltaX; // optimisation, actually double invertion of f_deltaY here
578 f_deltaY = -f_deltaY;
580 // positive for left / down, negative otherwise
581 CGFloat f_delta = f_deltaX + f_deltaY;
585 if (f_delta > 0.0f) {
586 i_vlckey = ACTIONID_JUMP_BACKWARD_EXTRASHORT;
590 i_vlckey = ACTIONID_JUMP_FORWARD_EXTRASHORT;
594 for (NSUInteger i = 0; i < (int)(f_abs/4.+1.) && f_abs > 0.05 ; i++)
595 var_SetInteger( p_intf->p_libvlc, "key-action", i_vlckey );
598 - (BOOL)acceptsFirstResponder
605 /*****************************************************************************
607 *****************************************************************************/
609 @implementation TimeLineSlider
613 if (config_GetInt( VLCIntf, "macosx-interfacestyle" )) {
614 o_knob_img = [NSImage imageNamed:@"progression-knob_dark"];
617 o_knob_img = [NSImage imageNamed:@"progression-knob"];
620 img_rect.size = [o_knob_img size];
621 img_rect.origin.x = img_rect.origin.y = 0;
626 [o_knob_img release];
630 - (CGFloat)knobPosition
632 NSRect knobRect = [[self cell] knobRectFlipped:NO];
633 knobRect.origin.x += knobRect.size.width / 2;
634 return knobRect.origin.x;
637 - (void)drawKnobInRect:(NSRect)knobRect
639 knobRect.origin.x += (knobRect.size.width - img_rect.size.width) / 2;
640 knobRect.size.width = img_rect.size.width;
641 knobRect.size.height = img_rect.size.height;
642 [o_knob_img drawInRect:knobRect fromRect:img_rect operation:NSCompositeSourceOver fraction:1];
645 - (void)drawRect:(NSRect)rect
647 [[[VLCMain sharedInstance] mainWindow] drawFancyGradientEffectForTimeSlider];
648 msleep( 10000 ); //wait for the gradient to draw completely
650 /* Draw default to make sure the slider behaves correctly */
651 [[NSGraphicsContext currentContext] saveGraphicsState];
652 NSRectClip(NSZeroRect);
653 [super drawRect:rect];
654 [[NSGraphicsContext currentContext] restoreGraphicsState];
656 NSRect knobRect = [[self cell] knobRectFlipped:NO];
658 knobRect.origin.y+=2;
660 knobRect.origin.y+=1;
661 [self drawKnobInRect: knobRect];
666 /*****************************************************************************
667 * VLCVolumeSliderCommon
668 *****************************************************************************/
670 @implementation VLCVolumeSliderCommon : NSSlider
672 - (void)scrollWheel:(NSEvent *)o_event
674 intf_thread_t * p_intf = VLCIntf;
675 CGFloat f_deltaY = [o_event deltaY];
676 CGFloat f_deltaX = [o_event deltaX];
678 if (!OSX_SNOW_LEOPARD && [o_event isDirectionInvertedFromDevice])
679 f_deltaX = -f_deltaX; // optimisation, actually double invertion of f_deltaY here
681 f_deltaY = -f_deltaY;
683 // positive for left / down, negative otherwise
684 CGFloat f_delta = f_deltaX + f_deltaY;
688 if (f_delta > 0.0f) {
689 i_vlckey = ACTIONID_VOL_DOWN;
693 i_vlckey = ACTIONID_VOL_UP;
697 for (NSUInteger i = 0; i < (int)(f_abs/4.+1.) && f_abs > 0.05 ; i++)
698 var_SetInteger(p_intf->p_libvlc, "key-action", i_vlckey);
703 /*****************************************************************************
705 *****************************************************************************/
707 @implementation ITSlider
711 BOOL b_dark = config_GetInt( VLCIntf, "macosx-interfacestyle" );
713 img = [NSImage imageNamed:@"volume-slider-knob_dark"];
715 img = [NSImage imageNamed:@"volume-slider-knob"];
717 image_rect.size = [img size];
718 image_rect.origin.x = 0;
721 image_rect.origin.y = -1;
723 image_rect.origin.y = 0;
726 - (void)drawKnobInRect:(NSRect)knobRect
728 knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;
729 knobRect.size.width = image_rect.size.width;
730 knobRect.size.height = image_rect.size.height;
731 [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];
734 - (void)drawRect:(NSRect)rect
736 /* Draw default to make sure the slider behaves correctly */
737 [[NSGraphicsContext currentContext] saveGraphicsState];
738 NSRectClip(NSZeroRect);
739 [super drawRect:rect];
740 [[NSGraphicsContext currentContext] restoreGraphicsState];
742 NSRect knobRect = [[self cell] knobRectFlipped:NO];
743 knobRect.origin.y+=2;
744 [self drawKnobInRect: knobRect];
749 /*****************************************************************************
750 * VLCTimeField implementation
751 *****************************************************************************
752 * we need this to catch our click-event in the controller window
753 *****************************************************************************/
755 @implementation VLCTimeField
757 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
758 NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"NO" forKey:@"DisplayTimeAsTimeRemaining"];
760 [defaults registerDefaults:appDefaults];
765 NSColor *o_string_color;
766 if (!config_GetInt( VLCIntf, "macosx-interfacestyle"))
767 o_string_color = [NSColor colorWithCalibratedRed:0.229 green:0.229 blue:0.229 alpha:100.0];
769 o_string_color = [NSColor colorWithCalibratedRed:0.64 green:0.64 blue:0.64 alpha:100.0];
771 textAlignment = NSCenterTextAlignment;
772 o_string_attributes_dict = [[NSDictionary dictionaryWithObjectsAndKeys: o_string_color, NSForegroundColorAttributeName, [NSFont titleBarFontOfSize:10.0], NSFontAttributeName, nil] retain];
775 - (void)setAlignment:(NSTextAlignment)alignment
777 textAlignment = alignment;
778 [self setStringValue:[self stringValue]];
783 [o_string_shadow release];
784 [o_string_attributes_dict release];
788 - (void)setStringValue:(NSString *)string
790 if (!o_string_shadow) {
791 o_string_shadow = [[NSShadow alloc] init];
792 [o_string_shadow setShadowColor: [NSColor colorWithCalibratedWhite:1.0 alpha:0.5]];
793 [o_string_shadow setShadowOffset:NSMakeSize(0.0, -1.5)];
794 [o_string_shadow setShadowBlurRadius:0.0];
797 NSMutableAttributedString *o_attributed_string = [[NSMutableAttributedString alloc] initWithString:string attributes: o_string_attributes_dict];
798 NSUInteger i_stringLength = [string length];
800 [o_attributed_string addAttribute: NSShadowAttributeName value: o_string_shadow range: NSMakeRange(0, i_stringLength)];
801 [o_attributed_string setAlignment: textAlignment range: NSMakeRange(0, i_stringLength)];
802 [self setAttributedStringValue: o_attributed_string];
803 [o_attributed_string release];
806 - (void)mouseDown: (NSEvent *)ourEvent
808 if ( [ourEvent clickCount] > 1 )
809 [[[VLCMain sharedInstance] controls] goToSpecificTime: nil];
812 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayTimeAsTimeRemaining"])
813 [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"DisplayTimeAsTimeRemaining"];
815 [[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"DisplayTimeAsTimeRemaining"];
819 - (BOOL)timeRemaining
821 return [[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayTimeAsTimeRemaining"];
825 /*****************************************************************************
826 * VLCMainWindowSplitView implementation
827 * comment 1 + 2 taken from NSSplitView.h (10.7 SDK)
828 *****************************************************************************/
829 @implementation VLCMainWindowSplitView : NSSplitView
830 /* Return the color of the dividers that the split view is drawing between subviews. The default implementation of this method returns [NSColor clearColor] for the thick divider style. It will also return [NSColor clearColor] for the thin divider style when the split view is in a textured window. All other thin dividers are drawn with a color that looks good between two white panes. You can override this method to change the color of dividers.
832 - (NSColor *)dividerColor
834 return [NSColor colorWithCalibratedRed:.60 green:.60 blue:.60 alpha:1.];
837 /* Return the thickness of the dividers that the split view is drawing between subviews. The default implementation returns a value that depends on the divider style. You can override this method to change the size of dividers.
839 - (CGFloat)dividerThickness
845 /*****************************************************************************
846 * VLCThreePartImageView interface
847 *****************************************************************************/
848 @implementation VLCThreePartImageView
852 [o_left_img release];
853 [o_middle_img release];
854 [o_right_img release];
859 - (void)setImagesLeft:(NSImage *)left middle: (NSImage *)middle right:(NSImage *)right
862 [o_left_img release];
864 [o_middle_img release];
866 [o_right_img release];
868 o_left_img = [left retain];
869 o_middle_img = [middle retain];
870 o_right_img = [right retain];
873 - (void)drawRect:(NSRect)rect
875 NSRect bnds = [self bounds];
876 NSDrawThreePartImage( bnds, o_left_img, o_middle_img, o_right_img, NO, NSCompositeSourceOver, 1, NO );
881 @implementation VLCThreePartDropView
883 - (BOOL)mouseDownCanMoveWindow
890 [self unregisterDraggedTypes];
896 [self registerForDraggedTypes:[NSArray arrayWithObject: NSFilenamesPboardType]];
899 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
901 if ((NSDragOperationGeneric & [sender draggingSourceOperationMask]) == NSDragOperationGeneric)
902 return NSDragOperationGeneric;
904 return NSDragOperationNone;
907 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
912 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
915 b_returned = [[VLCCoreInteraction sharedInstance] performDragOperation: sender];
917 [self setNeedsDisplay:YES];
921 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
923 [self setNeedsDisplay:YES];