VLCMovieViewControlPanelView.m 12 KB

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