Bläddra i källkod

添加视频界面分类

liuzhenxing1118 7 månader sedan
förälder
incheckning
34a1752fd6

+ 1 - 0
artimenring-iOS/Artimenring/Classes/Data/VideoManager+agora.h

@@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
 @interface VideoManager (agora)
 
 - (BOOL)initAgora;
+- (void)clearAgora;
 
 @end
 

+ 40 - 0
artimenring-iOS/Artimenring/Classes/Data/VideoManager+agora.m

@@ -8,10 +8,50 @@
 
 #import "VideoManager+agora.h"
 
+#define APPKEY_AGORA @"92c4358b9f98419f9a10d345e59a77f1"
+#define CER_AGORA @"d4055ad6ce2a4c2faca9eed2acdab2dc"
+
 @implementation VideoManager (agora)
 
 - (BOOL)initAgora {
+    self.agoraKit = [AgoraRtcEngineKit sharedEngineWithAppId:APPKEY_AGORA delegate:self];
+    [self.agoraKit enableVideo];
     return YES;
 }
 
+- (void)joinChannel:(NSString*)token channelId:(NSString*)channelId uid:(NSUInteger)uid {
+    AgoraRtcChannelMediaOptions *options = [[AgoraRtcChannelMediaOptions alloc] init];
+    // 自动订阅所有音频流
+    options.autoSubscribeAudio = YES;
+    // 自动订阅所有视频流
+    options.autoSubscribeVideo = YES;
+    // 发布摄像头采集的视频
+    options.publishCameraTrack = YES;
+    // 发布麦克风采集的音频
+    options.publishMicrophoneTrack = YES;
+    // 设置用户角色为主播;如果要将用户角色设置为观众,保持默认值即可
+    options.clientRoleType = AgoraClientRoleBroadcaster;
+    // 使用临时 Token 加入频道,在这里传入你的项目的 Token 和频道名
+    // uid 为 0 表示由引擎内部随机生成; 成功后会触发 didJoinChannel 回调
+    int result = [self.agoraKit joinChannelByToken:token channelId:channelId uid:uid mediaOptions:options joinSuccess:nil];
+}
+
+- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine didJoinChannel:(NSString * _Nonnull)channel withUid:(NSUInteger)uid elapsed:(NSInteger)elapsed NS_SWIFT_NAME(rtcEngine(_:didJoinChannel:withUid:elapsed:)) {
+    
+}
+
+- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine didJoinedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed NS_SWIFT_NAME(rtcEngine(_:didJoinedOfUid:elapsed:)) {
+    
+}
+
+- (void)rtcEngine:(AgoraRtcEngineKit * _Nonnull)engine didOfflineOfUid:(NSUInteger)uid reason:(AgoraUserOfflineReason)reason NS_SWIFT_NAME(rtcEngine(_:didOfflineOfUid:reason:)) {
+    
+}
+
+- (void)clearAgora {
+    [self.agoraKit stopPreview];
+    [self.agoraKit leaveChannel:nil];
+    [AgoraRtcEngineKit destroy];
+}
+
 @end

+ 2 - 0
artimenring-iOS/Artimenring/Classes/Data/VideoManager+juphoon.h

@@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN
 - (void)loginJuphoon;
 - (void)logoutJuphoon;
 
+- (BOOL)call:(NSString*)sid ticket:(NSString*)ticket;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 10 - 9
artimenring-iOS/Artimenring/Classes/Data/VideoManager+juphoon.m

@@ -9,9 +9,6 @@
 #import "VideoManager+juphoon.h"
 #import "VideoManager+timer.h"
 
-@interface VideoManager() <JCClientCallback, JCMediaDeviceCallback, JCCallCallback>
-@end
-
 @implementation VideoManager (juphoon)
 
 //初始化
@@ -21,9 +18,7 @@
     self.mJuphoonCall = [JCCall create:self.mJuphoonClient mediaDevice:self.mJuphoonMediaDevice callback:self];
     self.mJuphoonCall.mediaConfig = [JCCallMediaConfig generateByMode:JCCallMediaConfigModeIOT];
     
-    // 现在设置屏幕方向固定,竖直角度
-    //self.mJuphoonMediaDevice.autoRotate = false;
-    //[self.mJuphoonMediaDevice setSawtooth:YES];
+    self.mJuphoonMediaDevice.videoAngle = JCMediaDeviceVideoAngel0;
     [self.mJuphoonMediaDevice setCameraProperty:640 height:360 framerate:10];
     
     //Zmf_VideoCaptureListenRotation(0, 0);
@@ -47,6 +42,12 @@
     }
 }
 
+- (BOOL)call:(NSString*)sid ticket:(NSString*)ticket {
+    self.mSID = sid;
+    self.mTicket = ticket;
+    JCCallParam* callParam = [JCCallParam callParamWithExtraParam:@"" ticket:ticket];
+    return [self.mJuphoonCall call:ticket video:true callParam:callParam];
+}
 
 #pragma mark - JCMediaDeviceCallback
 /**
@@ -178,9 +179,9 @@
  * @param changeParam JCCallChangeParam 更新标识对象
  */
 - (void)onCallItemUpdate:(JCCallItem* __nonnull)item changeParam:(JCCallChangeParam * __nullable)changeParam {
-    if (item.state == JCCallStateTalking && [self.mInCallVC getRemoteCanvas] == nil && item.uploadVideoStreamOther) {
-        [self stopVideoTimer];
-    }
+//    if (item.state == JCCallStateTalking && [self.mInCallVC getRemoteCanvas] == nil && item.uploadVideoStreamOther) {
+//        [self stopTimeoutTimer];
+//    }
     [[NSNotificationCenter defaultCenter] postNotificationName:kCallNotification object:nil];
 }
 

+ 2 - 2
artimenring-iOS/Artimenring/Classes/Data/VideoManager+timer.h

@@ -12,8 +12,8 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface VideoManager (timer)
 
-- (void)startVideoTimer;
-- (void)stopVideoTimer;
+- (void)startTimeoutTimer;
+- (void)stopTimeoutTimer;
 
 @end
 

+ 6 - 6
artimenring-iOS/Artimenring/Classes/Data/VideoManager+timer.m

@@ -11,18 +11,18 @@
 @implementation VideoManager (timer)
 
 #pragma mark - Heart
-- (void)startVideoTimer {
-    [self stopVideoTimer];
-    self.mTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(videoTimerCallback:) userInfo:nil repeats:YES];
+- (void)startTimeoutTimer {
+    [self stopTimeoutTimer];
+    self.mTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:@selector(timeoutCallback:) userInfo:nil repeats:YES];
 }
 
-- (void)videoTimerCallback:(id)sender {
-    [self stopVideoTimer];
+- (void)timeoutCallback:(id)sender {
+    [self stopTimeoutTimer];
     [self autoTermWithTimeout];
 }
 
 #pragma mark - stopTimer
-- (void)stopVideoTimer {
+- (void)stopTimeoutTimer {
     if (self.mTimeoutTimer)
         [self.mTimeoutTimer invalidate];
     self.mTimeoutTimer = nil;

+ 11 - 1
artimenring-iOS/Artimenring/Classes/Data/VideoManager.h

@@ -7,6 +7,7 @@
 //
 
 #import <Foundation/Foundation.h>
+#import <AgoraRtcKit/AgoraRtcKit.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -19,10 +20,18 @@ NS_ASSUME_NONNULL_BEGIN
 
 + (VideoManager *)shared;
 
+@property(nonatomic, strong) SKInCallViewController* mInCallVC;
+
+//Juphoon
 @property(nonatomic, strong) JCClient *mJuphoonClient;
 @property(nonatomic, strong) JCCall *mJuphoonCall;
 @property(nonatomic, strong) JCMediaDevice *mJuphoonMediaDevice;
-@property(nonatomic, strong) SKInCallViewController* mInCallVC;
+
+//声网
+@property(nonatomic, strong) AgoraRtcEngineKit *agoraKit;
+@property(nonatomic, strong) AgoraMediaRecorder *localRecorder;
+@property(nonatomic, strong) AgoraMediaRecorder *remoteRecorder;
+
 @property(nonatomic, strong) NSString* mSID;
 @property(nonatomic, strong) NSString* mTicket;
 @property(nonatomic, strong) NSTimer* mTimeoutTimer;
@@ -38,6 +47,7 @@ NS_ASSUME_NONNULL_BEGIN
 - (void)showInCallVC;
 - (void)removeInCallVC;
 
+- (JCCallItem*)getActiveCall;
 - (NSString*)getTalkName;
 - (NSString*)getTalkHeadImageURL;
 

+ 15 - 8
artimenring-iOS/Artimenring/Classes/Data/VideoManager.m

@@ -12,7 +12,7 @@
 #import "VideoManager+timer.h"
 
 
-@interface VideoManager() 
+@interface VideoManager() <JCClientCallback, JCMediaDeviceCallback, JCCallCallback, AgoraRtcEngineDelegate>
 @end
 
 @implementation VideoManager
@@ -27,12 +27,13 @@
 }
 
 - (void)initManager {
-    [self initJuphoon];
-    [self initAgora];
+    //[self initJuphoon];
+    //[self initAgora];
 }
 
 - (void)clear {
     [self logoutJuphoon];
+    [self clearAgora];
 }
 
 - (void)requestVideo:(NSString*)sid ticket:(NSString*)ticket dial:(NSInteger)dial {
@@ -60,17 +61,14 @@
         return;
     }
     HDNormalLog(([NSString stringWithFormat:@"VideoManager: videoStart: sid:%@  ticket:%@  dial:%ld", sid, ticket, dial]));
-    self.mSID = sid;
-    self.mTicket = ticket;
-    JCCallParam* callParam = [JCCallParam callParamWithExtraParam:@"" ticket:ticket];
-    BOOL isok =  [self.mJuphoonCall call:ticket video:true callParam:callParam];
+    BOOL isok = [self call:sid ticket:ticket];
     if (!isok) {
         //如果失败,很有可能登录失败,重新登录//
         [self loginJuphoon];
         [EasyTextView showErrorText:[NSString stringWithFormat:NSLocalizedString(@"Video.Error.User.Login", nil)]];
     } else {
         [self requestVideo:sid ticket:ticket dial:1];
-        [self startVideoTimer];
+        [self startTimeoutTimer];
     }
 }
 
@@ -140,6 +138,15 @@
     [self autoTerm];
 }
 
+- (JCCallItem*)getActiveCall {
+    for (JCCallItem* item in self.mJuphoonCall.callItems) {
+        if (item.active) {
+            return item;
+        }
+    }
+    return nil;
+}
+
 - (NSString*)getJuphoonSID {
     JCCallItem *activeCall = self.mJuphoonCall.callItems.firstObject;
     if (activeCall.direction == JCCallDirectionOut) {

+ 17 - 0
artimenring-iOS/Artimenring/Classes/ViewController/Call/SKInCallViewController+agora.h

@@ -0,0 +1,17 @@
+//
+//  SKInCallViewController+agora.h
+//  SikeyComm
+//
+//  Created by 刘振兴 on 2025/2/13.
+//  Copyright © 2025 BaH Cy. All rights reserved.
+//
+
+#import "SKInCallViewController.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SKInCallViewController (agora)
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 40 - 0
artimenring-iOS/Artimenring/Classes/ViewController/Call/SKInCallViewController+agora.m

@@ -0,0 +1,40 @@
+//
+//  SKInCallViewController+agora.m
+//  SikeyComm
+//
+//  Created by 刘振兴 on 2025/2/13.
+//  Copyright © 2025 BaH Cy. All rights reserved.
+//
+
+#import "SKInCallViewController+agora.h"
+
+@implementation SKInCallViewController (agora)
+
+- (void)initView {
+    self.localView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
+    [self.view insertSubview:self.localView aboveSubview:self.backgroudView];
+    
+    self.remoteView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
+    [self.remoteView setHidden:YES];
+    [self.view insertSubview:self.remoteView aboveSubview:self.backgroudView];
+}
+
+- (void)startLocal {
+    AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
+    videoCanvas.uid = 0;
+    videoCanvas.view = self.localView;
+    videoCanvas.renderMode = AgoraVideoRenderModeHidden;
+    [[VideoManager shared].agoraKit setupLocalVideo:videoCanvas];
+    [[VideoManager shared].agoraKit startPreview];
+}
+
+- (void)startRemote:(NSInteger)uid {
+    AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc]init];
+    videoCanvas.uid = uid;
+    // the view to be binded
+    videoCanvas.view = self.remoteView;
+    videoCanvas.renderMode = AgoraVideoRenderModeHidden;
+    [[VideoManager shared].agoraKit setupRemoteVideo:videoCanvas];
+}
+
+@end

+ 25 - 0
artimenring-iOS/Artimenring/Classes/ViewController/Call/SKInCallViewController+juphoon.h

@@ -0,0 +1,25 @@
+//
+//  SKInCallViewController+juphoon.h
+//  SikeyComm
+//
+//  Created by 刘振兴 on 2025/2/13.
+//  Copyright © 2025 BaH Cy. All rights reserved.
+//
+
+#import "SKInCallViewController.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SKInCallViewController (juphoon)
+
+@property(nonatomic, strong) JCMediaDeviceVideoCanvas* jcLocalCanvas;
+@property(nonatomic, strong) JCMediaDeviceVideoCanvas* jcRemoteCanvas;
+
+- (void)updateUI:(NSNotification *)notification;
+- (NSString *)getNetStatus:(JCCallItem *)item;
+
+- (NSObject*)getRemoteCanvas;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 138 - 0
artimenring-iOS/Artimenring/Classes/ViewController/Call/SKInCallViewController+juphoon.m

@@ -0,0 +1,138 @@
+//
+//  SKInCallViewController+juphoon.m
+//  SikeyComm
+//
+//  Created by 刘振兴 on 2025/2/13.
+//  Copyright © 2025 BaH Cy. All rights reserved.
+//
+
+#import "SKInCallViewController+juphoon.h"
+#import "VideoManager+ringtone.h"
+
+@implementation SKInCallViewController (juphoon)
+
+- (void)updateUI:(NSNotification *)notification {
+    NSInteger count = [VideoManager shared].mJuphoonCall.callItems.count;
+    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
+    HDNormalLog(([NSString stringWithFormat:@"VideoManager: updateUI count:%ld updateUI: %ld", count, activeCall.state]));
+
+    if (activeCall.state == JCCallStateInit || activeCall.state == JCCallStatePending) {
+        self.mInVideoView.hidden = !activeCall.video || activeCall.direction == JCCallDirectionOut;
+        self.mOutView.hidden = activeCall.direction != JCCallDirectionOut;
+        self.mWaitHeaderView.hidden = NO;
+        self.mIngHeaderView.hidden = YES;
+        self.mIngView.hidden = YES;
+        
+        self.mIngNameLabel.text = @"";
+        self.mWaitNameLabel.text = [[VideoManager shared] getTalkName];
+        self.mWaitInHintLabel.hidden = activeCall.direction != JCCallDirectionIn;
+        self.mWaitOutHintLabel.hidden = activeCall.direction != JCCallDirectionOut;
+        
+        if (activeCall.video) {
+            if (self.jcLocalCanvas == nil && activeCall.uploadVideoStreamSelf) {
+                self.jcLocalCanvas = [[VideoManager shared].mJuphoonMediaDevice startCameraVideo:JCMediaDeviceRenderFullScreen];
+                //self.jcLocalCanvas.videoView.frame = CGRectMake(SCREEN_WIDTH - 150, SCREEN_HEIGHT - 150 - 160, 120, 160);
+                self.jcLocalCanvas.videoView.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+                [self.view insertSubview:self.jcLocalCanvas.videoView aboveSubview:self.backgroudView];
+            } else if (self.jcLocalCanvas != nil && !activeCall.uploadVideoStreamSelf) {
+                [[VideoManager shared].mJuphoonMediaDevice stopVideo:self.jcLocalCanvas];
+                [self.jcLocalCanvas.videoView removeFromSuperview];
+                self.jcLocalCanvas = nil;
+            }
+        }
+    } else if (activeCall.state == JCCallStateTalking) {
+        self.mInVideoView.hidden = YES;
+        self.mOutView.hidden = YES;
+        self.mWaitHeaderView.hidden = YES;
+        self.mIngHeaderView.hidden = NO;
+        self.mIngView.hidden = NO;
+        self.mIngNameLabel.text = [[VideoManager shared] getTalkName];
+
+        self.switchCameraBtn.enabled = activeCall.video;
+        self.holdBtn.enabled = !activeCall.held;
+        self.holdBtn.selected = activeCall.hold;
+        self.muteBtn.selected = activeCall.mute;
+        self.speakerBtn.selected = [VideoManager shared].mJuphoonMediaDevice.isSpeakerOn;
+        
+        if (activeCall != nil && activeCall.audioRecord && (activeCall.hold || activeCall.held)) {
+            [[VideoManager shared].mJuphoonCall audioRecord:activeCall enable:false filePath:@""];
+        }
+        if (activeCall != nil && activeCall.localVideoRecord && !activeCall.uploadVideoStreamSelf) {
+            //[[VideoManager shared].mJuphoonCall videoRecord:activeCall enable:false remote:false width:0 height:0 filePath:@""];
+            [[VideoManager shared].mJuphoonCall videoRecord:activeCall enable:false remote:false width:0 height:0 filePath:@"" bothAudio:false keyFrame:10];
+        }
+        if (activeCall != nil && activeCall.remoteVideoRecord && !activeCall.uploadVideoStreamOther) {
+            [[VideoManager shared].mJuphoonCall videoRecord:activeCall enable:false remote:true width:0 height:0 filePath:@"" bothAudio:false keyFrame:10];
+        }
+        if (activeCall.video) {
+            if (self.jcLocalCanvas != nil && activeCall.uploadVideoStreamSelf) {
+                if (self.smallView == nil) {
+                    self.jcLocalCanvas.videoView.frame = CGRectMake(SCREEN_WIDTH - 130, SCREEN_STATUS_HEIGHT+10, 120, 160);
+                }
+                self.smallView = self.jcLocalCanvas.videoView;
+            }
+            
+            if (self.jcRemoteCanvas == nil && activeCall.uploadVideoStreamOther) {
+                self.jcRemoteCanvas = [[VideoManager shared].mJuphoonMediaDevice startVideo:activeCall.renderId renderType:JCMediaDeviceRenderFullContent];
+                self.jcRemoteCanvas.videoView.frame = self.view.frame;
+                self.jcRemoteCanvas.videoView.hidden = !activeCall.uploadVideoStreamSelf;
+                [self.view insertSubview:self.jcRemoteCanvas.videoView aboveSubview:self.backgroudView];
+                [[VideoManager shared].mJuphoonMediaDevice enableSpeaker:YES];
+            } else if (self.jcRemoteCanvas != nil && !activeCall.uploadVideoStreamOther) {
+                [[VideoManager shared].mJuphoonMediaDevice stopVideo:self.jcRemoteCanvas];
+                [self.jcRemoteCanvas.videoView removeFromSuperview];
+                self.jcRemoteCanvas = nil;
+            }
+        }
+
+        [self startTimer];
+        [[VideoManager shared] stopVideoRingtone];
+    } else {
+        self.mInVideoView.hidden = YES;
+    }
+    if (!activeCall.video) {
+        [self removeCanvas];
+    }
+}
+
+- (NSString *)getNetStatus:(JCCallItem *)item {
+    if (item.state != JCCallStateTalking) {
+        return @"";
+    }
+    switch (item.videoNetSendStatus) {
+        case JCCallNetWorkDisconnected:
+            return NSLocalizedString(@"Video.Network.Status.0", nil);
+        case JCCallNetWorkVeryBad:
+            return NSLocalizedString(@"Video.Network.Status.1", nil);
+        case JCCallNetWorkBad:
+            return NSLocalizedString(@"Video.Network.Status.2", nil);
+        case JCCallNetWorkNormal:
+            return NSLocalizedString(@"Video.Network.Status.3", nil);
+        case JCCallNetWorkGood:
+            return NSLocalizedString(@"Video.Network.Status.4", nil);
+        case JCCallNetWorkVeryGood:
+            return NSLocalizedString(@"Video.Network.Status.5", nil);
+        default:
+            return @"";
+    }
+}
+
+- (NSObject*)getRemoteCanvas {
+    return self.jcRemoteCanvas;
+}
+
+- (void)removeCanvas {
+    if (self.jcLocalCanvas) {
+        [[VideoManager shared].mJuphoonMediaDevice stopVideo:self.jcLocalCanvas];
+        [self.jcLocalCanvas.videoView removeFromSuperview];
+        self.jcLocalCanvas = nil;
+        self.smallView = nil;
+    }
+    if (self.jcRemoteCanvas) {
+        [[VideoManager shared].mJuphoonMediaDevice stopVideo:self.jcRemoteCanvas];
+        [self.jcRemoteCanvas.videoView removeFromSuperview];
+        self.jcRemoteCanvas = nil;
+    }
+}
+
+@end

+ 21 - 0
artimenring-iOS/Artimenring/Classes/ViewController/Call/SKInCallViewController+touch.h

@@ -0,0 +1,21 @@
+//
+//  SKInCallViewController+touch.h
+//  SikeyComm
+//
+//  Created by 刘振兴 on 2025/2/13.
+//  Copyright © 2025 BaH Cy. All rights reserved.
+//
+
+#import "SKInCallViewController.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SKInCallViewController (touch)
+
+@property(nonatomic, assign) BOOL isTouchInSmallCanvas;
+@property(nonatomic, assign) BOOL isMoveInSmallCanvas;
+@property(nonatomic, assign) CGPoint mStartPoint;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 94 - 0
artimenring-iOS/Artimenring/Classes/ViewController/Call/SKInCallViewController+touch.m

@@ -0,0 +1,94 @@
+//
+//  SKInCallViewController+touch.m
+//  SikeyComm
+//
+//  Created by 刘振兴 on 2025/2/13.
+//  Copyright © 2025 BaH Cy. All rights reserved.
+//
+
+#import "SKInCallViewController+touch.h"
+
+@implementation SKInCallViewController (touch)
+
+- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+    //如果不在通话
+    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
+    if (!activeCall.video && activeCall.state != JCCallStateTalking)
+        return;
+    
+    UITouch *touch = [touches anyObject];
+    //当前的坐标,第一次触摸
+    CGPoint point = [touch locationInView: self.view];
+    self.mStartPoint = point;
+    
+    point = [self.smallView.layer convertPoint:point fromLayer:self.view.layer];
+    if ([self.smallView.layer containsPoint:point]) {
+        self.isTouchInSmallCanvas = YES;
+    }
+    else {
+        self.isTouchInSmallCanvas = NO;
+    }
+}
+
+- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+    //如果不在通话
+    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
+    if (!activeCall.video && activeCall.state != JCCallStateTalking)
+        return;
+    
+    if (!self.isTouchInSmallCanvas)
+        return;
+    
+    UITouch *touch = [touches anyObject];
+    CGPoint movePoint = [touch locationInView: self.view];
+    
+    CGPoint offsetPoint = CGPointMake(movePoint.x - self.mStartPoint.x, movePoint.y - self.mStartPoint.y);
+    if (offsetPoint.x == 0 && offsetPoint.y == 0)
+        return;
+    
+    self.isMoveInSmallCanvas = YES;
+    CGRect canvasRect = self.smallView.frame;
+    CGPoint endPoint = CGPointMake(canvasRect.origin.x + offsetPoint.x, canvasRect.origin.y + offsetPoint.y);
+    
+    //避免超框
+    if (endPoint.x < 0.0) {
+        endPoint.x = 0.0;
+    }
+    if (endPoint.y < SCREEN_STATUS_HEIGHT) {
+        endPoint.y = SCREEN_STATUS_HEIGHT;
+    }
+    if (endPoint.x + canvasRect.size.width > SCREEN_WIDTH) {
+        endPoint.x = SCREEN_WIDTH - canvasRect.size.width;
+    }
+    if (endPoint.y + canvasRect.size.height > SCREEN_HEIGHT) {
+        endPoint.y = SCREEN_HEIGHT - canvasRect.size.height;
+    }
+    
+    [self.smallView setOrigin:endPoint];
+    
+    self.mStartPoint = movePoint;
+}
+
+- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+    //如果不在通话
+    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
+    if (!activeCall.video && activeCall.state != JCCallStateTalking)
+        return;
+    
+    self.isTouchInSmallCanvas = NO;
+    self.isMoveInSmallCanvas = NO;
+    self.mStartPoint = CGPointMake(0, 0);
+}
+
+- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+    //如果不在通话
+    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
+    if (!activeCall.video && activeCall.state != JCCallStateTalking)
+        return;
+    
+    self.isTouchInSmallCanvas = NO;
+    self.isMoveInSmallCanvas = NO;
+    self.mStartPoint = CGPointMake(0, 0);
+}
+
+@end

+ 36 - 1
artimenring-iOS/Artimenring/Classes/ViewController/Call/SKInCallViewController.h

@@ -9,6 +9,41 @@
 #import <UIKit/UIKit.h>
 
 @interface SKInCallViewController : UIViewController
-- (NSObject*)getRemoteCanvas;
+
+//video view
+@property (nonatomic, strong) UIView* localView;
+@property (nonatomic, strong) UIView* remoteView;
+@property (nonatomic, strong) UIView* smallView;
+
+//base view
+@property (nonatomic, strong) IBOutlet UIImageView *backgroudView;
+@property (nonatomic, strong) IBOutlet UIView *mIngHeaderView;
+@property (nonatomic, strong) IBOutlet UILabel *mIngNameLabel;
+@property (nonatomic, strong) IBOutlet UILabel *mIngTimeLabel;
+@property (nonatomic, strong) IBOutlet UILabel *mIngNetWorkLabel;
+
+@property (nonatomic, strong) IBOutlet UIView *mWaitHeaderView;
+@property (nonatomic, strong) IBOutlet UIImageView *mWaitHeadImage;
+@property (nonatomic, strong) IBOutlet UILabel *mWaitNameLabel;
+@property (nonatomic, strong) IBOutlet UILabel *mWaitInHintLabel;
+@property (nonatomic, strong) IBOutlet UILabel *mWaitOutHintLabel;
+
+@property (nonatomic, strong) IBOutlet UIView *mInVideoView;
+@property (nonatomic, strong) IBOutlet UIView *mOutView;
+@property (nonatomic, strong) IBOutlet UIView *mIngView;
+
+// selected 为相机打开状态, default 为相机关闭状态
+@property (nonatomic, strong) IBOutlet UIButton *switchCameraBtn;
+// selected 为保持通话状态, default 为未保持通话状态, disable 为被保持通话状态
+@property (nonatomic, strong) IBOutlet UIButton *holdBtn;
+// selected 为静音状态, default 为正常状态
+@property (nonatomic, strong) IBOutlet UIButton *muteBtn;
+
+// selected 为听筒模式, default 为扬声器模式
+@property (nonatomic, strong) IBOutlet UIButton *speakerBtn;
+@property (nonatomic, strong) IBOutlet UIButton *endCallBtn;
+
+- (void)startTimer;
+- (void)stopTimer;
 
 @end

+ 23 - 270
artimenring-iOS/Artimenring/Classes/ViewController/Call/SKInCallViewController.m

@@ -7,51 +7,15 @@
 //
 
 #import "SKInCallViewController.h"
+#import "SKInCallViewController+juphoon.h"
+#import "SKInCallViewController+agora.h"
+#import "SKInCallViewController+touch.h"
 #import "VideoManager+ringtone.h"
 
-#define kDoodleVersionChecker 1
-#define AUDIO_RECORD_DIR @"audio_record"
-#define SNAPSHOT_DIR @"snapshot"
-#define VIDEO_RECORD_DIR @"video_record"
-
 
 @interface SKInCallViewController() {
-    JCMediaDeviceVideoCanvas* _localCanvas;
-    JCMediaDeviceVideoCanvas* _remoteCanvas;
-    JCMediaDeviceVideoCanvas* _mSmallCanvas;
     NSTimer* _timer;
-    BOOL isTouchInSmallCanvas;
-    BOOL isMoveInSmallCanvas;
-    CGPoint mStartPoint;
 }
-
-@property (weak, nonatomic) IBOutlet UIImageView *backgroudView;
-@property (weak, nonatomic) IBOutlet UIView *mIngHeaderView;
-@property (weak, nonatomic) IBOutlet UILabel *mIngNameLabel;
-@property (weak, nonatomic) IBOutlet UILabel *mIngTimeLabel;
-@property (weak, nonatomic) IBOutlet UILabel *mIngNetWorkLabel;
-
-@property (weak, nonatomic) IBOutlet UIView *mWaitHeaderView;
-@property (weak, nonatomic) IBOutlet UIImageView *mWaitHeadImage;
-@property (weak, nonatomic) IBOutlet UILabel *mWaitNameLabel;
-@property (weak, nonatomic) IBOutlet UILabel *mWaitInHintLabel;
-@property (weak, nonatomic) IBOutlet UILabel *mWaitOutHintLabel;
-
-@property (weak, nonatomic) IBOutlet UIView *mInVideoView;
-@property (weak, nonatomic) IBOutlet UIView *mOutView;
-@property (weak, nonatomic) IBOutlet UIView *mIngView;
-
-// selected 为相机打开状态, default 为相机关闭状态
-@property (weak, nonatomic) IBOutlet UIButton *switchCameraBtn;
-// selected 为保持通话状态, default 为未保持通话状态, disable 为被保持通话状态
-@property (weak, nonatomic) IBOutlet UIButton *holdBtn;
-// selected 为静音状态, default 为正常状态
-@property (weak, nonatomic) IBOutlet UIButton *muteBtn;
-
-// selected 为听筒模式, default 为扬声器模式
-@property (weak, nonatomic) IBOutlet UIButton *speakerBtn;
-@property (weak, nonatomic) IBOutlet UIButton *endCallBtn;
-
 @end
 
 @implementation SKInCallViewController
@@ -64,16 +28,15 @@
     [EUtil setViewShadow:self.mWaitNameLabel color:[UIColor colorWithRed:0/255.0f green:1/255.0f blue:75/255.0f alpha:0.2] offset:CGSizeMake(0, 2) opacity:1 radius:4];
     [EUtil setViewShadow:self.mWaitOutHintLabel color:[UIColor colorWithRed:0/255.0f green:1/255.0f blue:75/255.0f alpha:0.2] offset:CGSizeMake(0, 2) opacity:1 radius:4];
     [EUtil setViewShadow:self.mWaitInHintLabel color:[UIColor colorWithRed:0/255.0f green:1/255.0f blue:75/255.0f alpha:0.2] offset:CGSizeMake(0, 2) opacity:1 radius:4];
-    [VideoManager shared].mJuphoonMediaDevice.videoAngle = JCMediaDeviceVideoAngel0;
     
     [EUtil setViewShadow:self.mIngNameLabel color:[UIColor colorWithRed:0/255.0f green:1/255.0f blue:75/255.0f alpha:0.2] offset:CGSizeMake(0, 2) opacity:1 radius:4];
     [EUtil setViewShadow:self.mIngTimeLabel color:[UIColor colorWithRed:0/255.0f green:1/255.0f blue:75/255.0f alpha:0.2] offset:CGSizeMake(0, 2) opacity:1 radius:4];
     [EUtil setViewShadow:self.mIngNetWorkLabel color:[UIColor colorWithRed:0/255.0f green:1/255.0f blue:75/255.0f alpha:0.2] offset:CGSizeMake(0, 2) opacity:1 radius:4];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateUI:) name:kCallNotification object:nil];
     
-    _mSmallCanvas = nil;
-    isTouchInSmallCanvas = NO;
-    isMoveInSmallCanvas = NO;
+    _smallView = nil;
+    self.isTouchInSmallCanvas = NO;
+    self.isMoveInSmallCanvas = NO;
     [self initView];
     [self updateUI:nil];
     [[VideoManager shared] playVideoWaitingRingtone];
@@ -106,98 +69,11 @@
     [[VideoManager shared] playVideoFinishRingtone];
 }
 
-- (NSObject*)getRemoteCanvas {
-    return _remoteCanvas;
-}
-
 - (void)initView {
     [EUtil setURLImage:self.mWaitHeadImage placeHolderName:@"avatar" imageURL:[[VideoManager shared] getTalkHeadImageURL] cornerRadius:self.mWaitHeadImage.frame.size.width/2];
 }
 
-- (void)updateUI:(NSNotification *)noti {
-    NSInteger count = [VideoManager shared].mJuphoonCall.callItems.count;
-    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
-    HDNormalLog(([NSString stringWithFormat:@"VideoManager: updateUI count:%ld updateUI: %ld", count, activeCall.state]));
-
-    if (activeCall.state == JCCallStateInit || activeCall.state == JCCallStatePending) {
-        
-        self.mInVideoView.hidden = !activeCall.video || activeCall.direction == JCCallDirectionOut;
-        self.mOutView.hidden = activeCall.direction != JCCallDirectionOut;
-        self.mWaitHeaderView.hidden = NO;
-        self.mIngHeaderView.hidden = YES;
-        self.mIngView.hidden = YES;
-        
-        self.mIngNameLabel.text = @"";
-        self.mWaitNameLabel.text = [[VideoManager shared] getTalkName];
-        self.mWaitInHintLabel.hidden = activeCall.direction != JCCallDirectionIn;
-        self.mWaitOutHintLabel.hidden = activeCall.direction != JCCallDirectionOut;
-        
-        if (activeCall.video) {
-            if (_localCanvas == nil && activeCall.uploadVideoStreamSelf) {
-                _localCanvas = [[VideoManager shared].mJuphoonMediaDevice startCameraVideo:JCMediaDeviceRenderFullScreen];
-                //_localCanvas.videoView.frame = CGRectMake(SCREEN_WIDTH - 150, SCREEN_HEIGHT - 150 - 160, 120, 160);
-                _localCanvas.videoView.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
-                [self.view insertSubview:_localCanvas.videoView aboveSubview:self.backgroudView];
-            } else if (_localCanvas != nil && !activeCall.uploadVideoStreamSelf) {
-                [[VideoManager shared].mJuphoonMediaDevice stopVideo:_localCanvas];
-                [_localCanvas.videoView removeFromSuperview];
-                _localCanvas = nil;
-            }
-        }
-    } else if (activeCall.state == JCCallStateTalking) {
-        self.mInVideoView.hidden = YES;
-        self.mOutView.hidden = YES;
-        self.mWaitHeaderView.hidden = YES;
-        self.mIngHeaderView.hidden = NO;
-        self.mIngView.hidden = NO;
-        self.mIngNameLabel.text = [[VideoManager shared] getTalkName];
-
-        self.switchCameraBtn.enabled = activeCall.video;
-        self.holdBtn.enabled = !activeCall.held;
-        self.holdBtn.selected = activeCall.hold;
-        self.muteBtn.selected = activeCall.mute;
-        self.speakerBtn.selected = [VideoManager shared].mJuphoonMediaDevice.isSpeakerOn;
-        
-        if (activeCall != nil && activeCall.audioRecord && (activeCall.hold || activeCall.held)) {
-            [[VideoManager shared].mJuphoonCall audioRecord:activeCall enable:false filePath:@""];
-        }
-        if (activeCall != nil && activeCall.localVideoRecord && !activeCall.uploadVideoStreamSelf) {
-            //[[VideoManager shared].mJuphoonCall videoRecord:activeCall enable:false remote:false width:0 height:0 filePath:@""];
-            [[VideoManager shared].mJuphoonCall videoRecord:activeCall enable:false remote:false width:0 height:0 filePath:@"" bothAudio:false keyFrame:10];
-        }
-        if (activeCall != nil && activeCall.remoteVideoRecord && !activeCall.uploadVideoStreamOther) {
-            [[VideoManager shared].mJuphoonCall videoRecord:activeCall enable:false remote:true width:0 height:0 filePath:@"" bothAudio:false keyFrame:10];
-        }
-        if (activeCall.video) {
-            if (_localCanvas != nil && activeCall.uploadVideoStreamSelf) {
-                if (_mSmallCanvas == nil) {
-                    _localCanvas.videoView.frame = CGRectMake(SCREEN_WIDTH - 130, SCREEN_STATUS_HEIGHT+10, 120, 160);
-                }
-                _mSmallCanvas = _localCanvas;
-            }
-            
-            if (_remoteCanvas == nil && activeCall.uploadVideoStreamOther) {
-                _remoteCanvas = [[VideoManager shared].mJuphoonMediaDevice startVideo:activeCall.renderId renderType:JCMediaDeviceRenderFullContent];
-                _remoteCanvas.videoView.frame = self.view.frame;
-                _remoteCanvas.videoView.hidden = !activeCall.uploadVideoStreamSelf;
-                [self.view insertSubview:_remoteCanvas.videoView aboveSubview:self.backgroudView];
-                [[VideoManager shared].mJuphoonMediaDevice enableSpeaker:YES];
-            } else if (_remoteCanvas != nil && !activeCall.uploadVideoStreamOther) {
-                [[VideoManager shared].mJuphoonMediaDevice stopVideo:_remoteCanvas];
-                [_remoteCanvas.videoView removeFromSuperview];
-                _remoteCanvas = nil;
-            }
-        }
-            
-        [self startTimer];
-        [[VideoManager shared] stopVideoRingtone];
-    } else {
-        self.mInVideoView.hidden = YES;
-    }
-    if (!activeCall.video) {
-        [self removeCanvas];
-    }
-}
+
 
 #pragma mark - Incoming Actions
 - (IBAction)endCall:(id)sender {
@@ -211,17 +87,20 @@
 }
 
 - (IBAction)videoAnswer:(id)sender {
-    [[VideoManager shared].mJuphoonCall answer:[self getActiveCall] video:true];
+    JCCallItem *activeCall = [[VideoManager shared] getActiveCall];
+    [[VideoManager shared].mJuphoonCall answer:activeCall video:true];
 }
 
 - (IBAction)voiceAnswer:(id)sender {
-    [[VideoManager shared].mJuphoonCall answer:[self getActiveCall] video:false];
+    JCCallItem *activeCall = [[VideoManager shared] getActiveCall];
+    [[VideoManager shared].mJuphoonCall answer:activeCall video:false];
 }
 
 #pragma mark - In Calling Actions
 
 - (IBAction)setCameraState:(id)sender {
-    [[VideoManager shared].mJuphoonCall enableUploadVideoStream:[self getActiveCall]];
+    JCCallItem *activeCall = [[VideoManager shared] getActiveCall];
+    [[VideoManager shared].mJuphoonCall enableUploadVideoStream:activeCall];
 }
 
 - (IBAction)addNewCall:(id)sender {
@@ -232,11 +111,13 @@
 }
 
 - (IBAction)hold:(id)sender {
-    [[VideoManager shared].mJuphoonCall hold:[self getActiveCall]];
+    JCCallItem *activeCall = [[VideoManager shared] getActiveCall];
+    [[VideoManager shared].mJuphoonCall hold:activeCall];
 }
 
 - (IBAction)mute:(id)sender {
-    [[VideoManager shared].mJuphoonCall mute:[self getActiveCall]];
+    JCCallItem *activeCall = [[VideoManager shared] getActiveCall];
+    [[VideoManager shared].mJuphoonCall mute:activeCall];
 }
 
 - (IBAction)audioRecord:(id)sender {
@@ -257,16 +138,7 @@
 }
 
 #pragma mark - 工具函数
--(JCCallItem*)getActiveCall {
-    for (JCCallItem* item in [VideoManager shared].mJuphoonCall.callItems) {
-        if (item.active) {
-            return item;
-        }
-    }
-    return nil;
-}
-
-- (NSString *)genCallInfo:(JCCallItem*)item {
+- (NSString *)getCallInfo:(JCCallItem*)item {
     switch (item.state) {
         case JCCallStateTalking:
             return [self formatTalkingTime:((long)[[NSDate date] timeIntervalSince1970] - item.talkingBeginTime)];
@@ -275,50 +147,12 @@
     }
 }
 
-- (NSString *)genNetStatus:(JCCallItem *)item {
-    if (item.state != JCCallStateTalking) {
-        return @"";
-    }
-    switch (item.videoNetSendStatus) {
-        case JCCallNetWorkDisconnected:
-            return NSLocalizedString(@"Video.Network.Status.0", nil);
-        case JCCallNetWorkVeryBad:
-            return NSLocalizedString(@"Video.Network.Status.1", nil);
-        case JCCallNetWorkBad:
-            return NSLocalizedString(@"Video.Network.Status.2", nil);
-        case JCCallNetWorkNormal:
-            return NSLocalizedString(@"Video.Network.Status.3", nil);
-        case JCCallNetWorkGood:
-            return NSLocalizedString(@"Video.Network.Status.4", nil);
-        case JCCallNetWorkVeryGood:
-            return NSLocalizedString(@"Video.Network.Status.5", nil);
-        default:
-            return @"";
-    }
-}
-
-- (NSString *)formatTalkingTime:(long)time
-{
+- (NSString *)formatTalkingTime:(long)time {
     return [NSString stringWithFormat:@"%02ld:%02ld", time/60, time%60];
 }
 
-- (void)removeCanvas {
-    if (_localCanvas) {
-        [[VideoManager shared].mJuphoonMediaDevice stopVideo:_localCanvas];
-        [_localCanvas.videoView removeFromSuperview];
-        _localCanvas = nil;
-        _mSmallCanvas = nil;
-    }
-    if (_remoteCanvas) {
-        [[VideoManager shared].mJuphoonMediaDevice stopVideo:_remoteCanvas];
-        [_remoteCanvas.videoView removeFromSuperview];
-        _remoteCanvas = nil;
-    }
-}
-
 #pragma mark - Timer
-- (void)startTimer
-{
+- (void)startTimer {
     if (_timer == nil) {
         _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerProc) userInfo:nil repeats:YES];
     }
@@ -335,92 +169,11 @@
 
 - (void)timerProc {
     self.mIngHeaderView.hidden = NO;
-    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
-    self.mIngTimeLabel.text = [self genCallInfo:activeCall];
-    self.mIngNetWorkLabel.text = [self genNetStatus:activeCall];
+    JCCallItem *activeCall = [[VideoManager shared] getActiveCall];
+    self.mIngTimeLabel.text = [self getCallInfo:activeCall];
+    self.mIngNetWorkLabel.text = [self getNetStatus:activeCall];
     if (activeCall.direction == JCCallDirectionOut) {
     }
 }
 
-- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
-    //如果不在通话
-    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
-    if (!activeCall.video && activeCall.state != JCCallStateTalking)
-        return;
-    
-    UITouch *touch = [touches anyObject];
-    //当前的坐标,第一次触摸
-    CGPoint point = [touch locationInView: self.view];
-    mStartPoint = point;
-    
-    point = [_mSmallCanvas.videoView.layer convertPoint:point fromLayer:self.view.layer];
-    if ([_mSmallCanvas.videoView.layer containsPoint:point]) {
-        isTouchInSmallCanvas = YES;
-    }
-    else {
-        isTouchInSmallCanvas = NO;
-    }
-}
-
-- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
-    //如果不在通话
-    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
-    if (!activeCall.video && activeCall.state != JCCallStateTalking)
-        return;
-    
-    if (!isTouchInSmallCanvas)
-        return;
-    
-    UITouch *touch = [touches anyObject];
-    CGPoint movePoint = [touch locationInView: self.view];
-    
-    CGPoint offsetPoint = CGPointMake(movePoint.x - mStartPoint.x, movePoint.y - mStartPoint.y);
-    if (offsetPoint.x == 0 && offsetPoint.y == 0)
-        return;
-    
-    isMoveInSmallCanvas = YES;
-    CGRect canvasRect = _mSmallCanvas.videoView.frame;
-    CGPoint endPoint = CGPointMake(canvasRect.origin.x + offsetPoint.x, canvasRect.origin.y + offsetPoint.y);
-    
-    //避免超框
-    if (endPoint.x < 0.0) {
-        endPoint.x = 0.0;
-    }
-    if (endPoint.y < SCREEN_STATUS_HEIGHT) {
-        endPoint.y = SCREEN_STATUS_HEIGHT;
-    }
-    if (endPoint.x + canvasRect.size.width > SCREEN_WIDTH) {
-        endPoint.x = SCREEN_WIDTH - canvasRect.size.width;
-    }
-    if (endPoint.y + canvasRect.size.height > SCREEN_HEIGHT) {
-        endPoint.y = SCREEN_HEIGHT - canvasRect.size.height;
-    }
-    
-    [_mSmallCanvas.videoView setOrigin:endPoint];
-    
-    mStartPoint = movePoint;
-}
-
-- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
-    //如果不在通话
-    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
-    if (!activeCall.video && activeCall.state != JCCallStateTalking)
-        return;
-    
-    isTouchInSmallCanvas = NO;
-    isMoveInSmallCanvas = NO;
-    mStartPoint = CGPointMake(0, 0);
-}
-
-- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
-    //如果不在通话
-    JCCallItem *activeCall = [VideoManager shared].mJuphoonCall.callItems.firstObject;
-    if (!activeCall.video && activeCall.state != JCCallStateTalking)
-        return;
-    
-    isTouchInSmallCanvas = NO;
-    isMoveInSmallCanvas = NO;
-    mStartPoint = CGPointMake(0, 0);
-}
-
 @end

+ 30 - 12
artimenring-iOS/SikeyComm.xcodeproj/project.pbxproj

@@ -232,8 +232,11 @@
 		E43C72D92B0C7C3A0089E25B /* ZSActionButton.m in Sources */ = {isa = PBXBuildFile; fileRef = E43C72D72B0C7C3A0089E25B /* ZSActionButton.m */; };
 		E4499A822D5B4DF000653B56 /* VideoManager+ringtone.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A7F2D5B4DF000653B56 /* VideoManager+ringtone.m */; };
 		E4499A832D5B4DF000653B56 /* VideoManager+timer.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A812D5B4DF000653B56 /* VideoManager+timer.m */; };
-		E4499A862D5B4F1300653B56 /* VideoManager+agora.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A852D5B4F1300653B56 /* VideoManager+agora.m */; };
-		E4499A892D5B4F3800653B56 /* VideoManager+juphoon.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A882D5B4F3800653B56 /* VideoManager+juphoon.m */; };
+		E4499A8C2D5D954200653B56 /* SKInCallViewController+juphoon.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A8B2D5D954200653B56 /* SKInCallViewController+juphoon.m */; };
+		E4499A8F2D5D955200653B56 /* SKInCallViewController+agora.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A8E2D5D955200653B56 /* SKInCallViewController+agora.m */; };
+		E4499A922D5DD55700653B56 /* SKInCallViewController+touch.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A912D5DD55700653B56 /* SKInCallViewController+touch.m */; };
+		E4499A972D5DDFEA00653B56 /* VideoManager+juphoon.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A932D5DDFEA00653B56 /* VideoManager+juphoon.m */; };
+		E4499A982D5DDFEA00653B56 /* VideoManager+agora.m in Sources */ = {isa = PBXBuildFile; fileRef = E4499A942D5DDFEA00653B56 /* VideoManager+agora.m */; };
 		E44FCB072BA1542B00C7E9CF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E44FCB032BA1542B00C7E9CF /* Main.storyboard */; };
 		E44FCB142BA15BB500C7E9CF /* View.xib in Resources */ = {isa = PBXBuildFile; fileRef = E44FCB122BA15BB400C7E9CF /* View.xib */; };
 		E459F07E2B6B3D16002571E3 /* WifiAddListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E459F0352B6B3D16002571E3 /* WifiAddListViewController.m */; };
@@ -809,10 +812,16 @@
 		E4499A7F2D5B4DF000653B56 /* VideoManager+ringtone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "VideoManager+ringtone.m"; sourceTree = "<group>"; };
 		E4499A802D5B4DF000653B56 /* VideoManager+timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "VideoManager+timer.h"; sourceTree = "<group>"; };
 		E4499A812D5B4DF000653B56 /* VideoManager+timer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "VideoManager+timer.m"; sourceTree = "<group>"; };
-		E4499A842D5B4F1300653B56 /* VideoManager+agora.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VideoManager+agora.h"; sourceTree = "<group>"; };
-		E4499A852D5B4F1300653B56 /* VideoManager+agora.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "VideoManager+agora.m"; sourceTree = "<group>"; };
-		E4499A872D5B4F3800653B56 /* VideoManager+juphoon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VideoManager+juphoon.h"; sourceTree = "<group>"; };
-		E4499A882D5B4F3800653B56 /* VideoManager+juphoon.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "VideoManager+juphoon.m"; sourceTree = "<group>"; };
+		E4499A8A2D5D954200653B56 /* SKInCallViewController+juphoon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SKInCallViewController+juphoon.h"; sourceTree = "<group>"; };
+		E4499A8B2D5D954200653B56 /* SKInCallViewController+juphoon.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SKInCallViewController+juphoon.m"; sourceTree = "<group>"; };
+		E4499A8D2D5D955200653B56 /* SKInCallViewController+agora.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SKInCallViewController+agora.h"; sourceTree = "<group>"; };
+		E4499A8E2D5D955200653B56 /* SKInCallViewController+agora.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SKInCallViewController+agora.m"; sourceTree = "<group>"; };
+		E4499A902D5DD55700653B56 /* SKInCallViewController+touch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SKInCallViewController+touch.h"; sourceTree = "<group>"; };
+		E4499A912D5DD55700653B56 /* SKInCallViewController+touch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SKInCallViewController+touch.m"; sourceTree = "<group>"; };
+		E4499A932D5DDFEA00653B56 /* VideoManager+juphoon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "VideoManager+juphoon.m"; sourceTree = "<group>"; };
+		E4499A942D5DDFEA00653B56 /* VideoManager+agora.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "VideoManager+agora.m"; sourceTree = "<group>"; };
+		E4499A952D5DDFEA00653B56 /* VideoManager+juphoon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "VideoManager+juphoon.h"; sourceTree = "<group>"; };
+		E4499A962D5DDFEA00653B56 /* VideoManager+agora.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "VideoManager+agora.h"; sourceTree = "<group>"; };
 		E44FCB042BA1542B00C7E9CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
 		E44FCB132BA15BB400C7E9CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/View.xib; sourceTree = "<group>"; };
 		E459F0332B6B3D16002571E3 /* WifiListCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WifiListCell.h; sourceTree = "<group>"; };
@@ -2282,6 +2291,12 @@
 			children = (
 				E49A83702B625B3A00D5B289 /* SKInCallViewController.h */,
 				E49A83712B625B3A00D5B289 /* SKInCallViewController.m */,
+				E4499A8A2D5D954200653B56 /* SKInCallViewController+juphoon.h */,
+				E4499A8B2D5D954200653B56 /* SKInCallViewController+juphoon.m */,
+				E4499A8D2D5D955200653B56 /* SKInCallViewController+agora.h */,
+				E4499A8E2D5D955200653B56 /* SKInCallViewController+agora.m */,
+				E4499A902D5DD55700653B56 /* SKInCallViewController+touch.h */,
+				E4499A912D5DD55700653B56 /* SKInCallViewController+touch.m */,
 			);
 			path = Call;
 			sourceTree = "<group>";
@@ -2376,10 +2391,10 @@
 				E437147A2B4FCC1E003CA842 /* DataManager+timer.m */,
 				E420015C2BAC1FDD000D26B2 /* VideoManager.h */,
 				E420015D2BAC1FDD000D26B2 /* VideoManager.m */,
-				E4499A842D5B4F1300653B56 /* VideoManager+agora.h */,
-				E4499A852D5B4F1300653B56 /* VideoManager+agora.m */,
-				E4499A872D5B4F3800653B56 /* VideoManager+juphoon.h */,
-				E4499A882D5B4F3800653B56 /* VideoManager+juphoon.m */,
+				E4499A962D5DDFEA00653B56 /* VideoManager+agora.h */,
+				E4499A942D5DDFEA00653B56 /* VideoManager+agora.m */,
+				E4499A952D5DDFEA00653B56 /* VideoManager+juphoon.h */,
+				E4499A932D5DDFEA00653B56 /* VideoManager+juphoon.m */,
 				E4499A7E2D5B4DF000653B56 /* VideoManager+ringtone.h */,
 				E4499A7F2D5B4DF000653B56 /* VideoManager+ringtone.m */,
 				E4499A802D5B4DF000653B56 /* VideoManager+timer.h */,
@@ -2900,7 +2915,6 @@
 			files = (
 				E49951FC2B2C6C9B0018438F /* SKWebSocket+observer.m in Sources */,
 				27BECA221CBB504E00E3FD19 /* wav.mm in Sources */,
-				E4499A892D5B4F3800653B56 /* VideoManager+juphoon.m in Sources */,
 				E46FBAEB2B2FE4F7000404E9 /* SKWebSocket+domains.m in Sources */,
 				E4FE9B952AD9465100DEABCA /* MYBlurIntroductionView.m in Sources */,
 				E4FE9B712AD9465100DEABCA /* NSCalendar+FSExtension.m in Sources */,
@@ -2921,6 +2935,7 @@
 				E49F8D652BA3F8C900EDBAA8 /* NSString+http.m in Sources */,
 				27F64DBD205124620004B6CD /* PushAllMessage+CoreDataClass.m in Sources */,
 				E43714722B4D50D2003CA842 /* DataManager+delegate.m in Sources */,
+				E4499A982D5DDFEA00653B56 /* VideoManager+agora.m in Sources */,
 				27CF315E2003048B008600C2 /* SKFenceDetailViewController.m in Sources */,
 				27E011CA202AA01900F1F22E /* SKBabyQRCodeViewController.m in Sources */,
 				E4B054632D2CBFF00047C60A /* SKSelectAreaViewController.m in Sources */,
@@ -2952,6 +2967,7 @@
 				E4FE9B902AD9465100DEABCA /* PDTSimpleCalendarViewController.m in Sources */,
 				E42D819E2C057A1200398588 /* UIImagePickerController+GJImagePickerVC.m in Sources */,
 				273268151FFDF58F0096C8C1 /* SKContactListViewController.m in Sources */,
+				E4499A8F2D5D955200653B56 /* SKInCallViewController+agora.m in Sources */,
 				E41ECB5E2CF95C6C00C4C36C /* SKMainViewController+banner.m in Sources */,
 				E41ECB612CF95C6C00C4C36C /* SKMainViewController+server.m in Sources */,
 				E45EFDFA2B1755CA001BAB84 /* DataManager+session.m in Sources */,
@@ -3012,6 +3028,7 @@
 				E459F0972B6B3D16002571E3 /* SKTimeRepeatCustomViewController.m in Sources */,
 				272F224B1FC7BB7E0016FD5B /* SKTabbarViewController.m in Sources */,
 				E45EFDB32B15EDA1001BAB84 /* AppDelegate+login.m in Sources */,
+				E4499A8C2D5D954200653B56 /* SKInCallViewController+juphoon.m in Sources */,
 				E459F08C2B6B3D16002571E3 /* SKStrangerInterceptRecordViewCell.m in Sources */,
 				E4FE9B992AD9465100DEABCA /* RSKTouchView.m in Sources */,
 				2747E10E2064F834002F84E9 /* NSDictionary+crash.m in Sources */,
@@ -3021,6 +3038,7 @@
 				E41ECB952CF95DD700C4C36C /* SKChatViewController+more.m in Sources */,
 				E459F0852B6B3D16002571E3 /* SKWatchFlagViewController.m in Sources */,
 				E4FA8B992AF8E86900B984B9 /* SKWebSocket.m in Sources */,
+				E4499A972D5DDFEA00653B56 /* VideoManager+juphoon.m in Sources */,
 				E4FE9B6A2AD9465100DEABCA /* SSHolidayTW.m in Sources */,
 				E4FE9B7C2AD9465100DEABCA /* IanClickImageView.m in Sources */,
 				27ADEA611CBFD17B0013EADA /* RedFlowerCompleteTaskViewController.m in Sources */,
@@ -3097,7 +3115,6 @@
 				E4E75FBE2B9F1C6100236F73 /* PGCustomBannerView.m in Sources */,
 				E4E75FDA2BA06FFE00236F73 /* WeatherWarnView.m in Sources */,
 				271F9B721D198D5D00CA98DC /* HealthWalkViewController.m in Sources */,
-				E4499A862D5B4F1300653B56 /* VideoManager+agora.m in Sources */,
 				E459F0932B6B3D16002571E3 /* SKSchoolTimeListCell.m in Sources */,
 				27FFF948202845AA006C9F75 /* PushAllMessageViewCell.m in Sources */,
 				E4E75FD62BA06FFE00236F73 /* MagicReportView.m in Sources */,
@@ -3199,6 +3216,7 @@
 				28159C011A3FC46C00A3E1A3 /* UIView+EAddition.m in Sources */,
 				E4E75FBA2B9F146C00236F73 /* SKChildCellView.m in Sources */,
 				E49A83732B625B3A00D5B289 /* SKInCallViewController.m in Sources */,
+				E4499A922D5DD55700653B56 /* SKInCallViewController+touch.m in Sources */,
 				271CD1742004A4F20060C574 /* SKMessageCenterViewController.m in Sources */,
 				E459F08E2B6B3D16002571E3 /* SKFactoryInfoViewController.m in Sources */,
 				271CD1702004A1300060C574 /* ConfimMessageViewCell.m in Sources */,