WFCUVideoViewController.m 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  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 = kWFAVVideoScalingTypeAspectFit;
  92. self.bigVideoView = [[UIView alloc] initWithFrame:self.view.bounds];
  93. UITapGestureRecognizer *tapBigVideo = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onClickedBigVideoView:)];
  94. [self.bigVideoView addGestureRecognizer:tapBigVideo];
  95. [self.view addSubview:self.bigVideoView];
  96. self.smallVideoView = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width - SmallVideoView, kStatusBarAndNavigationBarHeight, SmallVideoView, SmallVideoView * 4 /3)];
  97. [self.smallVideoView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(onSmallVideoPan:)]];
  98. [self.smallVideoView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onSmallVideoTaped:)]];
  99. [self.view addSubview:self.smallVideoView];
  100. [self checkAVPermission];
  101. if(self.currentSession.state == kWFAVEngineStateOutgoing && !self.currentSession.isAudioOnly) {
  102. [[WFAVEngineKit sharedEngineKit] startPreview];
  103. }
  104. WFCCUserInfo *user = [[WFCCIMService sharedWFCIMService] getUserInfo:self.currentSession.participantIds[0] inGroup:self.currentSession.conversation.type == Group_Type ? self.currentSession.conversation.target : nil refresh:NO];
  105. self.portraitView = [[UIImageView alloc] init];
  106. [self.portraitView sd_setImageWithURL:[NSURL URLWithString:[user.portrait stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:[UIImage imageNamed:@"PersonalChat"]];
  107. self.portraitView.layer.masksToBounds = YES;
  108. self.portraitView.layer.cornerRadius = 10.f;
  109. self.portraitView.layer.borderColor = [UIColor whiteColor].CGColor;
  110. self.portraitView.layer.borderWidth = 1.0;
  111. [self.view addSubview:self.portraitView];
  112. self.userNameLabel = [[UILabel alloc] init];
  113. self.userNameLabel.font = [UIFont pingFangSCWithWeight:FontWeightStyleMedium size:27];
  114. self.userNameLabel.text = user.displayName;
  115. self.userNameLabel.textColor = [UIColor colorWithHexString:@"0xffffff"];
  116. [self.view addSubview:self.userNameLabel];
  117. self.stateLabel = [[UILabel alloc] init];
  118. self.stateLabel.font = [UIFont pingFangSCWithWeight:FontWeightStyleRegular size:14];
  119. self.stateLabel.textColor = [UIColor colorWithHexString:@"0xB4B4B6"];
  120. [self.view addSubview:self.stateLabel];
  121. [self updateTopViewFrame];
  122. [self didChangeState:self.currentSession.state];//update ui
  123. [[NSNotificationCenter defaultCenter] addObserver:self
  124. selector:@selector(onDeviceOrientationDidChange)
  125. name:UIDeviceOrientationDidChangeNotification
  126. object:nil];
  127. [self onDeviceOrientationDidChange];
  128. }
  129. - (UIButton *)hangupButton {
  130. if (!_hangupButton) {
  131. _hangupButton = [[UIButton alloc] init];
  132. [_hangupButton setImage:[UIImage imageNamed:@"hangup"] forState:UIControlStateNormal];
  133. [_hangupButton setImage:[UIImage imageNamed:@"hangup_hover"] forState:UIControlStateHighlighted];
  134. [_hangupButton setImage:[UIImage imageNamed:@"hangup_hover"] forState:UIControlStateSelected];
  135. _hangupButton.backgroundColor = [UIColor clearColor];
  136. [_hangupButton addTarget:self action:@selector(hanupButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  137. _hangupButton.hidden = YES;
  138. [self.view addSubview:_hangupButton];
  139. }
  140. return _hangupButton;
  141. }
  142. - (UIButton *)answerButton {
  143. if (!_answerButton) {
  144. _answerButton = [[UIButton alloc] init];
  145. if (self.currentSession.audioOnly) {
  146. [_answerButton setImage:[UIImage imageNamed:@"answer"] forState:UIControlStateNormal];
  147. [_answerButton setImage:[UIImage imageNamed:@"answer_hover"] forState:UIControlStateHighlighted];
  148. [_answerButton setImage:[UIImage imageNamed:@"answer_hover"] forState:UIControlStateSelected];
  149. } else {
  150. [_answerButton setImage:[UIImage imageNamed:@"video_answer"] forState:UIControlStateNormal];
  151. [_answerButton setImage:[UIImage imageNamed:@"video_answer_hover"] forState:UIControlStateHighlighted];
  152. [_answerButton setImage:[UIImage imageNamed:@"video_answer_hover"] forState:UIControlStateSelected];
  153. }
  154. _answerButton.backgroundColor = [UIColor clearColor];
  155. [_answerButton addTarget:self action:@selector(answerButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  156. _answerButton.hidden = YES;
  157. [self.view addSubview:_answerButton];
  158. }
  159. return _answerButton;
  160. }
  161. - (UIButton *)minimizeButton {
  162. if (!_minimizeButton) {
  163. _minimizeButton = [[UIButton alloc] initWithFrame:CGRectMake(16, 26, 30, 30)];
  164. [_minimizeButton setImage:[UIImage imageNamed:@"minimize"] forState:UIControlStateNormal];
  165. [_minimizeButton setImage:[UIImage imageNamed:@"minimize_hover"] forState:UIControlStateHighlighted];
  166. [_minimizeButton setImage:[UIImage imageNamed:@"minimize_hover"] forState:UIControlStateSelected];
  167. _minimizeButton.backgroundColor = [UIColor clearColor];
  168. [_minimizeButton addTarget:self action:@selector(minimizeButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  169. // _minimizeButton.hidden = YES;
  170. [self.view addSubview:_minimizeButton];
  171. }
  172. return _minimizeButton;
  173. }
  174. - (UIButton *)switchCameraButton {
  175. if (!_switchCameraButton) {
  176. _switchCameraButton = [[UIButton alloc] init];
  177. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera"] forState:UIControlStateNormal];
  178. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera_hover"] forState:UIControlStateHighlighted];
  179. [_switchCameraButton setImage:[UIImage imageNamed:@"switchcamera_hover"] forState:UIControlStateSelected];
  180. _switchCameraButton.backgroundColor = [UIColor clearColor];
  181. [_switchCameraButton addTarget:self action:@selector(switchCameraButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  182. _switchCameraButton.hidden = YES;
  183. [self.view addSubview:_switchCameraButton];
  184. }
  185. return _switchCameraButton;
  186. }
  187. - (UIButton *)downgradeButton {
  188. if (!_downgradeButton) {
  189. _downgradeButton = [[UIButton alloc] init];
  190. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio"] forState:UIControlStateNormal];
  191. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateHighlighted];
  192. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateSelected];
  193. _downgradeButton.backgroundColor = [UIColor clearColor];
  194. [_downgradeButton addTarget:self action:@selector(downgradeButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  195. _downgradeButton.hidden = YES;
  196. [self.view addSubview:_downgradeButton];
  197. }
  198. return _downgradeButton;
  199. }
  200. - (UIButton *)audioButton {
  201. if (!_audioButton) {
  202. _audioButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  203. [_audioButton setImage:[UIImage imageNamed:@"mute"] forState:UIControlStateNormal];
  204. [_audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateHighlighted];
  205. [_audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateSelected];
  206. _audioButton.backgroundColor = [UIColor clearColor];
  207. [_audioButton addTarget:self action:@selector(audioButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  208. _audioButton.hidden = YES;
  209. [self updateAudioButton];
  210. [self.view addSubview:_audioButton];
  211. }
  212. return _audioButton;
  213. }
  214. - (UIButton *)speakerButton {
  215. if (!_speakerButton) {
  216. _speakerButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  217. [_speakerButton setImage:[UIImage imageNamed:@"speaker"] forState:UIControlStateNormal];
  218. [_speakerButton setImage:[UIImage imageNamed:@"speaker_hover"] forState:UIControlStateHighlighted];
  219. [_speakerButton setImage:[UIImage imageNamed:@"speaker_hover"] forState:UIControlStateSelected];
  220. _speakerButton.backgroundColor = [UIColor clearColor];
  221. [_speakerButton addTarget:self action:@selector(speakerButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  222. _speakerButton.hidden = YES;
  223. [self.view addSubview:_speakerButton];
  224. }
  225. return _speakerButton;
  226. }
  227. - (UIButton *)videoButton {
  228. if (!_videoButton) {
  229. _videoButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  230. [_videoButton setTitle:WFCString(@"Video") forState:UIControlStateNormal];
  231. _videoButton.backgroundColor = [UIColor greenColor];
  232. [_videoButton addTarget:self action:@selector(videoButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  233. _videoButton.hidden = YES;
  234. [self.view addSubview:_videoButton];
  235. }
  236. return _videoButton;
  237. }
  238. - (UIButton *)scalingButton {
  239. if (!_scalingButton) {
  240. _scalingButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-10-ButtonSize, ButtonSize, ButtonSize)];
  241. [_scalingButton setTitle:WFCString(@"Scale") forState:UIControlStateNormal];
  242. _scalingButton.backgroundColor = [UIColor greenColor];
  243. [_scalingButton addTarget:self action:@selector(scalingButtonDidTap:) forControlEvents:UIControlEventTouchDown];
  244. _scalingButton.hidden = YES;
  245. [self.view addSubview:_scalingButton];
  246. }
  247. return _scalingButton;
  248. }
  249. - (void)setSwapVideoView:(BOOL)swapVideoView {
  250. _swapVideoView = swapVideoView;
  251. if (self.currentSession.state == kWFAVEngineStateIdle) {
  252. return;
  253. }
  254. if (swapVideoView) {
  255. [self.currentSession setupLocalVideoView:self.bigVideoView scalingType:self.scalingType];
  256. [self.currentSession setupRemoteVideoView:self.smallVideoView scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  257. } else {
  258. [self.currentSession setupLocalVideoView:self.smallVideoView scalingType:self.scalingType];
  259. [self.currentSession setupRemoteVideoView:self.bigVideoView scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  260. }
  261. }
  262. - (void)startConnectedTimer {
  263. [self stopConnectedTimer];
  264. self.connectedTimer = [NSTimer scheduledTimerWithTimeInterval:1
  265. target:self
  266. selector:@selector(updateConnectedTimeLabel)
  267. userInfo:nil
  268. repeats:YES];
  269. [self.connectedTimer fire];
  270. }
  271. - (void)stopConnectedTimer {
  272. if (self.connectedTimer) {
  273. [self.connectedTimer invalidate];
  274. self.connectedTimer = nil;
  275. }
  276. }
  277. - (void)updateConnectedTimeLabel {
  278. long sec = [[NSDate date] timeIntervalSince1970] - self.currentSession.connectedTime / 1000;
  279. if (sec < 60 * 60) {
  280. self.stateLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", sec / 60, sec % 60];
  281. } else {
  282. self.stateLabel.text = [NSString stringWithFormat:@"%02ld:%02ld:%02ld", sec / 60 / 60, (sec / 60) % 60, sec % 60];
  283. }
  284. }
  285. - (void)hanupButtonDidTap:(UIButton *)button {
  286. if(self.currentSession.state != kWFAVEngineStateIdle) {
  287. [self.currentSession endCall];
  288. }
  289. }
  290. - (void)answerButtonDidTap:(UIButton *)button {
  291. if (self.currentSession.state == kWFAVEngineStateIncomming) {
  292. [self.currentSession answerCall:NO];
  293. }
  294. }
  295. - (void)minimizeButtonDidTap:(UIButton *)button {
  296. [WFCUFloatingWindow startCallFloatingWindow:self.currentSession focusUser:self.currentSession.participantIds[0] withTouchedBlock:^(WFAVCallSession *callSession) {
  297. [[WFAVEngineKit sharedEngineKit] presentViewController:[[WFCUVideoViewController alloc] initWithSession:callSession]];
  298. }];
  299. [[WFAVEngineKit sharedEngineKit] dismissViewController:self];
  300. }
  301. - (void)switchCameraButtonDidTap:(UIButton *)button {
  302. if (self.currentSession.state != kWFAVEngineStateIdle) {
  303. [self.currentSession switchCamera];
  304. }
  305. }
  306. - (void)downgradeButtonDidTap:(UIButton *)button {
  307. if (self.currentSession.state == kWFAVEngineStateIncomming) {
  308. [self.currentSession answerCall:YES];
  309. } else if(self.currentSession.state == kWFAVEngineStateConnected) {
  310. self.currentSession.audioOnly = !self.currentSession.isAudioOnly;
  311. }
  312. }
  313. - (void)audioButtonDidTap:(UIButton *)button {
  314. if (self.currentSession.state != kWFAVEngineStateIdle) {
  315. [self.currentSession muteAudio:!self.currentSession.audioMuted];
  316. [self updateAudioButton];
  317. }
  318. }
  319. - (void)updateAudioButton {
  320. if (self.currentSession.audioMuted) {
  321. [self.audioButton setImage:[UIImage imageNamed:@"mute_hover"] forState:UIControlStateNormal];
  322. } else {
  323. [self.audioButton setImage:[UIImage imageNamed:@"mute"] forState:UIControlStateNormal];
  324. }
  325. }
  326. - (void)speakerButtonDidTap:(UIButton *)button {
  327. if (self.currentSession.state != kWFAVEngineStateIdle) {
  328. [self.currentSession enableSpeaker:!self.currentSession.isSpeaker];
  329. [self updateSpeakerButton];
  330. }
  331. }
  332. - (void)updateSpeakerButton {
  333. if (!self.currentSession.isSpeaker) {
  334. [self.speakerButton setImage:[UIImage imageNamed:@"speaker"] forState:UIControlStateNormal];
  335. } else {
  336. [self.speakerButton setImage:[UIImage imageNamed:@"speaker_hover"] forState:UIControlStateNormal];
  337. }
  338. }
  339. - (void)viewWillAppear:(BOOL)animated {
  340. [super viewWillAppear:animated];
  341. if (_currentSession.state == kWFAVEngineStateConnected) {
  342. [self updateConnectedTimeLabel];
  343. [self startConnectedTimer];
  344. }
  345. }
  346. - (void)viewWillDisappear:(BOOL)animated {
  347. [super viewWillDisappear:animated];
  348. [self stopConnectedTimer];
  349. }
  350. - (void)setPanStartPoint:(CGPoint)panStartPoint {
  351. _panStartPoint = panStartPoint;
  352. _panStartVideoFrame = self.smallVideoView.frame;
  353. }
  354. - (void)moveToPanPoint:(CGPoint)panPoint {
  355. CGRect frame = self.panStartVideoFrame;
  356. CGSize moveSize = CGSizeMake(panPoint.x - self.panStartPoint.x, panPoint.y - self.panStartPoint.y);
  357. frame.origin.x += moveSize.width;
  358. frame.origin.y += moveSize.height;
  359. self.smallVideoView.frame = frame;
  360. }
  361. - (void)onSmallVideoPan:(UIPanGestureRecognizer *)recognize {
  362. switch (recognize.state) {
  363. case UIGestureRecognizerStateBegan:
  364. self.panStartPoint = [recognize translationInView:self.view];
  365. break;
  366. case UIGestureRecognizerStateChanged: {
  367. CGPoint currentPoint = [recognize translationInView:self.view];
  368. [self moveToPanPoint:currentPoint];
  369. break;
  370. }
  371. case UIGestureRecognizerStateEnded: {
  372. CGPoint endPoint = [recognize translationInView:self.view];
  373. [self moveToPanPoint:endPoint];
  374. break;
  375. }
  376. case UIGestureRecognizerStateCancelled:
  377. case UIGestureRecognizerStateFailed:
  378. default:
  379. break;
  380. }
  381. }
  382. - (void)onSmallVideoTaped:(id)sender {
  383. if (self.currentSession.state == kWFAVEngineStateConnected) {
  384. self.swapVideoView = !_swapVideoView;
  385. }
  386. }
  387. - (void)videoButtonDidTap:(UIButton *)button {
  388. if (self.currentSession.state != kWFAVEngineStateIdle) {
  389. [self.currentSession muteVideo:!self.currentSession.isVideoMuted];
  390. }
  391. }
  392. - (void)scalingButtonDidTap:(UIButton *)button {
  393. if (self.currentSession.state != kWFAVEngineStateIdle) {
  394. if (self.scalingType < kWFAVVideoScalingTypeAspectBalanced) {
  395. self.scalingType++;
  396. } else {
  397. self.scalingType = kWFAVVideoScalingTypeAspectFit;
  398. }
  399. self.swapVideoView = _swapVideoView;
  400. }
  401. }
  402. - (CGRect)getButtomCenterButtonFrame {
  403. return CGRectMake(self.view.frame.size.width/2-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  404. }
  405. - (CGRect)getButtomLeftButtonFrame {
  406. return CGRectMake(self.view.frame.size.width/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  407. }
  408. - (CGRect)getButtomRightButtonFrame {
  409. return CGRectMake(self.view.frame.size.width*3/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize, ButtonSize, ButtonSize);
  410. }
  411. - (CGRect)getToAudioButtonFrame {
  412. return CGRectMake(self.view.frame.size.width*3/4-ButtonSize/2, self.view.frame.size.height-45-ButtonSize-ButtonSize-2, ButtonSize, ButtonSize);
  413. }
  414. - (void)updateTopViewFrame {
  415. CGFloat containerWidth = self.view.bounds.size.width;
  416. CGFloat containerHeight = self.view.bounds.size.height;
  417. if (self.currentSession.isAudioOnly) {
  418. CGFloat postionY = (containerHeight - 110) / 2.0 - 70;
  419. self.portraitView.frame = CGRectMake((containerWidth-110)/2, postionY, 110, 110);;
  420. postionY += 110 + 16;
  421. self.userNameLabel.frame = CGRectMake((containerWidth - 240)/2, postionY, 240, 27);
  422. self.userNameLabel.textAlignment = NSTextAlignmentCenter;
  423. postionY += 12 + 27;
  424. self.stateLabel.frame = CGRectMake((containerWidth - 240)/2, postionY, 240, 26);
  425. self.stateLabel.textAlignment = NSTextAlignmentCenter;
  426. } else {
  427. CGFloat postionX = 16;
  428. self.portraitView.frame = CGRectMake(postionX, kStatusBarAndNavigationBarHeight, 62, 62);
  429. postionX += 62;
  430. postionX += 8;
  431. self.userNameLabel.frame = CGRectMake(postionX, kStatusBarAndNavigationBarHeight + 8, 240, 26);
  432. self.userNameLabel.textAlignment = NSTextAlignmentLeft;
  433. if(![NSThread isMainThread]) {
  434. NSLog(@"error not main thread");
  435. }
  436. if(self.currentSession.state == kWFAVEngineStateConnected) {
  437. self.stateLabel.frame = CGRectMake(54, 30, 240, 20);
  438. } else {
  439. self.stateLabel.frame = CGRectMake(88, kStatusBarAndNavigationBarHeight + 26 + 14, 240, 16);
  440. }
  441. // self.stateLabel.hidden = YES;
  442. self.stateLabel.textAlignment = NSTextAlignmentLeft;
  443. }
  444. }
  445. - (void)onClickedBigVideoView:(id)sender {
  446. if (self.currentSession.state != kWFAVEngineStateConnected) {
  447. return;
  448. }
  449. if (self.currentSession.audioOnly) {
  450. return;
  451. }
  452. if (self.smallVideoView.hidden) {
  453. if (self.hangupButton.hidden) {
  454. self.hangupButton.hidden = NO;
  455. self.audioButton.hidden = NO;
  456. self.switchCameraButton.hidden = NO;
  457. self.smallVideoView.hidden = NO;
  458. self.minimizeButton.hidden = NO;
  459. self.downgradeButton.hidden = NO;
  460. } else {
  461. self.hangupButton.hidden = YES;
  462. self.audioButton.hidden = YES;
  463. self.downgradeButton.hidden = YES;
  464. self.switchCameraButton.hidden = YES;
  465. self.minimizeButton.hidden = YES;
  466. }
  467. } else {
  468. self.smallVideoView.hidden = YES;
  469. }
  470. }
  471. #pragma mark - WFAVEngineDelegate
  472. - (void)didChangeState:(WFAVEngineState)state {
  473. if (!self.viewLoaded) {
  474. return;
  475. }
  476. switch (state) {
  477. case kWFAVEngineStateIdle:
  478. self.answerButton.hidden = YES;
  479. self.hangupButton.hidden = YES;
  480. self.switchCameraButton.hidden = YES;
  481. self.audioButton.hidden = YES;
  482. self.videoButton.hidden = YES;
  483. self.scalingButton.hidden = YES;
  484. [self stopConnectedTimer];
  485. self.userNameLabel.hidden = NO;
  486. self.portraitView.hidden = NO;
  487. self.stateLabel.text = WFCString(@"CallEnded");
  488. self.smallVideoView.hidden = YES;
  489. self.bigVideoView.hidden = YES;
  490. self.minimizeButton.hidden = YES;
  491. self.speakerButton.hidden = YES;
  492. self.downgradeButton.hidden = YES;
  493. [self updateTopViewFrame];
  494. break;
  495. case kWFAVEngineStateOutgoing:
  496. self.answerButton.hidden = YES;
  497. self.hangupButton.hidden = NO;
  498. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  499. self.switchCameraButton.hidden = YES;
  500. if (self.currentSession.isAudioOnly) {
  501. self.speakerButton.hidden = YES;
  502. [self updateSpeakerButton];
  503. self.speakerButton.frame = [self getButtomRightButtonFrame];
  504. self.audioButton.hidden = YES;
  505. self.audioButton.frame = [self getButtomLeftButtonFrame];
  506. } else {
  507. self.speakerButton.hidden = YES;
  508. self.audioButton.hidden = YES;
  509. }
  510. self.videoButton.hidden = YES;
  511. self.scalingButton.hidden = YES;
  512. [self.currentSession setupLocalVideoView:self.bigVideoView scalingType:self.scalingType];
  513. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  514. self.stateLabel.text = WFCString(@"WaitingAccept");
  515. self.smallVideoView.hidden = YES;
  516. self.userNameLabel.hidden = NO;
  517. self.portraitView.hidden = NO;
  518. self.minimizeButton.hidden = NO;
  519. [self updateTopViewFrame];
  520. break;
  521. case kWFAVEngineStateConnecting:
  522. self.answerButton.hidden = YES;
  523. self.hangupButton.hidden = NO;
  524. self.speakerButton.hidden = YES;
  525. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  526. self.switchCameraButton.hidden = YES;
  527. self.audioButton.hidden = YES;
  528. self.videoButton.hidden = YES;
  529. self.scalingButton.hidden = YES;
  530. self.swapVideoView = NO;
  531. self.stateLabel.text = WFCString(@"CallConnecting");
  532. self.smallVideoView.hidden = NO;
  533. self.downgradeButton.hidden = YES;
  534. break;
  535. case kWFAVEngineStateConnected:
  536. self.answerButton.hidden = YES;
  537. self.hangupButton.hidden = NO;
  538. self.hangupButton.frame = [self getButtomCenterButtonFrame];
  539. if (self.currentSession.isAudioOnly) {
  540. self.speakerButton.hidden = NO;
  541. self.speakerButton.frame = [self getButtomRightButtonFrame];
  542. [self updateSpeakerButton];
  543. self.audioButton.hidden = NO;
  544. self.audioButton.frame = [self getButtomLeftButtonFrame];
  545. self.switchCameraButton.hidden = YES;
  546. } else {
  547. self.speakerButton.hidden = YES;
  548. [self.currentSession enableSpeaker:YES];
  549. self.audioButton.hidden = NO;
  550. self.audioButton.frame = [self getButtomLeftButtonFrame];
  551. self.switchCameraButton.hidden = NO;
  552. self.switchCameraButton.frame = [self getButtomRightButtonFrame];
  553. }
  554. self.videoButton.hidden = YES;
  555. self.scalingButton.hidden = YES;
  556. self.minimizeButton.hidden = NO;
  557. if (self.currentSession.isAudioOnly) {
  558. self.downgradeButton.hidden = YES;;
  559. } else {
  560. self.downgradeButton.hidden = NO;
  561. self.downgradeButton.frame = [self getToAudioButtonFrame];
  562. }
  563. if (self.currentSession.isAudioOnly) {
  564. [self.currentSession setupLocalVideoView:nil scalingType:self.scalingType];
  565. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  566. self.smallVideoView.hidden = YES;
  567. self.bigVideoView.hidden = YES;
  568. [_downgradeButton setImage:[UIImage imageNamed:@"to_video"] forState:UIControlStateNormal];
  569. [_downgradeButton setImage:[UIImage imageNamed:@"to_video_hover"] forState:UIControlStateHighlighted];
  570. [_downgradeButton setImage:[UIImage imageNamed:@"to_video_hover"] forState:UIControlStateSelected];
  571. } else {
  572. [self.currentSession setupLocalVideoView:self.smallVideoView scalingType:self.scalingType];
  573. [self.currentSession setupRemoteVideoView:self.bigVideoView scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  574. self.smallVideoView.hidden = NO;
  575. self.bigVideoView.hidden = NO;
  576. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio"] forState:UIControlStateNormal];
  577. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateHighlighted];
  578. [_downgradeButton setImage:[UIImage imageNamed:@"to_audio_hover"] forState:UIControlStateSelected];
  579. }
  580. if (!_currentSession.isAudioOnly) {
  581. self.userNameLabel.hidden = YES;
  582. self.portraitView.hidden = YES;
  583. } else {
  584. self.userNameLabel.hidden = NO;
  585. self.portraitView.hidden = NO;
  586. }
  587. [self updateConnectedTimeLabel];
  588. [self startConnectedTimer];
  589. [self updateTopViewFrame];
  590. break;
  591. case kWFAVEngineStateIncomming:
  592. self.answerButton.hidden = NO;
  593. self.answerButton.frame = [self getButtomRightButtonFrame];
  594. self.hangupButton.hidden = NO;
  595. self.hangupButton.frame = [self getButtomLeftButtonFrame];
  596. self.switchCameraButton.hidden = YES;
  597. self.audioButton.hidden = YES;
  598. self.videoButton.hidden = YES;
  599. self.scalingButton.hidden = YES;
  600. self.downgradeButton.hidden = NO;
  601. self.downgradeButton.frame = [self getToAudioButtonFrame];
  602. [self.currentSession setupLocalVideoView:self.bigVideoView scalingType:self.scalingType];
  603. [self.currentSession setupRemoteVideoView:nil scalingType:self.scalingType forUser:self.currentSession.participantIds[0]];
  604. self.stateLabel.text = WFCString(@"InvitingYou");
  605. self.smallVideoView.hidden = YES;
  606. if (self.currentSession.isAudioOnly) {
  607. self.downgradeButton.hidden = YES;;
  608. } else {
  609. self.downgradeButton.hidden = NO;
  610. self.downgradeButton.frame = [self getToAudioButtonFrame];
  611. }
  612. self.minimizeButton.hidden = NO;
  613. break;
  614. default:
  615. break;
  616. }
  617. }
  618. - (void)didCreateLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
  619. }
  620. - (void)didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack fromUser:(NSString *)userId {
  621. }
  622. - (void)didVideoMuted:(BOOL)videoMuted fromUser:(NSString *)userId {
  623. }
  624. - (void)didReportAudioVolume:(NSInteger)volume ofUser:(NSString *)userId {
  625. }
  626. - (void)didCallEndWithReason:(WFAVCallEndReason)reason {
  627. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  628. [[WFAVEngineKit sharedEngineKit] dismissViewController:self];
  629. });
  630. }
  631. - (void)didParticipantJoined:(NSString *)userId {
  632. }
  633. - (void)didParticipantConnected:(NSString *)userId {
  634. }
  635. - (void)didParticipantLeft:(NSString *)userId withReason:(WFAVCallEndReason)reason {
  636. }
  637. - (void)didChangeMode:(BOOL)isAudioOnly {
  638. [self didChangeState:self.currentSession.state];
  639. }
  640. - (void)didError:(NSError *)error {
  641. }
  642. - (void)didGetStats:(NSArray *)stats {
  643. }
  644. - (void)checkAVPermission {
  645. [self checkCapturePermission:nil];
  646. [self checkRecordPermission:nil];
  647. }
  648. - (void)checkCapturePermission:(void (^)(BOOL granted))complete {
  649. AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  650. if (authStatus == AVAuthorizationStatusDenied || authStatus == AVAuthorizationStatusRestricted) {
  651. if (complete) {
  652. complete(NO);
  653. }
  654. } else if (authStatus == AVAuthorizationStatusNotDetermined) {
  655. [AVCaptureDevice
  656. requestAccessForMediaType:AVMediaTypeVideo
  657. completionHandler:^(BOOL granted) {
  658. if (complete) {
  659. complete(granted);
  660. }
  661. }];
  662. } else {
  663. if (complete) {
  664. complete(YES);
  665. }
  666. }
  667. }
  668. - (void)checkRecordPermission:(void (^)(BOOL granted))complete {
  669. if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(requestRecordPermission:)]) {
  670. [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
  671. if (complete) {
  672. complete(granted);
  673. }
  674. }];
  675. }
  676. }
  677. //1.决定当前界面是否开启自动转屏,如果返回NO,后面两个方法也不会被调用,只是会支持默认的方向
  678. - (BOOL)shouldAutorotate {
  679. return YES;
  680. }
  681. //2.返回支持的旋转方向
  682. //iPad设备上,默认返回值UIInterfaceOrientationMaskAllButUpSideDwon
  683. //iPad设备上,默认返回值是UIInterfaceOrientationMaskAll
  684. - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
  685. return UIDeviceOrientationLandscapeLeft | UIDeviceOrientationLandscapeRight | UIDeviceOrientationPortrait;
  686. }
  687. //3.返回进入界面默认显示方向
  688. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
  689. return UIInterfaceOrientationPortrait;
  690. }
  691. - (BOOL)onDeviceOrientationDidChange{
  692. if (self.currentSession.state == kWFAVEngineStateIdle) {
  693. return YES;
  694. }
  695. //获取当前设备Device
  696. UIDevice *device = [UIDevice currentDevice] ;
  697. //识别当前设备的旋转方向
  698. CGRect smallVideoFrame = CGRectZero;
  699. CGFloat width = self.view.bounds.size.width;
  700. CGFloat height = self.view.bounds.size.height;
  701. switch (device.orientation) {
  702. case UIDeviceOrientationFaceUp:
  703. break;
  704. case UIDeviceOrientationFaceDown:
  705. break;
  706. case UIDeviceOrientationUnknown:
  707. //系统当前无法识别设备朝向,可能是倾斜
  708. break;
  709. case UIDeviceOrientationLandscapeLeft:
  710. self.smallVideoView.transform = CGAffineTransformMakeRotation(M_PI_2);
  711. self.bigVideoView.transform = CGAffineTransformMakeRotation(M_PI_2);
  712. self.bigVideoView.frame = self.view.bounds;
  713. smallVideoFrame = CGRectMake(width - SmallVideoView - 8, height - 8 - kStatusBarAndNavigationBarHeight + 64 - SmallVideoView - SmallVideoView/3 - kTabbarSafeBottomMargin, SmallVideoView * 4 /3, SmallVideoView);
  714. self.smallVideoView.frame = smallVideoFrame;
  715. self.swapVideoView = _swapVideoView;
  716. break;
  717. case UIDeviceOrientationLandscapeRight:
  718. self.smallVideoView.transform = CGAffineTransformMakeRotation(-M_PI_2);
  719. self.bigVideoView.transform = CGAffineTransformMakeRotation(-M_PI_2);
  720. self.bigVideoView.frame = self.view.bounds;
  721. smallVideoFrame = CGRectMake(8-SmallVideoView/3, 8 + kStatusBarAndNavigationBarHeight - 64+SmallVideoView/3, SmallVideoView * 4 /3, SmallVideoView);
  722. self.smallVideoView.frame = smallVideoFrame;
  723. self.swapVideoView = _swapVideoView;
  724. break;
  725. case UIDeviceOrientationPortrait:
  726. self.smallVideoView.transform = CGAffineTransformMakeRotation(0);
  727. self.bigVideoView.transform = CGAffineTransformMakeRotation(0);
  728. self.bigVideoView.frame = self.view.bounds;
  729. smallVideoFrame = CGRectMake(self.view.frame.size.width - SmallVideoView, kStatusBarAndNavigationBarHeight, SmallVideoView, SmallVideoView * 4 /3);
  730. self.smallVideoView.frame = smallVideoFrame;
  731. self.swapVideoView = _swapVideoView;
  732. break;
  733. case UIDeviceOrientationPortraitUpsideDown:
  734. break;
  735. default:
  736. NSLog(@"無法识别");
  737. break;
  738. }
  739. return YES;
  740. }
  741. #endif
  742. @end