1 /*****************************************************************************
2 * ControlsBar.m: MacOS X interface module
3 *****************************************************************************
4 * Copyright (C) 2012-2016 VLC authors and VideoLAN
7 * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8 * David Fuhrmann <david dot fuhrmann at googlemail dot com>
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 #import "VLCControlsBarCommon.h"
26 #import "VLCMainWindowControlsBar.h"
28 #import "VLCCoreInteraction.h"
29 #import "VLCMainMenu.h"
30 #import "VLCPlaylist.h"
31 #import "CompatibilityFixes.h"
33 /*****************************************************************************
34 * VLCMainWindowControlsBar
36 * Holds all specific outlets, actions and code for the main window controls bar.
37 *****************************************************************************/
39 @interface VLCMainWindowControlsBar()
41 NSImage * _repeatImage;
42 NSImage * _pressedRepeatImage;
43 NSImage * _repeatAllImage;
44 NSImage * _pressedRepeatAllImage;
45 NSImage * _repeatOneImage;
46 NSImage * _pressedRepeatOneImage;
47 NSImage * _shuffleImage;
48 NSImage * _pressedShuffleImage;
49 NSImage * _shuffleOnImage;
50 NSImage * _pressedShuffleOnImage;
52 NSButton * _previousButton;
53 NSButton * _nextButton;
55 BOOL b_show_jump_buttons;
56 BOOL b_show_playmode_buttons;
59 - (void)addJumpButtons:(BOOL)b_fast;
60 - (void)removeJumpButtons:(BOOL)b_fast;
61 - (void)addPlaymodeButtons:(BOOL)b_fast;
62 - (void)removePlaymodeButtons:(BOOL)b_fast;
66 @implementation VLCMainWindowControlsBar
72 [self.stopButton setToolTip: _NS("Stop")];
73 [[self.stopButton cell] accessibilitySetOverrideValue:_NS("Click to stop playback.") forAttribute:NSAccessibilityDescriptionAttribute];
74 [[self.stopButton cell] accessibilitySetOverrideValue:[self.stopButton toolTip] forAttribute:NSAccessibilityTitleAttribute];
76 [self.playlistButton setToolTip: _NS("Show/Hide Playlist")];
77 [[self.playlistButton cell] accessibilitySetOverrideValue:_NS("Click to switch between video output and playlist. If no video is shown in the main window, this allows you to hide the playlist.") forAttribute:NSAccessibilityDescriptionAttribute];
78 [[self.playlistButton cell] accessibilitySetOverrideValue:[self.playlistButton toolTip] forAttribute:NSAccessibilityTitleAttribute];
80 [self.repeatButton setToolTip: _NS("Repeat")];
81 [[self.repeatButton cell] accessibilitySetOverrideValue:_NS("Click to change repeat mode. There are 3 states: repeat one, repeat all and off.") forAttribute:NSAccessibilityDescriptionAttribute];
82 [[self.repeatButton cell] accessibilitySetOverrideValue:[self.repeatButton toolTip] forAttribute:NSAccessibilityTitleAttribute];
84 [self.shuffleButton setToolTip: _NS("Shuffle")];
85 [[self.shuffleButton cell] accessibilitySetOverrideValue:[self.shuffleButton toolTip] forAttribute:NSAccessibilityTitleAttribute];
86 [[self.shuffleButton cell] accessibilitySetOverrideValue:_NS("Click to enable or disable random playback.") forAttribute:NSAccessibilityDescriptionAttribute];
88 NSString *volumeTooltip = [NSString stringWithFormat:_NS("Volume: %i %%"), 100];
89 [self.volumeSlider setToolTip: volumeTooltip];
90 [[self.volumeSlider cell] accessibilitySetOverrideValue:_NS("Click and move the mouse while keeping the button pressed to use this slider to change the volume.") forAttribute:NSAccessibilityDescriptionAttribute];
91 [[self.volumeSlider cell] accessibilitySetOverrideValue:[self.volumeSlider toolTip] forAttribute:NSAccessibilityTitleAttribute];
92 [self.volumeDownButton setToolTip: _NS("Mute")];
93 [[self.volumeDownButton cell] accessibilitySetOverrideValue:_NS("Click to mute or unmute the audio.") forAttribute:NSAccessibilityDescriptionAttribute];
94 [[self.volumeDownButton cell] accessibilitySetOverrideValue:[self.volumeDownButton toolTip] forAttribute:NSAccessibilityTitleAttribute];
95 [self.volumeUpButton setToolTip: _NS("Full Volume")];
96 [[self.volumeUpButton cell] accessibilitySetOverrideValue:_NS("Click to play the audio at maximum volume.") forAttribute:NSAccessibilityDescriptionAttribute];
97 [[self.volumeUpButton cell] accessibilitySetOverrideValue:[self.volumeUpButton toolTip] forAttribute:NSAccessibilityTitleAttribute];
99 [self.effectsButton setToolTip: _NS("Audio Effects")];
100 [[self.effectsButton cell] accessibilitySetOverrideValue:_NS("Click to show an Audio Effects panel featuring an equalizer and further filters.") forAttribute:NSAccessibilityDescriptionAttribute];
101 [[self.effectsButton cell] accessibilitySetOverrideValue:[self.effectsButton toolTip] forAttribute:NSAccessibilityTitleAttribute];
103 if (!self.darkInterface) {
104 [self.stopButton setImage: imageFromRes(@"stop")];
105 [self.stopButton setAlternateImage: imageFromRes(@"stop-pressed")];
107 [self.playlistButton setImage: imageFromRes(@"playlist-btn")];
108 [self.playlistButton setAlternateImage: imageFromRes(@"playlist-btn-pressed")];
109 _repeatImage = imageFromRes(@"repeat");
110 _pressedRepeatImage = imageFromRes(@"repeat-pressed");
111 _repeatAllImage = imageFromRes(@"repeat-all");
112 _pressedRepeatAllImage = imageFromRes(@"repeat-all-pressed");
113 _repeatOneImage = imageFromRes(@"repeat-one");
114 _pressedRepeatOneImage = imageFromRes(@"repeat-one-pressed");
115 _shuffleImage = imageFromRes(@"shuffle");
116 _pressedShuffleImage = imageFromRes(@"shuffle-pressed");
117 _shuffleOnImage = imageFromRes(@"shuffle-blue");
118 _pressedShuffleOnImage = imageFromRes(@"shuffle-blue-pressed");
120 [self.volumeDownButton setImage: imageFromRes(@"volume-low")];
121 [self.volumeTrackImageView setImage: imageFromRes(@"volume-slider-track")];
122 [self.volumeUpButton setImage: imageFromRes(@"volume-high")];
123 [self.volumeSlider setUsesBrightArtwork: YES];
125 if (self.nativeFullscreenMode) {
126 [self.effectsButton setImage: imageFromRes(@"effects-one-button")];
127 [self.effectsButton setAlternateImage: imageFromRes(@"effects-one-button-pressed")];
129 [self.effectsButton setImage: imageFromRes(@"effects-double-buttons")];
130 [self.effectsButton setAlternateImage: imageFromRes(@"effects-double-buttons-pressed")];
133 [self.fullscreenButton setImage: imageFromRes(@"fullscreen-double-buttons")];
134 [self.fullscreenButton setAlternateImage: imageFromRes(@"fullscreen-double-buttons-pressed")];
136 [self.stopButton setImage: imageFromRes(@"stop_dark")];
137 [self.stopButton setAlternateImage: imageFromRes(@"stop-pressed_dark")];
139 [self.playlistButton setImage: imageFromRes(@"playlist_dark")];
140 [self.playlistButton setAlternateImage: imageFromRes(@"playlist-pressed_dark")];
141 _repeatImage = imageFromRes(@"repeat_dark");
142 _pressedRepeatImage = imageFromRes(@"repeat-pressed_dark");
143 _repeatAllImage = imageFromRes(@"repeat-all-blue_dark");
144 _pressedRepeatAllImage = imageFromRes(@"repeat-all-blue-pressed_dark");
145 _repeatOneImage = imageFromRes(@"repeat-one-blue_dark");
146 _pressedRepeatOneImage = imageFromRes(@"repeat-one-blue-pressed_dark");
147 _shuffleImage = imageFromRes(@"shuffle_dark");
148 _pressedShuffleImage = imageFromRes(@"shuffle-pressed_dark");
149 _shuffleOnImage = imageFromRes(@"shuffle-blue_dark");
150 _pressedShuffleOnImage = imageFromRes(@"shuffle-blue-pressed_dark");
152 [self.volumeDownButton setImage: imageFromRes(@"volume-low_dark")];
153 [self.volumeTrackImageView setImage: imageFromRes(@"volume-slider-track_dark")];
154 [self.volumeUpButton setImage: imageFromRes(@"volume-high_dark")];
155 [self.volumeSlider setUsesBrightArtwork: NO];
157 if (self.nativeFullscreenMode) {
158 [self.effectsButton setImage: imageFromRes(@"effects-one-button_dark")];
159 [self.effectsButton setAlternateImage: imageFromRes(@"effects-one-button-pressed-dark")];
161 [self.effectsButton setImage: imageFromRes(@"effects-double-buttons_dark")];
162 [self.effectsButton setAlternateImage: imageFromRes(@"effects-double-buttons-pressed_dark")];
165 [self.fullscreenButton setImage: imageFromRes(@"fullscreen-double-buttons_dark")];
166 [self.fullscreenButton setAlternateImage: imageFromRes(@"fullscreen-double-buttons-pressed_dark")];
168 [self.repeatButton setImage: _repeatImage];
169 [self.repeatButton setAlternateImage: _pressedRepeatImage];
170 [self.shuffleButton setImage: _shuffleImage];
171 [self.shuffleButton setAlternateImage: _pressedShuffleImage];
173 BOOL b_mute = ![[VLCCoreInteraction sharedInstance] mute];
174 [self.volumeSlider setEnabled: b_mute];
175 [self.volumeSlider setMaxValue: [[VLCCoreInteraction sharedInstance] maxVolume]];
176 [self.volumeUpButton setEnabled: b_mute];
178 // remove fullscreen button for lion fullscreen
179 if (self.nativeFullscreenMode) {
182 // == [fullscreenButton frame].size.width;
183 // button is already removed!
185 #define moveItem(item) \
186 frame = [item frame]; \
187 frame.origin.x = f_width + frame.origin.x; \
188 [item setFrame: frame]
190 moveItem(self.effectsButton);
191 moveItem(self.volumeUpButton);
192 moveItem(self.volumeSlider);
193 moveItem(self.volumeTrackImageView);
194 moveItem(self.volumeDownButton);
197 // time field and progress bar are moved in super method!
201 b_show_jump_buttons = config_GetInt(getIntf(), "macosx-show-playback-buttons");
202 if (b_show_jump_buttons)
203 [self addJumpButtons:YES];
205 b_show_playmode_buttons = config_GetInt(getIntf(), "macosx-show-playmode-buttons");
206 if (!b_show_playmode_buttons)
207 [self removePlaymodeButtons:YES];
209 if (!config_GetInt(getIntf(), "macosx-show-effects-button"))
210 [self removeEffectsButton:YES];
212 [[[VLCMain sharedInstance] playlist] playbackModeUpdated];
217 #pragma mark interface customization
220 - (void)toggleEffectsButton
222 if (config_GetInt(getIntf(), "macosx-show-effects-button"))
223 [self addEffectsButton:NO];
225 [self removeEffectsButton:NO];
228 - (void)addEffectsButton:(BOOL)b_fast
230 if (!self.effectsButton)
234 [self.effectsButton setHidden: NO];
236 [[self.effectsButton animator] setHidden: NO];
239 #define moveItem(item) \
240 frame = [item frame]; \
241 frame.origin.x = frame.origin.x - f_space; \
243 [item setFrame: frame]; \
245 [[item animator] setFrame: frame]
248 CGFloat f_space = [self.effectsButton frame].size.width;
249 // extra margin between button and volume up button
250 if (self.nativeFullscreenMode)
254 moveItem(self.volumeUpButton);
255 moveItem(self.volumeSlider);
256 moveItem(self.volumeTrackImageView);
257 moveItem(self.volumeDownButton);
258 moveItem(self.timeField);
262 frame = [self.progressView frame];
263 frame.size.width = frame.size.width - f_space;
265 [self.progressView setFrame: frame];
267 [[self.progressView animator] setFrame: frame];
269 if (!self.nativeFullscreenMode) {
270 if (self.darkInterface) {
271 [self.fullscreenButton setImage: imageFromRes(@"fullscreen-double-buttons_dark")];
272 [self.fullscreenButton setAlternateImage: imageFromRes(@"fullscreen-double-buttons-pressed_dark")];
274 [self.fullscreenButton setImage: imageFromRes(@"fullscreen-double-buttons")];
275 [self.fullscreenButton setAlternateImage: imageFromRes(@"fullscreen-double-buttons-pressed")];
279 [self.bottomBarView setNeedsDisplay:YES];
282 - (void)removeEffectsButton:(BOOL)b_fast
284 if (!self.effectsButton)
287 [self.effectsButton setHidden: YES];
289 #define moveItem(item) \
290 frame = [item frame]; \
291 frame.origin.x = frame.origin.x + f_space; \
293 [item setFrame: frame]; \
295 [[item animator] setFrame: frame]
298 CGFloat f_space = [self.effectsButton frame].size.width;
299 // extra margin between button and volume up button
300 if (self.nativeFullscreenMode)
303 moveItem(self.volumeUpButton);
304 moveItem(self.volumeSlider);
305 moveItem(self.volumeTrackImageView);
306 moveItem(self.volumeDownButton);
307 moveItem(self.timeField);
311 frame = [self.progressView frame];
312 frame.size.width = frame.size.width + f_space;
314 [self.progressView setFrame: frame];
316 [[self.progressView animator] setFrame: frame];
318 if (!self.nativeFullscreenMode) {
319 if (self.darkInterface) {
320 [[self.fullscreenButton animator] setImage: imageFromRes(@"fullscreen-one-button_dark")];
321 [[self.fullscreenButton animator] setAlternateImage: imageFromRes(@"fullscreen-one-button-pressed_dark")];
323 [[self.fullscreenButton animator] setImage: imageFromRes(@"fullscreen-one-button")];
324 [[self.fullscreenButton animator] setAlternateImage: imageFromRes(@"fullscreen-one-button-pressed")];
328 [self.bottomBarView setNeedsDisplay:YES];
331 - (void)toggleJumpButtons
333 b_show_jump_buttons = config_GetInt(getIntf(), "macosx-show-playback-buttons");
335 if (b_show_jump_buttons)
336 [self addJumpButtons:NO];
338 [self removeJumpButtons:NO];
341 - (void)addJumpButtons:(BOOL)b_fast
343 NSRect preliminaryFrame = [self.backwardButton frame];
344 BOOL b_enabled = [self.backwardButton isEnabled];
345 preliminaryFrame.size.width = 29.;
346 _previousButton = [[NSButton alloc] initWithFrame:preliminaryFrame];
347 [_previousButton setButtonType: NSMomentaryChangeButton];
348 [_previousButton setBezelStyle:NSRegularSquareBezelStyle];
349 [_previousButton setBordered:NO];
350 [_previousButton setTarget:self];
351 [_previousButton setAction:@selector(prev:)];
352 [_previousButton setToolTip: _NS("Previous")];
353 [[_previousButton cell] accessibilitySetOverrideValue:_NS("Previous") forAttribute:NSAccessibilityTitleAttribute];
354 [[_previousButton cell] accessibilitySetOverrideValue:_NS("Click to go to the previous playlist item.") forAttribute:NSAccessibilityDescriptionAttribute];
355 [_previousButton setEnabled: b_enabled];
357 _nextButton = [[NSButton alloc] initWithFrame:preliminaryFrame];
358 [_nextButton setButtonType: NSMomentaryChangeButton];
359 [_nextButton setBezelStyle:NSRegularSquareBezelStyle];
360 [_nextButton setBordered:NO];
361 [_nextButton setTarget:self];
362 [_nextButton setAction:@selector(next:)];
363 [_nextButton setToolTip: _NS("Next")];
364 [[_nextButton cell] accessibilitySetOverrideValue:_NS("Next") forAttribute:NSAccessibilityTitleAttribute];
365 [[_nextButton cell] accessibilitySetOverrideValue:_NS("Click to go to the next playlist item.") forAttribute:NSAccessibilityDescriptionAttribute];
366 [_nextButton setEnabled: b_enabled];
368 if (self.darkInterface) {
369 [_previousButton setImage: imageFromRes(@"previous-6btns-dark")];
370 [_previousButton setAlternateImage: imageFromRes(@"previous-6btns-dark-pressed")];
371 [_nextButton setImage: imageFromRes(@"next-6btns-dark")];
372 [_nextButton setAlternateImage: imageFromRes(@"next-6btns-dark-pressed")];
374 [_previousButton setImage: imageFromRes(@"previous-6btns")];
375 [_previousButton setAlternateImage: imageFromRes(@"previous-6btns-pressed")];
376 [_nextButton setImage: imageFromRes(@"next-6btns")];
377 [_nextButton setAlternateImage: imageFromRes(@"next-6btns-pressed")];
381 frame = [self.backwardButton frame];
383 [self.backwardButton setFrame:frame];
384 frame = [self.forwardButton frame];
386 [self.forwardButton setFrame:frame];
388 #define moveItem(item) \
389 frame = [item frame]; \
390 frame.origin.x = frame.origin.x + f_space; \
392 [item setFrame: frame]; \
394 [[item animator] setFrame: frame]
397 moveItem(self.backwardButton);
399 moveItem(self.playButton);
400 moveItem(self.forwardButton);
402 moveItem(self.stopButton);
403 moveItem(self.playlistButton);
404 moveItem(self.repeatButton);
405 moveItem(self.shuffleButton);
408 frame = [self.progressView frame];
409 frame.size.width = frame.size.width - f_space;
410 frame.origin.x = frame.origin.x + f_space;
412 [self.progressView setFrame: frame];
414 [[self.progressView animator] setFrame: frame];
416 if (self.darkInterface) {
417 [[self.forwardButton animator] setImage:imageFromRes(@"forward-6btns-dark")];
418 [[self.forwardButton animator] setAlternateImage:imageFromRes(@"forward-6btns-dark-pressed")];
419 [[self.backwardButton animator] setImage:imageFromRes(@"backward-6btns-dark")];
420 [[self.backwardButton animator] setAlternateImage:imageFromRes(@"backward-6btns-dark-pressed")];
422 [[self.forwardButton animator] setImage:imageFromRes(@"forward-6btns")];
423 [[self.forwardButton animator] setAlternateImage:imageFromRes(@"forward-6btns-pressed")];
424 [[self.backwardButton animator] setImage:imageFromRes(@"backward-6btns")];
425 [[self.backwardButton animator] setAlternateImage:imageFromRes(@"backward-6btns-pressed")];
428 preliminaryFrame.origin.x = [_previousButton frame].origin.x + [_previousButton frame].size.width + [self.backwardButton frame].size.width + [self.playButton frame].size.width + [self.forwardButton frame].size.width;
429 [_nextButton setFrame: preliminaryFrame];
431 // wait until the animation is done, if displayed
433 [self.bottomBarView addSubview:_previousButton];
434 [self.bottomBarView addSubview:_nextButton];
436 [self.bottomBarView performSelector:@selector(addSubview:) withObject:_previousButton afterDelay:.2];
437 [self.bottomBarView performSelector:@selector(addSubview:) withObject:_nextButton afterDelay:.2];
440 [self toggleForwardBackwardMode: YES];
443 - (void)removeJumpButtons:(BOOL)b_fast
445 if (!_previousButton || !_nextButton)
449 [_previousButton setHidden: YES];
450 [_nextButton setHidden: YES];
452 [[_previousButton animator] setHidden: YES];
453 [[_nextButton animator] setHidden: YES];
455 [_previousButton removeFromSuperviewWithoutNeedingDisplay];
456 [_nextButton removeFromSuperviewWithoutNeedingDisplay];
457 _previousButton = nil;
461 frame = [self.backwardButton frame];
463 [self.backwardButton setFrame:frame];
464 frame = [self.forwardButton frame];
466 [self.forwardButton setFrame:frame];
468 #define moveItem(item) \
469 frame = [item frame]; \
470 frame.origin.x = frame.origin.x - f_space; \
472 [item setFrame: frame]; \
474 [[item animator] setFrame: frame]
477 moveItem(self.backwardButton);
479 moveItem(self.playButton);
480 moveItem(self.forwardButton);
482 moveItem(self.stopButton);
483 moveItem(self.playlistButton);
484 moveItem(self.repeatButton);
485 moveItem(self.shuffleButton);
488 frame = [self.progressView frame];
489 frame.size.width = frame.size.width + f_space;
490 frame.origin.x = frame.origin.x - f_space;
492 [self.progressView setFrame: frame];
494 [[self.progressView animator] setFrame: frame];
496 if (self.darkInterface) {
497 [[self.forwardButton animator] setImage:imageFromRes(@"forward-3btns-dark")];
498 [[self.forwardButton animator] setAlternateImage:imageFromRes(@"forward-3btns-dark-pressed")];
499 [[self.backwardButton animator] setImage:imageFromRes(@"backward-3btns-dark")];
500 [[self.backwardButton animator] setAlternateImage:imageFromRes(@"backward-3btns-dark-pressed")];
502 [[self.forwardButton animator] setImage:imageFromRes(@"forward-3btns")];
503 [[self.forwardButton animator] setAlternateImage:imageFromRes(@"forward-3btns-pressed")];
504 [[self.backwardButton animator] setImage:imageFromRes(@"backward-3btns")];
505 [[self.backwardButton animator] setAlternateImage:imageFromRes(@"backward-3btns-pressed")];
508 [self toggleForwardBackwardMode: NO];
510 [self.bottomBarView setNeedsDisplay:YES];
513 - (void)togglePlaymodeButtons
515 b_show_playmode_buttons = config_GetInt(getIntf(), "macosx-show-playmode-buttons");
517 if (b_show_playmode_buttons)
518 [self addPlaymodeButtons:NO];
520 [self removePlaymodeButtons:NO];
523 - (void)addPlaymodeButtons:(BOOL)b_fast
526 CGFloat f_space = [self.repeatButton frame].size.width + [self.shuffleButton frame].size.width - 6.;
528 if (self.darkInterface) {
529 [[self.playlistButton animator] setImage:imageFromRes(@"playlist_dark")];
530 [[self.playlistButton animator] setAlternateImage:imageFromRes(@"playlist-pressed_dark")];
532 [[self.playlistButton animator] setImage:imageFromRes(@"playlist-btn")];
533 [[self.playlistButton animator] setAlternateImage:imageFromRes(@"playlist-btn-pressed")];
535 frame = [self.playlistButton frame];
537 [self.playlistButton setFrame:frame];
540 [self.repeatButton setHidden: NO];
541 [self.shuffleButton setHidden: NO];
543 [[self.repeatButton animator] setHidden: NO];
544 [[self.shuffleButton animator] setHidden: NO];
547 frame = [self.progressView frame];
548 frame.size.width = frame.size.width - f_space;
549 frame.origin.x = frame.origin.x + f_space;
551 [self.progressView setFrame: frame];
553 [[self.progressView animator] setFrame: frame];
556 - (void)removePlaymodeButtons:(BOOL)b_fast
559 CGFloat f_space = [self.repeatButton frame].size.width + [self.shuffleButton frame].size.width - 6.;
560 [self.repeatButton setHidden: YES];
561 [self.shuffleButton setHidden: YES];
563 if (self.darkInterface) {
564 [[self.playlistButton animator] setImage:imageFromRes(@"playlist-1btn-dark")];
565 [[self.playlistButton animator] setAlternateImage:imageFromRes(@"playlist-1btn-dark-pressed")];
567 [[self.playlistButton animator] setImage:imageFromRes(@"playlist-1btn")];
568 [[self.playlistButton animator] setAlternateImage:imageFromRes(@"playlist-1btn-pressed")];
570 frame = [self.playlistButton frame];
572 [self.playlistButton setFrame:frame];
574 frame = [self.progressView frame];
575 frame.size.width = frame.size.width + f_space;
576 frame.origin.x = frame.origin.x - f_space;
578 [self.progressView setFrame: frame];
580 [[self.progressView animator] setFrame: frame];
584 #pragma mark Extra button actions
586 - (IBAction)stop:(id)sender
588 [[VLCCoreInteraction sharedInstance] stop];
591 // dynamically created next / prev buttons
592 - (IBAction)prev:(id)sender
594 [[VLCCoreInteraction sharedInstance] previous];
597 - (IBAction)next:(id)sender
599 [[VLCCoreInteraction sharedInstance] next];
604 [self.repeatButton setImage: _repeatOneImage];
605 [self.repeatButton setAlternateImage: _pressedRepeatOneImage];
610 [self.repeatButton setImage: _repeatAllImage];
611 [self.repeatButton setAlternateImage: _pressedRepeatAllImage];
616 [self.repeatButton setImage: _repeatImage];
617 [self.repeatButton setAlternateImage: _pressedRepeatImage];
620 - (IBAction)repeat:(id)sender
622 vlc_value_t looping,repeating;
623 intf_thread_t * p_intf = getIntf();
624 playlist_t * p_playlist = pl_Get(p_intf);
626 var_Get(p_playlist, "repeat", &repeating);
627 var_Get(p_playlist, "loop", &looping);
629 if (!repeating.b_bool && !looping.b_bool) {
630 /* was: no repeating at all, switching to Repeat One */
631 [[VLCCoreInteraction sharedInstance] repeatOne];
634 else if (repeating.b_bool && !looping.b_bool) {
635 /* was: Repeat One, switching to Repeat All */
636 [[VLCCoreInteraction sharedInstance] repeatAll];
639 /* was: Repeat All or bug in VLC, switching to Repeat Off */
640 [[VLCCoreInteraction sharedInstance] repeatOff];
648 playlist_t *p_playlist = pl_Get(getIntf());
649 b_value = var_GetBool(p_playlist, "random");
652 [self.shuffleButton setImage: _shuffleOnImage];
653 [self.shuffleButton setAlternateImage: _pressedShuffleOnImage];
655 [self.shuffleButton setImage: _shuffleImage];
656 [self.shuffleButton setAlternateImage: _pressedShuffleImage];
660 - (IBAction)shuffle:(id)sender
662 [[VLCCoreInteraction sharedInstance] shuffle];
666 - (IBAction)togglePlaylist:(id)sender
668 [[[VLCMain sharedInstance] mainWindow] changePlaylistState: psUserEvent];
671 - (IBAction)volumeAction:(id)sender
673 if (sender == self.volumeSlider)
674 [[VLCCoreInteraction sharedInstance] setVolume: [sender intValue]];
675 else if (sender == self.volumeDownButton)
676 [[VLCCoreInteraction sharedInstance] toggleMute];
678 [[VLCCoreInteraction sharedInstance] setVolume: AOUT_VOLUME_MAX];
681 - (IBAction)effects:(id)sender
683 [[[VLCMain sharedInstance] mainMenu] showAudioEffects: sender];
687 #pragma mark Extra updaters
689 - (void)updateVolumeSlider
691 int i_volume = [[VLCCoreInteraction sharedInstance] volume];
692 BOOL b_muted = [[VLCCoreInteraction sharedInstance] mute];
697 [self.volumeSlider setIntValue: i_volume];
699 i_volume = (i_volume * 200) / AOUT_VOLUME_MAX;
700 NSString *volumeTooltip = [NSString stringWithFormat:_NS("Volume: %i %%"), i_volume];
701 [self.volumeSlider setToolTip:volumeTooltip];
703 [self.volumeSlider setEnabled: !b_muted];
704 [self.volumeUpButton setEnabled: !b_muted];
707 - (void)updateControls
709 [super updateControls];
711 bool b_input = false;
712 bool b_seekable = false;
713 bool b_plmul = false;
714 bool b_control = false;
715 bool b_chapters = false;
717 playlist_t * p_playlist = pl_Get(getIntf());
720 b_plmul = playlist_CurrentSize(p_playlist) > 1;
723 input_thread_t * p_input = playlist_CurrentInput(p_playlist);
724 if ((b_input = (p_input != NULL))) {
725 /* seekable streams */
726 b_seekable = var_GetBool(p_input, "can-seek");
728 /* check whether slow/fast motion is possible */
729 b_control = var_GetBool(p_input, "can-rate");
731 /* chapters & titles */
732 //FIXME! b_chapters = p_input->stream.i_area_nb > 1;
734 vlc_object_release(p_input);
737 [self.stopButton setEnabled: b_input];
739 if (b_show_jump_buttons) {
740 [_previousButton setEnabled: (b_seekable || b_plmul || b_chapters)];
741 [_nextButton setEnabled: (b_seekable || b_plmul || b_chapters)];
744 [[[VLCMain sharedInstance] mainMenu] setRateControlsEnabled: b_control];