WFCUVideoViewController.m 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. //
  2. // ViewController.m
  3. // WFDemo
  4. //
  5. // Created by heavyrain on 17/9/27.
  6. // Copyright © 2017年 WildFireChat. All rights reserved.
  7. //
  8. #import "WFCUVideoViewController.h"
  9. #import <AVFoundation/AVFoundation.h>
  10. #import <AVKit/AVKit.h>
  11. #if WFCU_SUPPORT_VOIP
  12. #import <WebRTC/WebRTC.h>
  13. #import <WFAVEngineKit/WFAVEngineKit.h>
  14. #import "WFCUFloatingWindow.h"
  15. #endif
  16. #import "SDWebImage.h"
  17. #import <WFChatClient/WFCCConversation.h>
  18. @interface WFCUVideoViewController () <UITextFieldDelegate
  19. #if WFCU_SUPPORT_VOIP
  20. ,WFAVCallSessionDelegate
  21. #endif
  22. >
  23. #if WFCU_SUPPORT_VOIP
  24. @property (nonatomic, strong) UIView *bigVideoView;
  25. @property (nonatomic, strong) UIView *smallVideoView;
  26. @property (nonatomic, strong) UIButton *hangupButton;
  27. @property (nonatomic, strong) UIButton *answerButton;
  28. @property (nonatomic, strong) UIButton *switchCameraButton;
  29. @property (nonatomic, strong) UIButton *audioButton;
  30. @property (nonatomic, strong) UIButton *speakerButton;
  31. @property (nonatomic, strong) UIButton *downgradeButton;
  32. @property (nonatomic, strong) UIButton *videoButton;
  33. @property (nonatomic, strong) UIButton *scalingButton;
  34. @property (nonatomic, strong) UIButton *minimizeButton;
  35. @property (nonatomic, strong) UIImageView *portraitView;
  36. @property (nonatomic, strong) UILabel *userNameLabel;
  37. @property (nonatomic, strong) UILabel *stateLabel;
  38. @property (nonatomic, assign) BOOL audioMuted;
  39. @property (nonatomic, assign) BOOL videoMuted;
  40. @property (nonatomic, strong) WFAVCallSession *currentSession;
  41. @property (nonatomic, strong) RTCVideoTrack *localVideoTrack;
  42. @property (nonatomic, strong) RTCVideoTrack *remoteVideoTrack;
  43. @property (nonatomic, assign) WFAVVideoScalingType scalingType;
  44. @property (nonatomic, assign) CGPoint panStartPoint;
  45. @property (nonatomic, assign) CGRect panStartVideoFrame;
  46. @property (nonatomic, strong) NSTimer *connectedTimer;
  47. #endif
  48. @end
  49. #define ButtonSize 90
  50. #define SmallVideoView 120
  51. #if !WFCU_SUPPORT_VOIP
  52. @interface WFAVCallSession : NSObject
  53. @end
  54. @implementation WFAVCallSession
  55. @end
  56. #endif
  57. @implementation WFCUVideoViewController
  58. #if !WFCU_SUPPORT_VOIP
  59. - (instancetype)initWithSession:(WFAVCallSession *)session {
  60. self = [super init];
  61. return self;
  62. }
  63. - (instancetype)initWithTarget:(NSString *)targetId conversation:(WFCCConversation *)conversation audioOnly:(BOOL)audioOnly {
  64. self = [super init];
  65. return self;
  66. }
  67. #else
  68. - (instancetype)initWithSession:(WFAVCallSession *)session {
  69. self = [super init];
  70. if (self) {
  71. self.currentSession = session;
  72. self.currentSession.delegate = self;
  73. [self didChangeState:kWFAVEngineStateIncomming];
  74. self.audioMuted = NO;
  75. self.videoMuted = NO;
  76. }
  77. return self;
  78. }
  79. - (instancetype)initWithTarget:(NSString *)targetId conversation:(WFCCConversation *)conversation audioOnly:(BOOL)audioOnly {
  80. self = [super init];
  81. if (self) {
  82. WFAVCallSession *session = [[WFAVEngineKit sharedEngineKit] startCall:targetId
  83. audioOnly:audioOnly
  84. conversation:conversation
  85. sessionDelegate:self];
  86. self.currentSession = session;
  87. self.audioMuted = NO;
  88. self.videoMuted = NO;
  89. }
  90. return self;
  91. }
  92. - (void)viewDidLoad {
  93. [super viewDidLoad];
  94. [self.view setBackgroundColor:[UIColor blackColor]];
  95. self.scalingType = kWFAVVideoScalingTypeAspectBalanced;
  96. self.bigVideoView = [[UIView alloc] initWithFrame:self.view.bounds];
  97. [self.view addSubview:self.bigVideoView];
  98. self.smallVideoView = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width - SmallVideoView, kStatusBarAndNavigationBarHeight, SmallVideoView, SmallVideoView * 4 /3)];
  99. [self.smallVideoView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onSmallVideoPan:)]];
  100. [self.view addSubview:self.smallVideoView];
  101. [self checkAVPermission];
  102. if(self.currentSession.state == kWFAVEngineStateOutgoing && !self.currentSession.isAudioOnly) {
  103. [[WFAVEngineKit sharedEngineKit] startPreview];
  104. }
  105. WFCCUserInfo *user = [[WFCCIMService sharedWFCIMService] getUserInfo:self.currentSession.clientId inGroup:self.currentSession.conversation.type == Group_Type ? self.currentSession.conversation.target : nil refresh:NO];
  106. self.portraitView = [[UIImageView alloc] init];
  107. [self.portraitView sd_setImageWithURL:[NSURL URLWithString:user.portrait] placeholderImage:[UIImage imageNamed:@"PersonalChat"]];
  108. self.portraitView.layer.masksToBounds = YES;
  109. self.portraitView.layer.cornerRadius = 8.f;
  110. [self.view addSubview:self.portraitView];
  111. self.userNameLabel = [[UILabel alloc] init];
  112. self.userNameLabel.font = [UIFont systemFontOfSize:26];
  113. self.userNameLabel.text = user.displayName;
  114. self.userNameLabel.textColor = [UIColor whiteColor];
  115. [self.view addSubview:self.userNameLabel];
  116. self.stateLabel = [[UILabel alloc] init];
  117. self.stateLabel.font = [UIFont systemFontOfSize:16];
  118. self.stateLabel.textColor = [UIColor whiteColor];
  119. [self.view addSubview:self.stateLabel];
  120. [self updateTopViewFrame];
  121. [self didChangeState:self.currentSession.state];//update ui
  122. }
  123. - (UIButton *)hangupButton {
  124. if (!_hangupButton) {
  125. _hangupButton = [[UIButton alloc] init];
  126. [_hangupButton setImage:[UIImage imageNamed:@"hangup"] forState:UIControlStateNormal];
  127. [_hangupButton setImage:[UIImage imageNamed:@"hangup_hover"] forState:UIControlStateHighlighted];
  128. [_hangupButton setImage:[UIImage imageNamed:@"hangup_hover"] forState:UIControlStateSelected];
  129. _hangupButton.backgroundColor = [UIColor clearColor];
  130. [_hangupButton addTarget:self action:@selector(hanupButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  131. _hangupButton.hidden = YES;
  132. [self.view addSubview:_hangupButton];
  133. }
  134. return _hangupButton;
  135. }
  136. - (UIButton *)answerButton {
  137. if (!_answerButton) {
  138. _answerButton = [[UIButton alloc] init];
  139. [_answerButton setImage:[UIImage imageNamed:@"answer"] forState:UIControlStateNormal];
  140. [_answerButton setImage:[UIImage imageNamed:@"answer_hover"] forState:UIControlStateHighlighted];
  141. [_answerButton setImage:[UIImage imageNamed:@"answer_hover"] forState:UIControlStateSelected];
  142. _answerButton.backgroundColor = [UIColor clearColor];
  143. [_answerButton addTarget:self action:@selector(answerButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  144. _answerButton.hidden = YES;
  145. [self.view addSubview:_answerButton];
  146. }
  147. return _answerButton;
  148. }
  149. - (UIButton *)minimizeButton {
  150. if (!_minimizeButton) {
  151. _minimizeButton = [[UIButton alloc] initWithFrame:CGRectMake(16, 26, 30, 30)];
  152. [_minimizeButton setImage:[UIImage imageNamed:@"minimize"] forState:UIControlStateNormal];
  153. [_minimizeButton setImage:[UIImage imageNamed:@"minimize_hover"] forState:UIControlStateHighlighted];
  154. [_minimizeButton setImage:[UIImage imageNamed:@"minimize_hover"] forState:UIControlStateSelected];
  155. _minimizeButton.backgroundColor = [UIColor clearColor];
  156. [_minimizeButton addTarget:self action:@selector(minimizeButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  157. _minimizeButton.hidden = YES;
  158. [self.view addSubview:_minimizeButton];
  159. }
  160. return _minimizeButton;
  161. }
  162. - (UIButton *)switchCameraButton {
  163. if (!_switchCameraButton) {
  164. _switchCameraButton = [[UIButton alloc] init];
  165. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera"] forState:UIControlStateNormal];
  166. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera_hover"] forState:UIControlStateHighlighted];
  167. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera_hover"] forState:UIControlStateSelected];
  168. _switchCameraButton.backgroundColor = [UIColor clearColor];
  169. [_switchCameraButton addTarget:self action:@selector(switchCameraButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  170. _switchCameraButton.hidden = YES;
  171. [self.view addSubview:_switchCameraButton];
  172. }
  173. return _switchCameraButton;
  174. }
  175. - (UIButton *)downgradeButton {
  176. if (!_downgradeButton) {
  177. _downgradeButton = [[UIButton alloc] init];
  178. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio"] forState:UIControlStateNormal];
  179. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateHighlighted];
  180. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateSelected];
  181. _downgradeButton.backgroundColor = [UIColor clearColor];
  182. [_downgradeButton addTarget:self action:@selector(downgradeButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  183. _downgradeButton.hidden = YES;
  184. [self.view addSubview:_downgradeButton];
  185. }
  186. return _downgradeButton;
  187. }
  188. - (UIButton *)audioButton {
  189. if (!_audioButton) {
  190. _audioButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  191. [_audioButton setImage:[UIImage imageNamed:@"mute"] forState:UIControlStateNormal];
  192. [_audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateHighlighted];
  193. [_audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateSelected];
  194. _audioButton.backgroundColor = [UIColor clearColor];
  195. [_audioButton addTarget:self action:@selector(audioButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  196. _audioButton.hidden = YES;
  197. [self.view addSubview:_audioButton];
  198. }
  199. return _audioButton;
  200. }
  201. - (UIButton *)speakerButton {
  202. if (!_speakerButton) {
  203. _speakerButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  204. [_speakerButton setImage:[UIImage imageNamed:@"speaker"] forState:UIControlStateNormal];
  205. [_speakerButton setImage:[UIImage imageNamed:@"speaker_hover"] forState:UIControlStateHighlighted];
  206. [_speakerButton setImage:[UIImage imageNamed:@"speaker_hover"] forState:UIControlStateSelected];
  207. _speakerButton.backgroundColor = [UIColor clearColor];
  208. [_speakerButton addTarget:self action:@selector(speakerButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  209. _speakerButton.hidden = YES;
  210. [self.view addSubview:_speakerButton];
  211. }
  212. return _speakerButton;
  213. }
  214. - (UIButton *)videoButton {
  215. if (!_videoButton) {
  216. _videoButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  217. [_videoButton setTitle:@"视频" forState:UIControlStateNormal];
  218. _videoButton.backgroundColor = [UIColor greenColor];
  219. [_videoButton addTarget:self action:@selector(videoButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  220. _videoButton.hidden = YES;
  221. [self.view addSubview:_videoButton];
  222. }
  223. return _videoButton;
  224. }
  225. - (UIButton *)scalingButton {
  226. if (!_scalingButton) {
  227. _scalingButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  228. [_scalingButton setTitle:@"缩放" forState:UIControlStateNormal];
  229. _scalingButton.backgroundColor = [UIColor greenColor];
  230. [_scalingButton addTarget:self action:@selector(scalingButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  231. _scalingButton.hidden = YES;
  232. [self.view addSubview:_scalingButton];
  233. }
  234. return _scalingButton;
  235. }
  236. - (void)startConnectedTimer {
  237. [self stopConnectedTimer];
  238. self.connectedTimer = [NSTimer scheduledTimerWithTimeInterval:1
  239. target:self
  240. selector:@selector(updateConnectedTimeLabel)
  241. userInfo:nil
  242. repeats:YES];
  243. [self.connectedTimer fire];
  244. }
  245. - (void)stopConnectedTimer {
  246. if (self.connectedTimer) {
  247. [self.connectedTimer invalidate];
  248. self.connectedTimer = nil;
  249. }
  250. }
  251. - (void)updateConnectedTimeLabel {
  252. long sec = [[NSDate date] timeIntervalSince1970] - self.currentSession.connectedTime / 1000;
  253. if (sec < 60 * 60) {
  254. self.stateLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", sec / 60, sec % 60];
  255. } else {
  256. self.stateLabel.text = [NSString stringWithFormat:@"%02ld:%02ld:%02ld", sec / 60 / 60, (sec / 60) % 60, sec % 60];
  257. }
  258. }
  259. - (void)hanupButtonDidTap:(UIButton *)button {
  260. if(self.currentSession.state != kWFAVEngineStateIdle) {
  261. [self.currentSession endCall];
  262. }
  263. }
  264. - (void)answerButtonDidTap:(UIButton *)button {
  265. if (self.currentSession.state == kWFAVEngineStateIncomming) {
  266. [self.currentSession answerCall:NO];
  267. }
  268. }
  269. - (void)minimizeButtonDidTap:(UIButton *)button {
  270. [WFCUFloatingWindow startCallFloatingWindow:self.currentSession withTouchedBlock:^(WFAVCallSession *callSession) {
  271. [[WFAVEngineKit sharedEngineKit] presentViewController:[[WFCUVideoViewController alloc] initWithSession:callSession]];
  272. }];
  273. [[WFAVEngineKit sharedEngineKit] dismissViewController:self];
  274. }
  275. - (void)switchCameraButtonDidTap:(UIButton *)button {
  276. if (self.currentSession.state != kWFAVEngineStateIdle) {
  277. [self.currentSession switchCamera];
  278. }
  279. }
  280. - (void)downgradeButtonDidTap:(UIButton *)button {
  281. if (self.currentSession.state == kWFAVEngineStateIncomming) {
  282. [self.currentSession answerCall:YES];
  283. } else if(self.currentSession.state == kWFAVEngineStateConnected) {
  284. self.currentSession.audioOnly = !self.currentSession.isAudioOnly;
  285. }
  286. }
  287. - (void)audioButtonDidTap:(UIButton *)button {
  288. if (self.currentSession.state != kWFAVEngineStateIdle) {
  289. BOOL result = [self.currentSession muteAudio:!self.audioMuted];
  290. if (result) {
  291. self.audioMuted = !self.audioMuted;
  292. if (self.audioMuted) {
  293. [self.audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateNormal];
  294. } else {
  295. [self.audioButton setImage:[UIImage imageNamed:@"mute"] forState:UIControlStateNormal];
  296. }
  297. }
  298. }
  299. }
  300. - (void)speakerButtonDidTap:(UIButton *)button {
  301. if (self.currentSession.state != kWFAVEngineStateIdle) {
  302. [self.currentSession enableSpeaker:!self.currentSession.isSpeaker];
  303. [self updateSpeakerButton];
  304. }
  305. }
  306. - (void)updateSpeakerButton {
  307. if (!self.currentSession.isSpeaker) {
  308. [self.speakerButton setImage:[UIImage imageNamed:@"speaker"] forState:UIControlStateNormal];
  309. } else {
  310. [self.speakerButton setImage:[UIImage imageNamed:@"speaker_hover"] forState:UIControlStateNormal];
  311. }
  312. }
  313. - (void)viewWillAppear:(BOOL)animated {
  314. [super viewWillAppear:animated];
  315. if (_currentSession.state == kWFAVEngineStateConnected) {
  316. [self updateConnectedTimeLabel];
  317. [self startConnectedTimer];
  318. }
  319. }
  320. - (void)viewWillDisappear:(BOOL)animated {
  321. [super viewWillDisappear:animated];
  322. [self stopConnectedTimer];
  323. }
  324. - (void)setPanStartPoint:(CGPoint)panStartPoint {
  325. _panStartPoint = panStartPoint;
  326. _panStartVideoFrame = self.smallVideoView.frame;
  327. }
  328. - (void)moveToPanPoint:(CGPoint)panPoint {
  329. CGRect frame = self.panStartVideoFrame;
  330. CGSize moveSize = CGSizeMake(panPoint.x - self.panStartPoint.x, panPoint.y - self.panStartPoint.y);
  331. frame.origin.x += moveSize.width;
  332. frame.origin.y += moveSize.height;
  333. self.smallVideoView.frame = frame;
  334. }
  335. - (void)onSmallVideoPan:(UIPanGestureRecognizer *)recognize {
  336. switch (recognize.state) {
  337. case UIGestureRecognizerStateBegan:
  338. self.panStartPoint = [recognize translationInView:self.view];
  339. break;
  340. case UIGestureRecognizerStateChanged: {
  341. CGPoint currentPoint = [recognize translationInView:self.view];
  342. [self moveToPanPoint:currentPoint];
  343. break;
  344. }
  345. case UIGestureRecognizerStateEnded: {
  346. CGPoint endPoint = [recognize translationInView:self.view];
  347. [self moveToPanPoint:endPoint];
  348. break;
  349. }
  350. case UIGestureRecognizerStateCancelled:
  351. case UIGestureRecognizerStateFailed:
  352. default:
  353. break;
  354. }
  355. }
  356. - (void)videoButtonDidTap:(UIButton *)button {
  357. if (self.currentSession.state != kWFAVEngineStateIdle) {
  358. BOOL result = [self.currentSession muteVideo:!self.videoMuted];
  359. if (result) {
  360. self.videoMuted = !self.videoMuted;
  361. }
  362. }
  363. }
  364. - (void)scalingButtonDidTap:(UIButton *)button {
  365. if (self.currentSession.state != kWFAVEngineStateIdle) {
  366. if (self.scalingType < kWFAVVideoScalingTypeAspectBalanced) {
  367. self.scalingType++;
  368. } else {
  369. self.scalingType = kWFAVVideoScalingTypeAspectFit;
  370. }
  371. [self.currentSession setupLocalVideoView:self.smallVideoView scalingType:self.scalingType];
  372. [self.currentSession setupRemoteVideoView:self.bigVideoView scalingType:self.scalingType];
  373. }
  374. }
  375. - (CGRect)getButtomCenterButtonFrame {
  376. return CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  377. }
  378. - (CGRect)getButtomLeftButtonFrame {
  379. return CGRectMake(self.view.frame.size.width/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  380. }
  381. - (CGRect)getButtomRightButtonFrame {
  382. return CGRectMake(self.view.frame.size.width*3/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  383. }
  384. - (CGRect)getToAudioButtonFrame {
  385. return CGRectMake(self.view.frame.size.width*3/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize-ButtonSize-2, ButtonSize, ButtonSize);
  386. }
  387. - (void)updateTopViewFrame {
  388. if (self.currentSession.isAudioOnly) {
  389. CGFloat containerWidth = self.view.bounds.size.width;
  390. self.portraitView.frame = CGRectMake((containerWidth-64)/2, kStatusBarAndNavigationBarHeight, 64, 64);;
  391. self.userNameLabel.frame = CGRectMake((containerWidth - 240)/2, kStatusBarAndNavigationBarHeight + 64 + 8, 240, 26);
  392. self.userNameLabel.textAlignment = NSTextAlignmentCenter;
  393. self.stateLabel.frame = CGRectMake((containerWidth - 240)/2, kStatusBarAndNavigationBarHeight + 64 + 26 + 8, 240, 26);
  394. self.stateLabel.textAlignment = NSTextAlignmentCenter;
  395. } else {
  396. self.portraitView.frame = CGRectMake(16, kStatusBarAndNavigationBarHeight, 64, 64);
  397. self.userNameLabel.frame = CGRectMake(96, kStatusBarAndNavigationBarHeight + 8, 240, 26);
  398. if(![NSThread isMainThread]) {
  399. NSLog(@"error not main thread");
  400. }
  401. self.userNameLabel.textAlignment = NSTextAlignmentLeft;
  402. if(self.currentSession.state == kWFAVEngineStateConnected) {
  403. self.stateLabel.frame = CGRectMake(54, 30, 240, 20);
  404. } else {
  405. self.stateLabel.frame = CGRectMake(96, kStatusBarAndNavigationBarHeight + 26 + 14, 240, 16);
  406. }
  407. self.stateLabel.textAlignment = NSTextAlignmentLeft;
  408. }
  409. }
  410. #pragma mark - WFAVEngineDelegate
  411. - (void)didChangeState:(WFAVEngineState)state {
  412. if (!self.viewLoaded) {
  413. return;
  414. }
  415. switch (state) {
  416. case kWFAVEngineStateIdle:
  417. self.answerButton.hidden = YES;
  418. self.hangupButton.hidden = YES;
  419. self.switchCameraButton.hidden = YES;
  420. self.audioButton.hidden = YES;
  421. self.videoButton.hidden = YES;
  422. self.scalingButton.hidden = YES;
  423. [self stopConnectedTimer];
  424. self.userNameLabel.hidden = NO;
  425. self.portraitView.hidden = NO;
  426. self.stateLabel.text = @"通话已结束";
  427. self.smallVideoView.hidden = YES;
  428. self.bigVideoView.hidden = YES;
  429. self.minimizeButton.hidden = YES;
  430. self.speakerButton.hidden = YES;
  431. self.downgradeButton.hidden = YES;
  432. [self updateTopViewFrame];
  433. break;
  434. case kWFAVEngineStateOutgoing:
  435. self.answerButton.hidden = YES;
  436. self.hangupButton.hidden = NO;
  437. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  438. self.switchCameraButton.hidden = YES;
  439. if (self.currentSession.isAudioOnly) {
  440. self.speakerButton.hidden = NO;
  441. [self updateSpeakerButton];
  442. self.speakerButton.frame = [self getButtomRightButtonFrame];
  443. self.audioButton.hidden = NO;
  444. self.audioButton.frame = [self getButtomLeftButtonFrame];
  445. } else {
  446. self.speakerButton.hidden = YES;
  447. self.audioButton.hidden = YES;
  448. }
  449. self.videoButton.hidden = YES;
  450. self.scalingButton.hidden = YES;
  451. [self.currentSession setupLocalVideoView:self.bigVideoView scalingType:self.scalingType];
  452. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType];
  453. self.stateLabel.text = @"等待对方接听";
  454. self.smallVideoView.hidden = YES;
  455. self.userNameLabel.hidden = NO;
  456. self.portraitView.hidden = NO;
  457. [self updateTopViewFrame];
  458. break;
  459. case kWFAVEngineStateConnecting:
  460. self.answerButton.hidden = YES;
  461. self.hangupButton.hidden = NO;
  462. self.speakerButton.hidden = YES;
  463. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  464. self.switchCameraButton.hidden = YES;
  465. self.audioButton.hidden = YES;
  466. self.videoButton.hidden = YES;
  467. self.scalingButton.hidden = YES;
  468. [self.currentSession setupLocalVideoView:self.smallVideoView scalingType:self.scalingType];
  469. [self.currentSession setupRemoteVideoView:self.bigVideoView scalingType:self.scalingType];
  470. self.stateLabel.text = @"连接建立中";
  471. self.smallVideoView.hidden = NO;
  472. self.downgradeButton.hidden = YES;
  473. break;
  474. case kWFAVEngineStateConnected:
  475. self.answerButton.hidden = YES;
  476. self.hangupButton.hidden = NO;
  477. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  478. if (self.currentSession.isAudioOnly) {
  479. self.speakerButton.hidden = NO;
  480. self.speakerButton.frame = [self getButtomRightButtonFrame];
  481. [self updateSpeakerButton];
  482. self.audioButton.hidden = NO;
  483. self.audioButton.frame = [self getButtomLeftButtonFrame];
  484. self.switchCameraButton.hidden = YES;
  485. } else {
  486. self.speakerButton.hidden = YES;
  487. [self.currentSession enableSpeaker:YES];
  488. self.audioButton.hidden = NO;
  489. self.audioButton.frame = [self getButtomLeftButtonFrame];
  490. self.switchCameraButton.hidden = NO;
  491. self.switchCameraButton.frame = [self getButtomRightButtonFrame];
  492. }
  493. self.videoButton.hidden = YES;
  494. self.scalingButton.hidden = YES;
  495. self.minimizeButton.hidden = NO;
  496. if (self.currentSession.isAudioOnly) {
  497. self.downgradeButton.hidden = YES;;
  498. } else {
  499. self.downgradeButton.hidden = NO;
  500. self.downgradeButton.frame = [self getToAudioButtonFrame];
  501. }
  502. if (self.currentSession.isAudioOnly) {
  503. [self.currentSession setupLocalVideoView:nil scalingType:self.scalingType];
  504. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType];
  505. self.smallVideoView.hidden = YES;
  506. self.bigVideoView.hidden = YES;
  507. [_downgradeButton setImage:[UIImage imageNamed:@"to_video"] forState:UIControlStateNormal];
  508. [_downgradeButton setImage:[UIImage imageNamed:@"to_video_hover"] forState:UIControlStateHighlighted];
  509. [_downgradeButton setImage:[UIImage imageNamed:@"to_video_hover"] forState:UIControlStateSelected];
  510. } else {
  511. [self.currentSession setupLocalVideoView:self.smallVideoView scalingType:self.scalingType];
  512. [self.currentSession setupRemoteVideoView:self.bigVideoView scalingType:self.scalingType];
  513. self.smallVideoView.hidden = NO;
  514. self.bigVideoView.hidden = NO;
  515. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio"] forState:UIControlStateNormal];
  516. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateHighlighted];
  517. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateSelected];
  518. }
  519. if (!_currentSession.isAudioOnly) {
  520. self.userNameLabel.hidden = YES;
  521. self.portraitView.hidden = YES;
  522. } else {
  523. self.userNameLabel.hidden = NO;
  524. self.portraitView.hidden = NO;
  525. }
  526. [self updateConnectedTimeLabel];
  527. [self startConnectedTimer];
  528. [self updateTopViewFrame];
  529. break;
  530. case kWFAVEngineStateIncomming:
  531. self.answerButton.hidden = NO;
  532. self.answerButton.frame = [self getButtomRightButtonFrame];
  533. self.hangupButton.hidden = NO;
  534. self.hangupButton.frame = [self getButtomLeftButtonFrame];
  535. self.switchCameraButton.hidden = YES;
  536. self.audioButton.hidden = YES;
  537. self.videoButton.hidden = YES;
  538. self.scalingButton.hidden = YES;
  539. self.downgradeButton.hidden = NO;
  540. self.downgradeButton.frame = [self getToAudioButtonFrame];
  541. [self.currentSession setupLocalVideoView:self.bigVideoView scalingType:self.scalingType];
  542. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType];
  543. self.stateLabel.text = @"对方正在邀请您通话";
  544. self.smallVideoView.hidden = YES;
  545. if (self.currentSession.isAudioOnly) {
  546. self.downgradeButton.hidden = YES;;
  547. } else {
  548. self.downgradeButton.hidden = NO;
  549. self.downgradeButton.frame = [self getToAudioButtonFrame];
  550. }
  551. break;
  552. default:
  553. break;
  554. }
  555. }
  556. - (void)didCreateLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
  557. }
  558. - (void)didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
  559. }
  560. - (void)didCallEndWithReason:(WFAVCallEndReason)reason {
  561. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  562. [[WFAVEngineKit sharedEngineKit] dismissViewController:self];
  563. });
  564. }
  565. - (void)didChangeMode:(BOOL)isAudioOnly {
  566. [self didChangeState:self.currentSession.state];
  567. }
  568. - (void)didError:(NSError *)error {
  569. }
  570. - (void)didGetStats:(NSArray *)stats {
  571. }
  572. - (void)checkAVPermission {
  573. [self checkCapturePermission:nil];
  574. [self checkRecordPermission:nil];
  575. }
  576. - (void)checkCapturePermission:(void (^)(BOOL granted))complete {
  577. AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  578. if (authStatus == AVAuthorizationStatusDenied || authStatus == AVAuthorizationStatusRestricted) {
  579. if (complete) {
  580. complete(NO);
  581. }
  582. } else if (authStatus == AVAuthorizationStatusNotDetermined) {
  583. [AVCaptureDevice
  584. requestAccessForMediaType:AVMediaTypeVideo
  585. completionHandler:^(BOOL granted) {
  586. if (complete) {
  587. complete(granted);
  588. }
  589. }];
  590. } else {
  591. if (complete) {
  592. complete(YES);
  593. }
  594. }
  595. }
  596. - (void)checkRecordPermission:(void (^)(BOOL granted))complete {
  597. if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(requestRecordPermission:)]) {
  598. [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
  599. if (complete) {
  600. complete(granted);
  601. }
  602. }];
  603. }
  604. }
  605. #endif
  606. @end