WidgetViewController.m 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. //
  2. // WidgetViewController.m
  3. // KulexiuForStudent
  4. //
  5. // Created by 王智 on 2022/9/13.
  6. //
  7. #import "WidgetViewController.h"
  8. #import "WidgetNavView.h"
  9. #import "WidgetDotView.h"
  10. #import "WidgetSpeedView.h"
  11. #import "WidgetFunctionView.h"
  12. #import "KSChoosePicker.h"
  13. #import "WidgetBottomButtonView.h"
  14. #import <AVFoundation/AVFoundation.h>
  15. #import "KSMetronomePlayer.h"
  16. @interface WidgetViewController ()<MetronomeControlViewDelegate,MetronomeFunctionDelegate>
  17. @property (nonatomic, strong) WidgetNavView *navView;
  18. @property (nonatomic, strong) WidgetDotView *dotView;
  19. @property (nonatomic, strong) WidgetSpeedView *speedView;
  20. @property (nonatomic, strong) WidgetFunctionView *functionView;
  21. @property (nonatomic, assign) int speed;
  22. @property (nonatomic, assign) KSWidgeMetronomeType metronomeType;
  23. @property (nonatomic, strong) KSChoosePicker *pickerView;
  24. @property (nonatomic, strong) WidgetBottomButtonView *bottomView;
  25. /** 定时器 */
  26. @property (nonatomic, strong) NSTimer *timer;
  27. /** 定时器多少秒循环一次 */
  28. @property (nonatomic, assign) double timerLength;
  29. @property (nonatomic, assign) int currentNo;
  30. @property (nonatomic, assign) NSInteger totalNoCount;
  31. @property (nonatomic, assign) float playVolume;
  32. @property (nonatomic, strong) KSMetronomePlayer *nodePlayer;
  33. @end
  34. @implementation WidgetViewController
  35. - (void)viewDidLoad {
  36. [super viewDidLoad];
  37. // Do any additional setup after loading the view.
  38. self.ks_prefersNavigationBarHidden = YES;
  39. [self configUI];
  40. }
  41. - (void)viewDidAppear:(BOOL)animated {
  42. [super viewDidAppear:animated];
  43. [self setDefaultConfig];
  44. }
  45. - (void)backAction {
  46. [self removeAll];
  47. [self.navigationController popViewControllerAnimated:YES];
  48. }
  49. - (void)setDefaultConfig {
  50. self.speed = 90;
  51. self.playVolume = 1.0f;
  52. [self updateSpeedUI];
  53. self.metronomeType = KSWidgeMetronomeType4V4;
  54. [self changeBeat];
  55. self.functionView.volumeRate = 1.0f;
  56. }
  57. - (void)configUI {
  58. [self.scrollView removeFromSuperview];
  59. self.view.backgroundColor = HexRGB(0xECF9F7);
  60. [self.view addSubview:self.navView];
  61. [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
  62. make.left.right.top.mas_equalTo(self.view);
  63. make.height.mas_equalTo(kNaviBarHeight);
  64. }];
  65. [self.view addSubview:self.dotView];
  66. [self.dotView mas_makeConstraints:^(MASConstraintMaker *make) {
  67. make.left.right.mas_equalTo(self.view);
  68. make.top.mas_equalTo(self.navView.mas_bottom).offset(10);
  69. make.height.mas_equalTo(44);
  70. }];
  71. [self.view addSubview:self.speedView];
  72. [self.speedView mas_makeConstraints:^(MASConstraintMaker *make) {
  73. make.left.right.mas_equalTo(self.view);
  74. make.top.mas_equalTo(self.dotView.mas_bottom);
  75. make.height.mas_equalTo(300);
  76. }];
  77. [self.view addSubview:self.functionView];
  78. [self.functionView mas_makeConstraints:^(MASConstraintMaker *make) {
  79. make.left.right.mas_equalTo(self.view);
  80. make.top.mas_equalTo(self.speedView.mas_bottom);
  81. make.height.mas_equalTo(115);
  82. }];
  83. [self.view addSubview:self.bottomView];
  84. [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
  85. make.left.right.mas_equalTo(self.view);
  86. make.top.mas_equalTo(self.functionView.mas_bottom).offset(10);
  87. make.height.mas_equalTo(60);
  88. }];
  89. }
  90. #pragma mark --- delegate
  91. - (void)volumeChange:(float)volume {
  92. self.playVolume = volume;
  93. self.nodePlayer.volume = volume;
  94. }
  95. - (void)clickChangeBeat {
  96. // 显示节拍选择弹窗
  97. MJWeakSelf;
  98. self.pickerView = [[KSChoosePicker alloc] initWithTitle:@"节拍" sourceData:@[@"1/2",@"2/2",@"1/4",@"2/4",@"3/4",@"4/4",@"3/8",@"6/8"] chooseReturnWithBlock:^(NSString * _Nonnull returnValue, NSInteger chooseIndex) {
  99. KSWidgeMetronomeType type = chooseIndex;
  100. weakSelf.metronomeType = type;
  101. [weakSelf changeBeat];
  102. } cancel:^{
  103. }];
  104. [self.pickerView showPicker];
  105. }
  106. - (void)clickChangeSpeed:(int)speed {
  107. self.speed = speed;
  108. // 更新UI
  109. [self updateSpeedUI];
  110. }
  111. - (void)changeSpeedWithIsAdd:(BOOL)isAdd speed:(int)speed {
  112. if (isAdd) {
  113. self.speed = MIN(self.speed +speed, 200);
  114. }else{
  115. self.speed = MAX(self.speed -speed, 50);
  116. }
  117. // 更新UI
  118. [self updateSpeedUI];
  119. }
  120. - (void)updateSpeedUI {
  121. self.speedView.speed = self.speed;
  122. self.functionView.speed = self.speed;
  123. [self stopBeat];
  124. }
  125. #pragma mark --- lazying
  126. - (WidgetNavView *)navView {
  127. if (!_navView) {
  128. _navView = [WidgetNavView shareInstance];
  129. MJWeakSelf;
  130. [_navView navBackAction:^{
  131. [weakSelf backAction];
  132. }];
  133. }
  134. return _navView;
  135. }
  136. - (WidgetDotView *)dotView {
  137. if (!_dotView) {
  138. _dotView = [WidgetDotView shareInstance];
  139. }
  140. return _dotView;
  141. }
  142. - (WidgetSpeedView *)speedView {
  143. if (!_speedView) {
  144. _speedView = [WidgetSpeedView shareInstance];
  145. _speedView.delegate = self;
  146. }
  147. return _speedView;
  148. }
  149. - (WidgetFunctionView *)functionView {
  150. if (!_functionView) {
  151. _functionView = [WidgetFunctionView shareInstance];
  152. _functionView.delegate = self;
  153. }
  154. return _functionView;
  155. }
  156. - (WidgetBottomButtonView *)bottomView {
  157. if (!_bottomView) {
  158. _bottomView = [WidgetBottomButtonView shareInstance];
  159. MJWeakSelf;
  160. [_bottomView metronomePlayCallback:^(BOOL isPlay) {
  161. if (isPlay) {
  162. [weakSelf playBeat];
  163. }
  164. else {
  165. [weakSelf stopBeat];
  166. }
  167. }];
  168. }
  169. return _bottomView;
  170. }
  171. - (void)playBeat {
  172. // 重置
  173. self.currentNo = 0;
  174. [self.nodePlayer playPrepareAction:self.speed];
  175. // 开始播放
  176. [self.timer setFireDate:[NSDate distantPast]];
  177. }
  178. - (void)stopBeat {
  179. [self.timer setFireDate:[NSDate distantFuture]];//暂停计时器
  180. self.currentNo = 0;
  181. self.bottomView.isPlay = NO;
  182. }
  183. - (void)changeBeat {
  184. [self.dotView updateSpotView:self.metronomeType];
  185. self.functionView.currentMetronomeType = self.metronomeType;
  186. self.speedView.currentType = self.metronomeType;
  187. [self stopBeat];
  188. }
  189. - (void)setSpeed:(int)speed {
  190. _speed = speed;
  191. int rateFloat = speed;
  192. self.timerLength = 1.0 / (rateFloat / 60.0);
  193. [self resetTimerPlay];
  194. }
  195. - (KSMetronomePlayer *)nodePlayer {
  196. if (!_nodePlayer) {
  197. _nodePlayer = [[KSMetronomePlayer alloc] init];
  198. }
  199. return _nodePlayer;
  200. }
  201. - (void)resetTimerPlay {
  202. if (_timer) {
  203. [self resetTimer];
  204. _timer = [NSTimer scheduledTimerWithTimeInterval:self.timerLength target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
  205. [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
  206. [_timer setFireDate:[NSDate distantFuture]];
  207. }
  208. }
  209. - (NSTimer *)timer{
  210. if (!_timer) {
  211. _timer = [NSTimer scheduledTimerWithTimeInterval:self.timerLength target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
  212. [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
  213. [_timer setFireDate:[NSDate distantFuture]];
  214. }
  215. return _timer;
  216. }
  217. - (void)timerAction {
  218. if (_metronomeType == KSWidgeMetronomeType1V2 || _metronomeType == KSWidgeMetronomeType1V4) {
  219. [self.nodePlayer playDing];
  220. }
  221. else {
  222. if ((_metronomeType == KSWidgeMetronomeType2V2 || _metronomeType == KSWidgeMetronomeType2V4) && self.currentNo %2 == 0) {
  223. [self.nodePlayer playDing];
  224. }else if ((_metronomeType == KSWidgeMetronomeType3V4 || _metronomeType == KSWidgeMetronomeType3V8) && self.currentNo %3 == 0){
  225. [self.nodePlayer playDing];
  226. }else if (_metronomeType == KSWidgeMetronomeType4V4 && self.currentNo %4 == 0){
  227. [self.nodePlayer playDing];
  228. }else if (_metronomeType == KSWidgeMetronomeType6V8 && self.currentNo %6 == 0){
  229. [self.nodePlayer playDing];
  230. }else{
  231. [self.nodePlayer playDong];
  232. }
  233. }
  234. [self.dotView updateSpotViewHeightState:self.currentNo];
  235. self.currentNo++;
  236. }
  237. #pragma mark -- 重置定时器
  238. - (void)resetTimer{
  239. [self.timer setFireDate:[NSDate distantPast]];
  240. [_timer invalidate];
  241. _timer = nil;
  242. }
  243. - (void)removeAll{
  244. if (_timer) {
  245. [_timer invalidate];
  246. _timer = nil;
  247. }
  248. }
  249. - (void)dealloc {
  250. NSLog(@"----dealloc ");
  251. [self removeAll];
  252. }
  253. /*
  254. #pragma mark - Navigation
  255. // In a storyboard-based application, you will often want to do a little preparation before navigation
  256. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  257. // Get the new view controller using [segue destinationViewController].
  258. // Pass the selected object to the new view controller.
  259. }
  260. */
  261. @end