VLCMovieViewControlPanelView.m 12 KB

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