|
|
|
@ -1,10 +1,10 @@ |
|
|
|
/***************************************************************************** |
|
|
|
* ControlsBar.m: MacOS X interface module |
|
|
|
* VLCMainWindowControlsBar.m: MacOS X interface module |
|
|
|
***************************************************************************** |
|
|
|
* Copyright (C) 2012-2016 VLC authors and VideoLAN |
|
|
|
* Copyright (C) 2012-2019 VLC authors and VideoLAN |
|
|
|
* |
|
|
|
* Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org> |
|
|
|
* David Fuhrmann <david dot fuhrmann at googlemail dot com> |
|
|
|
* Authors: Felix Paul Kühne <fkuehne # videolan dot org> |
|
|
|
* David Fuhrmann <dfuhrmann # videolan dot org> |
|
|
|
* |
|
|
|
* This program is free software; you can redistribute it and/or modify |
|
|
|
* it under the terms of the GNU General Public License as published by |
|
|
|
@ -21,18 +21,16 @@ |
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
|
|
|
*****************************************************************************/ |
|
|
|
|
|
|
|
#import "VLCMainWindowControlsBar.h" |
|
|
|
#import "VLCControlsBarCommon.h" |
|
|
|
|
|
|
|
#import <vlc_aout.h> |
|
|
|
|
|
|
|
#import "extensions/NSString+Helpers.h" |
|
|
|
#import "main/CompatibilityFixes.h" |
|
|
|
#import "main/VLCMain.h" |
|
|
|
#import "menus/VLCMainMenu.h" |
|
|
|
#import "windows/mainwindow/VLCMainWindowControlsBar.h" |
|
|
|
#import "playlist/VLCPlaylistController.h" |
|
|
|
#import "playlist/VLCPlayerController.h" |
|
|
|
#import "library/VLCLibraryWindow.h" |
|
|
|
|
|
|
|
CGFloat VLCVolumeMaximum = 2.; |
|
|
|
CGFloat VLCVolumeDefault = 1.; |
|
|
|
|
|
|
|
/***************************************************************************** |
|
|
|
* VLCMainWindowControlsBar |
|
|
|
@ -42,20 +40,9 @@ |
|
|
|
|
|
|
|
@interface VLCMainWindowControlsBar() |
|
|
|
{ |
|
|
|
NSImage * _repeatImage; |
|
|
|
NSImage * _pressedRepeatImage; |
|
|
|
NSImage * _repeatAllImage; |
|
|
|
NSImage * _pressedRepeatAllImage; |
|
|
|
NSImage * _repeatOneImage; |
|
|
|
NSImage * _pressedRepeatOneImage; |
|
|
|
NSImage * _shuffleImage; |
|
|
|
NSImage * _pressedShuffleImage; |
|
|
|
NSImage * _shuffleOnImage; |
|
|
|
NSImage * _pressedShuffleOnImage; |
|
|
|
VLCPlaylistController *_playlistController; |
|
|
|
VLCPlayerController *_playerController; |
|
|
|
} |
|
|
|
|
|
|
|
@end |
|
|
|
|
|
|
|
@implementation VLCMainWindowControlsBar |
|
|
|
@ -70,22 +57,11 @@ |
|
|
|
[notificationCenter addObserver:self selector:@selector(updatePlaybackControls:) name:VLCPlaylistCurrentItemChanged object:nil]; |
|
|
|
[notificationCenter addObserver:self selector:@selector(updateVolumeSlider:) name:VLCPlayerVolumeChanged object:nil]; |
|
|
|
[notificationCenter addObserver:self selector:@selector(updateVolumeSlider:) name:VLCPlayerMuteChanged object:nil]; |
|
|
|
[notificationCenter addObserver:self selector:@selector(playbackOrderUpdated:) name:VLCPlaybackOrderChanged object:nil]; |
|
|
|
[notificationCenter addObserver:self selector:@selector(playbackRepeatChanged:) name:VLCPlaybackRepeatChanged object:nil]; |
|
|
|
[notificationCenter addObserver:self selector:@selector(playbackStateChanged:) name:VLCPlayerStateChanged object:nil]; |
|
|
|
|
|
|
|
[self.stopButton setToolTip: _NS("Stop")]; |
|
|
|
self.stopButton.accessibilityLabel = self.stopButton.toolTip; |
|
|
|
|
|
|
|
[self.playlistButton setToolTip: _NS("Show/Hide Playlist")]; |
|
|
|
self.playlistButton.accessibilityLabel = self.playlistButton.toolTip; |
|
|
|
|
|
|
|
[self.repeatButton setToolTip: _NS("Repeat")]; |
|
|
|
self.repeatButton.accessibilityLabel = _NS("Change repeat mode. Modes: repeat one, repeat all and no repeat."); |
|
|
|
self.repeatButton.accessibilityTitle = self.repeatButton.toolTip; |
|
|
|
|
|
|
|
[self.shuffleButton setToolTip: _NS("Shuffle")]; |
|
|
|
self.shuffleButton.accessibilityLabel = self.shuffleButton.toolTip; |
|
|
|
|
|
|
|
NSString *volumeTooltip = [NSString stringWithFormat:_NS("Volume: %i %%"), 100]; |
|
|
|
[self.volumeSlider setToolTip: volumeTooltip]; |
|
|
|
self.volumeSlider.accessibilityLabel = _NS("Volume"); |
|
|
|
@ -96,37 +72,12 @@ |
|
|
|
[self.volumeUpButton setToolTip: _NS("Full Volume")]; |
|
|
|
self.volumeUpButton.accessibilityLabel = self.volumeUpButton.toolTip; |
|
|
|
|
|
|
|
[self.effectsButton setToolTip: _NS("Audio Effects")]; |
|
|
|
self.effectsButton.accessibilityTitle = _NS("Open Audio Effects window"); |
|
|
|
self.effectsButton.accessibilityLabel = self.effectsButton.toolTip; |
|
|
|
|
|
|
|
[self.stopButton setImage: imageFromRes(@"stop")]; |
|
|
|
[self.stopButton setAlternateImage: imageFromRes(@"stop-pressed")]; |
|
|
|
|
|
|
|
[self.playlistButton setImage: imageFromRes(@"playlist-btn")]; |
|
|
|
[self.playlistButton setAlternateImage: imageFromRes(@"playlist-btn-pressed")]; |
|
|
|
_repeatImage = imageFromRes(@"repeat"); |
|
|
|
_pressedRepeatImage = imageFromRes(@"repeat-pressed"); |
|
|
|
_repeatAllImage = imageFromRes(@"repeat-all"); |
|
|
|
_pressedRepeatAllImage = imageFromRes(@"repeat-all-pressed"); |
|
|
|
_repeatOneImage = imageFromRes(@"repeat-one"); |
|
|
|
_pressedRepeatOneImage = imageFromRes(@"repeat-one-pressed"); |
|
|
|
_shuffleImage = imageFromRes(@"shuffle"); |
|
|
|
_pressedShuffleImage = imageFromRes(@"shuffle-pressed"); |
|
|
|
_shuffleOnImage = imageFromRes(@"shuffle-blue"); |
|
|
|
_pressedShuffleOnImage = imageFromRes(@"shuffle-blue-pressed"); |
|
|
|
|
|
|
|
[self.volumeDownButton setImage: imageFromRes(@"volume-low")]; |
|
|
|
[self.volumeUpButton setImage: imageFromRes(@"volume-high")]; |
|
|
|
|
|
|
|
if (self.nativeFullscreenMode) { |
|
|
|
[self.effectsButton setImage: imageFromRes(@"effects-one-button")]; |
|
|
|
[self.effectsButton setAlternateImage: imageFromRes(@"effects-one-button-pressed")]; |
|
|
|
} else { |
|
|
|
[self.effectsButton setImage: imageFromRes(@"effects-double-buttons")]; |
|
|
|
[self.effectsButton setAlternateImage: imageFromRes(@"effects-double-buttons-pressed")]; |
|
|
|
} |
|
|
|
|
|
|
|
[self.fullscreenButton setImage: imageFromRes(@"fullscreen-double-buttons")]; |
|
|
|
[self.fullscreenButton setAlternateImage: imageFromRes(@"fullscreen-double-buttons-pressed")]; |
|
|
|
|
|
|
|
@ -134,158 +85,12 @@ |
|
|
|
[self.prevButton setAlternateImage: imageFromRes(@"previous-6btns-pressed")]; |
|
|
|
[self.nextButton setImage: imageFromRes(@"next-6btns")]; |
|
|
|
[self.nextButton setAlternateImage: imageFromRes(@"next-6btns-pressed")]; |
|
|
|
[self.repeatButton setImage: _repeatImage]; |
|
|
|
[self.repeatButton setAlternateImage: _pressedRepeatImage]; |
|
|
|
[self.shuffleButton setImage: _shuffleImage]; |
|
|
|
[self.shuffleButton setAlternateImage: _pressedShuffleImage]; |
|
|
|
|
|
|
|
BOOL b_mute = ![_playerController mute]; |
|
|
|
[self.volumeSlider setEnabled: b_mute]; |
|
|
|
[self.volumeSlider setMaxValue: AOUT_VOLUME_MAX]; |
|
|
|
[self.volumeSlider setDefaultValue: AOUT_VOLUME_DEFAULT]; |
|
|
|
[self.volumeUpButton setEnabled: b_mute]; |
|
|
|
|
|
|
|
// configure optional buttons |
|
|
|
if (!var_InheritBool(getIntf(), "macosx-show-effects-button")) |
|
|
|
[self removeEffectsButton:NO]; |
|
|
|
|
|
|
|
if (!var_InheritBool(getIntf(), "macosx-show-playmode-buttons")) |
|
|
|
[self removePlaymodeButtons:NO]; |
|
|
|
[self.volumeSlider setMaxValue: VLCVolumeMaximum]; |
|
|
|
[self.volumeSlider setDefaultValue: VLCVolumeDefault]; |
|
|
|
[self updateVolumeSlider:nil]; |
|
|
|
|
|
|
|
if (!var_InheritBool(getIntf(), "macosx-show-playback-buttons")) |
|
|
|
[self removeJumpButtons:NO]; |
|
|
|
|
|
|
|
// FIXME: make sure that buttons appear in the correct state |
|
|
|
} |
|
|
|
|
|
|
|
#pragma mark - |
|
|
|
#pragma mark interface customization |
|
|
|
|
|
|
|
|
|
|
|
- (void)hideButtonWithConstraint:(NSLayoutConstraint *)constraint animation:(BOOL)animation |
|
|
|
{ |
|
|
|
NSAssert([constraint.firstItem isKindOfClass:[NSButton class]], @"Constraint must be for NSButton object"); |
|
|
|
|
|
|
|
NSLayoutConstraint *animatedConstraint = animation ? constraint.animator : constraint; |
|
|
|
animatedConstraint.constant = 0; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)showButtonWithConstraint:(NSLayoutConstraint *)constraint animation:(BOOL)animation |
|
|
|
{ |
|
|
|
NSAssert([constraint.firstItem isKindOfClass:[NSButton class]], @"Constraint must be for NSButton object"); |
|
|
|
|
|
|
|
NSLayoutConstraint *animatedConstraint = animation ? constraint.animator : constraint; |
|
|
|
animatedConstraint.constant = ((NSButton *)constraint.firstItem).image.size.width; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)toggleEffectsButton |
|
|
|
{ |
|
|
|
if (var_InheritBool(getIntf(), "macosx-show-effects-button")) |
|
|
|
[self addEffectsButton:YES]; |
|
|
|
else |
|
|
|
[self removeEffectsButton:YES]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)addEffectsButton:(BOOL)withAnimation |
|
|
|
{ |
|
|
|
[NSAnimationContext beginGrouping]; |
|
|
|
[self showButtonWithConstraint:self.effectsButtonWidthConstraint animation:withAnimation]; |
|
|
|
|
|
|
|
id button = withAnimation ? self.fullscreenButton.animator : self.fullscreenButton; |
|
|
|
if (!self.nativeFullscreenMode) { |
|
|
|
[button setImage: imageFromRes(@"fullscreen-double-buttons")]; |
|
|
|
[button setAlternateImage: imageFromRes(@"fullscreen-double-buttons-pressed")]; |
|
|
|
} |
|
|
|
[NSAnimationContext endGrouping]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)removeEffectsButton:(BOOL)withAnimation |
|
|
|
{ |
|
|
|
[NSAnimationContext beginGrouping]; |
|
|
|
[self hideButtonWithConstraint:self.effectsButtonWidthConstraint animation:withAnimation]; |
|
|
|
|
|
|
|
id button = withAnimation ? self.fullscreenButton.animator : self.fullscreenButton; |
|
|
|
if (!self.nativeFullscreenMode) { |
|
|
|
[button setImage: imageFromRes(@"fullscreen-one-button")]; |
|
|
|
[button setAlternateImage: imageFromRes(@"fullscreen-one-button-pressed")]; |
|
|
|
} |
|
|
|
[NSAnimationContext endGrouping]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)toggleJumpButtons |
|
|
|
{ |
|
|
|
if (var_InheritBool(getIntf(), "macosx-show-playback-buttons")) |
|
|
|
[self addJumpButtons:YES]; |
|
|
|
else |
|
|
|
[self removeJumpButtons:YES]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)addJumpButtons:(BOOL)withAnimation |
|
|
|
{ |
|
|
|
[NSAnimationContext beginGrouping]; |
|
|
|
[self showButtonWithConstraint:self.prevButtonWidthConstraint animation:withAnimation]; |
|
|
|
[self showButtonWithConstraint:self.nextButtonWidthConstraint animation:withAnimation]; |
|
|
|
|
|
|
|
id backwardButton = withAnimation ? self.backwardButton.animator : self.backwardButton; |
|
|
|
id forwardButton = withAnimation ? self.forwardButton.animator : self.forwardButton; |
|
|
|
[forwardButton setImage:imageFromRes(@"forward-6btns")]; |
|
|
|
[forwardButton setAlternateImage:imageFromRes(@"forward-6btns-pressed")]; |
|
|
|
[backwardButton setImage:imageFromRes(@"backward-6btns")]; |
|
|
|
[backwardButton setAlternateImage:imageFromRes(@"backward-6btns-pressed")]; |
|
|
|
|
|
|
|
[NSAnimationContext endGrouping]; |
|
|
|
|
|
|
|
[self toggleForwardBackwardMode: YES]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)removeJumpButtons:(BOOL)withAnimation |
|
|
|
{ |
|
|
|
[NSAnimationContext beginGrouping]; |
|
|
|
[self hideButtonWithConstraint:self.prevButtonWidthConstraint animation:withAnimation]; |
|
|
|
[self hideButtonWithConstraint:self.nextButtonWidthConstraint animation:withAnimation]; |
|
|
|
|
|
|
|
id backwardButton = withAnimation ? self.backwardButton.animator : self.backwardButton; |
|
|
|
id forwardButton = withAnimation ? self.forwardButton.animator : self.forwardButton; |
|
|
|
[forwardButton setImage:imageFromRes(@"forward-3btns")]; |
|
|
|
[forwardButton setAlternateImage:imageFromRes(@"forward-3btns-pressed")]; |
|
|
|
[backwardButton setImage:imageFromRes(@"backward-3btns")]; |
|
|
|
[backwardButton setAlternateImage:imageFromRes(@"backward-3btns-pressed")]; |
|
|
|
[NSAnimationContext endGrouping]; |
|
|
|
|
|
|
|
[self toggleForwardBackwardMode: NO]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)togglePlaymodeButtons |
|
|
|
{ |
|
|
|
if (var_InheritBool(getIntf(), "macosx-show-playmode-buttons")) |
|
|
|
[self addPlaymodeButtons:YES]; |
|
|
|
else |
|
|
|
[self removePlaymodeButtons:YES]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)addPlaymodeButtons:(BOOL)withAnimation |
|
|
|
{ |
|
|
|
[NSAnimationContext beginGrouping]; |
|
|
|
[self showButtonWithConstraint:self.repeatButtonWidthConstraint animation:withAnimation]; |
|
|
|
[self showButtonWithConstraint:self.shuffleButtonWidthConstraint animation:withAnimation]; |
|
|
|
|
|
|
|
id button = withAnimation ? self.playlistButton.animator : self.playlistButton; |
|
|
|
[button setImage:imageFromRes(@"playlist-btn")]; |
|
|
|
[button setAlternateImage:imageFromRes(@"playlist-btn-pressed")]; |
|
|
|
[NSAnimationContext endGrouping]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)removePlaymodeButtons:(BOOL)withAnimation |
|
|
|
{ |
|
|
|
[NSAnimationContext beginGrouping]; |
|
|
|
|
|
|
|
[self hideButtonWithConstraint:self.repeatButtonWidthConstraint animation:withAnimation]; |
|
|
|
[self hideButtonWithConstraint:self.shuffleButtonWidthConstraint animation:withAnimation]; |
|
|
|
|
|
|
|
id button = withAnimation ? self.playlistButton.animator : self.playlistButton; |
|
|
|
[button setImage:imageFromRes(@"playlist-1btn")]; |
|
|
|
[button setAlternateImage:imageFromRes(@"playlist-1btn-pressed")]; |
|
|
|
[NSAnimationContext endGrouping]; |
|
|
|
[self playbackStateChanged:nil]; |
|
|
|
} |
|
|
|
|
|
|
|
#pragma mark - |
|
|
|
@ -307,100 +112,14 @@ |
|
|
|
[_playlistController playNextItem]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)setRepeatOne |
|
|
|
{ |
|
|
|
[self.repeatButton setImage: _repeatOneImage]; |
|
|
|
[self.repeatButton setAlternateImage: _pressedRepeatOneImage]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)setRepeatAll |
|
|
|
{ |
|
|
|
[self.repeatButton setImage: _repeatAllImage]; |
|
|
|
[self.repeatButton setAlternateImage: _pressedRepeatAllImage]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)setRepeatOff |
|
|
|
{ |
|
|
|
[self.repeatButton setImage: _repeatImage]; |
|
|
|
[self.repeatButton setAlternateImage: _pressedRepeatImage]; |
|
|
|
} |
|
|
|
|
|
|
|
- (IBAction)repeat:(id)sender |
|
|
|
{ |
|
|
|
enum vlc_playlist_playback_repeat repeatState = _playlistController.playbackRepeat; |
|
|
|
switch (repeatState) { |
|
|
|
case VLC_PLAYLIST_PLAYBACK_REPEAT_NONE: |
|
|
|
/* was: no repeating at all, switching to Repeat One */ |
|
|
|
_playlistController.playbackRepeat = VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT; |
|
|
|
break; |
|
|
|
case VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT: |
|
|
|
/* was: Repeat One, switching to Repeat All */ |
|
|
|
_playlistController.playbackRepeat = VLC_PLAYLIST_PLAYBACK_REPEAT_ALL; |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
/* was: Repeat All, switching to Repeat Off */ |
|
|
|
_playlistController.playbackRepeat = VLC_PLAYLIST_PLAYBACK_REPEAT_NONE; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
- (void)playbackOrderUpdated:(NSNotification *)aNotification |
|
|
|
{ |
|
|
|
if (_playlistController.playbackOrder == VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL) { |
|
|
|
[self.shuffleButton setImage: _shuffleImage]; |
|
|
|
[self.shuffleButton setAlternateImage: _pressedShuffleImage]; |
|
|
|
} else { |
|
|
|
[self.shuffleButton setImage: _shuffleOnImage]; |
|
|
|
[self.shuffleButton setAlternateImage: _pressedShuffleOnImage]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
- (void)playbackRepeatChanged:(NSNotification *)aNotification |
|
|
|
{ |
|
|
|
enum vlc_playlist_playback_repeat repeatState = _playlistController.playbackRepeat; |
|
|
|
switch (repeatState) { |
|
|
|
case VLC_PLAYLIST_PLAYBACK_REPEAT_ALL: |
|
|
|
[self setRepeatAll]; |
|
|
|
break; |
|
|
|
|
|
|
|
case VLC_PLAYLIST_PLAYBACK_REPEAT_CURRENT: |
|
|
|
[self setRepeatOne]; |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
[self setRepeatOff]; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
- (IBAction)shuffle:(id)sender |
|
|
|
{ |
|
|
|
if (_playlistController.playbackOrder == VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL) { |
|
|
|
_playlistController.playbackOrder = VLC_PLAYLIST_PLAYBACK_ORDER_RANDOM; |
|
|
|
} else { |
|
|
|
_playlistController.playbackOrder = VLC_PLAYLIST_PLAYBACK_ORDER_NORMAL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
- (IBAction)togglePlaylist:(id)sender |
|
|
|
{ |
|
|
|
// FIXME: this is a NO-OP |
|
|
|
} |
|
|
|
|
|
|
|
- (IBAction)volumeAction:(id)sender |
|
|
|
{ |
|
|
|
if (sender == self.volumeSlider) |
|
|
|
[_playerController setVolume: [sender floatValue]]; |
|
|
|
[_playerController setVolume:[sender floatValue]]; |
|
|
|
else if (sender == self.volumeDownButton) |
|
|
|
[_playerController toggleMute]; |
|
|
|
else |
|
|
|
[_playerController setVolume: AOUT_VOLUME_MAX]; |
|
|
|
} |
|
|
|
|
|
|
|
- (IBAction)effects:(id)sender |
|
|
|
{ |
|
|
|
[[[VLCMain sharedInstance] mainMenu] showAudioEffects: sender]; |
|
|
|
[_playerController setVolume:VLCVolumeMaximum]; |
|
|
|
} |
|
|
|
|
|
|
|
#pragma mark - |
|
|
|
@ -422,26 +141,28 @@ |
|
|
|
[self.volumeUpButton setEnabled: !b_muted]; |
|
|
|
} |
|
|
|
|
|
|
|
- (void)playbackStateChanged:(NSNotification *)aNotification |
|
|
|
{ |
|
|
|
switch (_playerController.playerState) { |
|
|
|
case VLC_PLAYER_STATE_STOPPING: |
|
|
|
case VLC_PLAYER_STATE_STOPPED: |
|
|
|
self.stopButton.enabled = NO; |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
self.stopButton.enabled = YES; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
- (void)updatePlaybackControls:(NSNotification *)aNotification |
|
|
|
{ |
|
|
|
bool b_input = false; |
|
|
|
bool b_seekable = _playerController.seekable; |
|
|
|
bool b_control = _playerController.rateChangable; |
|
|
|
// FIXME: re-add chapter navigation as needed |
|
|
|
bool b_chapters = false; |
|
|
|
|
|
|
|
input_item_t *p_item = _playerController.currentMedia; |
|
|
|
b_input = p_item != NULL; |
|
|
|
if (p_item) { |
|
|
|
b_input = YES; |
|
|
|
input_item_Release(p_item); |
|
|
|
} |
|
|
|
|
|
|
|
[self.stopButton setEnabled: b_input]; |
|
|
|
[self.prevButton setEnabled: (b_seekable || _playlistController.hasPreviousPlaylistItem || b_chapters)]; |
|
|
|
[self.nextButton setEnabled: (b_seekable || _playlistController.hasNextPlaylistItem || b_chapters)]; |
|
|
|
|
|
|
|
[[[VLCMain sharedInstance] mainMenu] setRateControlsEnabled: b_control]; |
|
|
|
} |
|
|
|
|
|
|
|
@end |
|
|
|
|