WFCUVideoViewController.m 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  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. #import "UIFont+YH.h"
  19. #import "UIColor+YH.h"
  20. @interface WFCUVideoViewController () <UITextFieldDelegate
  21. #if WFCU_SUPPORT_VOIP
  22. ,WFAVCallSessionDelegate
  23. #endif
  24. >
  25. #if WFCU_SUPPORT_VOIP
  26. @property (nonatomic, strong) UIView *bigVideoView;
  27. @property (nonatomic, strong) UIView *smallVideoView;
  28. @property (nonatomic, strong) UIButton *hangupButton;
  29. @property (nonatomic, strong) UIButton *answerButton;
  30. @property (nonatomic, strong) UIButton *switchCameraButton;
  31. @property (nonatomic, strong) UIButton *audioButton;
  32. @property (nonatomic, strong) UIButton *speakerButton;
  33. @property (nonatomic, strong) UIButton *downgradeButton;
  34. @property (nonatomic, strong) UIButton *videoButton;
  35. @property (nonatomic, strong) UIButton *scalingButton;
  36. @property (nonatomic, strong) UIButton *minimizeButton;
  37. @property (nonatomic, strong) UIImageView *portraitView;
  38. @property (nonatomic, strong) UIImageView *backGroudPortraitView;
  39. @property (nonatomic, strong) UILabel *userNameLabel;
  40. @property (nonatomic, strong) UILabel *stateLabel;
  41. @property (nonatomic, assign) BOOL swapVideoView;
  42. @property (nonatomic, strong) WFAVCallSession *currentSession;
  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)initWithTargets:(NSArray<NSString *> *)targetIds 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. }
  75. return self;
  76. }
  77. - (instancetype)initWithTargets:(NSArray<NSString *> *)targetIds conversation:(WFCCConversation *)conversation audioOnly:(BOOL)audioOnly {
  78. self = [super init];
  79. if (self) {
  80. WFAVCallSession *session = [[WFAVEngineKit sharedEngineKit] startCall:targetIds
  81. audioOnly:audioOnly
  82. conversation:conversation
  83. sessionDelegate:self];
  84. self.currentSession = session;
  85. }
  86. return self;
  87. }
  88. - (void)viewDidLoad {
  89. [super viewDidLoad];
  90. [self.view setBackgroundColor:[UIColor blackColor]];
  91. self.scalingType = kWFAVVideoScalingTypeAspectBalanced;
  92. self.bigVideoView = [[UIView alloc] initWithFrame:self.view.bounds];
  93. [self.view addSubview:self.bigVideoView];
  94. self.smallVideoView = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width - SmallVideoView, kStatusBarAndNavigationBarHeight, SmallVideoView, SmallVideoView * 4 /3)];
  95. [self.smallVideoView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onSmallVideoPan:)]];
  96. [self.smallVideoView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onSmallVideoTaped:)]];
  97. [self.view addSubview:self.smallVideoView];
  98. [self checkAVPermission];
  99. if(self.currentSession.state == kWFAVEngineStateOutgoing && !self.currentSession.isAudioOnly) {
  100. [[WFAVEngineKit sharedEngineKit] startPreview];
  101. }
  102. WFCCUserInfo *user = [[WFCCIMService sharedWFCIMService] getUserInfo:self.currentSession.participantIds[0] inGroup:self.currentSession.conversation.type == Group_Type ? self.currentSession.conversation.target : nil refresh:NO];
  103. self.portraitView = [[UIImageView alloc] init];
  104. [self.portraitView sd_setImageWithURL:[NSURL URLWithString:[user.portrait stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:[UIImage imageNamed:@"PersonalChat"]];
  105. self.portraitView.layer.masksToBounds = YES;
  106. self.portraitView.layer.cornerRadius = 10.f;
  107. self.portraitView.layer.borderColor = [UIColor whiteColor].CGColor;
  108. self.portraitView.layer.borderWidth = 1.0;
  109. [self.view addSubview:self.portraitView];
  110. self.userNameLabel = [[UILabel alloc] init];
  111. self.userNameLabel.font = [UIFont pingFangSCWithWeight:FontWeightStyleMedium size:27];
  112. self.userNameLabel.text = user.displayName;
  113. self.userNameLabel.textColor = [UIColor colorWithHexString:@"0xffffff"];
  114. [self.view addSubview:self.userNameLabel];
  115. self.stateLabel = [[UILabel alloc] init];
  116. self.stateLabel.font = [UIFont pingFangSCWithWeight:FontWeightStyleRegular size:14];
  117. self.stateLabel.textColor = [UIColor colorWithHexString:@"0xB4B4B6"];
  118. [self.view addSubview:self.stateLabel];
  119. [self updateTopViewFrame];
  120. [self didChangeState:self.currentSession.state];//update ui
  121. }
  122. - (UIButton *)hangupButton {
  123. if (!_hangupButton) {
  124. _hangupButton = [[UIButton alloc] init];
  125. [_hangupButton setImage:[UIImage imageNamed:@"hangup"] forState:UIControlStateNormal];
  126. [_hangupButton setImage:[UIImage imageNamed:@"hangup_hover"] forState:UIControlStateHighlighted];
  127. [_hangupButton setImage:[UIImage imageNamed:@"hangup_hover"] forState:UIControlStateSelected];
  128. _hangupButton.backgroundColor = [UIColor clearColor];
  129. [_hangupButton addTarget:self action:@selector(hanupButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  130. _hangupButton.hidden = YES;
  131. [self.view addSubview:_hangupButton];
  132. }
  133. return _hangupButton;
  134. }
  135. - (UIButton *)answerButton {
  136. if (!_answerButton) {
  137. _answerButton = [[UIButton alloc] init];
  138. [_answerButton setImage:[UIImage imageNamed:@"answer"] forState:UIControlStateNormal];
  139. [_answerButton setImage:[UIImage imageNamed:@"answer_hover"] forState:UIControlStateHighlighted];
  140. [_answerButton setImage:[UIImage imageNamed:@"answer_hover"] forState:UIControlStateSelected];
  141. _answerButton.backgroundColor = [UIColor clearColor];
  142. [_answerButton addTarget:self action:@selector(answerButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  143. _answerButton.hidden = YES;
  144. [self.view addSubview:_answerButton];
  145. }
  146. return _answerButton;
  147. }
  148. - (UIButton *)minimizeButton {
  149. if (!_minimizeButton) {
  150. _minimizeButton = [[UIButton alloc] initWithFrame:CGRectMake(16, 26, 30, 30)];
  151. [_minimizeButton setImage:[UIImage imageNamed:@"minimize"] forState:UIControlStateNormal];
  152. [_minimizeButton setImage:[UIImage imageNamed:@"minimize_hover"] forState:UIControlStateHighlighted];
  153. [_minimizeButton setImage:[UIImage imageNamed:@"minimize_hover"] forState:UIControlStateSelected];
  154. _minimizeButton.backgroundColor = [UIColor clearColor];
  155. [_minimizeButton addTarget:self action:@selector(minimizeButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  156. _minimizeButton.hidden = YES;
  157. [self.view addSubview:_minimizeButton];
  158. }
  159. return _minimizeButton;
  160. }
  161. - (UIButton *)switchCameraButton {
  162. if (!_switchCameraButton) {
  163. _switchCameraButton = [[UIButton alloc] init];
  164. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera"] forState:UIControlStateNormal];
  165. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera_hover"] forState:UIControlStateHighlighted];
  166. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera_hover"] forState:UIControlStateSelected];
  167. _switchCameraButton.backgroundColor = [UIColor clearColor];
  168. [_switchCameraButton addTarget:self action:@selector(switchCameraButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  169. _switchCameraButton.hidden = YES;
  170. [self.view addSubview:_switchCameraButton];
  171. }
  172. return _switchCameraButton;
  173. }
  174. - (UIButton *)downgradeButton {
  175. if (!_downgradeButton) {
  176. _downgradeButton = [[UIButton alloc] init];
  177. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio"] forState:UIControlStateNormal];
  178. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateHighlighted];
  179. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateSelected];
  180. _downgradeButton.backgroundColor = [UIColor clearColor];
  181. [_downgradeButton addTarget:self action:@selector(downgradeButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  182. _downgradeButton.hidden = YES;
  183. [self.view addSubview:_downgradeButton];
  184. }
  185. return _downgradeButton;
  186. }
  187. - (UIButton *)audioButton {
  188. if (!_audioButton) {
  189. _audioButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  190. [_audioButton setImage:[UIImage imageNamed:@"mute"] forState:UIControlStateNormal];
  191. [_audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateHighlighted];
  192. [_audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateSelected];
  193. _audioButton.backgroundColor = [UIColor clearColor];
  194. [_audioButton addTarget:self action:@selector(audioButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  195. _audioButton.hidden = YES;
  196. [self updateAudioButton];
  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:WFCString(@"Video") 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:WFCString(@"Scale") 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)setSwapVideoView:(BOOL)swapVideoView {
  237. _swapVideoView = swapVideoView;
  238. if (swapVideoView) {
  239. [self.currentSession setupLocalVideoView:self.bigVideoView scalingType:self.scalingType];
  240. [self.currentSession setupRemoteVideoView:self.smallVideoView scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  241. } else {
  242. [self.currentSession setupLocalVideoView:self.smallVideoView scalingType:self.scalingType];
  243. [self.currentSession setupRemoteVideoView:self.bigVideoView scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  244. }
  245. }
  246. - (void)startConnectedTimer {
  247. [self stopConnectedTimer];
  248. self.connectedTimer = [NSTimer scheduledTimerWithTimeInterval:1
  249. target:self
  250. selector:@selector(updateConnectedTimeLabel)
  251. userInfo:nil
  252. repeats:YES];
  253. [self.connectedTimer fire];
  254. }
  255. - (void)stopConnectedTimer {
  256. if (self.connectedTimer) {
  257. [self.connectedTimer invalidate];
  258. self.connectedTimer = nil;
  259. }
  260. }
  261. - (void)updateConnectedTimeLabel {
  262. long sec = [[NSDate date] timeIntervalSince1970] - self.currentSession.connectedTime / 1000;
  263. if (sec < 60 * 60) {
  264. self.stateLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", sec / 60, sec % 60];
  265. } else {
  266. self.stateLabel.text = [NSString stringWithFormat:@"%02ld:%02ld:%02ld", sec / 60 / 60, (sec / 60) % 60, sec % 60];
  267. }
  268. }
  269. - (void)hanupButtonDidTap:(UIButton *)button {
  270. if(self.currentSession.state != kWFAVEngineStateIdle) {
  271. [self.currentSession endCall];
  272. }
  273. }
  274. - (void)answerButtonDidTap:(UIButton *)button {
  275. if (self.currentSession.state == kWFAVEngineStateIncomming) {
  276. [self.currentSession answerCall:NO];
  277. }
  278. }
  279. - (void)minimizeButtonDidTap:(UIButton *)button {
  280. [WFCUFloatingWindow startCallFloatingWindow:self.currentSession focusUser:self.currentSession.participantIds[0] withTouchedBlock:^(WFAVCallSession *callSession) {
  281. [[WFAVEngineKit sharedEngineKit] presentViewController:[[WFCUVideoViewController alloc] initWithSession:callSession]];
  282. }];
  283. [[WFAVEngineKit sharedEngineKit] dismissViewController:self];
  284. }
  285. - (void)switchCameraButtonDidTap:(UIButton *)button {
  286. if (self.currentSession.state != kWFAVEngineStateIdle) {
  287. [self.currentSession switchCamera];
  288. }
  289. }
  290. - (void)downgradeButtonDidTap:(UIButton *)button {
  291. if (self.currentSession.state == kWFAVEngineStateIncomming) {
  292. [self.currentSession answerCall:YES];
  293. } else if(self.currentSession.state == kWFAVEngineStateConnected) {
  294. self.currentSession.audioOnly = !self.currentSession.isAudioOnly;
  295. }
  296. }
  297. - (void)audioButtonDidTap:(UIButton *)button {
  298. if (self.currentSession.state != kWFAVEngineStateIdle) {
  299. [self.currentSession muteAudio:!self.currentSession.audioMuted];
  300. [self updateAudioButton];
  301. }
  302. }
  303. - (void)updateAudioButton {
  304. if (self.currentSession.audioMuted) {
  305. [self.audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateNormal];
  306. } else {
  307. [self.audioButton setImage:[UIImage imageNamed:@"mute"] forState:UIControlStateNormal];
  308. }
  309. }
  310. - (void)speakerButtonDidTap:(UIButton *)button {
  311. if (self.currentSession.state != kWFAVEngineStateIdle) {
  312. [self.currentSession enableSpeaker:!self.currentSession.isSpeaker];
  313. [self updateSpeakerButton];
  314. }
  315. }
  316. - (void)updateSpeakerButton {
  317. if (!self.currentSession.isSpeaker) {
  318. [self.speakerButton setImage:[UIImage imageNamed:@"speaker"] forState:UIControlStateNormal];
  319. } else {
  320. [self.speakerButton setImage:[UIImage imageNamed:@"speaker_hover"] forState:UIControlStateNormal];
  321. }
  322. }
  323. - (void)viewWillAppear:(BOOL)animated {
  324. [super viewWillAppear:animated];
  325. if (_currentSession.state == kWFAVEngineStateConnected) {
  326. [self updateConnectedTimeLabel];
  327. [self startConnectedTimer];
  328. }
  329. }
  330. - (void)viewWillDisappear:(BOOL)animated {
  331. [super viewWillDisappear:animated];
  332. [self stopConnectedTimer];
  333. }
  334. - (void)setPanStartPoint:(CGPoint)panStartPoint {
  335. _panStartPoint = panStartPoint;
  336. _panStartVideoFrame = self.smallVideoView.frame;
  337. }
  338. - (void)moveToPanPoint:(CGPoint)panPoint {
  339. CGRect frame = self.panStartVideoFrame;
  340. CGSize moveSize = CGSizeMake(panPoint.x - self.panStartPoint.x, panPoint.y - self.panStartPoint.y);
  341. frame.origin.x += moveSize.width;
  342. frame.origin.y += moveSize.height;
  343. self.smallVideoView.frame = frame;
  344. }
  345. - (void)onSmallVideoPan:(UIPanGestureRecognizer *)recognize {
  346. switch (recognize.state) {
  347. case UIGestureRecognizerStateBegan:
  348. self.panStartPoint = [recognize translationInView:self.view];
  349. break;
  350. case UIGestureRecognizerStateChanged: {
  351. CGPoint currentPoint = [recognize translationInView:self.view];
  352. [self moveToPanPoint:currentPoint];
  353. break;
  354. }
  355. case UIGestureRecognizerStateEnded: {
  356. CGPoint endPoint = [recognize translationInView:self.view];
  357. [self moveToPanPoint:endPoint];
  358. break;
  359. }
  360. case UIGestureRecognizerStateCancelled:
  361. case UIGestureRecognizerStateFailed:
  362. default:
  363. break;
  364. }
  365. }
  366. - (void)onSmallVideoTaped:(id)sender {
  367. if (self.currentSession.state == kWFAVEngineStateConnected) {
  368. self.swapVideoView = !_swapVideoView;
  369. }
  370. }
  371. - (void)videoButtonDidTap:(UIButton *)button {
  372. if (self.currentSession.state != kWFAVEngineStateIdle) {
  373. [self.currentSession muteVideo:!self.currentSession.isVideoMuted];
  374. }
  375. }
  376. - (void)scalingButtonDidTap:(UIButton *)button {
  377. if (self.currentSession.state != kWFAVEngineStateIdle) {
  378. if (self.scalingType < kWFAVVideoScalingTypeAspectBalanced) {
  379. self.scalingType++;
  380. } else {
  381. self.scalingType = kWFAVVideoScalingTypeAspectFit;
  382. }
  383. self.swapVideoView = _swapVideoView;
  384. }
  385. }
  386. - (CGRect)getButtomCenterButtonFrame {
  387. return CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  388. }
  389. - (CGRect)getButtomLeftButtonFrame {
  390. return CGRectMake(self.view.frame.size.width/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  391. }
  392. - (CGRect)getButtomRightButtonFrame {
  393. return CGRectMake(self.view.frame.size.width*3/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  394. }
  395. - (CGRect)getToAudioButtonFrame {
  396. return CGRectMake(self.view.frame.size.width*3/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize-ButtonSize-2, ButtonSize, ButtonSize);
  397. }
  398. - (void)updateTopViewFrame {
  399. CGFloat containerWidth = self.view.bounds.size.width;
  400. CGFloat containerHeight = self.view.bounds.size.height;
  401. if (self.currentSession.isAudioOnly) {
  402. CGFloat postionY = (containerHeight - 110) / 2.0 - 70;
  403. self.portraitView.frame = CGRectMake((containerWidth-110)/2, postionY, 110, 110);;
  404. postionY += 110 + 16;
  405. self.userNameLabel.frame = CGRectMake((containerWidth - 240)/2, postionY, 240, 27);
  406. self.userNameLabel.textAlignment = NSTextAlignmentCenter;
  407. postionY += 12 + 27;
  408. self.stateLabel.frame = CGRectMake((containerWidth - 240)/2, postionY, 240, 26);
  409. self.stateLabel.textAlignment = NSTextAlignmentCenter;
  410. } else {
  411. CGFloat postionX = containerWidth - 16 - 62;
  412. self.portraitView.frame = CGRectMake(postionX, kStatusBarAndNavigationBarHeight, 62, 62);
  413. postionX -= (13 + 240);
  414. self.userNameLabel.frame = CGRectMake(postionX, kStatusBarAndNavigationBarHeight + 8, 240, 26);
  415. self.userNameLabel.textAlignment = NSTextAlignmentRight;
  416. if(![NSThread isMainThread]) {
  417. NSLog(@"error not main thread");
  418. }
  419. if(self.currentSession.state == kWFAVEngineStateConnected) {
  420. self.stateLabel.frame = CGRectMake(54, 30, 240, 20);
  421. } else {
  422. self.stateLabel.frame = CGRectMake(96, kStatusBarAndNavigationBarHeight + 26 + 14, 240, 16);
  423. }
  424. self.stateLabel.hidden = YES;
  425. self.stateLabel.textAlignment = NSTextAlignmentLeft;
  426. }
  427. }
  428. #pragma mark - WFAVEngineDelegate
  429. - (void)didChangeState:(WFAVEngineState)state {
  430. if (!self.viewLoaded) {
  431. return;
  432. }
  433. switch (state) {
  434. case kWFAVEngineStateIdle:
  435. self.answerButton.hidden = YES;
  436. self.hangupButton.hidden = YES;
  437. self.switchCameraButton.hidden = YES;
  438. self.audioButton.hidden = YES;
  439. self.videoButton.hidden = YES;
  440. self.scalingButton.hidden = YES;
  441. [self stopConnectedTimer];
  442. self.userNameLabel.hidden = NO;
  443. self.portraitView.hidden = NO;
  444. self.stateLabel.text = WFCString(@"CallEnded");
  445. self.smallVideoView.hidden = YES;
  446. self.bigVideoView.hidden = YES;
  447. self.minimizeButton.hidden = YES;
  448. self.speakerButton.hidden = YES;
  449. self.downgradeButton.hidden = YES;
  450. [self updateTopViewFrame];
  451. break;
  452. case kWFAVEngineStateOutgoing:
  453. self.answerButton.hidden = YES;
  454. self.hangupButton.hidden = NO;
  455. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  456. self.switchCameraButton.hidden = YES;
  457. if (self.currentSession.isAudioOnly) {
  458. self.speakerButton.hidden = YES;
  459. [self updateSpeakerButton];
  460. self.speakerButton.frame = [self getButtomRightButtonFrame];
  461. self.audioButton.hidden = YES;
  462. self.audioButton.frame = [self getButtomLeftButtonFrame];
  463. } else {
  464. self.speakerButton.hidden = YES;
  465. self.audioButton.hidden = YES;
  466. }
  467. self.videoButton.hidden = YES;
  468. self.scalingButton.hidden = YES;
  469. [self.currentSession setupLocalVideoView:self.bigVideoView scalingType:self.scalingType];
  470. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  471. self.stateLabel.text = WFCString(@"WaitingAccept");
  472. self.smallVideoView.hidden = YES;
  473. self.userNameLabel.hidden = NO;
  474. self.portraitView.hidden = NO;
  475. [self updateTopViewFrame];
  476. break;
  477. case kWFAVEngineStateConnecting:
  478. self.answerButton.hidden = YES;
  479. self.hangupButton.hidden = NO;
  480. self.speakerButton.hidden = YES;
  481. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  482. self.switchCameraButton.hidden = YES;
  483. self.audioButton.hidden = YES;
  484. self.videoButton.hidden = YES;
  485. self.scalingButton.hidden = YES;
  486. self.swapVideoView = NO;
  487. self.stateLabel.text = WFCString(@"CallConnecting");
  488. self.smallVideoView.hidden = NO;
  489. self.downgradeButton.hidden = YES;
  490. break;
  491. case kWFAVEngineStateConnected:
  492. self.answerButton.hidden = YES;
  493. self.hangupButton.hidden = NO;
  494. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  495. if (self.currentSession.isAudioOnly) {
  496. self.speakerButton.hidden = NO;
  497. self.speakerButton.frame = [self getButtomRightButtonFrame];
  498. [self updateSpeakerButton];
  499. self.audioButton.hidden = NO;
  500. self.audioButton.frame = [self getButtomLeftButtonFrame];
  501. self.switchCameraButton.hidden = YES;
  502. } else {
  503. self.speakerButton.hidden = YES;
  504. [self.currentSession enableSpeaker:YES];
  505. self.audioButton.hidden = NO;
  506. self.audioButton.frame = [self getButtomLeftButtonFrame];
  507. self.switchCameraButton.hidden = NO;
  508. self.switchCameraButton.frame = [self getButtomRightButtonFrame];
  509. }
  510. self.videoButton.hidden = YES;
  511. self.scalingButton.hidden = YES;
  512. self.minimizeButton.hidden = NO;
  513. if (self.currentSession.isAudioOnly) {
  514. self.downgradeButton.hidden = YES;;
  515. } else {
  516. self.downgradeButton.hidden = NO;
  517. self.downgradeButton.frame = [self getToAudioButtonFrame];
  518. }
  519. if (self.currentSession.isAudioOnly) {
  520. [self.currentSession setupLocalVideoView:nil scalingType:self.scalingType];
  521. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  522. self.smallVideoView.hidden = YES;
  523. self.bigVideoView.hidden = YES;
  524. [_downgradeButton setImage:[UIImage imageNamed:@"to_video"] forState:UIControlStateNormal];
  525. [_downgradeButton setImage:[UIImage imageNamed:@"to_video_hover"] forState:UIControlStateHighlighted];
  526. [_downgradeButton setImage:[UIImage imageNamed:@"to_video_hover"] forState:UIControlStateSelected];
  527. } else {
  528. [self.currentSession setupLocalVideoView:self.smallVideoView scalingType:self.scalingType];
  529. [self.currentSession setupRemoteVideoView:self.bigVideoView scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  530. self.smallVideoView.hidden = NO;
  531. self.bigVideoView.hidden = NO;
  532. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio"] forState:UIControlStateNormal];
  533. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateHighlighted];
  534. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateSelected];
  535. }
  536. if (!_currentSession.isAudioOnly) {
  537. self.userNameLabel.hidden = YES;
  538. self.portraitView.hidden = YES;
  539. } else {
  540. self.userNameLabel.hidden = NO;
  541. self.portraitView.hidden = NO;
  542. }
  543. [self updateConnectedTimeLabel];
  544. [self startConnectedTimer];
  545. [self updateTopViewFrame];
  546. break;
  547. case kWFAVEngineStateIncomming:
  548. self.answerButton.hidden = NO;
  549. self.answerButton.frame = [self getButtomRightButtonFrame];
  550. self.hangupButton.hidden = NO;
  551. self.hangupButton.frame = [self getButtomLeftButtonFrame];
  552. self.switchCameraButton.hidden = YES;
  553. self.audioButton.hidden = YES;
  554. self.videoButton.hidden = YES;
  555. self.scalingButton.hidden = YES;
  556. self.downgradeButton.hidden = NO;
  557. self.downgradeButton.frame = [self getToAudioButtonFrame];
  558. [self.currentSession setupLocalVideoView:self.bigVideoView scalingType:self.scalingType];
  559. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  560. self.stateLabel.text = WFCString(@"InvitingYou");
  561. self.smallVideoView.hidden = YES;
  562. if (self.currentSession.isAudioOnly) {
  563. self.downgradeButton.hidden = YES;;
  564. } else {
  565. self.downgradeButton.hidden = NO;
  566. self.downgradeButton.frame = [self getToAudioButtonFrame];
  567. }
  568. break;
  569. default:
  570. break;
  571. }
  572. }
  573. - (void)didCreateLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
  574. }
  575. - (void)didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack fromUser:(NSString *)userId {
  576. }
  577. - (void)didVideoMuted:(BOOL)videoMuted fromUser:(NSString *)userId {
  578. }
  579. - (void)didReportAudioVolume:(NSInteger)volume ofUser:(NSString *)userId {
  580. }
  581. - (void)didCallEndWithReason:(WFAVCallEndReason)reason {
  582. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  583. [[WFAVEngineKit sharedEngineKit] dismissViewController:self];
  584. });
  585. }
  586. - (void)didParticipantJoined:(NSString *)userId {
  587. }
  588. - (void)didParticipantConnected:(NSString *)userId {
  589. }
  590. - (void)didParticipantLeft:(NSString *)userId withReason:(WFAVCallEndReason)reason {
  591. }
  592. - (void)didChangeMode:(BOOL)isAudioOnly {
  593. [self didChangeState:self.currentSession.state];
  594. }
  595. - (void)didError:(NSError *)error {
  596. }
  597. - (void)didGetStats:(NSArray *)stats {
  598. }
  599. - (void)checkAVPermission {
  600. [self checkCapturePermission:nil];
  601. [self checkRecordPermission:nil];
  602. }
  603. - (void)checkCapturePermission:(void (^)(BOOL granted))complete {
  604. AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  605. if (authStatus == AVAuthorizationStatusDenied || authStatus == AVAuthorizationStatusRestricted) {
  606. if (complete) {
  607. complete(NO);
  608. }
  609. } else if (authStatus == AVAuthorizationStatusNotDetermined) {
  610. [AVCaptureDevice
  611. requestAccessForMediaType:AVMediaTypeVideo
  612. completionHandler:^(BOOL granted) {
  613. if (complete) {
  614. complete(granted);
  615. }
  616. }];
  617. } else {
  618. if (complete) {
  619. complete(YES);
  620. }
  621. }
  622. }
  623. - (void)checkRecordPermission:(void (^)(BOOL granted))complete {
  624. if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(requestRecordPermission:)]) {
  625. [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
  626. if (complete) {
  627. complete(granted);
  628. }
  629. }];
  630. }
  631. }
  632. #endif
  633. @end