PlayRecordAudioView.m 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // _____ _
  2. // |_ _| |_ _ _ ___ ___ _ __ __ _
  3. // | | | ' \| '_/ -_) -_) ' \/ _` |_
  4. // |_| |_||_|_| \___\___|_|_|_\__,_(_)
  5. //
  6. // Threema iOS Client
  7. // Copyright (c) 2014-2020 Threema GmbH
  8. //
  9. // This program is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU Affero General Public License, version 3,
  11. // as published by the Free Software Foundation.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU Affero General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Affero General Public License
  19. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. #import "PlayRecordAudioView.h"
  21. #import "UIImage+ColoredImage.h"
  22. #import "Utils.h"
  23. #import "BundleUtil.h"
  24. #import "AudioRecorder.h"
  25. #define AUDIO_PLAY_COLOR [UIColor blackColor]
  26. #define AUDIO_RECORD_COLOR [UIColor redColor]
  27. @interface PlayRecordAudioView () <RecordingMeterGraphProtocol>
  28. @property AudioRecorder *recorder;
  29. @property AVAudioPlayer *player;
  30. @property NSTimer *updateTimer;
  31. @property UIImage *playImage;
  32. @property UIImage *stopImage;
  33. @property UIImage *pauseImage;
  34. @property BOOL quitNameSet;
  35. @end
  36. @implementation PlayRecordAudioView
  37. - (void)setup {
  38. self.backgroundColor = [Colors backgroundDark];
  39. _playImage = [UIImage imageNamed:@"Play" inColor:[Colors fontNormal]];
  40. _playImage.accessibilityLabel = [BundleUtil localizedStringForKey:@"play"];
  41. _stopImage = [UIImage imageNamed:@"Stop" inColor:[Colors fontNormal]];
  42. _stopImage.accessibilityLabel = @"stop";
  43. _stopImage.accessibilityLabel = [BundleUtil localizedStringForKey:@"stop"];
  44. _pauseImage = [UIImage imageNamed:@"Pause" inColor:[Colors fontNormal]];
  45. _pauseImage.accessibilityLabel = [BundleUtil localizedStringForKey:@"pause"];
  46. [_playPauseStopButton setImage:_playImage forState:UIControlStateNormal];
  47. UIImage *tmpImage = [UIImage imageNamed:@"Record" inColor:AUDIO_RECORD_COLOR];
  48. UIImage *recordImage = [tmpImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
  49. [_recordButton setImage:recordImage forState:UIControlStateNormal];
  50. _recordButton.tintColor = AUDIO_RECORD_COLOR;
  51. _recordButton.accessibilityLabel = [BundleUtil localizedStringForKey:@"record"];
  52. self.layer.cornerRadius = 10.0;
  53. [_sendButton setTitle:NSLocalizedString(@"send", nil) forState:UIControlStateNormal];
  54. [self setupColors];
  55. }
  56. - (void)setupColors {
  57. [_sendButton setTitleColor:[Colors main] forState:UIControlStateNormal];
  58. _dataView.backgroundColor = [Colors background];
  59. _buttonView.backgroundColor = [Colors backgroundDark];
  60. _timeCursorLabel.textColor = [Colors fontNormal];
  61. _durationLabel.textColor = [Colors fontNormal];
  62. _horizontalDividerLine.backgroundColor = [Colors hairline];
  63. _verticalDividerLine.backgroundColor = [Colors hairline];
  64. }
  65. - (void)setupForPlaying:(AVAudioPlayer *)player {
  66. _player = player;
  67. _recorder = nil;
  68. _quitNameSet = NO;
  69. [_graphView drawAudioTrack: player];
  70. _graphView.delegate = self;
  71. [self setPlaying];
  72. }
  73. - (void)setPlaying {
  74. _recordButton.enabled = NO;
  75. [_playPauseStopButton setImage:_pauseImage forState:UIControlStateNormal];
  76. [self updateTimerFired];
  77. if (_player.playing) {
  78. [_graphView setPlaying:YES];
  79. [self startTimeUpdater];
  80. }
  81. }
  82. - (void)setupForRecording:(AudioRecorder *)recorder {
  83. _player = nil;
  84. _recorder = recorder;
  85. _quitNameSet = NO;
  86. [self setRecording];
  87. [_graphView reset];
  88. [_graphView drawLiveRecorder: recorder.recorder];
  89. }
  90. - (void)setRecording {
  91. _recordButton.enabled = NO;
  92. [_playPauseStopButton setImage:_stopImage forState:UIControlStateNormal];
  93. if (_recorder.recording) {
  94. [_graphView setRecording:YES];
  95. [self startTimeUpdater];
  96. } else {
  97. [_recorder setInterruptedAndNotStarted:true];
  98. }
  99. }
  100. - (void)setPaused {
  101. _recordButton.enabled = YES;
  102. [_playPauseStopButton setImage:_playImage forState:UIControlStateNormal];
  103. [self stopTimeUpdater];
  104. }
  105. - (void)setStopped {
  106. _recordButton.enabled = YES;
  107. [_playPauseStopButton setImage:_playImage forState:UIControlStateNormal];
  108. [_graphView setPlaying:NO];
  109. [self stopTimeUpdater];
  110. [self updateTimerFired];
  111. }
  112. - (void)startTimeUpdater {
  113. [_updateTimer invalidate];
  114. _updateTimer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(updateTimerFired) userInfo:nil repeats:YES];
  115. [[NSRunLoop mainRunLoop] addTimer:_updateTimer forMode:NSDefaultRunLoopMode];
  116. [self updateTimerFired];
  117. }
  118. - (void)stopTimeUpdater {
  119. [_updateTimer invalidate];
  120. _updateTimer = nil;
  121. }
  122. - (void)setFinishedRecording {
  123. [_playPauseStopButton setImage:_playImage forState:UIControlStateNormal];
  124. _recordButton.enabled = YES;
  125. }
  126. -(void)toggleButtonsForRecording:(BOOL)hidden {
  127. if (_recordButton.hidden && hidden)
  128. _playPauseStopButton.frame = CGRectOffset(_playPauseStopButton.frame, -10, 0);
  129. else if (!_recordButton.hidden && !hidden)
  130. _playPauseStopButton.frame = CGRectOffset(_playPauseStopButton.frame, 10, 0);
  131. _recordButton.hidden = !hidden;
  132. _verticalDividerLine.hidden = !hidden;
  133. _sendButton.hidden = !hidden;
  134. }
  135. - (void)updateTimerFired {
  136. NSTimeInterval duration, position;
  137. if (_recorder) {
  138. duration = 0.0;
  139. position = _recorder.currentTime;
  140. } else if (_player) {
  141. position = _player.currentTime;
  142. duration = _player.duration;
  143. } else {
  144. position = 0.0;
  145. duration = 0.0;
  146. }
  147. if (position > 2 && !_quitNameSet) {
  148. _quitNameSet = YES;
  149. [_delegate setAccessibilityLabelForQuit];
  150. }
  151. _durationLabel.text = [Utils timeStringForSeconds:duration];
  152. _timeCursorLabel.text = [Utils timeStringForSeconds:position];
  153. if (UIAccessibilityIsVoiceOverRunning()) {
  154. _durationLabel.accessibilityLabelBlock = ^NSString *() {
  155. return [Utils accessibilityStringAtTime:duration withPrefix:@"duration"];
  156. };
  157. _timeCursorLabel.accessibilityLabelBlock = ^NSString *() {
  158. return [Utils accessibilityStringAtTime:position withPrefix:@"current_position"];
  159. };
  160. }
  161. }
  162. #pragma mark - RecordingMeterGraphProtocol
  163. - (void)didUpdatePlayerPosition {
  164. [self updateTimerFired];
  165. }
  166. @end