VLCMovieViewControlPanelView.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*****************************************************************************
  2. * VLCMovieViewControlPanelView.m
  3. * VLC for iOS
  4. *****************************************************************************
  5. * Copyright (c) 2015 VideoLAN. All rights reserved.
  6. * $Id$
  7. *
  8. * Authors: Tobias Conradi <videolan@tobias-conradi.de>
  9. * Carola Nitz <nitz.carola@googlemail.com>
  10. *
  11. * Refer to the COPYING file of the official project for license.
  12. *****************************************************************************/
  13. #import "VLCMovieViewControlPanelView.h"
  14. #import "VLCPlaybackController.h"
  15. #import "VLCMetadata.h"
  16. #import "VLC-Swift.h"
  17. @interface VLCMovieViewControlPanelView ()
  18. @property (nonatomic, strong) UIView *playbackControls;
  19. @property (nonatomic, strong) UIView *spacer1;
  20. @property (nonatomic, strong) UIView *spacer2;
  21. @property (nonatomic, strong) NSMutableArray *constraints;
  22. @property (nonatomic, assign) BOOL compactMode;
  23. @property (nonatomic, strong) VLCPlaybackController *playbackController;
  24. @end
  25. @implementation VLCMovieViewControlPanelView
  26. static const CGFloat maxControlsWidth = 474.0;
  27. - (instancetype)initWithFrame:(CGRect)frame
  28. {
  29. self = [super initWithFrame:frame];
  30. if (self) {
  31. [self setupSubviews];
  32. [self setupConstraints];
  33. _compactMode = YES;
  34. [self setupConstraints:_compactMode];
  35. }
  36. return self;
  37. }
  38. - (void)setupSubviews
  39. {
  40. _playbackSpeedButton = [[UIButton alloc] initWithFrame:CGRectZero];
  41. [_playbackSpeedButton setImage:[UIImage imageNamed:@"speedIcon"] forState:UIControlStateNormal];
  42. _playbackSpeedButton.translatesAutoresizingMaskIntoConstraints = NO;
  43. [self addSubview:_playbackSpeedButton];
  44. _trackSwitcherButton = [[UIButton alloc] initWithFrame:CGRectZero];
  45. [_trackSwitcherButton setImage:[UIImage imageNamed:@"audioTrackIcon"] forState:UIControlStateNormal];
  46. _trackSwitcherButton.translatesAutoresizingMaskIntoConstraints = NO;
  47. [self addSubview:_trackSwitcherButton];
  48. _playbackControls = [[UIView alloc] initWithFrame:CGRectZero];
  49. _playbackControls.translatesAutoresizingMaskIntoConstraints = NO;
  50. [self addSubview:_playbackControls];
  51. _bwdButton = [[UIButton alloc] initWithFrame:CGRectZero];
  52. [_bwdButton setImage:[UIImage imageNamed:@"backIcon"] forState:UIControlStateNormal];
  53. _bwdButton.translatesAutoresizingMaskIntoConstraints = NO;
  54. [_playbackControls addSubview:_bwdButton];
  55. _spacer1 = [UIView new];
  56. _spacer1.backgroundColor = [UIColor clearColor];
  57. _spacer1.translatesAutoresizingMaskIntoConstraints = NO;
  58. [_playbackControls addSubview:_spacer1];
  59. _spacer2 = [UIView new];
  60. _spacer2.backgroundColor = [UIColor clearColor];
  61. _spacer2.translatesAutoresizingMaskIntoConstraints = NO;
  62. [_playbackControls addSubview:_spacer2];
  63. _playPauseButton = [[UIButton alloc] initWithFrame:CGRectZero];
  64. [_playPauseButton setImage:[UIImage imageNamed:@"playIcon"] forState:UIControlStateNormal];
  65. _playPauseButton.translatesAutoresizingMaskIntoConstraints = NO;
  66. [_playbackControls addSubview:_playPauseButton];
  67. _fwdButton = [[UIButton alloc] initWithFrame:CGRectZero];
  68. [_fwdButton setImage:[UIImage imageNamed:@"forwardIcon"] forState:UIControlStateNormal];
  69. _fwdButton.translatesAutoresizingMaskIntoConstraints = NO;
  70. [_playbackControls addSubview:_fwdButton];
  71. _videoFilterButton = [[UIButton alloc] initWithFrame:CGRectZero];
  72. [_videoFilterButton setImage:[UIImage imageNamed:@"videoEffectsIcon"] forState:UIControlStateNormal];
  73. _videoFilterButton.translatesAutoresizingMaskIntoConstraints = NO;
  74. [self addSubview:_videoFilterButton];
  75. _moreActionsButton = [[UIButton alloc] initWithFrame:CGRectZero];
  76. [_moreActionsButton setImage:[UIImage imageNamed:@"More"] forState:UIControlStateNormal];
  77. _moreActionsButton.translatesAutoresizingMaskIntoConstraints = NO;
  78. [self addSubview:_moreActionsButton];
  79. _volumeView = [[VLCVolumeView alloc] initWithFrame:CGRectZero];
  80. _volumeView.translatesAutoresizingMaskIntoConstraints = NO;
  81. [self addSubview:_volumeView];
  82. _playbackSpeedButton.accessibilityLabel = NSLocalizedString(@"PLAYBACK_SPEED", nil);
  83. _trackSwitcherButton.accessibilityLabel = NSLocalizedString(@"OPEN_TRACK_PANEL", nil);
  84. _bwdButton.accessibilityLabel = NSLocalizedString(@"BWD_BUTTON", nil);
  85. _playPauseButton.accessibilityLabel = NSLocalizedString(@"PLAY_PAUSE_BUTTON", nil);
  86. _playPauseButton.accessibilityIdentifier = VLCAccessibilityIdentifier.playPause;
  87. _playPauseButton.accessibilityHint = NSLocalizedString(@"LONGPRESS_TO_STOP", nil);
  88. _fwdButton.accessibilityLabel = NSLocalizedString(@"FWD_BUTTON", nil);
  89. _videoFilterButton.accessibilityLabel = NSLocalizedString(@"VIDEO_FILTER", nil);
  90. UILongPressGestureRecognizer *longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(playPauseLongPress:)];
  91. [_playPauseButton addGestureRecognizer:longPressRecognizer];
  92. [self.volumeView setVolumeThumbImage:[UIImage imageNamed:@"sliderKnob"] forState:UIControlStateNormal];
  93. }
  94. - (void)setupConstraints
  95. {
  96. NSDictionary *viewsDict = @{
  97. @"forward" : self.fwdButton,
  98. @"backward" : self.bwdButton,
  99. @"playpause" : self.playPauseButton,
  100. @"speed" : self.playbackSpeedButton,
  101. @"track" : self.trackSwitcherButton,
  102. @"more" : self.moreActionsButton,
  103. @"filter" : self.videoFilterButton,
  104. @"volume" : self.volumeView,
  105. @"spacer1" : _spacer1,
  106. @"spacer2" : _spacer2,
  107. };
  108. NSMutableArray *staticConstraints = [NSMutableArray new];
  109. [staticConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[backward(40)][spacer1(margin@750)][playpause(40)][spacer2(==spacer1)][forward(40)]|"
  110. options:NSLayoutFormatAlignAllCenterY
  111. metrics:@{@"margin": @15.0}
  112. views:viewsDict]];
  113. [staticConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[backward(40)]|"
  114. options:NSLayoutFormatAlignAllCenterX
  115. metrics:nil
  116. views:viewsDict]];
  117. for (NSString *object in viewsDict) {
  118. NSString *format = [NSString stringWithFormat:@"V:[%@(40)]", object];
  119. [staticConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:format
  120. options:NSLayoutFormatAlignAllCenterX
  121. metrics:nil
  122. views:viewsDict]];
  123. }
  124. [self addConstraints:staticConstraints];
  125. }
  126. - (void)updateViewConstraints
  127. {
  128. BOOL compactMode = CGRectGetWidth(self.frame) <= maxControlsWidth;
  129. if (self.compactMode != compactMode) {
  130. self.compactMode = compactMode;
  131. [self setupConstraints:compactMode];
  132. }
  133. }
  134. - (void)setupConstraints:(BOOL)compactMode
  135. {
  136. if (_constraints != nil) {
  137. [self removeConstraints:_constraints];
  138. }
  139. NSDictionary *viewsDict = @{@"speed" : self.playbackSpeedButton,
  140. @"track" : self.trackSwitcherButton,
  141. @"playback" : self.playbackControls,
  142. @"filter" : self.videoFilterButton,
  143. @"actions" : self.moreActionsButton,
  144. @"volume" : self.volumeView,
  145. };
  146. _constraints = [NSMutableArray array];
  147. if (compactMode) {
  148. [_constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[speed(35)]-[track(35)]-(>=8)-[playback]-(>=8)-[filter(35)]-[actions(35)]-|"
  149. options:NSLayoutFormatAlignAllCenterY
  150. metrics:nil
  151. views:viewsDict]];
  152. [_constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=10)-[volume(==300)]-(>=10)-|"
  153. options:0
  154. metrics:nil
  155. views:viewsDict]];
  156. [_constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[playback]-[volume]-|"
  157. options:NSLayoutFormatAlignAllCenterX
  158. metrics:nil
  159. views:viewsDict]];
  160. } else {
  161. [_constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[volume(>=150)]-(>=8)-[playback]-(>=8)-[speed(35)]-[track(35)]-[filter(35)]-[actions(35)]-|"
  162. options:NSLayoutFormatAlignAllCenterY
  163. metrics:nil
  164. views:viewsDict]];
  165. [_constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[playback]-|"
  166. options:0
  167. metrics:nil
  168. views:viewsDict]];
  169. }
  170. [_constraints addObject:[NSLayoutConstraint constraintWithItem:self.playbackControls
  171. attribute:NSLayoutAttributeCenterX
  172. relatedBy:NSLayoutRelationEqual
  173. toItem:self
  174. attribute:NSLayoutAttributeCenterX
  175. multiplier:1.0
  176. constant:0]];
  177. [self addConstraints:_constraints];
  178. }
  179. - (void)layoutSubviews
  180. {
  181. [super layoutSubviews];
  182. [self updateViewConstraints];
  183. }
  184. - (VLCPlaybackController *)playbackController
  185. {
  186. if (!_playbackController) {
  187. _playbackController = [VLCPlaybackController sharedInstance];
  188. }
  189. return _playbackController;
  190. }
  191. - (void)playPauseLongPress:(UILongPressGestureRecognizer *)recognizer
  192. {
  193. switch (recognizer.state) {
  194. case UIGestureRecognizerStateBegan:
  195. { UIImage *image = [UIImage imageNamed:@"stopIcon"];
  196. [_playPauseButton setImage:image forState:UIControlStateNormal];
  197. }
  198. break;
  199. case UIGestureRecognizerStateEnded:
  200. [self.playbackController stopPlayback];
  201. break;
  202. case UIGestureRecognizerStateCancelled:
  203. case UIGestureRecognizerStateFailed:
  204. [self updatePlayPauseButton];
  205. break;
  206. default:
  207. break;
  208. }
  209. }
  210. - (void)updateButtons
  211. {
  212. [self updatePlayPauseButton];
  213. self.trackSwitcherButton.hidden = !self.playbackController.currentMediaHasTrackToChooseFrom;
  214. self.videoFilterButton.hidden = self.playbackController.metadata.isAudioOnly;
  215. }
  216. - (void)updatePlayPauseButton
  217. {
  218. const BOOL isPlaying = self.playbackController.isPlaying;
  219. UIImage *playPauseImage = isPlaying ? [UIImage imageNamed:@"pauseIcon"] : [UIImage imageNamed:@"playIcon"];
  220. [_playPauseButton setImage:playPauseImage forState:UIControlStateNormal];
  221. }
  222. @end