1 /*****************************************************************************
2 * MainWindow.h: MacOS X interface module
3 *****************************************************************************
4 * Copyright (C) 2002-2011 VideoLAN
7 * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8 * Jon Lech Johansen <jon-vl@nanocrew.net>
9 * Christophe Massiot <massiot@via.ecp.fr>
10 * Derk-Jan Hartman <hartman at videolan.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 #import "MainWindow.h"
29 #import "CoreInteraction.h"
30 #import "AudioEffects.h"
33 #import "controls.h" // TODO: remove me
34 #import "SideBarItem.h"
35 #import <vlc_playlist.h>
36 #import <vlc_aout_intf.h>
38 #import <vlc_strings.h>
39 #import <vlc_services_discovery.h>
41 @implementation VLCMainWindow
42 static VLCMainWindow *_o_sharedInstance = nil;
44 + (VLCMainWindow *)sharedInstance
46 return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
50 #pragma mark Initialization
54 if( _o_sharedInstance)
57 return _o_sharedInstance;
61 o_fspanel = [[VLCFSPanel alloc] init];
62 _o_sharedInstance = [super init];
65 return _o_sharedInstance;
68 - (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask
69 backing:(NSBackingStoreType)backingType defer:(BOOL)flag
71 // styleMask ^= NSTexturedBackgroundWindowMask;
73 self = [super initWithContentRect:contentRect styleMask:styleMask //& ~NSTitledWindowMask
74 backing:backingType defer:flag];
76 [[VLCMain sharedInstance] updateTogglePlaylistState];
78 /* we want to be moveable regardless of our style */
79 [self setMovableByWindowBackground: YES];
81 /* we don't want this window to be restored on relaunch */
82 if ([self respondsToSelector:@selector(setRestorable:)])
83 [self setRestorable:NO];
88 - (BOOL)performKeyEquivalent:(NSEvent *)o_event
90 /* We indeed want to prioritize Cocoa key equivalent against libvlc,
91 so we perform the menu equivalent now. */
92 if([[NSApp mainMenu] performKeyEquivalent:o_event])
95 return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event] || [(VLCControls *)[[VLCMain sharedInstance] controls] keyEvent:o_event];
100 config_PutInt( VLCIntf->p_libvlc, "volume", i_lastShownVolume );
101 [o_sidebaritems release];
107 /* setup the styled interface */
108 b_dark_interface = config_GetInt( VLCIntf, "macosx-interfacestyle" );
109 i_lastShownVolume = -1;
111 [o_play_btn setToolTip: _NS("Play/Pause")];
112 [o_bwd_btn setToolTip: _NS("Backward")];
113 [o_fwd_btn setToolTip: _NS("Forward")];
114 [o_stop_btn setToolTip: _NS("Stop")];
115 [o_playlist_btn setToolTip: _NS("Show/Hide Playlist")];
116 [o_repeat_btn setToolTip: _NS("Repeat")];
117 [o_shuffle_btn setToolTip: _NS("Shuffle")];
118 [o_effects_btn setToolTip: _NS("Effects")];
119 [o_fullscreen_btn setToolTip: _NS("Toggle Fullscreen mode")];
120 [[o_search_fld cell] setPlaceholderString: _NS("Search")];
121 [o_volume_sld setToolTip: _NS("Volume")];
122 [o_volume_down_btn setToolTip: _NS("Mute")];
123 [o_volume_up_btn setToolTip: _NS("Full Volume")];
124 [o_time_sld setToolTip: _NS("Position")];
125 [o_dropzone_btn setTitle: _NS("Open media...")];
126 [o_dropzone_lbl setStringValue: _NS("Drop media here")];
128 if (!b_dark_interface) {
129 [o_bottombar_view setImage: [NSImage imageNamed:@"bottom-background"]];
130 [o_bwd_btn setImage: [NSImage imageNamed:@"back"]];
131 [o_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed"]];
132 o_play_img = [[NSImage imageNamed:@"play"] retain];
133 o_play_pressed_img = [[NSImage imageNamed:@"play-pressed"] retain];
134 o_pause_img = [[NSImage imageNamed:@"pause"] retain];
135 o_pause_pressed_img = [[NSImage imageNamed:@"pause-pressed"] retain];
136 [o_fwd_btn setImage: [NSImage imageNamed:@"forward"]];
137 [o_fwd_btn setAlternateImage: [NSImage imageNamed:@"forward-pressed"]];
138 [o_stop_btn setImage: [NSImage imageNamed:@"stop"]];
139 [o_stop_btn setAlternateImage: [NSImage imageNamed:@"stop-pressed"]];
140 [o_playlist_btn setImage: [NSImage imageNamed:@"playlist"]];
141 [o_playlist_btn setAlternateImage: [NSImage imageNamed:@"playlist-pressed"]];
142 o_repeat_img = [[NSImage imageNamed:@"repeat"] retain];
143 o_repeat_pressed_img = [[NSImage imageNamed:@"repeat-pressed"] retain];
144 o_repeat_all_img = [[NSImage imageNamed:@"repeat-all"] retain];
145 o_repeat_all_pressed_img = [[NSImage imageNamed:@"repeat-all-pressed"] retain];
146 o_repeat_one_img = [[NSImage imageNamed:@"repeat-one"] retain];
147 o_repeat_one_pressed_img = [[NSImage imageNamed:@"repeat-one-pressed"] retain];
148 o_shuffle_img = [[NSImage imageNamed:@"shuffle"] retain];
149 o_shuffle_pressed_img = [[NSImage imageNamed:@"shuffle-pressed"] retain];
150 o_shuffle_on_img = [[NSImage imageNamed:@"shuffle-blue"] retain];
151 o_shuffle_on_pressed_img = [[NSImage imageNamed:@"shuffle-blue-pressed"] retain];
152 [o_time_sld_left_view setImage: [NSImage imageNamed:@"progression-track-wrapper-left"]];
153 [o_time_sld_middle_view setImage: [NSImage imageNamed:@"progression-track-wrapper-middle"]];
154 [o_time_sld_right_view setImage: [NSImage imageNamed:@"progression-track-wrapper-right"]];
155 [o_volume_down_btn setImage: [NSImage imageNamed:@"volume-low"]];
156 [o_volume_track_view setImage: [NSImage imageNamed:@"volume-slider-track"]];
157 [o_volume_up_btn setImage: [NSImage imageNamed:@"volume-high"]];
158 [o_effects_btn setImage: [NSImage imageNamed:@"effects-double-buttons"]];
159 [o_effects_btn setAlternateImage: [NSImage imageNamed:@"effects-double-buttons-pressed"]];
160 [o_fullscreen_btn setImage: [NSImage imageNamed:@"fullscreen-double-buttons"]];
161 [o_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"fullscreen-double-buttons-pressed"]];
162 [o_time_sld_fancygradient_view loadImagesInDarkStyle:NO];
166 /* TODO: we also need to change the window style here... */
167 [o_bottombar_view setImage: [NSImage imageNamed:@"bottom-background_dark"]];
168 [o_bwd_btn setImage: [NSImage imageNamed:@"back_dark"]];
169 [o_bwd_btn setAlternateImage: [NSImage imageNamed:@"back-pressed_dark"]];
170 o_play_img = [[NSImage imageNamed:@"play_dark"] retain];
171 o_play_pressed_img = [[NSImage imageNamed:@"play-pressed_dark"] retain];
172 o_pause_img = [[NSImage imageNamed:@"pause_dark"] retain];
173 o_pause_pressed_img = [[NSImage imageNamed:@"pause-pressed_dark"] retain];
174 [o_fwd_btn setImage: [NSImage imageNamed:@"forward_dark"]];
175 [o_fwd_btn setAlternateImage: [NSImage imageNamed:@"forward-pressed_dark"]];
176 [o_stop_btn setImage: [NSImage imageNamed:@"stop_dark"]];
177 [o_stop_btn setAlternateImage: [NSImage imageNamed:@"stop-pressed_dark"]];
178 [o_playlist_btn setImage: [NSImage imageNamed:@"playlist_dark"]];
179 [o_playlist_btn setAlternateImage: [NSImage imageNamed:@"playlist-pressed_dark"]];
180 o_repeat_img = [[NSImage imageNamed:@"repeat_dark"] retain];
181 o_repeat_pressed_img = [[NSImage imageNamed:@"repeat-pressed_dark"] retain];
182 o_repeat_all_img = [[NSImage imageNamed:@"repeat-all-blue_dark"] retain];
183 o_repeat_all_pressed_img = [[NSImage imageNamed:@"repeat-all-blue-pressed_dark"] retain];
184 o_repeat_one_img = [[NSImage imageNamed:@"repeat-one-blue_dark"] retain];
185 o_repeat_one_pressed_img = [[NSImage imageNamed:@"repeat-one-blue-pressed_dark"] retain];
186 o_shuffle_img = [[NSImage imageNamed:@"shuffle_dark"] retain];
187 o_shuffle_pressed_img = [[NSImage imageNamed:@"shuffle-pressed_dark"] retain];
188 o_shuffle_on_img = [[NSImage imageNamed:@"shuffle-blue_dark"] retain];
189 o_shuffle_on_pressed_img = [[NSImage imageNamed:@"shuffle-blue-pressed_dark"] retain];
190 [o_time_fld setTextColor: [NSColor colorWithCalibratedRed:229.0 green:229.0 blue:229.0 alpha:100.0]];
191 [o_time_sld_left_view setImage: [NSImage imageNamed:@"progression-track-wrapper-left_dark"]];
192 [o_time_sld_middle_view setImage: [NSImage imageNamed:@"progression-track-wrapper-middle_dark"]];
193 [o_time_sld_right_view setImage: [NSImage imageNamed:@"progression-track-wrapper-right_dark"]];
194 [o_volume_down_btn setImage: [NSImage imageNamed:@"volume-low_dark"]];
195 [o_volume_track_view setImage: [NSImage imageNamed:@"volume-slider-track_dark"]];
196 [o_volume_up_btn setImage: [NSImage imageNamed:@"volume-high_dark"]];
197 [o_effects_btn setImage: [NSImage imageNamed:@"effects-double-buttons_dark"]];
198 [o_effects_btn setAlternateImage: [NSImage imageNamed:@"effects-double-buttons-pressed_dark"]];
199 [o_fullscreen_btn setImage: [NSImage imageNamed:@"fullscreen-double-buttons_dark"]];
200 [o_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"fullscreen-double-buttons-pressed_dark"]];
201 [o_time_sld_fancygradient_view loadImagesInDarkStyle:YES];
203 [o_repeat_btn setImage: o_repeat_img];
204 [o_repeat_btn setAlternateImage: o_repeat_pressed_img];
205 [o_shuffle_btn setImage: o_shuffle_img];
206 [o_shuffle_btn setAlternateImage: o_shuffle_pressed_img];
207 [o_play_btn setImage: o_play_img];
208 [o_play_btn setAlternateImage: o_play_pressed_img];
210 /* interface builder action */
211 [self setDelegate: self];
212 [self setExcludedFromWindowsMenu: YES];
213 // Set that here as IB seems to be buggy
214 [self setContentMinSize:NSMakeSize(500., 288.)];
215 [self setTitle: _NS("VLC media player")];
216 [o_playlist_btn setEnabled:NO];
217 [o_video_view setFrame: [o_split_view frame]];
218 o_temp_view = [[NSView alloc] init];
219 [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
220 [o_dropzone_view setFrame: [o_playlist_table frame]];
222 /* create the sidebar */
223 o_sidebaritems = [[NSMutableArray alloc] init];
224 SideBarItem *libraryItem = [SideBarItem itemWithTitle:_NS("LIBRARY") identifier:@"library"];
225 SideBarItem *playlistItem = [SideBarItem itemWithTitle:_NS("Playlist") identifier:@"playlist"];
226 [playlistItem setIcon: [NSImage imageNamed:@"document-music-playlist"]];
227 SideBarItem *mycompItem = [SideBarItem itemWithTitle:_NS("MY COMPUTER") identifier:@"mycomputer"];
228 SideBarItem *devicesItem = [SideBarItem itemWithTitle:_NS("DEVICES") identifier:@"devices"];
229 SideBarItem *lanItem = [SideBarItem itemWithTitle:_NS("LOCAL NETWORK") identifier:@"localnetwork"];
230 SideBarItem *internetItem = [SideBarItem itemWithTitle:_NS("INTERNET") identifier:@"internet"];
232 /* SD subnodes, inspired by the Qt4 intf */
233 char **ppsz_longnames;
235 char **ppsz_names = vlc_sd_GetNames( pl_Get( VLCIntf ), &ppsz_longnames, &p_categories );
237 msg_Err( VLCIntf, "no sd item found" ); //TODO
238 char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
239 int *p_category = p_categories;
240 NSMutableArray *internetItems = [[NSMutableArray alloc] init];
241 NSMutableArray *devicesItems = [[NSMutableArray alloc] init];
242 NSMutableArray *lanItems = [[NSMutableArray alloc] init];
243 NSMutableArray *mycompItems = [[NSMutableArray alloc] init];
244 NSString *o_identifier;
245 for (; *ppsz_name; ppsz_name++, ppsz_longname++, p_category++)
247 o_identifier = [NSString stringWithCString: *ppsz_name encoding: NSUTF8StringEncoding];
248 o_identifier = [[o_identifier componentsSeparatedByString:@"{"] objectAtIndex:0];
249 switch (*p_category) {
250 case SD_CAT_INTERNET:
252 [internetItems addObject: [SideBarItem itemWithTitle: [NSString stringWithCString: *ppsz_longname encoding: NSUTF8StringEncoding] identifier: o_identifier]];
253 if (!strncmp( *ppsz_name, "podcast", 7 ))
254 [[internetItems lastObject] setIcon: [NSImage imageNamed:@"film-cast"]];
256 [[internetItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
261 [devicesItems addObject: [SideBarItem itemWithTitle: [NSString stringWithCString: *ppsz_longname encoding: NSUTF8StringEncoding] identifier: o_identifier]];
262 [[devicesItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
267 [lanItems addObject: [SideBarItem itemWithTitle: [NSString stringWithCString: *ppsz_longname encoding: NSUTF8StringEncoding] identifier: o_identifier]];
268 [[lanItems lastObject] setIcon: [NSImage imageNamed:@"network-cloud"]];
271 case SD_CAT_MYCOMPUTER:
273 [mycompItems addObject: [SideBarItem itemWithTitle: [NSString stringWithCString: *ppsz_longname encoding: NSUTF8StringEncoding] identifier: o_identifier]];
274 if (!strncmp( *ppsz_name, "video_dir", 9 ))
275 [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"film"]];
276 else if (!strncmp( *ppsz_name, "audio_dir", 9 ))
277 [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"music-beam"]];
278 else if (!strncmp( *ppsz_name, "picture_dir", 11 ))
279 [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"picture"]];
281 [[mycompItems lastObject] setIcon: [NSImage imageNamed:@"NSApplicationIcon"]];
285 msg_Warn( VLCIntf, "unknown SD type found, skipping (%s)", *ppsz_name );
290 free( *ppsz_longname );
292 [mycompItem setChildren: [NSArray arrayWithArray: mycompItems]];
293 [devicesItem setChildren: [NSArray arrayWithArray: devicesItems]];
294 [lanItem setChildren: [NSArray arrayWithArray: lanItems]];
295 [internetItem setChildren: [NSArray arrayWithArray: internetItems]];
296 [mycompItems release];
297 [devicesItems release];
299 [internetItems release];
301 free( ppsz_longnames );
302 free( p_categories );
304 [libraryItem setChildren: [NSArray arrayWithObject: playlistItem]];
305 [o_sidebaritems addObject: libraryItem];
306 if ([mycompItem hasChildren])
307 [o_sidebaritems addObject: mycompItem];
308 if ([devicesItem hasChildren])
309 [o_sidebaritems addObject: devicesItem];
310 if ([lanItem hasChildren])
311 [o_sidebaritems addObject: lanItem];
312 if ([internetItem hasChildren])
313 [o_sidebaritems addObject: internetItem];
315 [o_sidebar_view reloadData];
316 [o_sidebar_view selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:YES];
320 #pragma mark Button Actions
322 - (IBAction)play:(id)sender
324 [[VLCCoreInteraction sharedInstance] play];
327 - (void)resetPreviousButton
329 if (([NSDate timeIntervalSinceReferenceDate] - last_bwd_event) >= 0.35) {
330 // seems like no further event occured, so let's switch the playback item
331 [[VLCCoreInteraction sharedInstance] previous];
332 just_triggered_previous = NO;
336 - (void)resetBackwardSkip
338 // the user stopped skipping, so let's allow him to change the item
339 if (([NSDate timeIntervalSinceReferenceDate] - last_bwd_event) >= 0.35)
340 just_triggered_previous = NO;
343 - (IBAction)bwd:(id)sender
345 if(!just_triggered_previous)
347 just_triggered_previous = YES;
348 [self performSelector:@selector(resetPreviousButton)
354 if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) > 0.12 )
356 // we just skipped 3 "continous" events, otherwise we are too fast
357 [[VLCCoreInteraction sharedInstance] backward];
358 last_bwd_event = [NSDate timeIntervalSinceReferenceDate];
359 [self performSelector:@selector(resetBackwardSkip)
366 - (void)resetNextButton
368 if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) >= 0.35) {
369 // seems like no further event occured, so let's switch the playback item
370 [[VLCCoreInteraction sharedInstance] next];
371 just_triggered_next = NO;
375 - (void)resetForwardSkip
377 // the user stopped skipping, so let's allow him to change the item
378 if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) >= 0.35)
379 just_triggered_next = NO;
382 - (IBAction)fwd:(id)sender
384 if(!just_triggered_next)
386 just_triggered_next = YES;
387 [self performSelector:@selector(resetNextButton)
393 if (([NSDate timeIntervalSinceReferenceDate] - last_fwd_event) > 0.12 )
395 // we just skipped 3 "continous" events, otherwise we are too fast
396 [[VLCCoreInteraction sharedInstance] forward];
397 last_fwd_event = [NSDate timeIntervalSinceReferenceDate];
398 [self performSelector:@selector(resetForwardSkip)
405 - (IBAction)stop:(id)sender
407 [[VLCCoreInteraction sharedInstance] stop];
410 - (IBAction)togglePlaylist:(id)sender
412 if ([o_video_view isHidden] && [o_playlist_btn isEnabled]) {
413 [o_playlist_table setHidden: YES];
414 [o_video_view setHidden: NO];
418 [o_video_view setHidden: YES];
419 [o_playlist_table setHidden: NO];
425 [o_repeat_btn setImage: o_repeat_one_img];
426 [o_repeat_btn setAlternateImage: o_repeat_one_pressed_img];
431 [o_repeat_btn setImage: o_repeat_all_img];
432 [o_repeat_btn setAlternateImage: o_repeat_all_pressed_img];
437 [o_repeat_btn setImage: o_repeat_img];
438 [o_repeat_btn setAlternateImage: o_repeat_pressed_img];
441 - (IBAction)repeat:(id)sender
443 vlc_value_t looping,repeating;
444 intf_thread_t * p_intf = VLCIntf;
445 playlist_t * p_playlist = pl_Get( p_intf );
447 var_Get( p_playlist, "repeat", &repeating );
448 var_Get( p_playlist, "loop", &looping );
450 if( !repeating.b_bool && !looping.b_bool )
452 /* was: no repeating at all, switching to Repeat One */
453 [[VLCCoreInteraction sharedInstance] repeatOne];
456 else if( repeating.b_bool && !looping.b_bool )
458 /* was: Repeat One, switching to Repeat All */
459 [[VLCCoreInteraction sharedInstance] repeatAll];
464 /* was: Repeat All or bug in VLC, switching to Repeat Off */
465 [[VLCCoreInteraction sharedInstance] repeatOff];
473 playlist_t *p_playlist = pl_Get( VLCIntf );
474 b_value = var_GetBool( p_playlist, "random" );
476 [o_shuffle_btn setImage: o_shuffle_on_img];
477 [o_shuffle_btn setAlternateImage: o_shuffle_on_pressed_img];
481 [o_shuffle_btn setImage: o_shuffle_img];
482 [o_shuffle_btn setAlternateImage: o_shuffle_pressed_img];
486 - (IBAction)shuffle:(id)sender
488 [[VLCCoreInteraction sharedInstance] shuffle];
492 - (IBAction)timeSliderAction:(id)sender
495 input_thread_t * p_input;
497 switch( [[NSApp currentEvent] type] )
500 case NSLeftMouseDown:
501 case NSLeftMouseDragged:
502 f_updated = [sender floatValue];
508 p_input = pl_CurrentInput( VLCIntf );
509 if( p_input != NULL )
514 char psz_time[MSTRTIME_MAX_SIZE];
516 pos.f_float = f_updated / 10000.;
517 var_Set( p_input, "position", pos );
518 [o_time_sld setFloatValue: f_updated];
520 var_Get( p_input, "time", &time );
522 mtime_t dur = input_item_GetDuration( input_GetItem( p_input ) );
523 if( [o_time_fld timeRemaining] && dur != -1 )
525 o_time = [NSString stringWithFormat: @"-%s", secstotimestr( psz_time, ((dur - time.i_time) / 1000000) )];
528 o_time = [NSString stringWithUTF8String: secstotimestr( psz_time, (time.i_time / 1000000) )];
530 [o_time_fld setStringValue: o_time];
531 [o_fspanel setStreamPos: f_updated andTime: o_time];
532 vlc_object_release( p_input );
534 [self drawFancyGradientEffectForTimeSlider];
537 - (IBAction)volumeAction:(id)sender
539 if (sender == o_volume_sld)
540 [[VLCCoreInteraction sharedInstance] setVolume: [sender intValue]];
541 else if (sender == o_volume_down_btn)
542 [[VLCCoreInteraction sharedInstance] mute];
544 [[VLCCoreInteraction sharedInstance] setVolume: 400];
547 - (IBAction)effects:(id)sender
549 [[VLCMainMenu sharedInstance] showAudioEffects: sender];
552 - (IBAction)fullscreen:(id)sender
554 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
557 - (IBAction)dropzoneButtonAction:(id)sender
559 [[[VLCMain sharedInstance] open] openFileGeneric];
563 #pragma mark Update interface and respond to foreign events
566 [o_right_split_view addSubview: o_dropzone_view];
567 [o_dropzone_view setFrame: [o_playlist_table frame]];
568 [[o_playlist_table animator] setHidden:YES];
573 [o_dropzone_view removeFromSuperview];
574 [[o_playlist_table animator] setHidden: NO];
577 - (void)updateTimeSlider
579 input_thread_t * p_input;
580 p_input = pl_CurrentInput( VLCIntf );
586 char psz_time[MSTRTIME_MAX_SIZE];
589 var_Get( p_input, "position", &pos );
590 f_updated = 10000. * pos.f_float;
591 [o_time_sld setFloatValue: f_updated];
593 var_Get( p_input, "time", &time );
595 mtime_t dur = input_item_GetDuration( input_GetItem( p_input ) );
596 if( [o_time_fld timeRemaining] && dur != -1 )
598 o_time = [NSString stringWithFormat: @"-%s", secstotimestr( psz_time, ((dur - time.i_time) / 1000000))];
601 o_time = [NSString stringWithUTF8String: secstotimestr( psz_time, (time.i_time / 1000000) )];
604 [o_time_sld setEnabled: NO];
605 [o_time_sld setHidden: YES];
607 [o_time_sld setEnabled: YES];
608 [o_time_sld setHidden: NO];
611 [o_time_fld setStringValue: o_time];
612 [o_time_fld setNeedsDisplay:YES];
613 [o_fspanel setStreamPos: f_updated andTime: o_time];
614 vlc_object_release( p_input );
618 [o_time_sld setFloatValue: 0.0];
619 [o_time_fld setStringValue: @"00:00"];
620 [o_time_sld setEnabled: NO];
621 [o_time_sld setHidden: YES];
624 [self performSelectorOnMainThread:@selector(drawFancyGradientEffectForTimeSlider) withObject:nil waitUntilDone:NO];
627 - (void)updateVolumeSlider
629 audio_volume_t i_volume;
630 playlist_t * p_playlist = pl_Get( VLCIntf );
632 i_volume = aout_VolumeGet( p_playlist );
634 if( i_volume != i_lastShownVolume )
636 i_lastShownVolume = i_volume;
637 int i_volume_step = 0;
638 i_volume_step = config_GetInt( VLCIntf->p_libvlc, "volume-step" );
639 [o_volume_sld setFloatValue: (float)i_lastShownVolume / i_volume_step];
640 [o_fspanel setVolumeLevel: (float)i_lastShownVolume / i_volume_step];
646 NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
647 input_thread_t * p_input;
648 p_input = pl_CurrentInput( VLCIntf );
652 char *format = var_InheritString( VLCIntf, "input-title-format" );
653 char *formated = str_format_meta( p_input, format );
655 aString = [NSString stringWithUTF8String:formated];
658 char *uri = input_item_GetURI( input_GetItem( p_input ) );
660 NSURL * o_url = [NSURL URLWithString: [NSString stringWithUTF8String: uri]];
661 if ([o_url isFileURL])
662 [self setRepresentedURL: o_url];
664 [self setRepresentedURL: [NSURL URLWithString:@""]];
667 if ([aString isEqualToString:@""])
669 if ([o_url isFileURL])
670 aString = [[NSFileManager defaultManager] displayNameAtPath: [o_url path]];
672 aString = [o_url absoluteString];
675 [self setTitle: aString];
676 [o_fspanel setStreamTitle: aString];
680 [self setTitle: _NS("VLC media player")];
681 [self setRepresentedURL: [NSURL URLWithString: @""]];
688 bool b_input = false;
689 bool b_plmul = false;
690 bool b_control = false;
691 bool b_seekable = false;
692 bool b_chapters = false;
694 playlist_t * p_playlist = pl_Get( VLCIntf );
697 b_plmul = playlist_CurrentSize( p_playlist ) > 1;
700 input_thread_t * p_input = playlist_CurrentInput( p_playlist );
702 bool b_buffering = NO;
704 if( ( b_input = ( p_input != NULL ) ) )
706 /* seekable streams */
707 cachedInputState = input_GetState( p_input );
708 if ( cachedInputState == INIT_S || cachedInputState == OPENING_S )
711 /* seekable streams */
712 b_seekable = var_GetBool( p_input, "can-seek" );
714 /* check whether slow/fast motion is possible */
715 b_control = var_GetBool( p_input, "can-rate" );
717 /* chapters & titles */
718 //FIXME! b_chapters = p_input->stream.i_area_nb > 1;
719 vlc_object_release( p_input );
724 [o_progress_bar startAnimation:self];
725 [o_progress_bar setIndeterminate:YES];
726 [o_progress_bar setHidden:NO];
728 [o_progress_bar stopAnimation:self];
729 [o_progress_bar setHidden:YES];
732 [o_stop_btn setEnabled: b_input];
733 [o_fwd_btn setEnabled: (b_seekable || b_plmul || b_chapters)];
734 [o_bwd_btn setEnabled: (b_seekable || b_plmul || b_chapters)];
735 [[VLCMainMenu sharedInstance] setRateControlsEnabled: b_control];
737 [o_time_sld setEnabled: b_seekable];
738 [self updateTimeSlider];
739 [o_fspanel setSeekable: b_seekable];
742 if (playlist_CurrentSize( p_playlist ) >= 1)
751 [o_play_btn setImage: o_pause_img];
752 [o_play_btn setAlternateImage: o_pause_pressed_img];
753 [o_play_btn setToolTip: _NS("Pause")];
754 [o_fspanel setPause];
759 [o_play_btn setImage: o_play_img];
760 [o_play_btn setAlternateImage: o_play_pressed_img];
761 [o_play_btn setToolTip: _NS("Play")];
765 - (void)drawFancyGradientEffectForTimeSlider
767 NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
768 float f_value = ([o_time_sld_middle_view frame].size.width -5) * ([o_time_sld intValue] / [o_time_sld maxValue]);
771 if (f_value != [o_time_sld_fancygradient_view frame].size.width)
773 [o_time_sld_fancygradient_view setHidden: NO];
774 [o_time_sld_fancygradient_view setFrame: NSMakeRect( [o_time_sld_fancygradient_view frame].origin.x, [o_time_sld_fancygradient_view frame].origin.y, f_value, [o_time_sld_fancygradient_view frame].size.height )];
775 [o_time_sld_fancygradient_view setNeedsDisplay:YES];
776 [o_time_sld_middle_view setNeedsDisplay:YES];
781 [o_time_sld_fancygradient_view setHidden: YES];
787 #pragma mark Video Output handling
794 - (void)setVideoplayEnabled
796 [o_playlist_btn setEnabled: [[VLCMain sharedInstance] activeVideoPlayback]];
804 NSPoint topleftscreen;
807 topleftbase.y = [self frame].size.height;
808 topleftscreen = [self convertBaseToScreen: topleftbase];
810 /* Calculate the window's new size */
811 new_frame.size.width = [self frame].size.width - [o_video_view frame].size.width + nativeVideoSize.width;
812 new_frame.size.height = [self frame].size.height - [o_video_view frame].size.height + nativeVideoSize.height;
814 new_frame.origin.x = topleftscreen.x;
815 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
817 [[self animator] setFrame:new_frame display:YES];
821 - (void)setNativeVideoSize:(NSSize)size
823 if (size.width != nativeVideoSize.width || size.height != nativeVideoSize.height )
825 nativeVideoSize = size;
831 #pragma mark Fullscreen support
832 - (void)showFullscreenController
843 - (void)lockFullscreenAnimation
845 [o_animation_lock lock];
848 - (void)unlockFullscreenAnimation
850 [o_animation_lock unlock];
853 - (void)enterFullscreen
855 NSMutableDictionary *dict1, *dict2;
859 vout_thread_t *p_vout = getVout();
860 BOOL blackout_other_displays = config_GetInt( VLCIntf, "macosx-black" );
863 screen = [NSScreen screenWithDisplayID:(CGDirectDisplayID)var_GetInteger( p_vout, "video-device" )];
865 [self lockFullscreenAnimation];
869 msg_Dbg( VLCIntf, "chosen screen isn't present, using current screen for fullscreen mode" );
870 screen = [self screen];
874 msg_Dbg( VLCIntf, "Using deepest screen" );
875 screen = [NSScreen deepestScreen];
879 vlc_object_release( p_vout );
881 screen_rect = [screen frame];
883 [o_fullscreen_btn setState: YES];
885 [NSCursor setHiddenUntilMouseMoves: YES];
887 if( blackout_other_displays )
888 [screen blackoutOtherScreens];
890 /* Make sure we don't see the window flashes in float-on-top mode */
891 i_originalLevel = [self level];
892 [self setLevel:NSNormalWindowLevel];
894 /* Only create the o_fullscreen_window if we are not in the middle of the zooming animation */
895 if (!o_fullscreen_window)
897 /* We can't change the styleMask of an already created NSWindow, so we create another window, and do eye catching stuff */
899 rect = [[o_video_view superview] convertRect: [o_video_view frame] toView: nil]; /* Convert to Window base coord */
900 rect.origin.x += [self frame].origin.x;
901 rect.origin.y += [self frame].origin.y;
902 o_fullscreen_window = [[VLCWindow alloc] initWithContentRect:rect styleMask: NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
903 [o_fullscreen_window setBackgroundColor: [NSColor blackColor]];
904 [o_fullscreen_window setCanBecomeKeyWindow: YES];
906 if (![self isVisible] || [self alphaValue] == 0.0)
908 /* We don't animate if we are not visible, instead we
909 * simply fade the display */
910 CGDisplayFadeReservationToken token;
912 if( blackout_other_displays )
914 CGAcquireDisplayFadeReservation( kCGMaxDisplayReservationInterval, &token );
915 CGDisplayFade( token, 0.5, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES );
918 if ([screen isMainScreen])
919 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
921 [[o_video_view superview] replaceSubview:o_video_view with:o_temp_view];
922 [o_temp_view setFrame:[o_video_view frame]];
923 [o_fullscreen_window setContentView:o_video_view];
925 [o_fullscreen_window makeKeyAndOrderFront:self];
926 [o_fullscreen_window orderFront:self animate:YES];
928 [o_fullscreen_window setFrame:screen_rect display:YES animate:YES];
929 [o_fullscreen_window setLevel:NSNormalWindowLevel];
931 if( blackout_other_displays )
933 CGDisplayFade( token, 0.3, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO );
934 CGReleaseDisplayFadeReservation( token );
937 /* Will release the lock */
938 [self hasBecomeFullscreen];
943 /* Make sure we don't see the o_video_view disappearing of the screen during this operation */
944 NSDisableScreenUpdates();
945 [[o_video_view superview] replaceSubview:o_video_view with:o_temp_view];
946 [o_temp_view setFrame:[o_video_view frame]];
947 [o_fullscreen_window setContentView:o_video_view];
948 [o_fullscreen_window makeKeyAndOrderFront:self];
949 NSEnableScreenUpdates();
952 /* We are in fullscreen (and no animation is running) */
955 /* Make sure we are hidden */
956 [super orderOut: self];
957 [self unlockFullscreenAnimation];
961 if (o_fullscreen_anim1)
963 [o_fullscreen_anim1 stopAnimation];
964 [o_fullscreen_anim1 release];
966 if (o_fullscreen_anim2)
968 [o_fullscreen_anim2 stopAnimation];
969 [o_fullscreen_anim2 release];
972 if ([screen isMainScreen])
973 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
975 dict1 = [[NSMutableDictionary alloc] initWithCapacity:2];
976 dict2 = [[NSMutableDictionary alloc] initWithCapacity:3];
978 [dict1 setObject:self forKey:NSViewAnimationTargetKey];
979 [dict1 setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
981 [dict2 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
982 [dict2 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
983 [dict2 setObject:[NSValue valueWithRect:screen_rect] forKey:NSViewAnimationEndFrameKey];
985 /* Strategy with NSAnimation allocation:
986 - Keep at most 2 animation at a time
987 - leaveFullscreen/enterFullscreen are the only responsible for releasing and alloc-ing
989 o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict1]];
990 o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict2]];
995 [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
996 [o_fullscreen_anim1 setDuration: 0.3];
997 [o_fullscreen_anim1 setFrameRate: 30];
998 [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
999 [o_fullscreen_anim2 setDuration: 0.2];
1000 [o_fullscreen_anim2 setFrameRate: 30];
1002 [o_fullscreen_anim2 setDelegate: self];
1003 [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
1005 [o_fullscreen_anim1 startAnimation];
1006 /* fullscreenAnimation will be unlocked when animation ends */
1009 - (void)hasBecomeFullscreen
1011 [o_fullscreen_window makeFirstResponder: o_video_view];
1013 [o_fullscreen_window makeKeyWindow];
1014 [o_fullscreen_window setAcceptsMouseMovedEvents: TRUE];
1016 /* tell the fspanel to move itself to front next time it's triggered */
1017 [o_fspanel setVoutWasUpdated: (int)[[o_fullscreen_window screen] displayID]];
1018 [o_fspanel setActive: nil];
1020 if([self isVisible])
1021 [super orderOut: self];
1023 [o_fspanel setActive: nil];
1026 [self unlockFullscreenAnimation];
1029 - (void)leaveFullscreen
1031 [self leaveFullscreenAndFadeOut: NO];
1034 - (void)leaveFullscreenAndFadeOut: (BOOL)fadeout
1036 NSMutableDictionary *dict1, *dict2;
1038 BOOL blackout_other_displays = config_GetInt( VLCIntf, "macosx-black" );
1040 [self lockFullscreenAnimation];
1043 [o_fullscreen_btn setState: NO];
1045 /* We always try to do so */
1046 [NSScreen unblackoutScreens];
1047 vout_thread_t *p_vout = getVout();
1050 if( var_GetBool( p_vout, "video-on-top" ) )
1051 [self setLevel: NSStatusWindowLevel];
1053 [self setLevel: NSNormalWindowLevel];
1054 vlc_object_release( p_vout );
1056 [self makeKeyAndOrderFront: nil];
1058 /* Don't do anything if o_fullscreen_window is already closed */
1059 if (!o_fullscreen_window)
1061 [self unlockFullscreenAnimation];
1067 /* We don't animate if we are not visible, instead we
1068 * simply fade the display */
1069 CGDisplayFadeReservationToken token;
1071 if( blackout_other_displays )
1073 CGAcquireDisplayFadeReservation( kCGMaxDisplayReservationInterval, &token );
1074 CGDisplayFade( token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0, 0, 0, YES );
1077 [o_fspanel setNonActive: nil];
1078 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
1080 /* Will release the lock */
1081 [self hasEndedFullscreen];
1083 /* Our window is hidden, and might be faded. We need to workaround that, so note it
1085 b_window_is_invisible = YES;
1087 if( blackout_other_displays )
1089 CGDisplayFade( token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0, 0, 0, NO );
1090 CGReleaseDisplayFadeReservation( token );
1096 [self setAlphaValue: 0.0];
1097 [self orderFront: self];
1099 [o_fspanel setNonActive: nil];
1100 SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
1102 if (o_fullscreen_anim1)
1104 [o_fullscreen_anim1 stopAnimation];
1105 [o_fullscreen_anim1 release];
1107 if (o_fullscreen_anim2)
1109 [o_fullscreen_anim2 stopAnimation];
1110 [o_fullscreen_anim2 release];
1113 frame = [[o_temp_view superview] convertRect: [o_temp_view frame] toView: nil]; /* Convert to Window base coord */
1114 frame.origin.x += [self frame].origin.x;
1115 frame.origin.y += [self frame].origin.y;
1117 dict2 = [[NSMutableDictionary alloc] initWithCapacity:2];
1118 [dict2 setObject:self forKey:NSViewAnimationTargetKey];
1119 [dict2 setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
1121 o_fullscreen_anim2 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict2, nil]];
1124 [o_fullscreen_anim2 setAnimationBlockingMode: NSAnimationNonblocking];
1125 [o_fullscreen_anim2 setDuration: 0.3];
1126 [o_fullscreen_anim2 setFrameRate: 30];
1128 [o_fullscreen_anim2 setDelegate: self];
1130 dict1 = [[NSMutableDictionary alloc] initWithCapacity:3];
1132 [dict1 setObject:o_fullscreen_window forKey:NSViewAnimationTargetKey];
1133 [dict1 setObject:[NSValue valueWithRect:[o_fullscreen_window frame]] forKey:NSViewAnimationStartFrameKey];
1134 [dict1 setObject:[NSValue valueWithRect:frame] forKey:NSViewAnimationEndFrameKey];
1136 o_fullscreen_anim1 = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict1, nil]];
1139 [o_fullscreen_anim1 setAnimationBlockingMode: NSAnimationNonblocking];
1140 [o_fullscreen_anim1 setDuration: 0.2];
1141 [o_fullscreen_anim1 setFrameRate: 30];
1142 [o_fullscreen_anim2 startWhenAnimation: o_fullscreen_anim1 reachesProgress: 1.0];
1144 /* Make sure o_fullscreen_window is the frontmost window */
1145 [o_fullscreen_window orderFront: self];
1147 [o_fullscreen_anim1 startAnimation];
1148 /* fullscreenAnimation will be unlocked when animation ends */
1151 - (void)hasEndedFullscreen
1153 /* This function is private and should be only triggered at the end of the fullscreen change animation */
1154 /* Make sure we don't see the o_video_view disappearing of the screen during this operation */
1155 NSDisableScreenUpdates();
1156 [o_video_view retain];
1157 [o_video_view removeFromSuperviewWithoutNeedingDisplay];
1158 [[o_temp_view superview] replaceSubview:o_temp_view with:o_video_view];
1159 [o_video_view release];
1160 [o_video_view setFrame:[o_temp_view frame]];
1161 [self makeFirstResponder: o_video_view];
1162 if ([self isVisible])
1163 [super makeKeyAndOrderFront:self]; /* our version contains a workaround */
1164 [o_fullscreen_window orderOut: self];
1165 NSEnableScreenUpdates();
1167 [o_fullscreen_window release];
1168 o_fullscreen_window = nil;
1169 [self setLevel:i_originalLevel];
1171 [self unlockFullscreenAnimation];
1174 - (void)animationDidEnd:(NSAnimation*)animation
1176 NSArray *viewAnimations;
1177 if( o_makekey_anim == animation )
1179 [o_makekey_anim release];
1182 if ([animation currentValue] < 1.0)
1185 /* Fullscreen ended or started (we are a delegate only for leaveFullscreen's/enterFullscren's anim2) */
1186 viewAnimations = [o_fullscreen_anim2 viewAnimations];
1187 if ([viewAnimations count] >=1 &&
1188 [[[viewAnimations objectAtIndex: 0] objectForKey: NSViewAnimationEffectKey] isEqualToString:NSViewAnimationFadeInEffect])
1190 /* Fullscreen ended */
1191 [self hasEndedFullscreen];
1195 /* Fullscreen started */
1196 [self hasBecomeFullscreen];
1200 - (void)orderOut: (id)sender
1202 [super orderOut: sender];
1204 /* Make sure we leave fullscreen */
1205 [self leaveFullscreenAndFadeOut: YES];
1208 - (void)makeKeyAndOrderFront: (id)sender
1211 * when we exit fullscreen and fade out, we may endup in
1212 * having a window that is faded. We can't have it fade in unless we
1215 if(!b_window_is_invisible)
1217 /* Make sure we don't do it too much */
1218 [super makeKeyAndOrderFront: sender];
1222 [super setAlphaValue:0.0f];
1223 [super makeKeyAndOrderFront: sender];
1225 NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithCapacity:2];
1226 [dict setObject:self forKey:NSViewAnimationTargetKey];
1227 [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
1229 o_makekey_anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
1232 [o_makekey_anim setAnimationBlockingMode: NSAnimationNonblocking];
1233 [o_makekey_anim setDuration: 0.1];
1234 [o_makekey_anim setFrameRate: 30];
1235 [o_makekey_anim setDelegate: self];
1237 [o_makekey_anim startAnimation];
1238 b_window_is_invisible = NO;
1240 /* fullscreenAnimation will be unlocked when animation ends */
1245 /* Make sure setFrame gets executed on main thread especially if we are animating.
1246 * (Thus we won't block the video output thread) */
1247 - (void)setFrame:(NSRect)frame display:(BOOL)display animate:(BOOL)animate
1249 struct { NSRect frame; BOOL display; BOOL animate;} args;
1253 args.display = display;
1254 args.animate = animate;
1256 packedargs = [NSData dataWithBytes:&args length:sizeof(args)];
1258 [self performSelectorOnMainThread:@selector(setFrameOnMainThread:)
1259 withObject: packedargs waitUntilDone: YES];
1262 - (void)setFrameOnMainThread:(NSData*)packedargs
1264 struct args { NSRect frame; BOOL display; BOOL animate; } * args = (struct args*)[packedargs bytes];
1268 /* Make sure we don't block too long and set up a non blocking animation */
1269 NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:
1270 self, NSViewAnimationTargetKey,
1271 [NSValue valueWithRect:[self frame]], NSViewAnimationStartFrameKey,
1272 [NSValue valueWithRect:args->frame], NSViewAnimationEndFrameKey, nil];
1274 NSViewAnimation * anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObject:dict]];
1277 [anim setAnimationBlockingMode: NSAnimationNonblocking];
1278 [anim setDuration: 0.4];
1279 [anim setFrameRate: 30];
1280 [anim startAnimation];
1283 [super setFrame:args->frame display:args->display animate:args->animate];
1288 #pragma mark Side Bar Data handling
1289 /* taken under BSD-new from the PXSourceList sample project, adapted for VLC */
1290 - (NSUInteger)sourceList:(PXSourceList*)sourceList numberOfChildrenOfItem:(id)item
1292 //Works the same way as the NSOutlineView data source: `nil` means a parent item
1294 return [o_sidebaritems count];
1297 return [[item children] count];
1302 - (id)sourceList:(PXSourceList*)aSourceList child:(NSUInteger)index ofItem:(id)item
1304 //Works the same way as the NSOutlineView data source: `nil` means a parent item
1306 return [o_sidebaritems objectAtIndex:index];
1309 return [[item children] objectAtIndex:index];
1314 - (id)sourceList:(PXSourceList*)aSourceList objectValueForItem:(id)item
1316 return [item title];
1319 - (void)sourceList:(PXSourceList*)aSourceList setObjectValue:(id)object forItem:(id)item
1321 [item setTitle:object];
1324 - (BOOL)sourceList:(PXSourceList*)aSourceList isItemExpandable:(id)item
1326 return [item hasChildren];
1330 - (BOOL)sourceList:(PXSourceList*)aSourceList itemHasBadge:(id)item
1332 return [item hasBadge];
1336 - (NSInteger)sourceList:(PXSourceList*)aSourceList badgeValueForItem:(id)item
1338 return [item badgeValue];
1342 - (BOOL)sourceList:(PXSourceList*)aSourceList itemHasIcon:(id)item
1344 return [item hasIcon];
1348 - (NSImage*)sourceList:(PXSourceList*)aSourceList iconForItem:(id)item
1353 - (NSMenu*)sourceList:(PXSourceList*)aSourceList menuForEvent:(NSEvent*)theEvent item:(id)item
1355 if ([theEvent type] == NSRightMouseDown || ([theEvent type] == NSLeftMouseDown && ([theEvent modifierFlags] & NSControlKeyMask) == NSControlKeyMask)) {
1356 NSMenu * m = [[NSMenu alloc] init];
1358 [m addItemWithTitle:[item title] action:nil keyEquivalent:@""];
1359 return [m autorelease];
1365 #pragma mark Side Bar Delegate Methods
1366 /* taken under BSD-new from the PXSourceList sample project, adapted for VLC */
1367 - (BOOL)sourceList:(PXSourceList*)aSourceList isGroupAlwaysExpanded:(id)group
1369 if([[group identifier] isEqualToString:@"library"])
1375 - (void)sourceListSelectionDidChange:(NSNotification *)notification
1377 NSIndexSet *selectedIndexes = [o_sidebar_view selectedRowIndexes];
1379 //Set the label text to represent the new selection
1380 if([selectedIndexes count]==1) {
1381 NSString *title = [[o_sidebar_view itemAtRow:[selectedIndexes firstIndex]] title];
1383 [o_chosen_category_lbl setStringValue:title];
1386 [o_chosen_category_lbl setStringValue:@"(none)"];
1392 @implementation VLCProgressBarGradientEffect
1395 [o_time_sld_gradient_left_img release];
1396 [o_time_sld_gradient_middle_img release];
1397 [o_time_sld_gradient_right_img release];
1401 - (void)loadImagesInDarkStyle: (BOOL)b_value
1405 o_time_sld_gradient_left_img = [[NSImage imageNamed:@"progressbar-fill-left_dark"] retain];
1406 o_time_sld_gradient_middle_img = [[NSImage imageNamed:@"progressbar-fill-middle_dark"] retain];
1407 o_time_sld_gradient_right_img = [[NSImage imageNamed:@"progressbar-fill-right_dark"] retain];
1411 o_time_sld_gradient_left_img = [[NSImage imageNamed:@"progression-fill-left"] retain];
1412 o_time_sld_gradient_middle_img = [[NSImage imageNamed:@"progression-fill-middle"] retain];
1413 o_time_sld_gradient_right_img = [[NSImage imageNamed:@"progression-fill-right"] retain];
1417 - (void)drawRect:(NSRect)rect
1419 NSRect bnds = [self bounds];
1420 NSDrawThreePartImage( bnds, o_time_sld_gradient_left_img, o_time_sld_gradient_middle_img, o_time_sld_gradient_right_img, NO, NSCompositeSourceOver, 1, NO );