macosx: Remove private API for sort indicator images
[vlc.git] / modules / gui / macosx / VLCMainWindowControlsBar.m
blob91805b8f04df809fe5aef3297154379fd306a2b9
1 /*****************************************************************************
2  * ControlsBar.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2012-2016 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8  *          David Fuhrmann <david dot fuhrmann at googlemail dot com>
9  *
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.
14  *
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.
19  *
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"
27 #import "VLCMain.h"
28 #import "VLCCoreInteraction.h"
29 #import "VLCMainMenu.h"
30 #import "VLCPlaylist.h"
31 #import "CompatibilityFixes.h"
32 #import <vlc_aout.h>
34 /*****************************************************************************
35  * VLCMainWindowControlsBar
36  *
37  *  Holds all specific outlets, actions and code for the main window controls bar.
38  *****************************************************************************/
40 @interface VLCMainWindowControlsBar()
42     NSImage * _repeatImage;
43     NSImage * _pressedRepeatImage;
44     NSImage * _repeatAllImage;
45     NSImage * _pressedRepeatAllImage;
46     NSImage * _repeatOneImage;
47     NSImage * _pressedRepeatOneImage;
48     NSImage * _shuffleImage;
49     NSImage * _pressedShuffleImage;
50     NSImage * _shuffleOnImage;
51     NSImage * _pressedShuffleOnImage;
54 @end
56 @implementation VLCMainWindowControlsBar
58 - (void)awakeFromNib
60     [super awakeFromNib];
62     [self.stopButton setToolTip: _NS("Stop")];
63     self.stopButton.accessibilityLabel = self.stopButton.toolTip;
65     [self.playlistButton setToolTip: _NS("Show/Hide Playlist")];
66     self.playlistButton.accessibilityLabel = self.playlistButton.toolTip;
68     [self.repeatButton setToolTip: _NS("Repeat")];
69     self.repeatButton.accessibilityLabel = _NS("Change repeat mode. Modes: repeat one, repeat all and no repeat.");
70     self.repeatButton.accessibilityTitle = self.repeatButton.toolTip;
72     [self.shuffleButton setToolTip: _NS("Shuffle")];
73     self.shuffleButton.accessibilityLabel = self.shuffleButton.toolTip;
75     NSString *volumeTooltip = [NSString stringWithFormat:_NS("Volume: %i %%"), 100];
76     [self.volumeSlider setToolTip: volumeTooltip];
77     self.volumeSlider.accessibilityLabel = _NS("Volume");
78     
79     [self.volumeDownButton setToolTip: _NS("Mute")];
80     self.volumeDownButton.accessibilityLabel = self.volumeDownButton.toolTip;
81     
82     [self.volumeUpButton setToolTip: _NS("Full Volume")];
83     self.volumeUpButton.accessibilityLabel = self.volumeUpButton.toolTip;
85     [self.effectsButton setToolTip: _NS("Audio Effects")];
86     self.effectsButton.accessibilityTitle = _NS("Open Audio Effects window");
87     self.effectsButton.accessibilityLabel = self.effectsButton.toolTip;
89     [self.stopButton setImage: imageFromRes(@"stop")];
90     [self.stopButton setAlternateImage: imageFromRes(@"stop-pressed")];
92     [self.playlistButton setImage: imageFromRes(@"playlist-btn")];
93     [self.playlistButton setAlternateImage: imageFromRes(@"playlist-btn-pressed")];
94     _repeatImage = imageFromRes(@"repeat");
95     _pressedRepeatImage = imageFromRes(@"repeat-pressed");
96     _repeatAllImage  = imageFromRes(@"repeat-all");
97     _pressedRepeatAllImage = imageFromRes(@"repeat-all-pressed");
98     _repeatOneImage = imageFromRes(@"repeat-one");
99     _pressedRepeatOneImage = imageFromRes(@"repeat-one-pressed");
100     _shuffleImage = imageFromRes(@"shuffle");
101     _pressedShuffleImage = imageFromRes(@"shuffle-pressed");
102     _shuffleOnImage = imageFromRes(@"shuffle-blue");
103     _pressedShuffleOnImage = imageFromRes(@"shuffle-blue-pressed");
105     [self.volumeDownButton setImage: imageFromRes(@"volume-low")];
106     [self.volumeUpButton setImage: imageFromRes(@"volume-high")];
107     [self.volumeSlider setUsesBrightArtwork: YES];
109     if (self.nativeFullscreenMode) {
110         [self.effectsButton setImage: imageFromRes(@"effects-one-button")];
111         [self.effectsButton setAlternateImage: imageFromRes(@"effects-one-button-pressed")];
112     } else {
113         [self.effectsButton setImage: imageFromRes(@"effects-double-buttons")];
114         [self.effectsButton setAlternateImage: imageFromRes(@"effects-double-buttons-pressed")];
115     }
117     [self.fullscreenButton setImage: imageFromRes(@"fullscreen-double-buttons")];
118     [self.fullscreenButton setAlternateImage: imageFromRes(@"fullscreen-double-buttons-pressed")];
120     [self.prevButton setImage: imageFromRes(@"previous-6btns")];
121     [self.prevButton setAlternateImage: imageFromRes(@"previous-6btns-pressed")];
122     [self.nextButton setImage: imageFromRes(@"next-6btns")];
123     [self.nextButton setAlternateImage: imageFromRes(@"next-6btns-pressed")];
124     [self.repeatButton setImage: _repeatImage];
125     [self.repeatButton setAlternateImage: _pressedRepeatImage];
126     [self.shuffleButton setImage: _shuffleImage];
127     [self.shuffleButton setAlternateImage: _pressedShuffleImage];
129     BOOL b_mute = ![[VLCCoreInteraction sharedInstance] mute];
130     [self.volumeSlider setEnabled: b_mute];
131     [self.volumeSlider setMaxValue: [[VLCCoreInteraction sharedInstance] maxVolume]];
132     [self.volumeSlider setDefaultValue: AOUT_VOLUME_DEFAULT];
133     [self.volumeUpButton setEnabled: b_mute];
135     // configure optional buttons
136     if (!var_InheritBool(getIntf(), "macosx-show-effects-button"))
137         [self removeEffectsButton:NO];
139     if (!var_InheritBool(getIntf(), "macosx-show-playmode-buttons"))
140         [self removePlaymodeButtons:NO];
142     if (!var_InheritBool(getIntf(), "macosx-show-playback-buttons"))
143         [self removeJumpButtons:NO];
145     [[[VLCMain sharedInstance] playlist] playbackModeUpdated];
149 #pragma mark -
150 #pragma mark interface customization
153 - (void)hideButtonWithConstraint:(NSLayoutConstraint *)constraint animation:(BOOL)animation
155     NSAssert([constraint.firstItem isKindOfClass:[NSButton class]], @"Constraint must be for NSButton object");
157     NSLayoutConstraint *animatedConstraint = animation ? constraint.animator : constraint;
158     animatedConstraint.constant = 0;
161 - (void)showButtonWithConstraint:(NSLayoutConstraint *)constraint animation:(BOOL)animation
163     NSAssert([constraint.firstItem isKindOfClass:[NSButton class]], @"Constraint must be for NSButton object");
165     NSLayoutConstraint *animatedConstraint = animation ? constraint.animator : constraint;
166     animatedConstraint.constant = ((NSButton *)constraint.firstItem).image.size.width;
169 - (void)toggleEffectsButton
171     if (var_InheritBool(getIntf(), "macosx-show-effects-button"))
172         [self addEffectsButton:YES];
173     else
174         [self removeEffectsButton:YES];
177 - (void)addEffectsButton:(BOOL)withAnimation
179     [NSAnimationContext beginGrouping];
180     [self showButtonWithConstraint:self.effectsButtonWidthConstraint animation:withAnimation];
182     id button = withAnimation ? self.fullscreenButton.animator : self.fullscreenButton;
183     if (!self.nativeFullscreenMode) {
184         [button setImage: imageFromRes(@"fullscreen-double-buttons")];
185         [button setAlternateImage: imageFromRes(@"fullscreen-double-buttons-pressed")];
186     }
187     [NSAnimationContext endGrouping];
190 - (void)removeEffectsButton:(BOOL)withAnimation
192     [NSAnimationContext beginGrouping];
193     [self hideButtonWithConstraint:self.effectsButtonWidthConstraint animation:withAnimation];
195     id button = withAnimation ? self.fullscreenButton.animator : self.fullscreenButton;
196     if (!self.nativeFullscreenMode) {
197         [button setImage: imageFromRes(@"fullscreen-one-button")];
198         [button setAlternateImage: imageFromRes(@"fullscreen-one-button-pressed")];
199     }
200     [NSAnimationContext endGrouping];
203 - (void)toggleJumpButtons
205     if (var_InheritBool(getIntf(), "macosx-show-playback-buttons"))
206         [self addJumpButtons:YES];
207     else
208         [self removeJumpButtons:YES];
211 - (void)addJumpButtons:(BOOL)withAnimation
213     [NSAnimationContext beginGrouping];
214     [self showButtonWithConstraint:self.prevButtonWidthConstraint animation:withAnimation];
215     [self showButtonWithConstraint:self.nextButtonWidthConstraint animation:withAnimation];
217     id backwardButton = withAnimation ? self.backwardButton.animator : self.backwardButton;
218     id forwardButton = withAnimation ? self.forwardButton.animator : self.forwardButton;
219     [forwardButton setImage:imageFromRes(@"forward-6btns")];
220     [forwardButton setAlternateImage:imageFromRes(@"forward-6btns-pressed")];
221     [backwardButton setImage:imageFromRes(@"backward-6btns")];
222     [backwardButton setAlternateImage:imageFromRes(@"backward-6btns-pressed")];
224     [NSAnimationContext endGrouping];
226     [self toggleForwardBackwardMode: YES];
229 - (void)removeJumpButtons:(BOOL)withAnimation
231     [NSAnimationContext beginGrouping];
232     [self hideButtonWithConstraint:self.prevButtonWidthConstraint animation:withAnimation];
233     [self hideButtonWithConstraint:self.nextButtonWidthConstraint animation:withAnimation];
235     id backwardButton = withAnimation ? self.backwardButton.animator : self.backwardButton;
236     id forwardButton = withAnimation ? self.forwardButton.animator : self.forwardButton;
237     [forwardButton setImage:imageFromRes(@"forward-3btns")];
238     [forwardButton setAlternateImage:imageFromRes(@"forward-3btns-pressed")];
239     [backwardButton setImage:imageFromRes(@"backward-3btns")];
240     [backwardButton setAlternateImage:imageFromRes(@"backward-3btns-pressed")];
241     [NSAnimationContext endGrouping];
243     [self toggleForwardBackwardMode: NO];
246 - (void)togglePlaymodeButtons
248     if (var_InheritBool(getIntf(), "macosx-show-playmode-buttons"))
249         [self addPlaymodeButtons:YES];
250     else
251         [self removePlaymodeButtons:YES];
254 - (void)addPlaymodeButtons:(BOOL)withAnimation
256     [NSAnimationContext beginGrouping];
257     [self showButtonWithConstraint:self.repeatButtonWidthConstraint animation:withAnimation];
258     [self showButtonWithConstraint:self.shuffleButtonWidthConstraint animation:withAnimation];
260     id button = withAnimation ? self.playlistButton.animator : self.playlistButton;
261     [button setImage:imageFromRes(@"playlist-btn")];
262     [button setAlternateImage:imageFromRes(@"playlist-btn-pressed")];
263     [NSAnimationContext endGrouping];
266 - (void)removePlaymodeButtons:(BOOL)withAnimation
268     [NSAnimationContext beginGrouping];
270     [self hideButtonWithConstraint:self.repeatButtonWidthConstraint animation:withAnimation];
271     [self hideButtonWithConstraint:self.shuffleButtonWidthConstraint animation:withAnimation];
273     id button = withAnimation ? self.playlistButton.animator : self.playlistButton;
274     [button setImage:imageFromRes(@"playlist-1btn")];
275     [button setAlternateImage:imageFromRes(@"playlist-1btn-pressed")];
276     [NSAnimationContext endGrouping];
279 #pragma mark -
280 #pragma mark Extra button actions
282 - (IBAction)stop:(id)sender
284     [[VLCCoreInteraction sharedInstance] stop];
287 // dynamically created next / prev buttons
288 - (IBAction)prev:(id)sender
290     [[VLCCoreInteraction sharedInstance] previous];
293 - (IBAction)next:(id)sender
295     [[VLCCoreInteraction sharedInstance] next];
298 - (void)setRepeatOne
300     [self.repeatButton setImage: _repeatOneImage];
301     [self.repeatButton setAlternateImage: _pressedRepeatOneImage];
304 - (void)setRepeatAll
306     [self.repeatButton setImage: _repeatAllImage];
307     [self.repeatButton setAlternateImage: _pressedRepeatAllImage];
310 - (void)setRepeatOff
312     [self.repeatButton setImage: _repeatImage];
313     [self.repeatButton setAlternateImage: _pressedRepeatImage];
316 - (IBAction)repeat:(id)sender
318     vlc_value_t looping,repeating;
319     intf_thread_t * p_intf = getIntf();
320     playlist_t * p_playlist = pl_Get(p_intf);
322     var_Get(p_playlist, "repeat", &repeating);
323     var_Get(p_playlist, "loop", &looping);
325     if (!repeating.b_bool && !looping.b_bool) {
326         /* was: no repeating at all, switching to Repeat One */
327         [[VLCCoreInteraction sharedInstance] repeatOne];
328         [self setRepeatOne];
329     }
330     else if (repeating.b_bool && !looping.b_bool) {
331         /* was: Repeat One, switching to Repeat All */
332         [[VLCCoreInteraction sharedInstance] repeatAll];
333         [self setRepeatAll];
334     } else {
335         /* was: Repeat All or bug in VLC, switching to Repeat Off */
336         [[VLCCoreInteraction sharedInstance] repeatOff];
337         [self setRepeatOff];
338     }
341 - (void)setShuffle
343     bool b_value;
344     playlist_t *p_playlist = pl_Get(getIntf());
345     b_value = var_GetBool(p_playlist, "random");
347     if (b_value) {
348         [self.shuffleButton setImage: _shuffleOnImage];
349         [self.shuffleButton setAlternateImage: _pressedShuffleOnImage];
350     } else {
351         [self.shuffleButton setImage: _shuffleImage];
352         [self.shuffleButton setAlternateImage: _pressedShuffleImage];
353     }
356 - (IBAction)shuffle:(id)sender
358     [[VLCCoreInteraction sharedInstance] shuffle];
359     [self setShuffle];
362 - (IBAction)togglePlaylist:(id)sender
364     [[[VLCMain sharedInstance] mainWindow] changePlaylistState: psUserEvent];
367 - (IBAction)volumeAction:(id)sender
369     if (sender == self.volumeSlider)
370         [[VLCCoreInteraction sharedInstance] setVolume: [sender intValue]];
371     else if (sender == self.volumeDownButton)
372         [[VLCCoreInteraction sharedInstance] toggleMute];
373     else
374         [[VLCCoreInteraction sharedInstance] setVolume: AOUT_VOLUME_MAX];
377 - (IBAction)effects:(id)sender
379     [[[VLCMain sharedInstance] mainMenu] showAudioEffects: sender];
382 #pragma mark -
383 #pragma mark Extra updaters
385 - (void)updateVolumeSlider
387     int i_volume = [[VLCCoreInteraction sharedInstance] volume];
388     BOOL b_muted = [[VLCCoreInteraction sharedInstance] mute];
390     if (b_muted)
391         i_volume = 0;
393     [self.volumeSlider setIntValue: i_volume];
395     i_volume = (i_volume * 200) / AOUT_VOLUME_MAX;
396     NSString *volumeTooltip = [NSString stringWithFormat:_NS("Volume: %i %%"), i_volume];
397     [self.volumeSlider setToolTip:volumeTooltip];
399     [self.volumeSlider setEnabled: !b_muted];
400     [self.volumeUpButton setEnabled: !b_muted];
403 - (void)updateControls
405     [super updateControls];
407     bool b_input = false;
408     bool b_seekable = false;
409     bool b_plmul = false;
410     bool b_control = false;
411     bool b_chapters = false;
413     playlist_t * p_playlist = pl_Get(getIntf());
415     PL_LOCK;
416     b_plmul = playlist_CurrentSize(p_playlist) > 1;
417     PL_UNLOCK;
419     input_thread_t * p_input = playlist_CurrentInput(p_playlist);
420     if ((b_input = (p_input != NULL))) {
421         /* seekable streams */
422         b_seekable = var_GetBool(p_input, "can-seek");
424         /* check whether slow/fast motion is possible */
425         b_control = var_GetBool(p_input, "can-rate");
427         /* chapters & titles */
428         //FIXME! b_chapters = p_input->stream.i_area_nb > 1;
430         vlc_object_release(p_input);
431     }
433     [self.stopButton setEnabled: b_input];
434     [self.prevButton setEnabled: (b_seekable || b_plmul || b_chapters)];
435     [self.nextButton setEnabled: (b_seekable || b_plmul || b_chapters)];
437     [[[VLCMain sharedInstance] mainMenu] setRateControlsEnabled: b_control];
440 @end