diff --git a/ios-rongcallkit/RongCallKit/AudioObserver/RCDAudioFrameObserver.h b/ios-rongcallkit/RongCallKit/AudioObserver/RCDAudioFrameObserver.h
index 41bf39a..4e0116f 100644
--- a/ios-rongcallkit/RongCallKit/AudioObserver/RCDAudioFrameObserver.h
+++ b/ios-rongcallkit/RongCallKit/AudioObserver/RCDAudioFrameObserver.h
@@ -19,6 +19,7 @@ class RCDAudioFrameObserver : public agora::media::IAudioFrameObserver {
static RCDAudioFrameObserver *sharedObserver();
bool onRecordAudioFrame(agora::media::IAudioFrameObserver::AudioFrame& audioFrame);
bool onPlaybackAudioFrame(agora::media::IAudioFrameObserver::AudioFrame& audioFrame);
+ bool onMixedAudioFrame(agora::media::IAudioFrameObserver::AudioFrame &audioFrame);
bool onPlaybackAudioFrameBeforeMixing(unsigned int uid, agora::media::IAudioFrameObserver::AudioFrame& audioFrame);
};
diff --git a/ios-rongcallkit/RongCallKit/AudioObserver/RCDAudioFrameObserver.mm b/ios-rongcallkit/RongCallKit/AudioObserver/RCDAudioFrameObserver.mm
index dd26f6e..1ad9148 100644
--- a/ios-rongcallkit/RongCallKit/AudioObserver/RCDAudioFrameObserver.mm
+++ b/ios-rongcallkit/RongCallKit/AudioObserver/RCDAudioFrameObserver.mm
@@ -13,13 +13,15 @@
return &sharedObserver;
}
-
bool RCDAudioFrameObserver::onRecordAudioFrame(agora::media::IAudioFrameObserver::AudioFrame& audioFrame) {
return true;
}
bool RCDAudioFrameObserver::onPlaybackAudioFrame(agora::media::IAudioFrameObserver::AudioFrame& audioFrame) {
return true;
}
+bool RCDAudioFrameObserver::onMixedAudioFrame(agora::media::IAudioFrameObserver::AudioFrame &audioFrame) {
+ return true;
+}
bool RCDAudioFrameObserver::onPlaybackAudioFrameBeforeMixing(unsigned int uid, agora::media::IAudioFrameObserver::AudioFrame& audioFrame) {
NSString *userId = rcGetUserIdFromAgoraUID(uid);
NSLog(@"the user id is %@", userId);
diff --git a/ios-rongcallkit/RongCallKit/Controller/RCCallAudioMultiCallViewController.m b/ios-rongcallkit/RongCallKit/Controller/RCCallAudioMultiCallViewController.m
index 7d43173..df12d0a 100644
--- a/ios-rongcallkit/RongCallKit/Controller/RCCallAudioMultiCallViewController.m
+++ b/ios-rongcallkit/RongCallKit/Controller/RCCallAudioMultiCallViewController.m
@@ -323,8 +323,7 @@ - (UICollectionView *)userCollectionView {
- (void)inviteUserButtonClicked {
[self didTapInviteUserButton];
- if (self.callSession.conversationType == ConversationType_DISCUSSION ||
- self.callSession.conversationType == ConversationType_GROUP) {
+ if (self.callSession.isMultiCall) {
[self inviteNewUser];
} else {
NSLog(@"not support add user for conversation type %zd",
@@ -340,7 +339,7 @@ - (void)inviteNewUser {
[existUserIdList addObject:currentUserId];
__weak typeof(self) weakSelf = self;
- RCCallSelectMemberViewController *selectViewController =
+ UIViewController *selectViewController =
[[RCCallSelectMemberViewController alloc]
initWithConversationType:self.conversationType
targetId:self.targetId
@@ -359,10 +358,10 @@ - (void)inviteNewUser {
});
}
-- (void)resetLayout:(RCConversationType)conversationType
+- (void)resetLayout:(BOOL)isMultiCall
mediaType:(RCCallMediaType)mediaType
callStatus:(RCCallStatus)callStatus {
- [super resetLayout:conversationType
+ [super resetLayout:isMultiCall
mediaType:mediaType
callStatus:callStatus];
diff --git a/ios-rongcallkit/RongCallKit/Controller/RCCallBaseViewController.h b/ios-rongcallkit/RongCallKit/Controller/RCCallBaseViewController.h
index 7a04390..5a7c2a1 100644
--- a/ios-rongcallkit/RongCallKit/Controller/RCCallBaseViewController.h
+++ b/ios-rongcallkit/RongCallKit/Controller/RCCallBaseViewController.h
@@ -161,13 +161,13 @@
/*!
重新Layout布局
- @param conversationType 会话类型
+ @param isMultiCall 是否多方通话
@param mediaType 通话媒体类型
@param callStatus 通话状态
@discussion 如果您需要重写并调整UI的布局,应该先调用super。
*/
-- (void)resetLayout:(RCConversationType)conversationType
+- (void)resetLayout:(BOOL)isMultiCall
mediaType:(RCCallMediaType)mediaType
callStatus:(RCCallStatus)callStatus;
diff --git a/ios-rongcallkit/RongCallKit/Controller/RCCallBaseViewController.m b/ios-rongcallkit/RongCallKit/Controller/RCCallBaseViewController.m
index ad56b28..e32cc6b 100644
--- a/ios-rongcallkit/RongCallKit/Controller/RCCallBaseViewController.m
+++ b/ios-rongcallkit/RongCallKit/Controller/RCCallBaseViewController.m
@@ -145,7 +145,7 @@ - (void)viewDidLoad {
object:nil];
[self registerTelephonyEvent];
-
+ [self addProximityMonitoringObserver];
// UIVisualEffect *blurEffect = [UIBlurEffect
// effectWithStyle:UIBlurEffectStyleDark];
// self.blurView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
@@ -155,7 +155,7 @@ - (void)viewDidLoad {
}
- (void)onOrientationChanged:(NSNotification *)notification {
- [self resetLayout:self.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -182,7 +182,7 @@ - (void)viewWillAppear:(BOOL)animated {
[self callDidDisconnect];
}
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -440,7 +440,7 @@ - (UIButton *)cameraCloseButton {
if (!_cameraCloseButton) {
_cameraCloseButton = [[UIButton alloc] init];
- if (self.conversationType == ConversationType_PRIVATE) {
+ if (!self.callSession.isMultiCall) {
[_cameraCloseButton
setImage:[RCCallKitUtility imageFromVoIPBundle:@"voip/audio.png"]
forState:UIControlStateNormal];
@@ -486,7 +486,7 @@ - (UIButton *)cameraCloseButton {
- (void)cameraCloseButtonClicked {
[self didTapCameraCloseButton];
- if (self.conversationType == ConversationType_PRIVATE) {
+ if (!self.callSession.isMultiCall) {
[self.callSession
setVideoView:nil
userId:[RCIMClient sharedRCIMClient].currentUserInfo.userId];
@@ -498,7 +498,7 @@ - (void)cameraCloseButtonClicked {
}
if ([self.callSession changeMediaType:RCCallMediaAudio]) {
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:RCCallMediaAudio
callStatus:self.callSession.callStatus];
}
@@ -512,7 +512,7 @@ - (UIButton *)cameraSwitchButton {
if (!_cameraSwitchButton) {
_cameraSwitchButton = [[UIButton alloc] init];
- if (self.conversationType == ConversationType_PRIVATE) {
+ if (!self.callSession.isMultiCall) {
[_cameraSwitchButton
setImage:[RCCallKitUtility imageFromVoIPBundle:@"voip/camera.png"]
forState:UIControlStateNormal];
@@ -561,11 +561,11 @@ - (void)cameraSwitchButtonClicked {
}
#pragma mark - layout
-- (void)resetLayout:(RCConversationType)conversationType
+- (void)resetLayout:(BOOL)isMultiCall
mediaType:(RCCallMediaType)mediaType
callStatus:(RCCallStatus)callStatus {
if (mediaType == RCCallMediaAudio &&
- conversationType == ConversationType_PRIVATE) {
+ !isMultiCall) {
self.backgroundView.backgroundColor = RongVoIPUIColorFromRGB(0x262e42);
self.backgroundView.hidden = NO;
@@ -686,7 +686,7 @@ - (void)resetLayout:(RCConversationType)conversationType
self.cameraSwitchButton.hidden = YES;
} else if (mediaType == RCCallMediaVideo &&
- conversationType == ConversationType_PRIVATE) {
+ !isMultiCall) {
self.backgroundView.hidden = NO;
self.blurView.hidden = YES;
@@ -824,7 +824,7 @@ - (void)resetLayout:(RCConversationType)conversationType
}
} else if (mediaType == RCCallMediaAudio &&
- conversationType != ConversationType_PRIVATE) {
+ isMultiCall) {
self.backgroundView.backgroundColor = RongVoIPUIColorFromRGB(0x262e42);
self.backgroundView.hidden = NO;
@@ -948,7 +948,7 @@ - (void)resetLayout:(RCConversationType)conversationType
self.cameraSwitchButton.hidden = YES;
} else if (mediaType == RCCallMediaVideo &&
- conversationType != ConversationType_PRIVATE) {
+ isMultiCall) {
self.backgroundView.hidden = NO;
self.blurView.hidden = YES;
@@ -1103,7 +1103,7 @@ - (void)callDidConnect {
self.tipsLabel.text = @"";
[self startActiveTimer];
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -1126,7 +1126,7 @@ - (void)callDidDisconnect {
self.tipsLabel.textColor = [UIColor whiteColor];
[self stopActiveTimer];
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
@@ -1134,6 +1134,7 @@ - (void)callDidDisconnect {
dispatch_get_main_queue(), ^{
[[RCCall sharedRCCall] dismissCallViewController:self];
});
+ [self removeProximityMonitoringObserver];
}
/*!
@@ -1142,7 +1143,7 @@ - (void)callDidDisconnect {
@param userId 对端的用户ID
*/
- (void)remoteUserDidRing:(NSString *)userId {
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -1155,7 +1156,7 @@ - (void)remoteUserDidRing:(NSString *)userId {
*/
- (void)remoteUserDidInvite:(NSString *)userId
mediaType:(RCCallMediaType)mediaType {
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -1168,7 +1169,7 @@ - (void)remoteUserDidInvite:(NSString *)userId
*/
- (void)remoteUserDidJoin:(NSString *)userId
mediaType:(RCCallMediaType)mediaType {
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -1181,7 +1182,7 @@ - (void)remoteUserDidJoin:(NSString *)userId
*/
- (void)remoteUserDidChangeMediaType:(NSString *)userId
mediaType:(RCCallMediaType)mediaType {
- if (self.callSession.conversationType == ConversationType_PRIVATE) {
+ if (!self.callSession.isMultiCall) {
if (mediaType == RCCallMediaAudio &&
self.callSession.mediaType != RCCallMediaAudio) {
if ([self.callSession changeMediaType:RCCallMediaAudio]) {
@@ -1189,7 +1190,7 @@ - (void)remoteUserDidChangeMediaType:(NSString *)userId
setVideoView:nil
userId:[RCIMClient sharedRCIMClient].currentUserInfo.userId];
[self.callSession setVideoView:nil userId:self.callSession.targetId];
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:RCCallMediaAudio
callStatus:self.callSession.callStatus];
}
@@ -1207,7 +1208,7 @@ - (void)remoteUserDidChangeMediaType:(NSString *)userId
@param muted 是否关闭camera
*/
- (void)remoteUserDidDisableCamera:(BOOL)muted byUser:(NSString *)userId {
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -1220,7 +1221,7 @@ - (void)remoteUserDidDisableCamera:(BOOL)muted byUser:(NSString *)userId {
*/
- (void)remoteUserDidLeft:(NSString *)userId
reason:(RCCallDisconnectReason)reason {
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -1304,6 +1305,36 @@ - (void)registerTelephonyEvent {
};
}
+#pragma mark - proximity
+- (void)addProximityMonitoringObserver {
+ [UIDevice currentDevice].proximityMonitoringEnabled = YES;
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(proximityStatueChanged:)
+ name:UIDeviceProximityStateDidChangeNotification
+ object:nil];
+}
+
+- (void)removeProximityMonitoringObserver {
+ [UIDevice currentDevice].proximityMonitoringEnabled = NO;
+
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:UIDeviceProximityStateDidChangeNotification
+ object:nil];
+}
+
+- (void)proximityStatueChanged:(NSNotificationCenter *)notification {
+ // if ([UIDevice currentDevice].proximityState) {
+ // [[AVAudioSession sharedInstance]
+ // setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
+ // } else {
+ // [[AVAudioSession sharedInstance]
+ // setCategory:AVAudioSessionCategoryPlayback error:nil];
+ // }
+}
+
#pragma mark - outside callback
- (void)callWillConnect {
}
diff --git a/ios-rongcallkit/RongCallKit/Controller/RCCallSingleCallViewController.m b/ios-rongcallkit/RongCallKit/Controller/RCCallSingleCallViewController.m
index 0fab794..363c38e 100644
--- a/ios-rongcallkit/RongCallKit/Controller/RCCallSingleCallViewController.m
+++ b/ios-rongcallkit/RongCallKit/Controller/RCCallSingleCallViewController.m
@@ -143,18 +143,19 @@ - (void)subVideoViewClicked {
[self.remotePortraitView
setImageURL:[NSURL URLWithString:userInfo.portraitUri]];
- [self.callSession setVideoView:self.mainVideoView
- userId:self.remoteUserInfo.userId];
+
[self.callSession
setVideoView:self.subVideoView
userId:[RCIMClient sharedRCIMClient].currentUserInfo.userId];
+ [self.callSession setVideoView:self.mainVideoView
+ userId:self.remoteUserInfo.userId];
}
}
-- (void)resetLayout:(RCConversationType)conversationType
+- (void)resetLayout:(BOOL)isMultiCall
mediaType:(RCCallMediaType)mediaType
callStatus:(RCCallStatus)callStatus {
- [super resetLayout:conversationType
+ [super resetLayout:isMultiCall
mediaType:mediaType
callStatus:callStatus];
diff --git a/ios-rongcallkit/RongCallKit/Controller/RCCallVideoMultiCallViewController.m b/ios-rongcallkit/RongCallKit/Controller/RCCallVideoMultiCallViewController.m
index 26eb825..7a29d6e 100644
--- a/ios-rongcallkit/RongCallKit/Controller/RCCallVideoMultiCallViewController.m
+++ b/ios-rongcallkit/RongCallKit/Controller/RCCallVideoMultiCallViewController.m
@@ -266,7 +266,7 @@ - (void)backgroundViewClicked {
if (self.callSession.callStatus == RCCallActive) {
self.isFullScreen = !self.isFullScreen;
- [self resetLayout:self.callSession.conversationType
+ [self resetLayout:self.callSession.isMultiCall
mediaType:self.callSession.mediaType
callStatus:self.callSession.callStatus];
}
@@ -360,8 +360,7 @@ - (UICollectionView *)userCollectionView {
- (void)inviteUserButtonClicked {
[self didTapInviteUserButton];
- if (self.callSession.conversationType == ConversationType_DISCUSSION ||
- self.callSession.conversationType) {
+ if (self.callSession.isMultiCall) {
[self inviteNewUser];
} else {
NSLog(@"not support add user for conversation type %zd",
@@ -396,10 +395,10 @@ - (void)inviteNewUser {
});
}
-- (void)resetLayout:(RCConversationType)conversationType
+- (void)resetLayout:(BOOL)isMultiCall
mediaType:(RCCallMediaType)mediaType
callStatus:(RCCallStatus)callStatus {
- [super resetLayout:conversationType
+ [super resetLayout:isMultiCall
mediaType:mediaType
callStatus:callStatus];
diff --git a/ios-rongcallkit/RongCallKit/Info.plist b/ios-rongcallkit/RongCallKit/Info.plist
index c1f419c..d90f8a6 100644
--- a/ios-rongcallkit/RongCallKit/Info.plist
+++ b/ios-rongcallkit/RongCallKit/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 2.8.16
+ 2.8.17
CFBundleSignature
????
CFBundleVersion
diff --git a/ios-rongcallkit/RongCallKit/RCCall.mm b/ios-rongcallkit/RongCallKit/RCCall.mm
index 036bcc5..594953b 100644
--- a/ios-rongcallkit/RongCallKit/RCCall.mm
+++ b/ios-rongcallkit/RongCallKit/RCCall.mm
@@ -235,14 +235,13 @@ - (BOOL)preCheckForStartCall:(RCCallMediaType)mediaType {
}
}
-- (void)presentCallViewController:(UIViewController *)viewController {
+- (void)presentCallViewController:(UIViewController *)viewController{
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
UIWindow *activityWindow =
- [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
activityWindow.windowLevel = UIWindowLevelAlert;
activityWindow.rootViewController = viewController;
[activityWindow makeKeyAndVisible];
- [self addProximityMonitoringObserver];
CATransition *animation = [CATransition animation];
[animation setDuration:0.3];
animation.type = kCATransitionMoveIn; //可更改为其他方式
@@ -252,9 +251,6 @@ - (void)presentCallViewController:(UIViewController *)viewController {
}
- (void)dismissCallViewController:(UIViewController *)viewController {
- if (self.currentCallSession == nil) {
- [self removeProximityMonitoringObserver];
- }
if ([viewController isKindOfClass:[RCCallBaseViewController class]]) {
UIViewController *rootVC = viewController;
@@ -268,6 +264,7 @@ - (void)dismissCallViewController:(UIViewController *)viewController {
if (window.rootViewController == viewController) {
[window resignKeyWindow];
window.hidden = YES;
+ [[UIApplication sharedApplication].delegate.window makeKeyWindow];
[self.callWindows removeObject:window];
break;
}
@@ -281,7 +278,7 @@ - (RCCallSession *)currentCallSession {
#pragma mark - receive call
- (void)didReceiveCall:(RCCallSession *)callSession {
- if (callSession.conversationType == ConversationType_PRIVATE) {
+ if (!callSession.isMultiCall) {
RCCallSingleCallViewController *singleCallViewController =
[[RCCallSingleCallViewController alloc]
initWithIncomingCall:callSession];
@@ -437,36 +434,6 @@ - (void)loadErrorAlertWithConfirm:(NSString *)title
[alert show];
}
-#pragma mark - proximity
-- (void)addProximityMonitoringObserver {
- [UIDevice currentDevice].proximityMonitoringEnabled = YES;
-
- [[NSNotificationCenter defaultCenter]
- addObserver:self
- selector:@selector(proximityStatueChanged:)
- name:UIDeviceProximityStateDidChangeNotification
- object:nil];
-}
-
-- (void)removeProximityMonitoringObserver {
- [UIDevice currentDevice].proximityMonitoringEnabled = NO;
-
- [[NSNotificationCenter defaultCenter]
- removeObserver:self
- name:UIDeviceProximityStateDidChangeNotification
- object:nil];
-}
-
-- (void)proximityStatueChanged:(NSNotificationCenter *)notification {
- // if ([UIDevice currentDevice].proximityState) {
- // [[AVAudioSession sharedInstance]
- // setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
- // } else {
- // [[AVAudioSession sharedInstance]
- // setCategory:AVAudioSessionCategoryPlayback error:nil];
- // }
-}
-
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
diff --git a/ios-rongcallkit/RongCallKit/Utility/RCCallFloatingBoard.m b/ios-rongcallkit/RongCallKit/Utility/RCCallFloatingBoard.m
index e0cc47c..ea1b006 100644
--- a/ios-rongcallkit/RongCallKit/Utility/RCCallFloatingBoard.m
+++ b/ios-rongcallkit/RongCallKit/Utility/RCCallFloatingBoard.m
@@ -58,6 +58,7 @@ - (void)initBoard {
selector:@selector(onOrientationChanged:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
+ [self addProximityMonitoringObserver];
}
- (void)registerTelephonyEvent {
@@ -395,7 +396,7 @@ - (void)layoutTextUnderImageButton:(UIButton *)button {
- (BOOL)isVideoViewEnabledSession {
if (self.callSession.mediaType == RCCallMediaVideo &&
- self.callSession.conversationType == ConversationType_PRIVATE) {
+ !self.callSession.isMultiCall) {
return YES;
} else {
return NO;
@@ -418,6 +419,7 @@ - (void)callDidDisconnect {
withObject:nil
afterDelay:2];
[RCCallKitUtility clearScreenForceOnStatus];
+ [self removeProximityMonitoringObserver];
}
/*!
@@ -456,7 +458,7 @@ - (void)remoteUserDidJoin:(NSString *)userId
*/
- (void)remoteUserDidChangeMediaType:(NSString *)userId
mediaType:(RCCallMediaType)mediaType {
- if (self.callSession.conversationType == ConversationType_PRIVATE) {
+ if (!self.callSession.isMultiCall) {
if (mediaType == RCCallMediaAudio &&
self.callSession.mediaType != RCCallMediaAudio) {
if ([self.callSession changeMediaType:RCCallMediaAudio]) {
@@ -513,4 +515,33 @@ - (void)shouldStopAlertAndRing {
*/
- (void)errorDidOccur:(RCCallErrorCode)error {
}
+
+- (void)addProximityMonitoringObserver {
+ [UIDevice currentDevice].proximityMonitoringEnabled = YES;
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(proximityStatueChanged:)
+ name:UIDeviceProximityStateDidChangeNotification
+ object:nil];
+}
+
+- (void)removeProximityMonitoringObserver {
+ [UIDevice currentDevice].proximityMonitoringEnabled = NO;
+
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:self
+ name:UIDeviceProximityStateDidChangeNotification
+ object:nil];
+}
+
+- (void)proximityStatueChanged:(NSNotificationCenter *)notification {
+ // if ([UIDevice currentDevice].proximityState) {
+ // [[AVAudioSession sharedInstance]
+ // setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
+ // } else {
+ // [[AVAudioSession sharedInstance]
+ // setCategory:AVAudioSessionCategoryPlayback error:nil];
+ // }
+}
@end
diff --git a/ios-rongcallkit/RongCallKit/Utility/RCCallKitUtility.m b/ios-rongcallkit/RongCallKit/Utility/RCCallKitUtility.m
index 02edff7..09643f5 100644
--- a/ios-rongcallkit/RongCallKit/Utility/RCCallKitUtility.m
+++ b/ios-rongcallkit/RongCallKit/Utility/RCCallKitUtility.m
@@ -119,6 +119,9 @@ + (NSString *)getReadableStringForMessageCell:
hangupReasonString = NSLocalizedStringFromTable(@"VoIPCallRemoteNoResponse",
@"RongCloudKit", nil);
break;
+ case RCCallDisconnectReasonAddToBlackList:
+ hangupReasonString = NSLocalizedStringFromTable(@"VoIPCallHasReject", @"RongCloudKit", nil);
+ break;
default:
hangupReasonString = [self getGeneralReadableString:hangupReason];
break;
@@ -146,6 +149,9 @@ + (NSString *)getReadableStringForCallViewController:
hangupReasonString = NSLocalizedStringFromTable(
@"VoIPCallRemoteBusyLineAndShowAdvice", @"RongCloudKit", nil);
break;
+ case RCCallDisconnectReasonAddToBlackList:
+ hangupReasonString = NSLocalizedStringFromTable(@"VoIP_Rejected_By_Blacklist", @"RongCloudKit", nil);
+ break;
default:
hangupReasonString = [self getGeneralReadableString:hangupReason];
break;
diff --git a/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/AgoraRtcEngineKit b/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/AgoraRtcEngineKit
index 8efccc7..a08afd3 100644
Binary files a/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/AgoraRtcEngineKit and b/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/AgoraRtcEngineKit differ
diff --git a/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/AgoraRtcEngineKit.h b/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/AgoraRtcEngineKit.h
index 4405e30..54f2097 100755
--- a/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/AgoraRtcEngineKit.h
+++ b/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/AgoraRtcEngineKit.h
@@ -19,19 +19,26 @@ typedef NSView VIEW_CLASS;
#endif
typedef NS_ENUM(NSInteger, AgoraRtcWarningCode) {
+ AgoraRtc_Warn_InvalidView = 8,
+ AgoraRtc_Warn_InitVideo = 16,
AgoraRtc_Warn_Pending = 20,
AgoraRtc_Warn_NoAvailableChannel = 103,
AgoraRtc_Warn_LookupChannelTimeout = 104,
AgoraRtc_Warn_LookupChannelRejected = 105,
AgoraRtc_Warn_OpenChannelTimeout = 106,
AgoraRtc_Warn_OpenChannelRejected = 107,
+ AgoraRtc_Warn_SwitchLiveVideoTimeout = 111,
+ // sdk:vos, callmanager, peermanager: 100~1000
+ AgoraRtc_Warn_SetClientRoleTimeout = 118,
+ AgoraRtc_Warn_SetClientRoleNotAuthorized = 119,
+ AgoraRtc_Warn_AudioMixingOpenError = 701,
+
AgoraRtc_Warn_Adm_RuntimePlayoutWarning = 1014,
AgoraRtc_Warn_Adm_RuntimeRecordingWarning = 1016,
AgoraRtc_Warn_Adm_RecordAudioSilence = 1019,
AgoraRtc_Warn_Adm_PlaybackMalfunction = 1020,
AgoraRtc_Warn_Adm_RecordMalfunction = 1021,
AgoraRtc_Warn_Adm_Interruption = 1025,
- AgoraRtc_Warn_Adm_RouteChange = 1026,
AgoraRtc_Warn_Apm_Howling = 1051,
};
@@ -44,7 +51,6 @@ typedef NS_ENUM(NSInteger, AgoraRtcErrorCode) {
AgoraRtc_Error_Refused = 5,
AgoraRtc_Error_BufferTooSmall = 6,
AgoraRtc_Error_NotInitialized = 7,
- AgoraRtc_Error_InvalidView = 8,
AgoraRtc_Error_NoPermission = 9,
AgoraRtc_Error_TimedOut = 10,
AgoraRtc_Error_Canceled = 11,
@@ -52,7 +58,6 @@ typedef NS_ENUM(NSInteger, AgoraRtcErrorCode) {
AgoraRtc_Error_BindSocket = 13,
AgoraRtc_Error_NetDown = 14,
AgoraRtc_Error_NoBufs = 15,
- AgoraRtc_Error_InitVideo = 16,
AgoraRtc_Error_JoinChannelRejected = 17,
AgoraRtc_Error_LeaveChannelRejected = 18,
AgoraRtc_Error_AlreadyInUse = 19,
@@ -61,14 +66,14 @@ typedef NS_ENUM(NSInteger, AgoraRtcErrorCode) {
AgoraRtc_Error_InvalidChannelName = 102,
AgoraRtc_Error_ChannelKeyExpired = 109,
AgoraRtc_Error_InvalidChannelKey = 110,
- AgoraRtc_Error_ConnectionInterrupted = 111, // only used in web sdk
- AgoraRtc_Error_ConnectionLost = 112, // only used in web sdk
+ AgoraRtc_Error_ConnectionInterrupted = 111, // only used in web sdk
+ AgoraRtc_Error_ConnectionLost = 112, // only used in web sdk
AgoraRtc_Error_NotInChannel = 113,
AgoraRtc_Error_SizeTooLarge = 114,
- AgoraRtc_Error_BitrateLimit = 115,
- AgoraRtc_Error_TooManyDataStreams = 116,
+ AgoraRtc_Error_BitrateLimit = 115,
+ AgoraRtc_Error_TooManyDataStreams = 116,
AgoraRtc_Error_DecryptionFailed = 120,
-
+
AgoraRtc_Error_LoadMediaEngine = 1001,
AgoraRtc_Error_StartCall = 1002,
AgoraRtc_Error_StartCamera = 1003,
@@ -89,15 +94,27 @@ typedef NS_ENUM(NSInteger, AgoraRtcErrorCode) {
AgoraRtc_Error_Adm_Record_Abnormal_Frequency = 1021,
AgoraRtc_Error_Adm_Init_Loopback = 1022,
AgoraRtc_Error_Adm_Start_Loopback = 1023,
- AgoraRtc_Error_Vdm_Camera_Not_Authorized = 1501,
// 1025, as warning for interruption of adm on ios
// 1026, as warning for route change of adm on ios
+ // VDM error code starts from 1500
+ AgoraRtc_Error_Vdm_Camera_Not_Authorized = 1501,
+
+ // VCM error code starts from 1600
+ AgoraRtc_Error_Vcm_Unknown_Error = 1600,
+ AgoraRtc_Error_Vcm_Encoder_Init_Error = 1601,
+ AgoraRtc_Error_Vcm_Encoder_Encode_Error = 1602,
+ AgoraRtc_Error_Vcm_Encoder_Set_Error = 1603,
};
typedef NS_ENUM(NSInteger, AgoraRtcChannelProfile) {
- AgoraRtc_ChannelProfile_Free = 0,
- AgoraRtc_ChannelProfile_Broadcaster = 1,
- AgoraRtc_ChannelProfile_Audience = 2,
+ AgoraRtc_ChannelProfile_Communication = 0,
+ AgoraRtc_ChannelProfile_LiveBroadcasting = 1,
+ AgoraRtc_ChannelProfile_Game = 2,
+};
+
+typedef NS_ENUM(NSInteger, AgoraRtcClientRole) {
+ AgoraRtc_ClientRole_Broadcaster = 1,
+ AgoraRtc_ClientRole_Audience = 2,
};
typedef NS_ENUM(NSInteger, AgoraRtcVideoProfile) {
@@ -123,6 +140,9 @@ typedef NS_ENUM(NSInteger, AgoraRtcVideoProfile) {
AgoraRtc_VideoProfile_360P_6 = 35, // 360x360 30 400
AgoraRtc_VideoProfile_360P_7 = 36, // 480x360 15 320
AgoraRtc_VideoProfile_360P_8 = 37, // 480x360 30 490
+ AgoraRtc_VideoProfile_360P_9 = 38, // 640x360 15 800
+ AgoraRtc_VideoProfile_360P_10 = 39, // 640x360 24 800
+ AgoraRtc_VideoProfile_360P_11 = 100, // 640x360 24 1000
AgoraRtc_VideoProfile_480P = 40, // 640x480 15 500
#if TARGET_OS_IPHONE
AgoraRtc_VideoProfile_480P_3 = 42, // 480x480 15 400
@@ -131,6 +151,7 @@ typedef NS_ENUM(NSInteger, AgoraRtcVideoProfile) {
AgoraRtc_VideoProfile_480P_6 = 45, // 480x480 30 600
AgoraRtc_VideoProfile_480P_8 = 47, // 848x480 15 610
AgoraRtc_VideoProfile_480P_9 = 48, // 848x480 30 930
+ AgoraRtc_VideoProfile_480P_10 = 49, // 640x480 10 400
AgoraRtc_VideoProfile_720P = 50, // 1280x720 15 1130
AgoraRtc_VideoProfile_720P_3 = 52, // 1280x720 30 1710
AgoraRtc_VideoProfile_720P_5 = 54, // 960x720 15 910
@@ -158,17 +179,44 @@ typedef NS_ENUM(NSUInteger, AgoraRtcQuality) {
typedef NS_ENUM(NSUInteger, AgoraRtcUserOfflineReason) {
AgoraRtc_UserOffline_Quit = 0,
AgoraRtc_UserOffline_Dropped = 1,
+ AgoraRtc_UserOffline_BecomeAudience = 2,
+};
+
+typedef NS_ENUM(NSInteger, AgoraRtcVideoStreamType) {
+ AgoraRtc_VideoStream_High = 0,
+ AgoraRtc_VideoStream_Low = 1,
+};
+
+typedef NS_ENUM(NSInteger, AgoraRtcAudioOutputRouting)
+{
+ AgoraRtc_AudioOutputRouting_Default = -1,
+ AgoraRtc_AudioOutputRouting_Headset = 0,
+ AgoraRtc_AudioOutputRouting_Earpiece = 1,
+ AgoraRtc_AudioOutputRouting_HeadsetNoMic = 2,
+ AgoraRtc_AudioOutputRouting_Speakerphone = 3,
+ AgoraRtc_AudioOutputRouting_Loudspeaker = 4,
+ AgoraRtc_AudioOutputRouting_HeadsetBluetooth = 5
+};
+
+typedef NS_ENUM(NSInteger, AgoraRtcAudioRecordingQuality) {
+ AgoraRtc_AudioRecordingQuality_Low = 0,
+ AgoraRtc_AudioRecordingQuality_Medium = 1,
+ AgoraRtc_AudioRecordingQuality_High = 2
};
typedef NS_ENUM(NSUInteger, AgoraRtcLogFilter) {
- AgoraRtc_LogFilter_Console = 0x08000,
- AgoraRtc_LogFilter_Debug = 0x0800,
- AgoraRtc_LogFilter_Info = 0x0001,
- AgoraRtc_LogFilter_Warn = 0x0002,
- AgoraRtc_LogFilter_Error = 0x0004,
+ AgoraRtc_LogFilter_Off = 0,
+ AgoraRtc_LogFilter_Debug = 0x080f,
+ AgoraRtc_LogFilter_Info = 0x000f,
+ AgoraRtc_LogFilter_Warn = 0x000e,
+ AgoraRtc_LogFilter_Error = 0x000c,
AgoraRtc_LogFilter_Critical = 0x0008,
};
+typedef NS_ENUM(NSInteger, AgoraRtmpStreamLifeCycle) {
+ RtmpStream_LifeCycle_Bind2Channel = 1,
+ RtmpStream_LifeCycle_Bind2Ownner = 2,
+};
typedef NS_ENUM(NSUInteger, AgoraRtcRenderMode) {
/**
@@ -192,6 +240,11 @@ typedef NS_ENUM(NSUInteger, AgoraRtcQualityReportFormat) {
AgoraRtc_QualityReportFormat_Html = 1,
};
+typedef NS_ENUM(NSInteger, AgoraRtcRawAudioFrameOpMode) {
+ AgoraRtc_RawAudioFrame_OpMode_ReadOnly = 0,
+ AgoraRtc_RawAudioFrame_OpMode_WriteOnly = 1,
+ AgoraRtc_RawAudioFrame_OpMode_ReadWrite = 2,
+};
#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
@@ -226,12 +279,55 @@ __attribute__((visibility("default"))) @interface AgoraRtcVideoCanvas : NSObject
@property (assign, nonatomic) NSUInteger uid; // the user id of view
@end
+/**
+ * For AgoraVideoFrame: color format field
+ */
+typedef NS_ENUM(NSUInteger, AgoraVideoFormat) {
+ AgoraRtc_FrameFormat_texture = 12,
+ AgoraRtc_FrameFormat_I420 = 1,
+ AgoraRtc_FrameFormat_RGBA = 4,
+ AgoraRtc_FrameFormat_IMC2 = 5,
+};
+
+__attribute__((visibility("default"))) @interface AgoraVideoFrame : NSObject
+@property (assign, nonatomic) NSInteger format; /* 10: android texture (GL_TEXTURE_2D)
+ 11: android texture (OES, typically from camera)
+ 12: ios texture (CVPixelBufferRef)
+ 1: I420
+ 2: BGRA
+ 3: NV21
+ 4: RGBA
+ 5: IMC2
+ 6: BGRA (same as 2)
+ 7: ARGB
+ 8: NV12
+ */
+@property (assign, nonatomic) long long timeStamp; // time stamp for this frame. in milli-second
+@property (assign, nonatomic) int stride; // how many pixels between 2 consecutive rows. Note: in pixel, not byte.
+ // in case of ios texture, it is not used
+@property (assign, nonatomic) int height; // how many rows of pixels, in case of ios texture, it is not used
+
+@property (assign, nonatomic) CVPixelBufferRef textureBuf;
+
+@property (strong, nonatomic) NSData *dataBuf; // raw data buffer. in case of ios texture, it is not used
+@property (assign, nonatomic) int cropLeft; // how many pixels to crop on the left boundary
+@property (assign, nonatomic) int cropTop; // how many pixels to crop on the top boundary
+@property (assign, nonatomic) int cropRight; // how many pixels to crop on the right boundary
+@property (assign, nonatomic) int cropBottom; // how many pixels to crop on the bottom boundary
+@property (assign, nonatomic) int rotation; // 0, 90, 180, 270. See document for rotation calculation
+@end
__attribute__((visibility("default"))) @interface AgoraRtcStats : NSObject
@property (assign, nonatomic) NSUInteger duration;
@property (assign, nonatomic) NSUInteger txBytes;
@property (assign, nonatomic) NSUInteger rxBytes;
-@property(assign, nonatomic) NSUInteger users;
+@property (assign, nonatomic) NSUInteger txAudioKBitrate;
+@property (assign, nonatomic) NSUInteger rxAudioKBitrate;
+@property (assign, nonatomic) NSUInteger txVideoKBitrate;
+@property (assign, nonatomic) NSUInteger rxVideoKBitrate;
+@property (assign, nonatomic) NSUInteger users;
+@property (assign, nonatomic) double cpuAppUsage;
+@property (assign, nonatomic) double cpuTotalUsage;
@end
__attribute__((visibility("default"))) @interface AgoraRtcLocalVideoStats : NSObject
@@ -246,6 +342,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcRemoteVideoStats : NSO
@property (assign, nonatomic) NSUInteger height;
@property (assign, nonatomic) NSUInteger receivedBitrate;
@property (assign, nonatomic) NSUInteger receivedFrameRate;
+@property (assign, nonatomic) AgoraRtcVideoStreamType rxStreamType;
@end
__attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSObject
@@ -253,6 +350,55 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
@property (assign, nonatomic) NSUInteger volume;
@end
+__attribute__((visibility("default"))) @interface AgoraRtcVideoCompositingRegion : NSObject
+@property (assign, nonatomic) NSUInteger uid;
+@property (assign, nonatomic) double x;
+@property (assign, nonatomic) double y;
+@property (assign, nonatomic) double width;
+@property (assign, nonatomic) double height;
+@property (assign, nonatomic) NSInteger zOrder; //optional, [0, 100] //0 (default): bottom most, 100: top most
+@property (assign, nonatomic) double alpha; //optional, [0, 1.0] where 0 denotes throughly transparent, 1.0 opaque
+@property (assign, nonatomic) AgoraRtcRenderMode renderMode;
+@end
+
+__attribute__((visibility("default"))) @interface AgoraRtcVideoCompositingLayout : NSObject
+@property (assign, nonatomic) NSInteger canvasWidth;
+@property (assign, nonatomic) NSInteger canvasHeight;
+@property (copy, nonatomic) NSString* backgroundColor;//e.g. "#c0c0c0"
+@property (retain, nonatomic) NSArray* regions; //array of AgoraRtcVideoCompositingRegion
+@property (copy, nonatomic) NSString* appData;//app defined data
+@end
+
+__attribute__((visibility("default"))) @interface AgoraPublisherConfiguration : NSObject
+@property (assign, nonatomic) BOOL owner;
+@property (assign, nonatomic) NSInteger width;
+@property (assign, nonatomic) NSInteger height;
+@property (assign, nonatomic) NSInteger framerate;
+@property (assign, nonatomic) NSInteger bitrate;
+@property (assign, nonatomic) NSInteger defaultLayout;
+@property (assign, nonatomic) AgoraRtmpStreamLifeCycle lifeCycle;
+@property (assign, nonatomic) NSInteger injectStreamWidth;
+@property (assign, nonatomic) NSInteger injectStreamHeight;
+@property (copy, nonatomic) NSString* injectStreamUrl;
+@property (copy, nonatomic) NSString* publishUrl;
+@property (copy, nonatomic) NSString* rawStreamUrl;
+@property (copy, nonatomic) NSString* extraInfo;
+-(BOOL) validate;
+-(NSString *) toJsonString;
+@end
+
+__attribute__((visibility("default"))) @interface AgoraPublisherConfigurationBuilder : NSObject
+- (AgoraPublisherConfigurationBuilder *) setOwner:(BOOL)isOwner;
+- (AgoraPublisherConfigurationBuilder *) setWidth:(NSInteger)width height:(NSInteger)height framerate:(NSInteger)framerate bitrate:(NSInteger)bitrate;
+- (AgoraPublisherConfigurationBuilder *) setDefaultLayout:(NSInteger)layoutStyle;
+- (AgoraPublisherConfigurationBuilder *) setLifeCycle:(AgoraRtmpStreamLifeCycle)lifecycle;
+- (AgoraPublisherConfigurationBuilder *) setPublisherUrl:(NSString*)url;
+- (AgoraPublisherConfigurationBuilder *) setRawStreamUrl:(NSString*)url;
+- (AgoraPublisherConfigurationBuilder *) setExtraInfo:(NSString *)info;
+- (AgoraPublisherConfigurationBuilder *) injectStream:(NSString *)url width:(NSInteger)width height:(NSInteger)height;
+- (AgoraPublisherConfiguration *) build;
+@end
+
@class AgoraRtcEngineKit;
@protocol AgoraRtcEngineDelegate
@optional
@@ -301,6 +447,16 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
*/
- (void)rtcEngine:(AgoraRtcEngineKit *)engine firstRemoteVideoDecodedOfUid:(NSUInteger)uid size:(CGSize)size elapsed:(NSInteger)elapsed;
+/**
+ * Event of video size changed for local or remote user
+ *
+ * @param engine The engine kit
+ * @param uid The user id
+ * @param size The new size of video
+ * @param rotation The new rotate of video
+ */
+- (void)rtcEngine:(AgoraRtcEngineKit *)engine videoSizeChangedOfUid:(NSUInteger)uid size:(CGSize)size rotation:(NSInteger)rotation;
+
/**
* Event of the first frame of remote user is rendering on the screen.
*
@@ -325,7 +481,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
*
* @param engine The engine kit
* @param uid The remote user id
- * @param reason Reason of user offline, quit or drop
+ * @param reason Reason of user offline, quit, drop or became audience
*/
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didOfflineOfUid:(NSUInteger)uid reason:(AgoraRtcUserOfflineReason)reason;
@@ -333,7 +489,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
* Event of remote user audio muted or unmuted
*
* @param engine The engine kit
- * @param muted Mute or unmute
+ * @param muted Muted or unmuted
* @param uid The remote user id
*/
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didAudioMuted:(BOOL)muted byUid:(NSUInteger)uid;
@@ -351,7 +507,16 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
* Event of remote user video muted or unmuted
*
* @param engine The engine kit
- * @param muted Muted or unmuted
+ * @param routing the current audio output routing
+ */
+- (void)rtcEngine:(AgoraRtcEngineKit *)engine didAudioRouteChanged:(AgoraRtcAudioOutputRouting)routing;
+
+
+/**
+ * Event of remote user video enabled or disabled
+ *
+ * @param engine The engine kit
+ * @param enabled Enabled or disabled
* @param uid The remote user id
*/
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didVideoEnabled:(BOOL)enabled byUid:(NSUInteger)uid;
@@ -360,24 +525,46 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
* The statistics of local video stream. Update every two seconds.
*
* @param engine The engine kit
- * @param sentBitrate The sent bit rate
- * @param sentFrameRate The sent video frame rate
+ * @param stats The statistics of local video, including sent bitrate, sent framerate
*/
-- (void)rtcEngine:(AgoraRtcEngineKit *)engine localVideoStatWithSentBitrate:(NSInteger)sentBitrate sentFrameRate:(NSInteger)sentFrameRate __deprecated;
- (void)rtcEngine:(AgoraRtcEngineKit *)engine localVideoStats:(AgoraRtcLocalVideoStats*)stats;
/**
* The statistics of remote video stream. Update every two seconds.
*
* @param engine The engine kit
- * @param uid The remote user id
- * @param delay The delay from remote user to local
- * @param receivedBitrate The received bit rate
- * @param receivedFrameRate The received frame rate
+ * @param stats The statistics of remote video, including user id, delay, resolution, received bitrate, received framerate, video stream type
*/
-- (void)rtcEngine:(AgoraRtcEngineKit *)engine remoteVideoStatOfUid:(NSUInteger)uid delay:(NSInteger)delay receivedBitrate:(NSInteger)receivedBitrate receivedFrameRate:(NSInteger)receivedFrameRate __deprecated;
- (void)rtcEngine:(AgoraRtcEngineKit *)engine remoteVideoStats:(AgoraRtcRemoteVideoStats*)stats;
+/**
+ * Event of load media engine success
+ *
+ * @param engine The engine kit
+ */
+- (void)rtcEngineMediaEngineDidLoaded:(AgoraRtcEngineKit *)engine;
+
+/**
+ * Event of media engine start call success
+ *
+ * @param engine The engine kit
+ */
+- (void)rtcEngineMediaEngineDidStartCall:(AgoraRtcEngineKit *)engine;
+
+/**
+ * Event of meida engine finish audio mixing.
+ *
+ * @param engine The engine kit
+ */
+- (void)rtcEngineMediaEngineDidAudioMixingFinish:(AgoraRtcEngineKit *)engine;
+
+/**
+ * Event of meida engine finish audio mixing.
+ *
+ * @param engine The engine kit
+ */
+- (void)rtcEngineMediaEngineDidAudioEffectFinish:(AgoraRtcEngineKit *)engine soundId:(NSInteger)soundId;
+
/**
* Event of camera opened
*
@@ -412,7 +599,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
* Event of the user joined the channel.
*
* @param engine The engine kit
- * @param channel The channnel name
+ * @param channel The channel name
* @param uid The remote user id
* @param elapsed The elapsed time (ms) from session beginning
*/
@@ -459,7 +646,9 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
* The network quality of local user.
*
* @param engine The engine kit
- * @param quality The network quality
+ * @param uid The id of user
+ * @param txQuality The sending network quality
+ * @param rxQuality The receiving network quality
*/
- (void)rtcEngine:(AgoraRtcEngineKit *)engine networkQuality:(NSUInteger)uid txQuality:(AgoraRtcQuality)txQuality rxQuality:(AgoraRtcQuality)rxQuality;
@@ -481,6 +670,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
* @param state state of device: 0: added; 1: removed
*/
- (void)rtcEngine:(AgoraRtcEngineKit *)engine device:(NSString*) deviceId type:(AgoraRtcDeviceType) deviceType stateChanged:(NSInteger) state;
+
#endif
/**
@@ -492,6 +682,12 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
*/
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didApiCallExecute:(NSString*)api error:(NSInteger)error;
+/**
+ * This callback returns the status code after executing the refreshRecordingServiceStatus method successfully.
+ *
+ * @param engine The engine kit
+ * @param status 0:Recording is stopped. 1:Recording is ongoing.
+ */
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didRefreshRecordingServiceStatus:(NSInteger)status;
/**
@@ -503,7 +699,54 @@ __attribute__((visibility("default"))) @interface AgoraRtcAudioVolumeInfo : NSOb
* @param data The user defined data
*/
- (void)rtcEngine:(AgoraRtcEngineKit *)engine receiveStreamMessageFromUid:(NSUInteger)uid streamId:(NSInteger)streamId data:(NSData*)data;
+
+/**
+ * the local user has not received the data stream from the other user within 5 seconds.
+ *
+ * @param engine The engine kit
+ * @param uid The remote user id
+ * @param streamId The stream id
+ * @param error The error code
+ * @param missed The number of lost messages
+ * @param cached The number of incoming cached messages when the data stream is interrupted
+ */
- (void)rtcEngine:(AgoraRtcEngineKit *)engine didOccurStreamMessageErrorFromUid:(NSUInteger)uid streamId:(NSInteger)streamId error:(NSInteger)error missed:(NSInteger)missed cached:(NSInteger)cached;
+
+
+/**
+ * when channel key is enabled, and specified channel key is invalid or expired, this function will be called.
+ * APP should generate a new channel key and call renewChannelKey() to refresh the key.
+ * NOTE: to be compatible with previous version, ERR_CHANNEL_KEY_EXPIRED and ERR_INVALID_CHANNEL_KEY are also reported via onError() callback.
+ * You should move renew of channel key logic into this callback.
+ * @param engine The engine kit
+ */
+- (void)rtcEngineRequestChannelKey:(AgoraRtcEngineKit *)engine;
+
+/**
+ * Event of the first audio frame is sent.
+ *
+ * @param engine The engine kit
+ * @param elapsed The elapsed time(ms) from the beginning of the session.
+ */
+- (void)rtcEngine:(AgoraRtcEngineKit *)engine firstLocalAudioFrame:(NSInteger)elapsed;
+
+/**
+ * Event of the first audio frame from remote user is received.
+ *
+ * @param engine The engine kit
+ * @param uid The remote user id
+ * @param elapsed The elapsed time(ms) from the beginning of the session.
+ */
+- (void)rtcEngine:(AgoraRtcEngineKit *)engine firstRemoteAudioFrameOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed;
+
+
+/**
+ * The sdk reports who is active speaker in the channel
+ *
+ * @param engine The engine kit
+ * @param speakerUid The speaker who is talking
+ */
+- (void)rtcEngine:(AgoraRtcEngineKit *)engine activeSpeaker:(NSUInteger)speakerUid;
@end
@@ -522,19 +765,23 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
* @return string, engine version
*/
+ (NSString *)getMediaEngineVersion;
+
+/**
+ * Get the native handler of sdk Engine
+ */
- (void*)getNativeHandle;
/**
* Initializes the AgoraRtcEngineKit object.
*
- * @param key The vendor key is issued to the application developers by Agora.
- * @param delegate
+ * @param appId The appId is issued to the application developers by Agora.
+ * @param delegate The AgoraRtcEngineDelegate
*
* @return an object of AgoraRtcEngineKit class
*/
+ (instancetype)sharedEngineWithAppId:(NSString*)appId
- delegate:(id)delegate;
+ delegate:(id)delegate;
/**
* deprecated
@@ -569,6 +816,15 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
- (void)mediaEngineEventBlock:(void(^)(NSInteger code))mediaEngineEventBlock __deprecated;
+/**
+ * Enable / Disable dispatching delegate to main queue. if disable, the app should dispatch UI operating to main queue by himself.
+ *
+ * @param enabled YES: dispatch delegate method to main queue. NO: not dispatch delegate methods to main queue
+ *
+ * @return 0 when executed successfully. return negative value if failed.
+ */
+- (int) enableMainQueueDispatch: (BOOL) enabled;
+
/** BEGIN OF COMMON METHODS */
/**
@@ -582,9 +838,9 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
* @param info Optional, this argument can be whatever the programmer likes personally.
* @param uid Optional, this argument is the unique ID for each member in one channel.
If not specified, or set to 0, the SDK automatically allocates an ID, and the id could be gotten in onJoinChannelSuccess.
- * @param joinSuccdessBlock
+ * @param joinSuccessBlock This callback indicates that the user has successfully joined the specified channel. Same as rtcEngine:didJoinChannel:withUid:elapsed:. If nil, the callback rtcEngine:didJoinChannel:withUid:elapsed: will works.
*
- * @return 0 when executed successfully, and return minus value when failed.
+ * @return 0 when executed successfully, and return negative value when failed.
*/
- (int)joinChannelByKey:(NSString *)channelKey
channelName:(NSString *)channelName
@@ -598,7 +854,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
It is synchronous, i.e., it only returns until the call ends and all resources are released.
* @param leaveChannelBlock indicate the statistics of this call, from joinChannel to leaveChannel, including duration, tx bytes and rx bytes in the call.
*
- * @return 0 if executed successfully, or return minus value if failed.
+ * @return 0 if executed successfully, or return negative value if failed.
*/
- (int)leaveChannel:(void(^)(AgoraRtcStats* stat))leaveChannelBlock;
@@ -608,14 +864,14 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
Recommandation: When the application is foreground, enable the network connection test; and when the application is switched to background, disable network test in order to reduce network traffic.
By default, the network test is disabled
*
- * @return 0 when executed successfully, and return minus value when failed.
+ * @return 0 when executed successfully, and return negative value when failed.
*/
- (int)enableLastmileTest;
/**
* Disables the network quality test.
*
- * @return 0 when executed successfully, and return minus value when failed.
+ * @return 0 when executed successfully, and return negative value when failed.
*/
- (int)disableLastmileTest;
@@ -623,7 +879,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
* Enables video mode. Switches from audio to video mode.
It could be called during a call and before entering a channel.
*
- * @return 0 when this method is called successfully, or minus value when this method failed.
+ * @return 0 when this method is called successfully, or negative value when this method failed.
*/
- (int)enableVideo;
@@ -631,28 +887,50 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
* Disable video mode. Switch from video to audio mode.
It could be called during a call and before entering a channel.
*
- * @return 0 when this method is called successfully, or minus value when this method failed.
+ * @return 0 when this method is called successfully, or negative value when this method failed.
*/
- (int)disableVideo;
+/**
+ * Enables local video.
+ *
+ * @param enabled YES to enabled local video capture and render (by default), NO to disable using local camera device.
+ * @return 0 when this method is called successfully, or negative value when this method failed.
+ */
+- (int)enableLocalVideo:(BOOL)enabled;
+
/**
* start local video preview, while not sending data to server
*
- * @return 0 when this method is called successfully, or minus value when this method failed.
+ * @return 0 when this method is called successfully, or negative value when this method failed.
*/
- (int)startPreview;
/**
* stop local video preview
*
- * @return 0 when this method is called successfully, or minus value when this method failed.
+ * @return 0 when this method is called successfully, or negative value when this method failed.
*/
- (int)stopPreview;
+/**
+ * Enables audio function, which is enabled by default.
+ *
+ * @return 0 when this method is called successfully, or negative value when this method failed.
+ */
+- (int)enableAudio;
+
+/**
+ * Disable audio function.
+ *
+ * @return 0 when this method is called successfully, or negative value when this method failed.
+ */
+- (int)disableAudio;
+
/**
* Specify sdk parameters
*
- * @param options, sdk options in json format.
+ * @param options sdk options in json format.
*/
- (int)setParameters:(NSString *)options;
@@ -698,9 +976,9 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
/**
* Enable / Disable speaker of device
*
- * @param mute YES: Switches to speakerphone. NO: Switches to headset.
+ * @param enableSpeaker YES: Switches to speakerphone. NO: Switches to headset.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setEnableSpeakerphone:(BOOL)enableSpeaker;
@@ -712,12 +990,22 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
- (BOOL)isSpeakerphoneEnabled;
+/**
+ * Set default audio route to Speakerphone
+ *
+ * @param defaultToSpeaker YES: default to speakerphone. NO: default to earpiece for voice chat, speaker for video chat.
+ *
+ * @return 0 when executed successfully. return negative value if failed.
+ */
+- (int)setDefaultAudioRouteToSpeakerphone:(BOOL)defaultToSpeaker;
+
+
/**
* Sets the speakerphone volume. The speaker volume could be adjust by MPMusicPlayerController and other iOS API easily.
*
* @param volume between 0 (lowest volume) to 255 (highest volume).
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setSpeakerphoneVolume:(NSUInteger)volume __deprecated;
@@ -730,7 +1018,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
>0 : The volume indication interval in milliseconds. Recommandation: >=200ms.
* @param smooth The smoothing factor. Recommended: 3.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)enableAudioVolumeIndication:(NSInteger)interval
smooth:(NSInteger)smooth;
@@ -740,16 +1028,18 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
* Start recording conversation to file specified by the file path.
*
* @param filePath file path to save recorded conversation.
+ * @param quality encode quality for the record file
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
-- (int)startAudioRecording:(NSString*)filePath;
+- (int)startAudioRecording:(NSString*)filePath
+ quality:(AgoraRtcAudioRecordingQuality)quality;
/**
* Stop conversation recording
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)stopAudioRecording;
@@ -758,41 +1048,32 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
replace:(BOOL) replace
cycle:(NSInteger) cycle;
- (int)stopAudioMixing;
+- (int)pauseAudioMixing;
+- (int)resumeAudioMixing;
+- (int)adjustAudioMixingVolume:(NSInteger) volume;
+- (int)getAudioMixingDuration;
+- (int)getAudioMixingCurrentPosition;
+- (int)setAudioMixingPosition:(NSInteger) pos;
-/**
- * Start screen capture
- *
- * @return 0 when executed successfully. return minus value if failed.
- */
-- (int)startScreenCapture:(NSUInteger)windowId;
-
-
-/**
- * Stop screen capture
- *
- * @return 0 when executed successfully. return minus value if failed.
- */
-- (int)stopScreenCapture;
-
-- (int)setScreenCaptureId:(NSUInteger)windowId;
+//- (int)setScreenCaptureId:(NSUInteger)windowId;
/**
* Launches an echo test to test if the audio devices (e.g., headset and speaker) and the network connection work properly. In the test, the user speaks first, and the recording will be played back in 10 seconds. If the user can hear what he said in 10 seconds, it indicates that the audio devices and network connection work properly.
Notes: Must call stopEchoTest to end the test, or won't start new test or join channel.
*
- * @param successBlock
+ * @param successBlock The callback indicates that the user has successfully joined the specified channel.
*
- * @return 0 when executed successfully. return minus value if failed. e.g. ERR_REFUSED (-5):Failed to launch the echo test, e.g., initialization failed.
+ * @return 0 when executed successfully. return negative value if failed. e.g. ERR_REFUSED (-5):Failed to launch the echo test, e.g., initialization failed.
*/
- (int)startEchoTest:(void(^)(NSString* channel, NSUInteger uid, NSInteger elapsed))successBlock;
/**
* Stop echo test.
*
- * @return 0 when executed successfully. return minus value if failed. e.g. ERR_REFUSED(-5):Failed to stop the echo test. It could be that the echo test is not running.
+ * @return 0 when executed successfully. return negative value if failed. e.g. ERR_REFUSED(-5):Failed to stop the echo test. It could be that the echo test is not running.
*/
- (int)stopEchoTest;
@@ -801,7 +1082,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param mute true: Mutes the local audio. false: Unmutes the local audio.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)muteLocalAudioStream:(BOOL)mute;
@@ -811,7 +1092,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param mute true: Mutes all remote received audio. false: Unmutes all remote received audio.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)muteAllRemoteAudioStreams:(BOOL)mute;
@@ -828,7 +1109,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param local the canvas is composed of view, renderMode and uid. How to initialize 'local'? please take a look at 'AgoraRtcVideoCanvas'
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setupLocalVideo:(AgoraRtcVideoCanvas*)local;
@@ -838,7 +1119,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param remote the canvas is composed of view, renderMode and uid. How to initialize 'remote'? please take a look at 'AgoraRtcVideoCanvas'
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setupRemoteVideo:(AgoraRtcVideoCanvas*)remote;
@@ -848,7 +1129,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param mode There are Hidden(1), Fit(2) and Adaptive(3) mode. Please take a look at definition of enum AgoraRtcRenderMode
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setLocalRenderMode:(AgoraRtcRenderMode) mode;
@@ -859,7 +1140,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
* @param uid The user id of remote view.
* @param mode There are Hidden(1), Fit(2) and Adaptive(3) mode. Please take a look at definition of enum AgoraRtcRenderMode
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setRemoteRenderMode: (NSUInteger)uid
mode:(AgoraRtcRenderMode) mode;
@@ -871,7 +1152,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
* @param uid1 The user ID of the user whose video is to be switched.
* @param uid2 The user ID of another user whose video is to be switched.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)switchView:(NSUInteger)uid1
andAnother:(NSUInteger)uid2 __deprecated;
@@ -880,7 +1161,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
/**
* Switches between front and back cameras.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)switchCamera;
@@ -889,9 +1170,10 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param profile enumeration definition about the video resolution, fps and max kbps
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
-- (int)setVideoProfile:(AgoraRtcVideoProfile)profile;
+- (int)setVideoProfile:(AgoraRtcVideoProfile)profile
+ swapWidthAndHeight:(BOOL)swapWidthAndHeight;
/**
@@ -899,7 +1181,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param mute YES: stop sending local video stream to the network, NO: start sending local video stream.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)muteLocalVideoStream:(BOOL)mute;
@@ -909,7 +1191,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param mute YES: stop playing, NO: start playing.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)muteAllRemoteVideoStreams:(BOOL)mute;
@@ -919,7 +1201,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
* @param uid The remote user id
* @param mute YES: discard the video stream from remote user, NO: start receiving remote video stream.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)muteRemoteVideoStream:(NSUInteger)uid
mute:(BOOL)mute;
@@ -931,7 +1213,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param filePath The full file path of the log file.
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setLogFile:(NSString*)filePath;
@@ -940,7 +1222,7 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param filter The log level
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setLogFilter:(NSUInteger)filter;
@@ -949,20 +1231,32 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*
* @param channelKey new channel key
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)renewChannelKey:(NSString*)channelKey;
/**
- * Set the role of user: such as broadcaster, audience and free(as broadcaster and audience at the same time)
+ * Set the channel profile: such as communication, live broadcasting
*
- * @param profile the role of user
+ * @param profile the channel profile
*
- * @return 0 when executed successfully. return minus value if failed.
+ * @return 0 when executed successfully. return negative value if failed.
*/
- (int)setChannelProfile:(AgoraRtcChannelProfile)profile;
+/**
+ * Set the role of user: such as broadcaster, audience
+ *
+ * @param role the role of client
+ * @param permissionKey the permission key of role change
+ *
+ * @return 0 when executed successfully. return negative value if failed.
+ */
+- (int)setClientRole:(AgoraRtcClientRole)role withKey: (NSString *)permissionKey;
+
+- (int)enableDualStreamMode:(BOOL)enabled;
+
/**
* Specify encryption mode of AES encryption algorithm.
* @param [in] encryptionMode
@@ -981,6 +1275,10 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
*/
- (int)setEncryptionSecret:(NSString*)secret;
+- (int) setRemoteVideoStream: (NSUInteger) uid
+ type: (AgoraRtcVideoStreamType) streamType;
+
+
- (int) startRecordingService:(NSString*)recordingKey;
- (int) stopRecordingService:(NSString*)recordingKey;
- (int) refreshRecordingServiceStatus;
@@ -991,9 +1289,67 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
- (int)sendStreamMessage:(NSInteger)streamId
data:(NSData*)data;
+- (int)setRecordingAudioFrameParametersWithSampleRate:(NSInteger)sampleRate
+ channel:(NSInteger)channel
+ mode:(AgoraRtcRawAudioFrameOpMode)mode
+ samplesPerCall:(NSInteger)samplesPerCall;
+- (int)setPlaybackAudioFrameParametersWithSampleRate:(NSInteger)sampleRate
+ channel:(NSInteger)channel
+ mode:(AgoraRtcRawAudioFrameOpMode)mode
+ samplesPerCall:(NSInteger)samplesPerCall;
+- (int)setMixedAudioFrameParametersWithSampleRate:(NSInteger)sampleRate
+ samplesPerCall:(NSInteger)samplesPerCall;
+
+/**
+ * adjust recording signal volume
+ *
+ * @param [in] volume range from 0 to 400
+ *
+ * @return return 0 if success or an error code
+ */
+- (int)adjustRecordingSignalVolume:(NSInteger)volume;
+
+/**
+ * adjust playback signal volume
+ *
+ * @param [in] volume range from 0 to 400
+ *
+ * @return return 0 if success or an error code
+ */
+- (int)adjustPlaybackSignalVolume:(NSInteger)volume;
+
+- (int)setHighQualityAudioParametersWithFullband:(BOOL)fullband
+ stereo:(BOOL)stereo
+ fullBitrate:(BOOL)fullBitrate;
+- (int)enableInEarMonitoring:(BOOL)enabled;
+
+- (int)enableWebSdkInteroperability:(BOOL)enabled;
+
+- (int)setVideoQualityParameters:(BOOL)preferFrameRateOverImageQuality;
+
+- (int)configPublisher:(AgoraPublisherConfiguration *)config;
+
+- (int)setVideoCompositingLayout:(AgoraRtcVideoCompositingLayout*)layout;
+
+- (int)clearVideoCompositingLayout;
#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
+/**
+ * Start screen capture
+ *
+ * @return 0 when executed successfully. return negative value if failed.
+ */
+- (int)startScreenCapture:(NSUInteger)windowId withCaptureFreq: (int) captureFreq AndRect :(CGRect)rect;
+
+/**
+ * Stop screen capture
+ *
+ * @return 0 when executed successfully. return negative value if failed.
+ */
+- (int)stopScreenCapture;
+
+- (void) monitorDeviceChange: (BOOL)enabled;
- (NSArray*) enumerateDevices:(AgoraRtcDeviceType)type; // return array of AgoraRtcDeviceInfo
- (NSString*) getDeviceId:(AgoraRtcDeviceType)type;
- (int) setDevice:(AgoraRtcDeviceType)type deviceId:(NSString *) deviceId;
@@ -1010,5 +1366,35 @@ __attribute__((visibility("default"))) @interface AgoraRtcEngineKit : NSObject
- (int) stopCaptureDeviceTest;
#endif
-
+//Audio Effects
+- (double) getEffectsVolume;
+- (int) setEffectsVolume:(double) volume;
+- (int) setVolumeOfEffect:(int) soundId
+ withVolume:(double) volume;
+- (int) playEffect:(int) soundId
+ filePath:(NSString*)filePath
+ loop:(BOOL)loop
+ pitch:(double) pitch
+ pan:(double) pan
+ gain:(double) gain;
+- (int) stopEffect:(int) soundId;
+- (int) stopAllEffects;
+- (int) preloadEffect:(int) soundId
+ filePath:(NSString*) filePath;
+- (int) unloadEffect:(int) soundId;
+- (int) pauseEffect:(int) soundId;
+- (int) pauseAllEffects;
+- (int) resumeEffect:(int) soundId;
+- (int) resumeAllEffects;
+
+/**
+ * External video source support
+ * For new application, uses this interface instead of the one in libvideoprp
+ */
+// query whether texture can be supported (always returns YES)
+//+ (BOOL) isTextureEncodeSupported;
+// If external video source is to use, call this API before enableVideo/startPreview
+- (void) setExternalVideoSource:(BOOL) enable useTexture:(BOOL)useTexture pushMode:(BOOL)pushMode;
+// Push a video frame to SDK
+- (BOOL) pushExternalVideoFrame:(AgoraVideoFrame *)frame;
@end
diff --git a/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/IAgoraMediaEngine.h b/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/IAgoraMediaEngine.h
old mode 100755
new mode 100644
index 32e30e8..e10b6a5
--- a/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/IAgoraMediaEngine.h
+++ b/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/IAgoraMediaEngine.h
@@ -15,154 +15,157 @@ namespace media
class IAudioFrameObserver
{
public:
- enum AUDIO_FRAME_TYPE {
- FRAME_TYPE_PCM16 = 0, //PCM 16bit little endian
- };
- struct AudioFrame {
- AUDIO_FRAME_TYPE type;
- int samples; //number of samples in this frame
- int bytesPerSample; //number of bytes per sample: 2 for PCM16
- int channels; //number of channels (data are interleaved if stereo)
- int samplesPerSec; //sampling rate
- void* buffer; //data buffer
- };
+ enum AUDIO_FRAME_TYPE {
+ FRAME_TYPE_PCM16 = 0, //PCM 16bit little endian
+ };
+ struct AudioFrame {
+ AUDIO_FRAME_TYPE type;
+ int samples; //number of samples in this frame
+ int bytesPerSample; //number of bytes per sample: 2 for PCM16
+ int channels; //number of channels (data are interleaved if stereo)
+ int samplesPerSec; //sampling rate
+ void* buffer; //data buffer
+ int64_t renderTimeMs;
+ };
public:
- virtual bool onRecordAudioFrame(AudioFrame& audioFrame) = 0;
- virtual bool onPlaybackAudioFrame(AudioFrame& audioFrame) = 0;
- virtual bool onPlaybackAudioFrameBeforeMixing(unsigned int uid, AudioFrame& audioFrame) = 0;
+ virtual bool onRecordAudioFrame(AudioFrame& audioFrame) = 0;
+ virtual bool onPlaybackAudioFrame(AudioFrame& audioFrame) = 0;
+ virtual bool onMixedAudioFrame(AudioFrame& audioFrame) = 0;
+ virtual bool onPlaybackAudioFrameBeforeMixing(unsigned int uid, AudioFrame& audioFrame) = 0;
};
class IVideoFrameObserver
{
public:
- enum VIDEO_FRAME_TYPE {
- FRAME_TYPE_YUV420 = 0, //YUV 420 format
- };
- struct VideoFrame {
- VIDEO_FRAME_TYPE type;
- int width; //width of video frame
- int height; //height of video frame
- int yStride; //stride of Y data buffer
- int uStride; //stride of U data buffer
- int vStride; //stride of V data buffer
- void* yBuffer; //Y data buffer
- void* uBuffer; //U data buffer
- void* vBuffer; //V data buffer
- int rotation; // rotation of this frame (0, 90, 180, 270)
- };
+ enum VIDEO_FRAME_TYPE {
+ FRAME_TYPE_YUV420 = 0, //YUV 420 format
+ };
+ struct VideoFrame {
+ VIDEO_FRAME_TYPE type;
+ int width; //width of video frame
+ int height; //height of video frame
+ int yStride; //stride of Y data buffer
+ int uStride; //stride of U data buffer
+ int vStride; //stride of V data buffer
+ void* yBuffer; //Y data buffer
+ void* uBuffer; //U data buffer
+ void* vBuffer; //V data buffer
+ int rotation; // rotation of this frame (0, 90, 180, 270)
+ int64_t renderTimeMs;
+ };
public:
- virtual bool onCaptureVideoFrame(VideoFrame& videoFrame) = 0;
- virtual bool onRenderVideoFrame(unsigned int uid, VideoFrame& videoFrame) = 0;
+ virtual bool onCaptureVideoFrame(VideoFrame& videoFrame) = 0;
+ virtual bool onRenderVideoFrame(unsigned int uid, VideoFrame& videoFrame) = 0;
};
class IVideoFrame
{
public:
- enum PLANE_TYPE {
- Y_PLANE = 0,
- U_PLANE = 1,
- V_PLANE = 2,
- NUM_OF_PLANES = 3
- };
- enum VIDEO_TYPE {
- VIDEO_TYPE_UNKNOWN = 0,
- VIDEO_TYPE_I420 = 1,
- VIDEO_TYPE_IYUV = 2,
- VIDEO_TYPE_RGB24 = 3,
- VIDEO_TYPE_ABGR = 4,
- VIDEO_TYPE_ARGB = 5,
- VIDEO_TYPE_ARGB4444 = 6,
- VIDEO_TYPE_RGB565 = 7,
- VIDEO_TYPE_ARGB1555 = 8,
- VIDEO_TYPE_YUY2 = 9,
- VIDEO_TYPE_YV12 = 10,
- VIDEO_TYPE_UYVY = 11,
- VIDEO_TYPE_MJPG = 12,
- VIDEO_TYPE_NV21 = 13,
- VIDEO_TYPE_NV12 = 14,
- VIDEO_TYPE_BGRA = 15,
- VIDEO_TYPE_RGBA = 16,
- };
- virtual void release() = 0;
- virtual const unsigned char* buffer(PLANE_TYPE type) const = 0;
-
- // Copy frame: If required size is bigger than allocated one, new buffers of
- // adequate size will be allocated.
- // Return value: 0 on success ,-1 on error.
- virtual int copyFrame(IVideoFrame** dest_frame) const = 0;
-
- // Convert frame
- // Input:
- // - src_frame : Reference to a source frame.
- // - dst_video_type : Type of output video.
- // - dst_sample_size : Required only for the parsing of MJPG.
- // - dst_frame : Pointer to a destination frame.
- // Return value: 0 if OK, < 0 otherwise.
- // It is assumed that source and destination have equal height.
- virtual int convertFrame(VIDEO_TYPE dst_video_type, int dst_sample_size, unsigned char* dst_frame) const = 0;
-
- // Get allocated size per plane.
- virtual int allocated_size(PLANE_TYPE type) const = 0;
-
- // Get allocated stride per plane.
- virtual int stride(PLANE_TYPE type) const = 0;
-
- // Get frame width.
- virtual int width() const = 0;
-
- // Get frame height.
- virtual int height() const = 0;
-
- // Get frame timestamp (90kHz).
- virtual unsigned int timestamp() const = 0;
-
- // Get render time in milliseconds.
- virtual int64_t render_time_ms() const = 0;
-
- // Return true if underlying plane buffers are of zero size, false if not.
- virtual bool IsZeroSize() const = 0;
+ enum PLANE_TYPE {
+ Y_PLANE = 0,
+ U_PLANE = 1,
+ V_PLANE = 2,
+ NUM_OF_PLANES = 3
+ };
+ enum VIDEO_TYPE {
+ VIDEO_TYPE_UNKNOWN = 0,
+ VIDEO_TYPE_I420 = 1,
+ VIDEO_TYPE_IYUV = 2,
+ VIDEO_TYPE_RGB24 = 3,
+ VIDEO_TYPE_ABGR = 4,
+ VIDEO_TYPE_ARGB = 5,
+ VIDEO_TYPE_ARGB4444 = 6,
+ VIDEO_TYPE_RGB565 = 7,
+ VIDEO_TYPE_ARGB1555 = 8,
+ VIDEO_TYPE_YUY2 = 9,
+ VIDEO_TYPE_YV12 = 10,
+ VIDEO_TYPE_UYVY = 11,
+ VIDEO_TYPE_MJPG = 12,
+ VIDEO_TYPE_NV21 = 13,
+ VIDEO_TYPE_NV12 = 14,
+ VIDEO_TYPE_BGRA = 15,
+ VIDEO_TYPE_RGBA = 16,
+ };
+ virtual void release() = 0;
+ virtual const unsigned char* buffer(PLANE_TYPE type) const = 0;
+
+ // Copy frame: If required size is bigger than allocated one, new buffers of
+ // adequate size will be allocated.
+ // Return value: 0 on success ,-1 on error.
+ virtual int copyFrame(IVideoFrame** dest_frame) const = 0;
+
+ // Convert frame
+ // Input:
+ // - src_frame : Reference to a source frame.
+ // - dst_video_type : Type of output video.
+ // - dst_sample_size : Required only for the parsing of MJPG.
+ // - dst_frame : Pointer to a destination frame.
+ // Return value: 0 if OK, < 0 otherwise.
+ // It is assumed that source and destination have equal height.
+ virtual int convertFrame(VIDEO_TYPE dst_video_type, int dst_sample_size, unsigned char* dst_frame) const = 0;
+
+ // Get allocated size per plane.
+ virtual int allocated_size(PLANE_TYPE type) const = 0;
+
+ // Get allocated stride per plane.
+ virtual int stride(PLANE_TYPE type) const = 0;
+
+ // Get frame width.
+ virtual int width() const = 0;
+
+ // Get frame height.
+ virtual int height() const = 0;
+
+ // Get frame timestamp (90kHz).
+ virtual unsigned int timestamp() const = 0;
+
+ // Get render time in milliseconds.
+ virtual int64_t render_time_ms() const = 0;
+
+ // Return true if underlying plane buffers are of zero size, false if not.
+ virtual bool IsZeroSize() const = 0;
};
class IExternalVideoRenderCallback
{
public:
- virtual void onViewSizeChanged(int width, int height) = 0;
- virtual void onViewDestroyed() = 0;
+ virtual void onViewSizeChanged(int width, int height) = 0;
+ virtual void onViewDestroyed() = 0;
};
struct ExternalVideoRenerContext
{
- IExternalVideoRenderCallback* renderCallback;
- void* view;
- int renderMode;
- int zOrder;
- float left;
- float top;
- float right;
- float bottom;
+ IExternalVideoRenderCallback* renderCallback;
+ void* view;
+ int renderMode;
+ int zOrder;
+ float left;
+ float top;
+ float right;
+ float bottom;
};
class IExternalVideoRender
{
public:
- virtual void release() = 0;
- virtual int initialize() = 0;
- virtual int deliverFrame(const IVideoFrame& videoFrame, int rotation, bool mirrored) = 0;
+ virtual void release() = 0;
+ virtual int initialize() = 0;
+ virtual int deliverFrame(const IVideoFrame& videoFrame, int rotation, bool mirrored) = 0;
};
class IExternalVideoRenderFactory
{
public:
- virtual IExternalVideoRender* createRenderInstance(const ExternalVideoRenerContext& context) = 0;
+ virtual IExternalVideoRender* createRenderInstance(const ExternalVideoRenerContext& context) = 0;
};
class IMediaEngine
{
public:
- virtual void release() = 0;
- virtual int registerAudioFrameObserver(IAudioFrameObserver* observer) = 0;
- virtual int registerVideoFrameObserver(IVideoFrameObserver* observer) = 0;
- virtual int registerVideoRenderFactory(IExternalVideoRenderFactory* factory) = 0;
+ virtual void release() = 0;
+ virtual int registerAudioFrameObserver(IAudioFrameObserver* observer) = 0;
+ virtual int registerVideoFrameObserver(IVideoFrameObserver* observer) = 0;
+ virtual int registerVideoRenderFactory(IExternalVideoRenderFactory* factory) = 0;
};
} //media
diff --git a/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/IAgoraRtcEngine.h b/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/IAgoraRtcEngine.h
index b4c8ea2..e493677 100755
--- a/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/IAgoraRtcEngine.h
+++ b/ios-rongcallkit/framework/AgoraRtcEngineKit.framework/Headers/IAgoraRtcEngine.h
@@ -24,6 +24,9 @@
#elif defined(__APPLE__)
#define AGORA_API __attribute__((visibility("default"))) extern "C"
#define AGORA_CALL
+#elif defined(__ANDROID__) || defined(__linux__)
+#define AGORA_API extern "C" __attribute__((visibility("default")))
+#define AGORA_CALL
#else
#define AGORA_API extern "C"
#define AGORA_CALL
@@ -69,10 +72,13 @@ class AutoPtr {
ptr_ = ptr;
}
template
- void queryInterface(C1& c, C2 iid) {
- pointer_type p;
- if (!c.queryInterface(iid, (void**)&p))
- reset(p);
+ bool queryInterface(C1* c, C2 iid) {
+ pointer_type p = NULL;
+ if (c && !c->queryInterface(iid, (void**)&p))
+ {
+ reset(p);
+ }
+ return p != NULL;;
}
private:
AutoPtr(const AutoPtr&);
@@ -99,24 +105,33 @@ enum INTERFACE_ID_TYPE
{
AGORA_IID_AUDIO_DEVICE_MANAGER = 1,
AGORA_IID_VIDEO_DEVICE_MANAGER = 2,
- AGORA_IID_RTC_ENGINE_PARAMETER = 3,
- AGORA_IID_MEDIA_ENGINE = 4,
+ AGORA_IID_RTC_ENGINE_PARAMETER = 3,
+ AGORA_IID_MEDIA_ENGINE = 4,
};
enum WARN_CODE_TYPE
{
- WARN_PENDING = 20,
+ WARN_INVALID_VIEW = 8,
+ WARN_INIT_VIDEO = 16,
+ WARN_PENDING = 20,
WARN_NO_AVAILABLE_CHANNEL = 103,
WARN_LOOKUP_CHANNEL_TIMEOUT = 104,
WARN_LOOKUP_CHANNEL_REJECTED = 105,
WARN_OPEN_CHANNEL_TIMEOUT = 106,
WARN_OPEN_CHANNEL_REJECTED = 107,
+
+ WARN_AUDIO_MIXING_OPEN_ERROR = 701,
WARN_ADM_RUNTIME_PLAYOUT_WARNING = 1014,
WARN_ADM_RUNTIME_RECORDING_WARNING = 1016,
WARN_ADM_RECORD_AUDIO_SILENCE = 1019,
WARN_ADM_PLAYOUT_MALFUNCTION = 1020,
WARN_ADM_RECORD_MALFUNCTION = 1021,
+ WARN_ADM_RECORD_AUDIO_LOWLEVEL = 1031,
WARN_APM_HOWLING = 1051,
+
+ // sdk: 100~1000
+ WARN_SWITCH_LIVE_VIDEO_TIMEOUT = 111,
+ WARN_SET_CLIENT_ROLE_TIMEOUT = 118,
};
enum ERROR_CODE_TYPE
@@ -130,7 +145,6 @@ enum ERROR_CODE_TYPE
ERR_REFUSED = 5,
ERR_BUFFER_TOO_SMALL = 6,
ERR_NOT_INITIALIZED = 7,
- ERR_INVALID_VIEW = 8,
ERR_NO_PERMISSION = 9,
ERR_TIMEDOUT = 10,
ERR_CANCELED = 11,
@@ -138,11 +152,11 @@ enum ERROR_CODE_TYPE
ERR_BIND_SOCKET = 13,
ERR_NET_DOWN = 14,
ERR_NET_NOBUFS = 15,
- ERR_INIT_VIDEO = 16,
ERR_JOIN_CHANNEL_REJECTED = 17,
ERR_LEAVE_CHANNEL_REJECTED = 18,
ERR_ALREADY_IN_USE = 19,
ERR_ABORTED = 20,
+ ERR_INIT_NET_ENGINE = 21,
ERR_INVALID_APP_ID = 101,
ERR_INVALID_CHANNEL_NAME = 102,
ERR_CHANNEL_KEY_EXPIRED = 109,
@@ -156,6 +170,7 @@ enum ERROR_CODE_TYPE
ERR_BITRATE_LIMIT = 115,
ERR_TOO_MANY_DATA_STREAMS = 116,
ERR_STREAM_MESSAGE_TIMEOUT = 117,
+ ERR_SET_CLIENT_ROLE_NOT_AUTHORIZED = 119,
//1001~2000
ERR_LOAD_MEDIA_ENGINE = 1001,
@@ -181,22 +196,28 @@ enum ERROR_CODE_TYPE
// VDM error code starts from 1500
ERR_VDM_CAMERA_NOT_AUTHORIZED = 1501,
+
+ // VCM error code starts from 1600
+ ERR_VCM_UNKNOWN_ERROR = 1600,
+ ERR_VCM_ENCODER_INIT_ERROR = 1601,
+ ERR_VCM_ENCODER_ENCODE_ERROR = 1602,
+ ERR_VCM_ENCODER_SET_ERROR = 1603,
};
enum LOG_FILTER_TYPE
{
- LOG_FILTER_CONSOLE = 0x8000,
- LOG_FILTER_DEBUG = 0x0800,
- LOG_FILTER_INFO = 0x0001,
- LOG_FILTER_WARN = 0x0002,
- LOG_FILTER_ERROR = 0x0004,
+ LOG_FILTER_OFF = 0,
+ LOG_FILTER_DEBUG = 0x080f,
+ LOG_FILTER_INFO = 0x000f,
+ LOG_FILTER_WARN = 0x000e,
+ LOG_FILTER_ERROR = 0x000c,
LOG_FILTER_CRITICAL = 0x0008,
- LOG_FILTER_MASK = 0x880f,
+ LOG_FILTER_MASK = 0x80f,
};
enum MAX_DEVICE_ID_LENGTH_TYPE
{
- MAX_DEVICE_ID_LENGTH = 128
+ MAX_DEVICE_ID_LENGTH = 512
};
enum QUALITY_REPORT_FORMAT_TYPE
@@ -210,7 +231,16 @@ enum MEDIA_ENGINE_EVENT_CODE_TYPE
MEDIA_ENGINE_RECORDING_ERROR = 0,
MEDIA_ENGINE_PLAYOUT_ERROR = 1,
MEDIA_ENGINE_RECORDING_WARNING = 2,
- MEDIA_ENGINE_PLAYOUT_WARNING = 3
+ MEDIA_ENGINE_PLAYOUT_WARNING = 3,
+ MEDIA_ENGINE_AUDIO_FILE_MIX_FINISH = 10,
+ // media engine role changed
+ MEDIA_ENGINE_ROLE_BROADCASTER_SOLO = 20,
+ MEDIA_ENGINE_ROLE_BROADCASTER_INTERACTIVE = 21,
+ MEDIA_ENGINE_ROLE_AUDIENCE = 22,
+ MEDIA_ENGINE_ROLE_COMM_PEER = 23,
+ MEDIA_ENGINE_ROLE_GAME_PEER = 24,
+ // iOS adm sample rate changed
+ MEDIA_ENGINE_AUDIO_ADM_REQUIRE_RESTART = 110
};
enum MEDIA_DEVICE_STATE_TYPE
@@ -230,6 +260,13 @@ enum MEDIA_DEVICE_TYPE
VIDEO_CAPTURE_DEVICE = 3,
};
+enum AUDIO_RECORDING_QUALITY_TYPE
+{
+ AUDIO_RECORDING_QUALITY_LOW = 0,
+ AUDIO_RECORDING_QUALITY_MEDIUM = 1,
+ AUDIO_RECORDING_QUALITY_HIGH = 2,
+};
+
enum QUALITY_TYPE
{
QUALITY_UNKNOWN = 0,
@@ -248,6 +285,13 @@ enum RENDER_MODE_TYPE
RENDER_MODE_ADAPTIVE = 3,
};
+enum VIDEO_MIRROR_MODE_TYPE
+{
+ VIDEO_MIRROR_MODE_AUTO = 0,//determined by SDK
+ VIDEO_MIRROR_MODE_ENABLED = 1,//enabled mirror
+ VIDEO_MIRROR_MODE_DISABLED = 2,//disable mirror
+};
+
enum VIDEO_PROFILE_TYPE
{ // res fps kbps
VIDEO_PROFILE_120P = 0, // 160x120 15 65
@@ -264,37 +308,61 @@ enum VIDEO_PROFILE_TYPE
VIDEO_PROFILE_360P_6 = 35, // 360x360 30 400
VIDEO_PROFILE_360P_7 = 36, // 480x360 15 320
VIDEO_PROFILE_360P_8 = 37, // 480x360 30 490
+ VIDEO_PROFILE_360P_9 = 38, // 640x360 15 800
+ VIDEO_PROFILE_360P_10 = 39, // 640x360 24 800
+ VIDEO_PROFILE_360P_11 = 100, // 640x360 24 1000
VIDEO_PROFILE_480P = 40, // 640x480 15 500
VIDEO_PROFILE_480P_3 = 42, // 480x480 15 400
VIDEO_PROFILE_480P_4 = 43, // 640x480 30 750
VIDEO_PROFILE_480P_6 = 45, // 480x480 30 600
VIDEO_PROFILE_480P_8 = 47, // 848x480 15 610
VIDEO_PROFILE_480P_9 = 48, // 848x480 30 930
+ VIDEO_PROFILE_480P_10 = 49, // 640x480 10 400
VIDEO_PROFILE_720P = 50, // 1280x720 15 1130
VIDEO_PROFILE_720P_3 = 52, // 1280x720 30 1710
- VIDEO_PROFILE_720P_5 = 54, // 960x720 15 910
- VIDEO_PROFILE_720P_6 = 55, // 960x720 30 1380
+ VIDEO_PROFILE_720P_5 = 54, // 960x720 15 910
+ VIDEO_PROFILE_720P_6 = 55, // 960x720 30 1380
VIDEO_PROFILE_1080P = 60, // 1920x1080 15 2080
- VIDEO_PROFILE_1080P_3 = 62, // 1920x1080 30 3150
- VIDEO_PROFILE_1080P_5 = 64, // 1920x1080 60 4780
- VIDEO_PROFILE_1440P = 66, // 2560x1440 30 4850
- VIDEO_PROFILE_1440P_2 = 67, // 2560x1440 60 7350
- VIDEO_PROFILE_4K = 70, // 3840x2160 30 8910
+ VIDEO_PROFILE_1080P_3 = 62, // 1920x1080 30 3150
+ VIDEO_PROFILE_1080P_5 = 64, // 1920x1080 60 4780
+ VIDEO_PROFILE_1440P = 66, // 2560x1440 30 4850
+ VIDEO_PROFILE_1440P_2 = 67, // 2560x1440 60 7350
+ VIDEO_PROFILE_4K = 70, // 3840x2160 30 8910
VIDEO_PROFILE_4K_3 = 72, // 3840x2160 60 13500
VIDEO_PROFILE_DEFAULT = VIDEO_PROFILE_360P,
};
enum CHANNEL_PROFILE_TYPE
{
- CHANNEL_PROFILE_FREE = 0,
- CHANNEL_PROFILE_BROADCASTER = 1,
- CHANNEL_PROFILE_AUDIENCE = 2,
+ CHANNEL_PROFILE_COMMUNICATION = 0,
+ CHANNEL_PROFILE_LIVE_BROADCASTING = 1,
+ CHANNEL_PROFILE_GAME = 2,
+};
+
+enum CLIENT_ROLE_TYPE
+{
+ CLIENT_ROLE_BROADCASTER = 1,
+ CLIENT_ROLE_AUDIENCE = 2,
};
enum USER_OFFLINE_REASON_TYPE
{
USER_OFFLINE_QUIT = 0,
USER_OFFLINE_DROPPED = 1,
+ USER_OFFLINE_BECOME_AUDIENCE = 2,
+};
+
+enum REMOTE_VIDEO_STREAM_TYPE
+{
+ REMOTE_VIDEO_STREAM_HIGH = 0,
+ REMOTE_VIDEO_STREAM_LOW = 1,
+};
+
+enum RAW_AUDIO_FRAME_OP_MODE_TYPE
+{
+ RAW_AUDIO_FRAME_OP_MODE_READ_ONLY = 0,
+ RAW_AUDIO_FRAME_OP_MODE_WRITE_ONLY = 1,
+ RAW_AUDIO_FRAME_OP_MODE_READ_WRITE = 2,
};
struct AudioVolumeInfo
@@ -310,6 +378,12 @@ struct RtcStats
unsigned int rxBytes;
unsigned short txKBitRate;
unsigned short rxKBitRate;
+
+ unsigned short rxAudioKBitRate;
+ unsigned short txAudioKBitRate;
+
+ unsigned short rxVideoKBitRate;
+ unsigned short txVideoKBitRate;
unsigned int users;
double cpuAppUsage;
double cpuTotalUsage;
@@ -329,8 +403,106 @@ struct RemoteVideoStats
int height;
int receivedBitrate;
int receivedFrameRate;
+ REMOTE_VIDEO_STREAM_TYPE rxStreamType;
+};
+
+struct VideoCompositingLayout
+{
+ struct Region {
+ uid_t uid;
+ double x;//[0,1]
+ double y;//[0,1]
+ double width;//[0,1]
+ double height;//[0,1]
+ int zOrder; //optional, [0, 100] //0 (default): bottom most, 100: top most
+
+ // Optional
+ // [0, 1.0] where 0 denotes throughly transparent, 1.0 opaque
+ double alpha;
+
+ RENDER_MODE_TYPE renderMode;//RENDER_MODE_HIDDEN: Crop, RENDER_MODE_FIT: Zoom to fit
+ Region()
+ :uid(0)
+ , x(0)
+ , y(0)
+ , width(0)
+ , height(0)
+ , zOrder(0)
+ , alpha(1.0)
+ , renderMode(RENDER_MODE_HIDDEN)
+ {}
+
+ };
+ int canvasWidth;
+ int canvasHeight;
+ const char* backgroundColor;//e.g. "#C0C0C0" in RGB
+ const Region* regions;
+ int regionCount;
+ const char* appData;
+ int appDataLength;
+ VideoCompositingLayout()
+ :canvasWidth(0)
+ ,canvasHeight(0)
+ ,backgroundColor(NULL)
+ ,regions(NULL)
+ , regionCount(0)
+ , appData(NULL)
+ , appDataLength(0)
+ {}
};
+typedef struct Rect {
+ int top;
+ int left;
+ int bottom;
+ int right;
+
+ Rect(): top(0), left(0), bottom(0), right(0) {}
+ Rect(int t, int l, int b, int r): top(t), left(l), bottom(b), right(r) {}
+} Rect;
+
+#if defined(_WIN32)
+
+enum RTMP_STREAM_LIFE_CYCLE_TYPE
+{
+ RTMP_STREAM_LIFE_CYCLE_BIND2CHANNEL = 1,
+ RTMP_STREAM_LIFE_CYCLE_BIND2OWNER = 2,
+};
+
+struct PublisherConfiguration {
+ int width;
+ int height;
+ int framerate;
+ int bitrate;
+ int defaultLayout;
+ int lifecycle;
+ bool owner;
+ int injectStreamWidth;
+ int injectStreamHeight;
+ const char* injectStreamUrl;
+ const char* publishUrl;
+ const char* rawStreamUrl;
+ const char* extraInfo;
+
+
+ PublisherConfiguration()
+ : width(640)
+ , height(360)
+ , framerate(15)
+ , bitrate(500)
+ , defaultLayout(1)
+ , lifecycle(RTMP_STREAM_LIFE_CYCLE_BIND2CHANNEL)
+ , owner(true)
+ , injectStreamWidth(0)
+ , injectStreamHeight(0)
+ , injectStreamUrl(NULL)
+ , publishUrl(NULL)
+ , rawStreamUrl(NULL)
+ , extraInfo(NULL)
+ {}
+
+};
+#endif
#if !defined(__ANDROID__)
struct VideoCanvas
{
@@ -367,7 +539,7 @@ class IPacketObserver
};
/**
* called by sdk before the audio packet is sent to other participants
- * @param [in,out] packet:
+ * @param [in,out] packet
* buffer *buffer points the data to be sent
* size of buffer data to be sent
* @return returns true to send out the packet, returns false to discard the packet
@@ -375,7 +547,7 @@ class IPacketObserver
virtual bool onSendAudioPacket(Packet& packet) = 0;
/**
* called by sdk before the video packet is sent to other participants
- * @param [in,out] packet:
+ * @param [in,out] packet
* buffer *buffer points the data to be sent
* size of buffer data to be sent
* @return returns true to send out the packet, returns false to discard the packet
@@ -412,7 +584,7 @@ class IRtcEngineEventHandler
* when join channel success, the function will be called
* @param [in] channel
* the channel name you have joined
- * @param [in] uid_t
+ * @param [in] uid
* the UID of you in this channel
* @param [in] elapsed
* the time elapsed in ms from the joinChannel been called to joining completed
@@ -427,7 +599,7 @@ class IRtcEngineEventHandler
* when join channel success, the function will be called
* @param [in] channel
* the channel name you have joined
- * @param [in] uid_t
+ * @param [in] uid
* the UID of you in this channel
* @param [in] elapsed
* the time elapsed in ms elapsed
@@ -467,7 +639,7 @@ class IRtcEngineEventHandler
* @param [in] uid
* the uid of the peer
* @param [in] quality
- * the quality of the user 0~5 the higher the better
+ * the quality of the user, see QUALITY_TYPE for value definition
* @param [in] delay
* the average time of the audio packages delayed
* @param [in] lost
@@ -497,12 +669,8 @@ class IRtcEngineEventHandler
/**
* when the audio volume information come, the function will be called
- * @param [in] speakers
- * the array of the speakers' audio volume information
- * @param [in] speakerNumber
- * the count of speakers in this array
- * @param [in] totalVolume
- * the total volume of all users
+ * @param [in] stats
+ * the statistics of the call
*/
virtual void onLeaveChannel(const RtcStats& stats) {
(void)stats;
@@ -510,7 +678,7 @@ class IRtcEngineEventHandler
/**
* when the information of the RTC engine stats come, the function will be called
- * @param [in] stat
+ * @param [in] stats
* the RTC engine stats
*/
virtual void onRtcStats(const RtcStats& stats) {
@@ -532,6 +700,18 @@ class IRtcEngineEventHandler
(void)deviceState;
}
+ /**
+ * When audio mixing file playback finished, this function will be called
+ */
+ virtual void onAudioMixingFinished() {
+ }
+
+ /**
+ * When audio effect playback finished, this function will be called
+ */
+ virtual void onAudioEffectFinished(int soundId) {
+ }
+
/**
* when the video device state changed(plugged or removed), the function will be called
* @param [in] deviceId
@@ -604,6 +784,24 @@ class IRtcEngineEventHandler
(void)elapsed;
}
+ /**
+ * when video size changed or rotation changed, the function will be called
+ * @param [in] uid
+ * the UID of the remote user or local user (0)
+ * @param [in] width
+ * the new width of the video
+ * @param [in] height
+ * the new height of the video
+ * @param [in] rotation
+ * the rotation of the video
+ */
+ virtual void onVideoSizeChanged(uid_t uid, int width, int height, int rotation) {
+ (void)uid;
+ (void)width;
+ (void)height;
+ (void)rotation;
+ }
+
/**
* when the first remote video frame displayed, the function will be called
* @param [in] uid
@@ -627,10 +825,6 @@ class IRtcEngineEventHandler
* @param [in] uid
* the UID of the remote user
* @param [in] elapsed
- * the time elapsed from the
- * @param [in] height
- * the height of the video frame
- * @param [in] elapsed
* the time elapsed from remote used called joinChannel to joining completed in ms
*/
virtual void onUserJoined(uid_t uid, int elapsed) {
@@ -743,7 +937,7 @@ class IRtcEngineEventHandler
* when stream message received, the function will be called
* @param [in] uid
* UID of the peer who sends the message
- * @param [in] stream ID
+ * @param [in] streamId
* APP can create multiple streams for sending messages of different purposes
* @param [in] data
* the message data
@@ -768,6 +962,46 @@ class IRtcEngineEventHandler
(void)missed;
(void)cached;
}
+
+ virtual void onMediaEngineLoadSuccess() {
+ }
+ virtual void onMediaEngineStartCallSuccess() {
+ }
+ /**
+ * when channel key is enabled, and specified channel key is invalid or expired, this function will be called.
+ * APP should generate a new channel key and call renewChannelKey() to refresh the key.
+ * NOTE: to be compatible with previous version, ERR_CHANNEL_KEY_EXPIRED and ERR_INVALID_CHANNEL_KEY are also reported via onError() callback.
+ * You should move renew of channel key logic into this callback.
+ */
+ virtual void onRequestChannelKey() {
+ }
+
+ /**
+ * when the first local audio frame generated, the function will be called
+ * @param [in] elapsed
+ * the time elapsed from remote user called joinChannel in ms
+ */
+ virtual void onFirstLocalAudioFrame(int elapsed) {
+ (void)elapsed;
+ }
+
+ /**
+ * when the first remote audio frame arrived, the function will be called
+ * @param [in] uid
+ * the UID of the remote user
+ * @param [in] elapsed
+ * the time elapsed from remote user called joinChannel in ms
+ */
+ virtual void onFirstRemoteAudioFrame(uid_t uid, int elapsed) {
+ (void)uid;
+ (void)elapsed;
+ }
+ /** @param [in] uid
+ * the speaker uid who is talking in the channel
+ */
+ virtual void onActiveSpeaker(uid_t uid) {
+ (void)uid;
+ }
};
/**
@@ -786,9 +1020,9 @@ class IVideoDeviceCollection
* get audio device information
* @param [in] index
* the index of the device in the device list
- * @param [in out] deviceName
+ * @param [in, out] deviceName
* the device name, UTF8 format
- * @param [in out] deviceId
+ * @param [in, out] deviceId
* the device ID, UTF8 format
* @return return 0 if success or an error code
*/
@@ -828,7 +1062,7 @@ class IVideoDeviceManager
/**
* get the current active video device
- * @param [in out] deviceId
+ * @param [in, out] deviceId
* the device id of the current active video device
* @return return 0 if success or an error code
*/
@@ -867,9 +1101,9 @@ class IAudioDeviceCollection
* get video device information
* @param [in] index
* the index of the device in the device list
- * @param [in out] deviceName
+ * @param [in, out] deviceName
* the device name, UTF8 format
- * @param [in out] deviceId
+ * @param [in, out] deviceId
* the device ID, UTF8 format
* @return return 0 if success or an error code
*/
@@ -914,7 +1148,7 @@ class IAudioDeviceManager
/**
* get the current active playback device
- * @param [in out] deviceId
+ * @param [in, out] deviceId
* the device id of the current active video device
* @return return 0 if success or an error code
*/
@@ -930,7 +1164,7 @@ class IAudioDeviceManager
/**
* get current playback device volume
- * @param [in out] *volume
+ * @param [in, out] volume
* the current playback device volume 0-255
* @return return 0 if success or an error code
*/
@@ -946,7 +1180,7 @@ class IAudioDeviceManager
/**
* get the current active recording device
- * @param [in out] deviceId
+ * @param [in, out] deviceId
* the device id of the current active recording audio device
* @return return 0 if success or an error code
*/
@@ -962,7 +1196,7 @@ class IAudioDeviceManager
/**
* get current recording device volume
- * @param [in out] *volume
+ * @param [in, out] volume
* the current recording device volume 0-255
* @return return 0 if success or an error code
*/
@@ -1006,6 +1240,10 @@ struct RtcEngineContext
{
IRtcEngineEventHandler* eventHandler;
const char* appId;
+ RtcEngineContext()
+ :eventHandler(NULL)
+ ,appId(NULL)
+ {}
};
@@ -1014,13 +1252,12 @@ class IRtcEngine
public:
/**
* release the engine resource
+ * @param [in] sync
+ * true: release the engine resources and return after all resources have been destroyed.
+ * APP should try not to call release(true) in the engine's callbacks, call it this way in a separate thread instead.
+ * false: notify engine to release its resources and returns without waiting for resources are really destroyed
*/
- virtual void release() = 0;
-
- /**
- * release the engine resource and return after all resources have been destroyed
- */
- virtual void sync_release() = 0;
+ virtual void release(bool sync=false) = 0;
/**
* initialize the engine
@@ -1034,7 +1271,7 @@ class IRtcEngine
* get the pointer of the device manager object.
* @param [in] iid
* the iid of the interface you want to get
- * @param [in out] inter
+ * @param [in, out] inter
* the pointer of the pointer you want to point to DeviceManager object
* @return return 0 if success or an error code
*/
@@ -1042,7 +1279,7 @@ class IRtcEngine
/**
* get the version information of the SDK
- * @param [in out] build
+ * @param [in, out] build
* the build number
* @return return the version number string in char format
*/
@@ -1050,7 +1287,7 @@ class IRtcEngine
/**
* get the version information of the SDK
- * @param [in out] build
+ * @param [in, out] code
* the build number
* @return return the version number string in char format
*/
@@ -1060,7 +1297,7 @@ class IRtcEngine
* join the channel, if the channel have not been created, it will been created automatically
* @param [in] channelKey
* the channel key, if you have initialized the engine with an available APP ID, it can be null here. If you enable channel key on the dashboard, specify channel key here
- * @param [in] channel name
+ * @param [in] channelName
* the channel name
* @param [in] info
* the additional information, it can be null here
@@ -1078,12 +1315,13 @@ class IRtcEngine
/**
* renew the channel key for the current channel
- * @param [in] channelKey
+ * @param [in] channelKey the renewed channel key, if old channel key expired.
* @return return 0 if success or an error code
*/
virtual int renewChannelKey(const char* channelKey) = 0;
virtual int setChannelProfile(CHANNEL_PROFILE_TYPE profile) = 0;
+ virtual int setClientRole(CLIENT_ROLE_TYPE role, const char* permissionKey) = 0;
/**
* start the echo testing, if every thing goes well you can hear your echo from the server
@@ -1110,13 +1348,13 @@ class IRtcEngine
virtual int disableLastmileTest() = 0;
/**
- * enable local and remote video showing
+ * enable video function
* @return return 0 if success or an error code
*/
virtual int enableVideo() = 0;
/**
- * disable local and remote video showing
+ * disable video function
* @return return 0 if success or an error code
*/
virtual int disableVideo() = 0;
@@ -1133,7 +1371,7 @@ class IRtcEngine
*/
virtual int stopPreview() = 0;
- virtual int setVideoProfile(VIDEO_PROFILE_TYPE profile) = 0;
+ virtual int setVideoProfile(VIDEO_PROFILE_TYPE profile, bool swapWidthAndHeight) = 0;
/**
* set the remote video canvas
* @param [in] canvas
@@ -1150,9 +1388,21 @@ class IRtcEngine
*/
virtual int setupLocalVideo(const VideoCanvas& canvas) = 0;
+ /**
+ * enable audio function, which is enabled by deault.
+ * @return return 0 if success or an error code
+ */
+ virtual int enableAudio() = 0;
+
+ /**
+ * disable audio function
+ * @return return 0 if success or an error code
+ */
+ virtual int disableAudio() = 0;
+
/**
* get self call id in the current channel
- * @param [in out] callId
+ * @param [in, out] callId
* the self call Id
* @return return 0 if success or an error code
*/
@@ -1188,6 +1438,13 @@ class IRtcEngine
virtual int createDataStream(int* streamId, bool reliable, bool ordered) = 0;
virtual int sendStreamMessage(int streamId, const char* data, size_t length) = 0;
+
+ virtual int setVideoCompositingLayout(const VideoCompositingLayout& sei) = 0;
+ virtual int clearVideoCompositingLayout() = 0;
+
+#if defined(_WIN32)
+ virtual int configPublisher(const PublisherConfiguration& config) = 0;
+#endif
};
@@ -1263,7 +1520,7 @@ class IRtcEngineParameter
* get bool value of the json
* @param [in] key
* the key name
- * @param [in out] value
+ * @param [in, out] value
* the value
* @return return 0 if success or an error code
*/
@@ -1273,7 +1530,7 @@ class IRtcEngineParameter
* get int value of the json
* @param [in] key
* the key name
- * @param [in out] value
+ * @param [in, out] value
* the value
* @return return 0 if success or an error code
*/
@@ -1283,7 +1540,7 @@ class IRtcEngineParameter
* get unsigned int value of the json
* @param [in] key
* the key name
- * @param [in out] value
+ * @param [in, out] value
* the value
* @return return 0 if success or an error code
*/
@@ -1293,7 +1550,7 @@ class IRtcEngineParameter
* get double value of the json
* @param [in] key
* the key name
- * @param [in out] value
+ * @param [in, out] value
* the value
* @return return 0 if success or an error code
*/
@@ -1303,7 +1560,7 @@ class IRtcEngineParameter
* get string value of the json
* @param [in] key
* the key name
- * @param [in out] value
+ * @param [in, out] value
* the value
* @return return 0 if success or an error code
*/
@@ -1313,7 +1570,7 @@ class IRtcEngineParameter
* get a child object value of the json
* @param [in] key
* the key name
- * @param [in out] value
+ * @param [in, out] value
* the value
* @return return 0 if success or an error code
*/
@@ -1323,7 +1580,7 @@ class IRtcEngineParameter
* get array value of the json
* @param [in] key
* the key name
- * @param [in out] value
+ * @param [in, out] value
* the value
* @return return 0 if success or an error code
*/
@@ -1353,7 +1610,7 @@ class IRtcEngineParameter
class AAudioDeviceManager : public agora::util::AutoPtr
{
public:
- AAudioDeviceManager(IRtcEngine& engine)
+ AAudioDeviceManager(IRtcEngine* engine)
{
queryInterface(engine, AGORA_IID_AUDIO_DEVICE_MANAGER);
}
@@ -1362,7 +1619,7 @@ class AAudioDeviceManager : public agora::util::AutoPtr
class AVideoDeviceManager : public agora::util::AutoPtr
{
public:
- AVideoDeviceManager(IRtcEngine& engine)
+ AVideoDeviceManager(IRtcEngine* engine)
{
queryInterface(engine, AGORA_IID_VIDEO_DEVICE_MANAGER);
}
@@ -1371,21 +1628,25 @@ class AVideoDeviceManager : public agora::util::AutoPtr
class AParameter : public agora::util::AutoPtr
{
public:
- AParameter(IRtcEngine& engine)
+ AParameter(IRtcEngine& engine) { initialize(&engine); }
+ AParameter(IRtcEngine* engine) { initialize(engine); }
+ AParameter(IRtcEngineParameter* p) :agora::util::AutoPtr(p) {}
+private:
+ bool initialize(IRtcEngine* engine)
{
- IRtcEngineParameter* p;
- if (!engine.queryInterface(AGORA_IID_RTC_ENGINE_PARAMETER, (void**)&p))
+ IRtcEngineParameter* p = NULL;
+ if (engine && !engine->queryInterface(AGORA_IID_RTC_ENGINE_PARAMETER, (void**)&p))
reset(p);
+ return p != NULL;
}
- AParameter(IRtcEngineParameter* p)
- :agora::util::AutoPtr(p)
- {}
};
class RtcEngineParameters
{
public:
RtcEngineParameters(IRtcEngine& engine)
+ :m_parameter(&engine){}
+ RtcEngineParameters(IRtcEngine* engine)
:m_parameter(engine){}
/**
@@ -1407,7 +1668,7 @@ class RtcEngineParameters
* @return return 0 if success or an error code
*/
int muteAllRemoteAudioStreams(bool mute) {
- return m_parameter->setBool("rtc.audio.mute_peers", mute);
+ return m_parameter ? m_parameter->setBool("rtc.audio.mute_peers", mute) : -ERR_NOT_INITIALIZED;
}
/**
@@ -1445,7 +1706,7 @@ class RtcEngineParameters
* @return return 0 if success or an error code
*/
int muteAllRemoteVideoStreams(bool mute) {
- return m_parameter->setBool("rtc.video.mute_peers", mute);
+ return m_parameter ? m_parameter->setBool("rtc.video.mute_peers", mute) : -ERR_NOT_INITIALIZED;
}
/**
@@ -1461,6 +1722,10 @@ class RtcEngineParameters
return setObject("rtc.video.mute_peer", "{\"uid\":%u,\"mute\":%s}", uid, mute ? "true" : "false");
}
+ int setRemoteVideoStreamType(uid_t uid, REMOTE_VIDEO_STREAM_TYPE streamType) {
+ return setObject("rtc.video.set_remote_video_stream", "{\"uid\":%u,\"stream\":%d}", uid, streamType);
+ }
+
/**
* set play sound volume
* @param [in] volume
@@ -1468,7 +1733,7 @@ class RtcEngineParameters
* @return return 0 if success or an error code
*/
int setPlaybackDeviceVolume(int volume) {// [0,255]
- return m_parameter->setInt("che.audio.output.volume", volume);
+ return m_parameter ? m_parameter->setInt("che.audio.output.volume", volume) : -ERR_NOT_INITIALIZED;
}
/**
@@ -1493,15 +1758,16 @@ class RtcEngineParameters
* the .wav file path you want to saved
* @return return 0 if success or an error code
*/
- int startAudioRecording(const char* filePath) {
+ int startAudioRecording(const char* filePath, AUDIO_RECORDING_QUALITY_TYPE quality) {
+ if (!m_parameter) return -ERR_NOT_INITIALIZED;
#if defined(_WIN32)
- util::AString path;
- if (!m_parameter->convertPath(filePath, path))
- filePath = path->c_str();
- else
- return -ERR_INVALID_ARGUMENT;
+ util::AString path;
+ if (!m_parameter->convertPath(filePath, path))
+ filePath = path->c_str();
+ else
+ return -ERR_INVALID_ARGUMENT;
#endif
- return m_parameter->setString("che.audio.start_recording", filePath);
+ return setObject("che.audio.start_recording", "{\"filePath\":\"%s\",\"quality\":%d}", filePath, quality);
}
/**
@@ -1509,7 +1775,7 @@ class RtcEngineParameters
* @return return 0 if success or an error code
*/
int stopAudioRecording() {
- return m_parameter->setBool("che.audio.stop_recording", true);
+ return m_parameter ? m_parameter->setBool("che.audio.stop_recording", true) : -ERR_NOT_INITIALIZED;
}
/**
@@ -1529,6 +1795,7 @@ class RtcEngineParameters
* @return return 0 if success or an error code
*/
int startAudioMixing(const char* filePath, bool loopback, bool replace, int cycle) {
+ if (!m_parameter) return -ERR_NOT_INITIALIZED;
#if defined(_WIN32)
util::AString path;
if (!m_parameter->convertPath(filePath, path))
@@ -1547,54 +1814,83 @@ class RtcEngineParameters
* @return return 0 if success or an error code
*/
int stopAudioMixing() {
- return m_parameter->setBool("che.audio.stop_file_as_playout", true);
+ return m_parameter ? m_parameter->setBool("che.audio.stop_file_as_playout", true) : -ERR_NOT_INITIALIZED;
}
-#if defined(__APPLE__)
- /**
- * start screen capture
- * @return return 0 if success or an error code
- */
- int startScreenCapture(unsigned int windowId) {
- return m_parameter->setUInt("che.video.start_screen_capture", windowId);
- }
+ int pauseAudioMixing() {
+ return m_parameter ? m_parameter->setBool("che.audio.pause_file_as_playout", true) : -ERR_NOT_INITIALIZED;
+ }
+ int resumeAudioMixing() {
+ return m_parameter ? m_parameter->setBool("che.audio.pause_file_as_playout", false) : -ERR_NOT_INITIALIZED;
+ }
+
+ int adjustAudioMixingVolume(int volume) {
+ return m_parameter ? m_parameter->setInt("che.audio.set_file_as_playout_volume", volume) : -ERR_NOT_INITIALIZED;
+ }
+ int getAudioMixingDuration() {
+ int duration = 0;
+ int r = m_parameter ? m_parameter->getInt("che.audio.get_mixing_file_length_ms", duration) : -ERR_NOT_INITIALIZED;
+ if (r == 0)
+ r = duration;
+ return r;
+ }
+ int getAudioMixingCurrentPosition() {
+ if (!m_parameter) return -ERR_NOT_INITIALIZED;
+ int pos = 0;
+ int r = m_parameter->getInt("che.audio.get_mixing_file_played_ms", pos);
+ if (r == 0)
+ r = pos;
+ return r;
+ }
+ int setAudioMixingPosition(int pos /*in ms*/) {
+ return m_parameter ? m_parameter->setInt("che.audio.mixing.file.position", pos) : -ERR_NOT_INITIALIZED;
+ }
+#if defined(__APPLE__)
/**
- * specify window id to capture
- * @return return 0 if success or an error code
+ * start screen/windows capture
+ *
+ * @param windowId screen capture, if windowId is 0; windows capture if windowsId isn't 0;
+ * @param rect valid when windowId is 0; whole screen if rect is NULL.
+ *
+ * @return return 0 if success or an error code
*/
- int setScreenCaptureWindow(unsigned int windowId) {
- return m_parameter->setUInt("che.video.set_screen_capture_window", windowId);
+ int startScreenCapture(unsigned int windowId, int captureFreq, const Rect *rect) {
+ if (!rect)
+ return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d}", windowId, captureFreq);
+ else
+ return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d,\"top\":%d,\"left\":%d,\"bottom\":%d,\"right\":%d}", windowId, captureFreq, rect->top, rect->left, rect->bottom, rect->right);
}
+
/**
* stop screen capture
* @return return 0 if success or an error code
*/
int stopScreenCapture() {
- return m_parameter->setBool("che.video.stop_screen_capture", true);
+ return m_parameter ? m_parameter->setBool("che.video.stop_screen_capture", true) : -ERR_NOT_INITIALIZED;
}
#elif defined(_WIN32)
/**
- * start screen capture
- * @return return 0 if success or an error code
- */
- int startScreenCapture(HWND windowId) {
- return m_parameter->setUInt("che.video.start_screen_capture", (unsigned int)windowId);
- }
-
- /**
- * specify window id to capture
- * @return return 0 if success or an error code
+ * start screen/windows capture
+ *
+ * @param windowId screen capture, if windowId is 0; windows capture if windowsId isn't 0;
+ * @param rect valid when windowId is 0; whole screen if rect is NULL.
+ *
+ * @return return 0 if success or an error code
*/
- int setScreenCaptureWindow(HWND windowId) {
- return m_parameter->setUInt("che.video.set_screen_capture_window", (unsigned int)windowId);
+ int startScreenCapture(HWND windowId, int captureFreq, const Rect *rect) {
+ if (!rect)
+ return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d}", (unsigned int)windowId, captureFreq);
+ else
+ return setObject("che.video.start_screen_capture", "{\"id\":%u,\"captureFreq\":%d,\"top\":%d,\"left\":%d,\"bottom\":%d,\"right\":%d}", (unsigned int)windowId, captureFreq, rect->top, rect->left, rect->bottom, rect->right);
}
+
/**
* stop screen capture
* @return return 0 if success or an error code
*/
int stopScreenCapture() {
- return m_parameter->setBool("che.video.stop_screen_capture", true);
+ return m_parameter ? m_parameter->setBool("che.video.stop_screen_capture", true) : -ERR_NOT_INITIALIZED;
}
#endif
@@ -1605,6 +1901,7 @@ class RtcEngineParameters
* @return return 0 if success or an error code
*/
int setLogFile(const char* filePath) {
+ if (!m_parameter) return -ERR_NOT_INITIALIZED;
#if defined(_WIN32)
util::AString path;
if (!m_parameter->convertPath(filePath, path))
@@ -1622,7 +1919,7 @@ class RtcEngineParameters
* @return return 0 if success or an error code
*/
int setLogFilter(unsigned int filter) {
- return m_parameter->setUInt("rtc.log_filter", filter&LOG_FILTER_MASK);
+ return m_parameter ? m_parameter->setUInt("rtc.log_filter", filter&LOG_FILTER_MASK) : -ERR_NOT_INITIALIZED;
}
/**
@@ -1645,18 +1942,74 @@ class RtcEngineParameters
return setObject("che.video.render_mode", "{\"uid\":%u,\"mode\":%d}", uid, renderMode);
}
+ int setLocalVideoMirrorMode(VIDEO_MIRROR_MODE_TYPE mirrorMode) {
+ if (!m_parameter) return -ERR_NOT_INITIALIZED;
+ const char *value;
+ switch (mirrorMode) {
+ case VIDEO_MIRROR_MODE_AUTO:
+ value = "default";
+ break;
+ case VIDEO_MIRROR_MODE_ENABLED:
+ value = "forceMirror";
+ break;
+ case VIDEO_MIRROR_MODE_DISABLED:
+ value = "disableMirror";
+ break;
+ default:
+ return -ERR_INVALID_ARGUMENT;
+ }
+ return m_parameter->setString("che.video.localViewMirrorSetting", value);
+ }
int startRecordingService(const char* recordingKey) {
- return m_parameter->setString("rtc.api.start_recording_service", recordingKey);
+ return m_parameter ? m_parameter->setString("rtc.api.start_recording_service", recordingKey) : -ERR_NOT_INITIALIZED;
}
int stopRecordingService(const char* recordingKey) {
- return m_parameter->setString("rtc.api.stop_recording_service", recordingKey);
+ return m_parameter ? m_parameter->setString("rtc.api.stop_recording_service", recordingKey) : -ERR_NOT_INITIALIZED;
}
int refreshRecordingServiceStatus() {
- return m_parameter->setBool("rtc.api.query_recording_service_status", true);
+ return m_parameter ? m_parameter->setBool("rtc.api.query_recording_service_status", true) : -ERR_NOT_INITIALIZED;
+ }
+
+ int enableDualStreamMode(bool enabled) {
+ return setParameters("{\"rtc.dual_stream_mode\":%s,\"che.video.enableLowBitRateStream\":%s}", enabled ? "true" : "false", enabled ? "true" : "false");
}
+ int setRecordingAudioFrameParameters(int sampleRate, int channel, RAW_AUDIO_FRAME_OP_MODE_TYPE mode, int samplesPerCall) {
+ return setObject("che.audio.set_capture_raw_audio_format", "{\"sampleRate\":%d,\"channelCnt\":%d,\"mode\":%d,\"samplesPerCall\":%d}", sampleRate, channel, mode, samplesPerCall);
+ }
+ int setPlaybackAudioFrameParameters(int sampleRate, int channel, RAW_AUDIO_FRAME_OP_MODE_TYPE mode, int samplesPerCall) {
+ return setObject("che.audio.set_render_raw_audio_format", "{\"sampleRate\":%d,\"channelCnt\":%d,\"mode\":%d,\"samplesPerCall\":%d}", sampleRate, channel, mode, samplesPerCall);
+ }
+ int setMixedAudioFrameParameters(int sampleRate, int samplesPerCall) {
+ return setObject("che.audio.set_mixed_raw_audio_format", "{\"sampleRate\":%d,\"samplesPerCall\":%d}", sampleRate, samplesPerCall);
+ }
+
+ int adjustRecordingSignalVolume(int volume) {//[0, 400]: e.g. 50~0.5x 100~1x 400~4x
+ if (volume < 0)
+ volume = 0;
+ else if (volume > 400)
+ volume = 400;
+ return m_parameter ? m_parameter->setInt("che.audio.record.signal.volume", volume) : -ERR_NOT_INITIALIZED;
+ }
+ int adjustPlaybackSignalVolume(int volume) {//[0, 400]
+ if (volume < 0)
+ volume = 0;
+ else if (volume > 400)
+ volume = 400;
+ return m_parameter ? m_parameter->setInt("che.audio.playout.signal.volume", volume) : -ERR_NOT_INITIALIZED;
+ }
+ int setHighQualityAudioParameters(bool fullband, bool stereo, bool fullBitrate) {
+ return setObject("che.audio.codec.hq", "{\"fullband\":%s,\"stereo\":%s,\"fullBitrate\":%s}", fullband ? "true" : "false", stereo ? "true" : "false", fullBitrate ? "true" : "false");
+ }
+ int enableWebSdkInteroperability(bool enabled) {//enable interoperability with zero-plugin web sdk
+ return setParameters("{\"rtc.video.web_h264_interop_enable\":%s,\"che.video.web_h264_interop_enable\":%s}", enabled ? "true" : "false", enabled ? "true" : "false");
+ }
+ //only for live broadcasting
+ int setVideoQualityParameters(bool preferFrameRateOverImageQuality) {
+ return setParameters("{\"rtc.video.prefer_frame_rate\":%s,\"che.video.prefer_frame_rate\":%s}", preferFrameRateOverImageQuality ? "true" : "false", preferFrameRateOverImageQuality ? "true" : "false");
+ }
protected:
AParameter& parameter() {
return m_parameter;
@@ -1667,7 +2020,7 @@ class RtcEngineParameters
va_start(args, format);
vsnprintf(buf, sizeof(buf)-1, format, args);
va_end(args);
- return m_parameter->setParameters(buf);
+ return m_parameter ? m_parameter->setParameters(buf) : -ERR_NOT_INITIALIZED;
}
int setObject(const char* key, const char* format, ...) {
char buf[512];
@@ -1675,19 +2028,19 @@ class RtcEngineParameters
va_start(args, format);
vsnprintf(buf, sizeof(buf)-1, format, args);
va_end(args);
- return m_parameter->setObject(key, buf);
+ return m_parameter ? m_parameter->setObject(key, buf) : -ERR_NOT_INITIALIZED;
}
int enableLocalVideoCapture(bool enabled) {
- return m_parameter->setBool("che.video.local.capture", enabled);
+ return m_parameter ? m_parameter->setBool("che.video.local.capture", enabled) : -ERR_NOT_INITIALIZED;
}
int enableLocalVideoRender(bool enabled) {
- return m_parameter->setBool("che.video.local.render", enabled);
+ return m_parameter ? m_parameter->setBool("che.video.local.render", enabled) : -ERR_NOT_INITIALIZED;
}
int enableLocalVideoSend(bool enabled) {
return muteLocalVideoStream(!enabled);
}
int stopAllRemoteVideo() {
- return m_parameter->setBool("che.video.peer.stop_render", true);
+ return m_parameter ? m_parameter->setBool("che.video.peer.stop_render", true) : -ERR_NOT_INITIALIZED;
}
private:
AParameter m_parameter;
@@ -1698,7 +2051,7 @@ class RtcEngineParameters
/**
* to get the version number of the SDK
-* @param [in out] build
+* @param [in, out] build
* the build number of Agora SDK
* @return returns the string of the version of the SDK
*/
diff --git a/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallClient.h b/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallClient.h
index 2156565..1f86095 100644
--- a/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallClient.h
+++ b/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallClient.h
@@ -117,6 +117,14 @@
*/
- (void)setVideoProfile:(RCVideoProfile)profile;
+/**
+ 设置本地视频属性,可用此接口设置本地视频分辨率,设置宽和高替换
+
+ @param profile profile
+ @param swapWidthAndHeight 是否交换宽和高 (默认不交换)
+ */
+- (void)setVideoProfile:(RCVideoProfile)profile swapWidthAndHeight:(BOOL)swapWidthAndHeight;
+
/*!
当前的通话会话实体
*/
diff --git a/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallCommonDefine.h b/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallCommonDefine.h
index 15338fa..559393b 100644
--- a/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallCommonDefine.h
+++ b/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallCommonDefine.h
@@ -9,6 +9,20 @@
#ifndef RCCallCommonDefine_h
#define RCCallCommonDefine_h
+/*!
+ 引擎类型
+ */
+typedef NS_ENUM(NSInteger, RCCallEngineType) {
+ RCCallEngineNone = 0,
+ /*!
+ 声网
+ */
+ RCCallEngineAgora = 1,
+ /*!
+ 融云
+ */
+ RCCallEngineRong = 2,
+};
/*!
媒体类型
*/
@@ -36,6 +50,27 @@ typedef NS_ENUM(NSUInteger, RCCallQuality) {
RCCall_Quality_Down = 6,
};
+/**
+ 视频显示模式
+ */
+typedef NS_ENUM(NSInteger, RCCallRenderModel) {
+
+ /*!
+ 默认: 如果视频尺寸与显示视窗尺寸不一致,则视频流会按照显示视窗的比例进行周边裁剪或图像拉伸后填满视窗。
+ */
+ RCCallRenderModelHidden = 1,
+
+ /*!
+ RenderFit: 如果视频尺寸与显示视窗尺寸不一致,在保持长宽比的前提下,将视频进行缩放后填满视窗。
+ */
+ RCCallRenderModelFit = 2,
+
+ /*!
+ RenderAdaptive: 如果自己和对方都是竖屏,或者如果自己和对方都是横屏,使用 RCCallRenderModelHidden;如果对方和自己一个竖屏一个横屏,则使用RCCallRenderModelFit。
+ */
+ RCCallRenderModelAdaptive = 3,
+};
+
#pragma mark - Call
/*!
@@ -153,6 +188,10 @@ typedef NS_ENUM(NSInteger, RCCallDisconnectReason) {
己方其他端已接听
*/
RCCallDisconnectReasonAcceptByOtherClient = 18,
+ /*!
+ 己方被加入黑名单
+ */
+ RCCallDisconnectReasonAddToBlackList = 19,
};
/*!
diff --git a/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallSession.h b/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallSession.h
index 0788072..3ab85e7 100644
--- a/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallSession.h
+++ b/ios-rongcallkit/framework/RongCallLib.framework/Headers/RCCallSession.h
@@ -135,6 +135,11 @@
*/
@property(nonatomic, strong, readonly) NSString *targetId;
+/*!
+ 是否是多方通话
+ */
+@property(nonatomic, assign, readonly, getter=isMultiCall) BOOL multiCall;
+
/*!
通话的扩展信息
*/
@@ -223,6 +228,15 @@
*/
- (void)setVideoView:(UIView *)view userId:(NSString *)userId;
+/**
+ 设置用户所在的视频View
+
+ @param view userId 用户ID(自己或他人)
+ @param userId 视频的View
+ @param renderMode 视频显示模式 (默认为RCCallRenderModelHidden)
+ */
+- (void)setVideoView:(UIView *)view userId:(NSString *)userId renderMode:(RCCallRenderModel)renderMode;
+
/*!
更换自己使用的媒体类型
diff --git a/ios-rongcallkit/framework/RongCallLib.framework/Info.plist b/ios-rongcallkit/framework/RongCallLib.framework/Info.plist
index 8834bf5..11fe1cb 100644
Binary files a/ios-rongcallkit/framework/RongCallLib.framework/Info.plist and b/ios-rongcallkit/framework/RongCallLib.framework/Info.plist differ
diff --git a/ios-rongcallkit/framework/RongCallLib.framework/RongCallLib b/ios-rongcallkit/framework/RongCallLib.framework/RongCallLib
index 37d64b1..f948731 100644
Binary files a/ios-rongcallkit/framework/RongCallLib.framework/RongCallLib and b/ios-rongcallkit/framework/RongCallLib.framework/RongCallLib differ
diff --git a/ios-rongcallkit/framework/RongCloud.bundle/chat_from_imagebg_normal@2x.png b/ios-rongcallkit/framework/RongCloud.bundle/chat_from_imagebg_normal@2x.png
deleted file mode 100644
index 8e139c0..0000000
Binary files a/ios-rongcallkit/framework/RongCloud.bundle/chat_from_imagebg_normal@2x.png and /dev/null differ
diff --git a/ios-rongcallkit/framework/RongCloud.bundle/chat_to_imagebg_normal@2x.png b/ios-rongcallkit/framework/RongCloud.bundle/chat_to_imagebg_normal@2x.png
deleted file mode 100644
index ed6f5ba..0000000
Binary files a/ios-rongcallkit/framework/RongCloud.bundle/chat_to_imagebg_normal@2x.png and /dev/null differ
diff --git a/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCChatSessionInputBarControl.h b/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCChatSessionInputBarControl.h
index a3c31a0..35ce80a 100644
--- a/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCChatSessionInputBarControl.h
+++ b/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCChatSessionInputBarControl.h
@@ -540,10 +540,21 @@ __deprecated_msg("已废弃,请勿使用。");
/*!
相册选择图片列表
+ @warning **已废弃,请勿使用。**
+ @param selectedImages 选中的图片
+ @param full 用户是否要求原图
+ */
+- (void)imageDidSelect:(NSArray *)selectedImages fullImageRequired:(BOOL)full
+__deprecated_msg("已废弃,请勿使用。");
+
+/*!
+ 相册选择图片列表,返回图片的 NSData(请不要同时实现 imageDidSelect:fullImageRequired:)
+
+ @warning **已废弃,请勿使用。**
@param selectedImages 选中的图片
@param full 用户是否要求原图
*/
-- (void)imageDidSelect:(NSArray *)selectedImages fullImageRequired:(BOOL)full;
+- (void)imageDataDidSelect:(NSArray *)selectedImages fullImageRequired:(BOOL)full;
/*!
选择文件列表
diff --git a/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCConversationListViewController.h b/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCConversationListViewController.h
index 9de7362..f2b3511 100644
--- a/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCConversationListViewController.h
+++ b/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCConversationListViewController.h
@@ -76,6 +76,7 @@
列表中会话数据模型的数据源
@discussion 数据源中存放的元素为会话Cell的数据模型,即RCConversationModel对象。
+ @warning 非线程安全,请在主线程操作此属性
*/
@property(nonatomic, strong) NSMutableArray *conversationListDataSource;
diff --git a/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCConversationViewController.h b/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCConversationViewController.h
index c504577..557a744 100644
--- a/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCConversationViewController.h
+++ b/ios-rongcallkit/framework/RongIMKit.framework/Headers/RCConversationViewController.h
@@ -86,6 +86,7 @@ typedef NS_ENUM(NSUInteger, RCCustomerServiceStatus) {
聊天内容的消息Cell数据模型的数据源
@discussion 数据源中存放的元素为消息Cell的数据模型,即RCMessageModel对象。
+ @warning 非线程安全,请在主线程操作该属性
*/
@property(nonatomic, strong) NSMutableArray *conversationDataRepository;
diff --git a/ios-rongcallkit/framework/RongIMKit.framework/Info.plist b/ios-rongcallkit/framework/RongIMKit.framework/Info.plist
index a6f40c0..ea2d8a1 100644
Binary files a/ios-rongcallkit/framework/RongIMKit.framework/Info.plist and b/ios-rongcallkit/framework/RongIMKit.framework/Info.plist differ
diff --git a/ios-rongcallkit/framework/RongIMKit.framework/RongIMKit b/ios-rongcallkit/framework/RongIMKit.framework/RongIMKit
index 9e00cd2..950e2a8 100644
Binary files a/ios-rongcallkit/framework/RongIMKit.framework/RongIMKit and b/ios-rongcallkit/framework/RongIMKit.framework/RongIMKit differ
diff --git a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCCustomerServiceConfig.h b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCCustomerServiceConfig.h
index 1005206..c12933c 100644
--- a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCCustomerServiceConfig.h
+++ b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCCustomerServiceConfig.h
@@ -52,7 +52,6 @@
@property(nonatomic) int userTipTime;
@property(nonatomic, strong) NSString *userTipWord;
-
/*!
* 评价时机
*/
diff --git a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCIMClient.h b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCIMClient.h
index ff59f26..c3be82a 100644
--- a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCIMClient.h
+++ b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCIMClient.h
@@ -28,9 +28,9 @@
#import "RCUserInfo.h"
#import "RCWatchKitStatusDelegate.h"
#import "RCCustomerServiceGroupItem.h"
-#import "RCUserOnlineStatusInfo.h"
#import "RCSearchConversationResult.h"
#import "RCPushProfile.h"
+#import "RCUserOnlineStatusInfo.h"
#pragma mark - 消息接收监听器
@@ -1450,6 +1450,16 @@ FOUNDATION_EXPORT NSString *const RCLibDispatchReadReceiptNotification;
targetId:(NSString *)targetId
isTop:(BOOL)isTop;
+/*!
+ 获取置顶的会话列表
+
+ @param conversationTypeList 会话类型的数组(需要将RCConversationType转为NSNumber构建Array)
+ @return 置顶的会话RCConversation的列表
+
+ @discussion 此方法会从本地数据库中,读取置顶的会话列表。
+ */
+- (NSArray *)getTopConversationList:(NSArray *)conversationTypeList;
+
#pragma mark 会话中的草稿操作
/*!
获取会话中的草稿信息
@@ -1586,6 +1596,16 @@ getConversationNotificationStatus:(RCConversationType)conversationType
nStatus))successBlock
error:(void (^)(RCErrorCode status))errorBlock;
+/*!
+ 获取屏蔽消息提醒的会话列表
+
+ @param conversationTypeList 会话类型的数组(需要将RCConversationType转为NSNumber构建Array)
+ @return 屏蔽消息提醒的会话RCConversation的列表
+
+ @discussion 此方法会从本地数据库中,读取屏蔽消息提醒的会话列表。
+ */
+- (NSArray *)getBlockedConversationList:(NSArray *)conversationTypeList;
+
#pragma mark 全局消息提醒
/*!
@@ -2396,9 +2416,9 @@ startCustomerService:(NSString *)kefuId
- (void)getVendorToken:(void (^)(NSString *vendorToken))successBlock
error:(void (^)(RCErrorCode nErrorCode))errorBlock;
-
//远程推送相关设置
@property(nonatomic,strong,readonly)RCPushProfile *pushProfile;
+
@end
#endif
diff --git a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCImageMessage.h b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCImageMessage.h
index b9abad6..2885bf0 100644
--- a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCImageMessage.h
+++ b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCImageMessage.h
@@ -59,6 +59,11 @@
*/
@property(nonatomic, strong) UIImage *originalImage;
+/*!
+ 图片消息的原始图片信息
+ */
+@property(nonatomic, strong,readonly) NSData *originalImageData;
+
/*!
初始化图片消息
@@ -75,4 +80,12 @@
*/
+ (instancetype)messageWithImageURI:(NSString *)imageURI;
+/*!
+ 初始化图片消息
+
+ @param imageData 图片的原始数据
+ @return 图片消息对象
+ */
++ (instancetype)messageWithImageData:(NSData *)imageData;
+
@end
diff --git a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCStatusDefine.h b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCStatusDefine.h
index e7d630d..b21cd90 100644
--- a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCStatusDefine.h
+++ b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCStatusDefine.h
@@ -366,7 +366,17 @@ typedef NS_ENUM(NSInteger, RCErrorCode) {
/*!
操作不支持。
*/
- RC_OPERATION_NOT_SUPPORT = 20606
+ RC_OPERATION_NOT_SUPPORT = 20606,
+
+ /*!
+ 发送的消息中包含敏感词 (发送方发送失败,接收方不会收到消息)
+ */
+ RC_MSG_BLOCKED_SENSITIVE_WORD = 21501,
+
+ /*!
+ 消息中敏感词已经被替换 (接收方可以收到被替换之后的消息)
+ */
+ RC_MSG_REPLACED_SENSITIVE_WORD = 21502
};
#pragma mark - 连接状态
@@ -897,6 +907,11 @@ typedef NS_ENUM(NSUInteger, RCCSEvaEntryPoint) {
无评价入口
*/
RCCSEvaNone = 2,
+
+ /*!
+ 坐席结束会话评价
+ */
+ RCCSEvaCSEnd = 3,
};
/*!
diff --git a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCUploadMediaStatusListener.h b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCUploadMediaStatusListener.h
index a36f086..3684883 100644
--- a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCUploadMediaStatusListener.h
+++ b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RCUploadMediaStatusListener.h
@@ -29,9 +29,23 @@
@property(nonatomic, strong) void (^updateBlock)(int progress);
/*!
- 上传成功需要调用的block [remoteUrl:媒体文件的网络URL]
+ 上传成功需要调用的block。
+ content:上传成功之后,需要发送的消息内容。
+ 您可以使用currentMessage,把其中content属性对应的url字段设置成您上传成功的网络URL。
+ 请参考下面代码。
+
+ 升级说明:如果您之前使用了此接口,请参考下面代码把参数从 url 替换成 message。
+ if ([currentMessage.content isKindOfClass:[RCImageMessage class]]) {
+ RCImageMessage *content = (RCImageMessage *)currentMessage.content;
+ content.imageUrl = remoteUrl;
+ successBlock(content);
+ } else if ([currentMessage.content isKindOfClass:[RCFileMessage class]]) {
+ RCFileMessage *content = (RCFilemessage *)currentMessage.content;
+ content.fileUrl = remoteUrl;
+ successBlock(content);
+ }
*/
-@property(nonatomic, strong) void (^successBlock)(NSString *remoteUrl);
+@property(nonatomic, strong) void (^successBlock)(RCMessageContent *content);
/*!
上传成功需要调用的block [errorCode:上传失败的错误码,非0整数]
@@ -56,7 +70,7 @@
*/
- (instancetype)initWithMessage:(RCMessage *)message
uploadProgress:(void (^)(int progress))progressBlock
- uploadSuccess:(void (^)(NSString *remoteUrl))successBlock
+ uploadSuccess:(void (^)(RCMessageContent *content))successBlock
uploadError:(void (^)(RCErrorCode errorCode))errorBlock
uploadCancel:(void (^)())cancelBlock;
diff --git a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RongIMLib.h b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RongIMLib.h
index 132290d..6717477 100644
--- a/ios-rongcallkit/framework/RongIMLib.framework/Headers/RongIMLib.h
+++ b/ios-rongcallkit/framework/RongIMLib.framework/Headers/RongIMLib.h
@@ -80,3 +80,4 @@ FOUNDATION_EXPORT const unsigned char RongIMLibVersionString[];
#import
#import
#import
+
diff --git a/ios-rongcallkit/framework/RongIMLib.framework/Info.plist b/ios-rongcallkit/framework/RongIMLib.framework/Info.plist
index 05ac112..febed44 100644
Binary files a/ios-rongcallkit/framework/RongIMLib.framework/Info.plist and b/ios-rongcallkit/framework/RongIMLib.framework/Info.plist differ
diff --git a/ios-rongcallkit/framework/RongIMLib.framework/RongIMLib b/ios-rongcallkit/framework/RongIMLib.framework/RongIMLib
index 240d7cc..695e24b 100644
Binary files a/ios-rongcallkit/framework/RongIMLib.framework/RongIMLib and b/ios-rongcallkit/framework/RongIMLib.framework/RongIMLib differ
diff --git a/ios-rongcallkit/framework/RongRTCEngine.framework/Headers/RongRTCEngine.h b/ios-rongcallkit/framework/RongRTCEngine.framework/Headers/RongRTCEngine.h
new file mode 100644
index 0000000..2d5b868
--- /dev/null
+++ b/ios-rongcallkit/framework/RongRTCEngine.framework/Headers/RongRTCEngine.h
@@ -0,0 +1,840 @@
+//
+// RongRTCEngine.h
+// RongRTCEngine
+//
+// Created by Tao Li on 2016/11/17.
+// Copyright © 2016年 RongCloud. All rights reserved.
+//
+
+#import
+
+#if TARGET_OS_IPHONE
+#import
+typedef UIView VIEW_CLASS;
+
+#elif TARGET_OS_MAC
+#import
+typedef NSView VIEW_CLASS;
+
+#endif
+
+typedef NS_ENUM(NSInteger, RongRtcWarningCode) {
+ RongRtc_Warn_Pending = 20,
+ RongRtc_Warn_NoAvailableChannel = 103,
+ RongRtc_Warn_LookupChannelTimeout = 104,
+ RongRtc_Warn_LookupChannelRejected = 105,
+ RongRtc_Warn_OpenChannelTimeout = 106,
+ RongRtc_Warn_OpenChannelRejected = 107,
+ RongRtc_Warn_Adm_RuntimePlayoutWarning = 1014,
+ RongRtc_Warn_Adm_RuntimeRecordingWarning = 1016,
+ RongRtc_Warn_Adm_RecordAudioSilence = 1019,
+ RongRtc_Warn_Adm_PlaybackMalfunction = 1020,
+ RongRtc_Warn_Adm_RecordMalfunction = 1021,
+ RongRtc_Warn_Adm_Interruption = 1025,
+ RongRtc_Warn_Adm_RouteChange = 1026,
+ RongRtc_Warn_Apm_Howling = 1051,
+};
+
+
+typedef NS_ENUM(NSInteger, RongRtcErrorCode) {
+ RongRtc_Error_NoError = 0,
+ RongRtc_Error_Failed = 1,
+ RongRtc_Error_InvalidArgument = 2,
+ RongRtc_Error_NotReady = 3,
+ RongRtc_Error_NotSupported = 4,
+ RongRtc_Error_Refused = 5,
+ RongRtc_Error_BufferTooSmall = 6,
+ RongRtc_Error_NotInitialized = 7,
+ RongRtc_Error_InvalidView = 8,
+ RongRtc_Error_NoPermission = 9,
+ RongRtc_Error_TimedOut = 10,
+ RongRtc_Error_Canceled = 11,
+ RongRtc_Error_TooOften = 12,
+ RongRtc_Error_BindSocket = 13,
+ RongRtc_Error_NetDown = 14,
+ RongRtc_Error_NoBufs = 15,
+ RongRtc_Error_InitVideo = 16,
+ RongRtc_Error_JoinChannelRejected = 17,
+ RongRtc_Error_LeaveChannelRejected = 18,
+ RongRtc_Error_AlreadyInUse = 19,
+
+ RongRtc_Error_InvalidAppId = 101,
+ RongRtc_Error_InvalidChannelName = 102,
+ RongRtc_Error_ChannelKeyExpired = 109,
+ RongRtc_Error_InvalidChannelKey = 110,
+ RongRtc_Error_ConnectionInterrupted = 111, // only used in web sdk
+ RongRtc_Error_ConnectionLost = 112, // only used in web sdk
+ RongRtc_Error_NotInChannel = 113,
+ RongRtc_Error_SizeTooLarge = 114,
+ RongRtc_Error_BitrateLimit = 115,
+ RongRtc_Error_TooManyDataStreams = 116,
+ RongRtc_Error_DecryptionFailed = 120,
+
+ RongRtc_Error_LoadMediaEngine = 1001,
+ RongRtc_Error_StartCall = 1002,
+ RongRtc_Error_StartCamera = 1003,
+ RongRtc_Error_StartVideoRender = 1004,
+ RongRtc_Error_Adm_GeneralError = 1005,
+ RongRtc_Error_Adm_JavaResource = 1006,
+ RongRtc_Error_Adm_SampleRate = 1007,
+ RongRtc_Error_Adm_InitPlayout = 1008,
+ RongRtc_Error_Adm_StartPlayout = 1009,
+ RongRtc_Error_Adm_StopPlayout = 1010,
+ RongRtc_Error_Adm_InitRecording = 1011,
+ RongRtc_Error_Adm_StartRecording = 1012,
+ RongRtc_Error_Adm_StopRecording = 1013,
+ RongRtc_Error_Adm_RuntimePlayoutError = 1015,
+ RongRtc_Error_Adm_RuntimeRecordingError = 1017,
+ RongRtc_Error_Adm_RecordAudioFailed = 1018,
+ RongRtc_Error_Adm_Play_Abnormal_Frequency = 1020,
+ RongRtc_Error_Adm_Record_Abnormal_Frequency = 1021,
+ RongRtc_Error_Adm_Init_Loopback = 1022,
+ RongRtc_Error_Adm_Start_Loopback = 1023,
+ RongRtc_Error_Vdm_Camera_Not_Authorized = 1501,
+ // 1025, as warning for interruption of adm on ios
+ // 1026, as warning for route change of adm on ios
+};
+
+typedef NS_ENUM(NSInteger, RongRtcChannelProfile) {
+ RongRtc_ChannelProfile_Free = 0,
+ RongRtc_ChannelProfile_Broadcaster = 1,
+ RongRtc_ChannelProfile_Audience = 2,
+};
+
+typedef NS_ENUM(NSInteger, RongRtcVideoProfile) {
+ // res fps kbps
+ RongRtc_VideoProfile_Invalid = -1,
+ RongRtc_VideoProfile_120P = 0, // 160x120 15 65
+#if TARGET_OS_IPHONE
+ RongRtc_VideoProfile_120P_3 = 2, // 120x120 15 50
+ RongRtc_VideoProfile_180P = 10, // 320x180 15 140
+ RongRtc_VideoProfile_180P_3 = 12, // 180x180 15 100
+ RongRtc_VideoProfile_180P_4 = 13, // 240x180 15 120
+#endif
+ RongRtc_VideoProfile_240P = 20, // 320x240 15 200
+#if TARGET_OS_IPHONE
+ RongRtc_VideoProfile_240P_3 = 22, // 240x240 15 140
+ RongRtc_VideoProfile_240P_4 = 23, // 424x240 15 220
+#endif
+ RongRtc_VideoProfile_360P = 30, // 640x360 15 400
+#if TARGET_OS_IPHONE
+ RongRtc_VideoProfile_360P_3 = 32, // 360x360 15 260
+#endif
+ RongRtc_VideoProfile_360P_4 = 33, // 640x360 30 600
+ RongRtc_VideoProfile_360P_6 = 35, // 360x360 30 400
+ RongRtc_VideoProfile_360P_7 = 36, // 480x360 15 320
+ RongRtc_VideoProfile_360P_8 = 37, // 480x360 30 490
+ RongRtc_VideoProfile_480P = 40, // 640x480 15 500
+#if TARGET_OS_IPHONE
+ RongRtc_VideoProfile_480P_3 = 42, // 480x480 15 400
+#endif
+ RongRtc_VideoProfile_480P_4 = 43, // 640x480 30 750
+ RongRtc_VideoProfile_480P_6 = 45, // 480x480 30 600
+ RongRtc_VideoProfile_480P_8 = 47, // 848x480 15 610
+ RongRtc_VideoProfile_480P_9 = 48, // 848x480 30 930
+ RongRtc_VideoProfile_720P = 50, // 1280x720 15 1130
+ RongRtc_VideoProfile_720P_3 = 52, // 1280x720 30 1710
+ RongRtc_VideoProfile_720P_5 = 54, // 960x720 15 910
+ RongRtc_VideoProfile_720P_6 = 55, // 960x720 30 1380
+ RongRtc_VideoProfile_1080P = 60, // 1920x1080 15 2080
+ RongRtc_VideoProfile_1080P_3 = 62, // 1920x1080 30 3150
+ RongRtc_VideoProfile_1080P_5 = 64, // 1920x1080 60 4780
+ RongRtc_VideoProfile_1440P = 66, // 2560x1440 30 4850
+ RongRtc_VideoProfile_1440P_2 = 67, // 2560x1440 60 7350
+ RongRtc_VideoProfile_4K = 70, // 3840x2160 30 8190
+ RongRtc_VideoProfile_4K_3 = 72, // 3840x2160 60 13500
+ RongRtc_VideoProfile_DEFAULT = RongRtc_VideoProfile_360P,
+};
+
+typedef NS_ENUM(NSUInteger, RongRtcQuality) {
+ RongRtc_Quality_Unknown = 0,
+ RongRtc_Quality_Excellent = 1,
+ RongRtc_Quality_Good = 2,
+ RongRtc_Quality_Poor = 3,
+ RongRtc_Quality_Bad = 4,
+ RongRtc_Quality_VBad = 5,
+ RongRtc_Quality_Down = 6,
+};
+
+typedef NS_ENUM(NSUInteger, RongRtcUserOfflineReason) {
+ RongRtc_UserOffline_Quit = 0,
+ RongRtc_UserOffline_Dropped = 1,
+};
+
+typedef NS_ENUM(NSUInteger, RongRtcLogFilter) {
+ RongRtc_LogFilter_Console = 0x08000,
+ RongRtc_LogFilter_Debug = 0x0800,
+ RongRtc_LogFilter_Info = 0x0001,
+ RongRtc_LogFilter_Warn = 0x0002,
+ RongRtc_LogFilter_Error = 0x0004,
+ RongRtc_LogFilter_Critical = 0x0008,
+};
+
+
+typedef NS_ENUM(NSUInteger, RongRtcRenderMode) {
+ /**
+ Hidden(1): If the video size is different than that of the display window, crops the borders of the video (if the video is bigger) or stretch the video (if the video is smaller) to fit it in the window.
+ */
+ RongRtc_Render_Hidden = 1,
+
+ /**
+ RongRtc_Render_Fit(2): If the video size is different than that of the display window, resizes the video proportionally to fit the window.
+ */
+ RongRtc_Render_Fit = 2,
+
+ /**
+ RongRtc_Render_Adaptive(3):If both callers use the same screen orientation, i.e., both use vertical screens or both use horizontal screens, the RongRtc_Render_Hidden mode applies; if they use different screen orientations, i.e., one vertical and one horizontal, the RongRtc_Render_Fit mode applies.
+ */
+ RongRtc_Render_Adaptive = 3,
+};
+
+typedef NS_ENUM(NSUInteger, RongRtcQualityReportFormat) {
+ RongRtc_QualityReportFormat_Json = 0,
+ RongRtc_QualityReportFormat_Html = 1,
+};
+
+#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
+
+typedef NS_ENUM(NSInteger, RongRtcDeviceType) {
+ RongRtc_DeviceType_Audio_Unknown = -1,
+ RongRtc_DeviceType_Audio_Recording = 0,
+ RongRtc_DeviceType_Audio_Playout = 1,
+ RongRtc_DeviceType_Video_Render = 2,
+ RongRtc_DeviceType_Video_Capture = 3,
+};
+
+__attribute__((visibility("default"))) @interface RongRtcDeviceInfo : NSObject
+
+@property (assign, nonatomic) int index;
+@property (assign, nonatomic) RongRtcDeviceType type; // 0: recording, 1: playback, 2: capture
+@property (copy, nonatomic) NSString* deviceId; //
+@property (copy, nonatomic) NSString* deviceName; //
+@end
+
+#endif
+
+
+__attribute__((visibility("default"))) @interface RongRtcVideoCanvas : NSObject
+
+/**
+ * The video display view. The SDK does not maintain the lifecycle of the view.
+ The view can be safely released after calling leaveChannel with a returned value.
+ The SDK keeps a cache of the view value, so 'setupLocalVideo' to set the view value to NULL could be able to clear cache before switching or releasing view.
+ */
+@property (strong, nonatomic) VIEW_CLASS* view;
+@property (assign, nonatomic) RongRtcRenderMode renderMode; // the render mode of view: hidden, fit and adaptive
+@property (assign, nonatomic) NSString *userId; // the user id of view
+@end
+
+
+__attribute__((visibility("default"))) @interface RongRtcStats : NSObject
+@property (assign, nonatomic) NSUInteger duration;
+@property (assign, nonatomic) NSUInteger txBytes;
+@property (assign, nonatomic) NSUInteger rxBytes;
+@property(assign, nonatomic) NSUInteger users;
+@end
+
+__attribute__((visibility("default"))) @interface RongRtcLocalVideoStats : NSObject
+@property (assign, nonatomic) NSUInteger sentBitrate;
+@property (assign, nonatomic) NSUInteger sentFrameRate;
+@end
+
+__attribute__((visibility("default"))) @interface RongRtcRemoteVideoStats : NSObject
+@property (assign, nonatomic) NSString *userId;
+@property (assign, nonatomic) NSUInteger delay;
+@property (assign, nonatomic) NSUInteger width;
+@property (assign, nonatomic) NSUInteger height;
+@property (assign, nonatomic) NSUInteger receivedBitrate;
+@property (assign, nonatomic) NSUInteger receivedFrameRate;
+@end
+
+__attribute__((visibility("default"))) @interface RongRtcAudioVolumeInfo : NSObject
+@property (assign, nonatomic) NSString *userId;
+@property (assign, nonatomic) NSUInteger volume;
+@end
+
+
+
+
+
+
+@class RongRTCEngine;
+@protocol RongRTCEngineDelegate
+@optional
+
+/**
+ * The warning occurred in SDK. The APP could igonre the warning, and the SDK could try to resume automically.
+ *
+ * @param engine The engine kit
+ * @param warningCode The warning code
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didOccurWarning:(RongRtcWarningCode)warningCode;
+
+/**
+ * The error occurred in SDK. The SDK couldn't resume to normal state, and the app need to handle it.
+ *
+ * @param engine The engine kit
+ * @param errorCode The error code
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didOccurError:(RongRtcErrorCode)errorCode;
+
+/**
+ * The sdk reports the volume of a speaker. The interface is disable by default, and it could be enable by API "enableAudioVolumeIndication"
+ *
+ * @param engine The engine kit
+ * @param speakers RongRtcAudioVolumeInfos array
+ * @param totalVolume The total volume of speakers
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine reportAudioVolumeIndicationOfSpeakers:(NSArray*)speakers totalVolume:(NSInteger)totalVolume;
+
+/**
+ * Event of the first local frame starts rendering on the screen.
+ *
+ * @param engine The engine kit
+ * @param size The size of local video stream
+ * @param elapsed The elapsed time(ms) from the beginning of the session.
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine firstLocalVideoFrameWithSize:(CGSize)size elapsed:(NSInteger)elapsed;
+
+/**
+ * Event of the first frame of remote user is decoded successfully.
+ *
+ * @param engine The engine kit
+ * @param userId The remote user id
+ * @param size The size of video stream
+ * @param elapsed The elapsed time(ms) from the beginning of the session.
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine firstRemoteVideoDecodedOfUser:(NSString *)userId size:(CGSize)size elapsed:(NSInteger)elapsed;
+
+/**
+ * Event of the first frame of remote user is rendering on the screen.
+ *
+ * @param engine The engine kit
+ * @param userId The remote user id
+ * @param size The size of video stream
+ * @param elapsed The elapsed time(ms) from the beginning of the session.
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine firstRemoteVideoFrameOfUser:(NSString *)userId size:(CGSize)size elapsed:(NSInteger)elapsed;
+
+/**
+ * Event of remote user joined
+ *
+ * @param engine The engine kit
+ * @param userId The remote user id
+ * @param elapsed The elapsed time(ms) from the beginning of the session.
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didJoinedOfUser:(NSString *)userId elapsed:(NSInteger)elapsed;
+
+/**
+ * Event of remote user offlined
+ *
+ * @param engine The engine kit
+ * @param userId The remote user id
+ * @param reason Reason of user offline, quit or drop
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didOfflineOfUser:(NSString *)userId reason:(RongRtcUserOfflineReason)reason;
+
+/**
+ * Event of remote user audio muted or unmuted
+ *
+ * @param engine The engine kit
+ * @param muted Mute or unmute
+ * @param userId The remote user id
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didAudioMuted:(BOOL)muted byUser:(NSString *)userId;
+
+/**
+ * Event of remote user video muted or unmuted
+ *
+ * @param engine The engine kit
+ * @param muted Muted or unmuted
+ * @param userId The remote user id
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didVideoMuted:(BOOL)muted byUser:(NSString *)userId;
+
+/**
+ * Event of remote user video muted or unmuted
+ *
+ * @param engine The engine kit
+ * @param enabled enable or disable
+ * @param userId The remote user id
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didVideoEnabled:(BOOL)enabled byUser:(NSString *)userId;
+
+/**
+ * The statistics of remote video stream. Update every two seconds.
+ *
+ * @param engine The engine kit
+ * @param stats The stats
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine remoteVideoStats:(RongRtcRemoteVideoStats*)stats;
+
+/**
+ * Event of camera opened
+ *
+ * @param engine The engine kit
+ */
+- (void)rtcEngineCameraDidReady:(RongRTCEngine *)engine;
+
+/**
+ * Event of camera stopped
+ *
+ * @param engine The engine kit
+ */
+- (void)rtcEngineVideoDidStop:(RongRTCEngine *)engine;
+
+/**
+ * Event of disconnected with server. This event is reported at the moment SDK loses connection with server.
+ * In the mean time SDK automatically tries to reconnect with the server until APP calls leaveChannel.
+ *
+ * @param engine The engine kit
+ */
+- (void)rtcEngineConnectionDidInterrupted:(RongRTCEngine *)engine;
+
+/**
+ * Event of loss connection with server. This event is reported after the connection is interrupted and exceed the retry period (10 seconds by default).
+ * In the mean time SDK automatically tries to reconnect with the server until APP calls leaveChannel.
+ *
+ * @param engine The engine kit
+ */
+- (void)rtcEngineConnectionDidLost:(RongRTCEngine *)engine;
+
+/**
+ * Event of the user joined the channel.
+ *
+ * @param engine The engine kit
+ * @param channel The channnel name
+ * @param userId The remote user id
+ * @param elapsed The elapsed time (ms) from session beginning
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didJoinChannel:(NSString*)channel withUser:(NSString *)userId elapsed:(NSInteger) elapsed;
+
+/**
+ * Event of the user rejoined the channel
+ *
+ * @param engine The engine kit
+ * @param channel The channel name
+ * @param userId The user id
+ * @param elapsed The elapsed time (ms) from session beginning
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didRejoinChannel:(NSString*)channel withUser:(NSString *)userId elapsed:(NSInteger) elapsed;
+
+/**
+ * Statistics of rtc engine status. Updated every two seconds.
+ *
+ * @param engine The engine kit
+ * @param stats The statistics of rtc status, including duration, sent bytes and received bytes
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine reportRtcStats:(RongRtcStats*)stats;
+
+/**
+ * The statistics of the call when leave channel
+ *
+ * @param engine The engine kit
+ * @param stats The statistics of the call, including duration, sent bytes and received bytes
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didLeaveChannelWithStats:(RongRtcStats*)stats;
+
+/**
+ * The audio quality of the user. updated every two seconds.
+ *
+ * @param engine The engine kit
+ * @param userId The id of user
+ * @param quality The audio quality
+ * @param delay The delay from the remote user
+ * @param lost The percentage of lost packets
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine audioQualityOfUser:(NSString *)userId quality:(RongRtcQuality)quality delay:(NSUInteger)delay lost:(NSUInteger)lost;
+
+/**
+ * The network quality of local user.
+ *
+ * @param engine The engine kit
+ * @param txQuality The network quality
+ * @param rxQuality The network quality
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine networkQuality:(NSString *)userId txQuality:(RongRtcQuality)txQuality rxQuality:(RongRtcQuality)rxQuality;
+
+/**
+ * The network quality of lastmile test.
+ *
+ * @param engine The engine kit
+ * @param quality The network quality
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine lastmileQuality:(RongRtcQuality)quality;
+
+#if (!(TARGET_OS_IPHONE) && (TARGET_OS_MAC))
+/**
+ * the notificaitoin of device added removed
+ *
+ * @param engine The engine kit
+ * @param deviceId the identification of device
+ * @param deviceType type of device: -1: audio unknown; 0: audio recording ; 1: audio playout ; 2: render; 4: capture
+ * @param state state of device: 0: added; 1: removed
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine device:(NSString*) deviceId type:(RongRtcDeviceType) deviceType stateChanged:(NSInteger) state;
+#endif
+
+/**
+ * Event of API call executed
+ *
+ * @param engine The engine kit
+ * @param api The API description
+ * @param error The error code
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine didApiCallExecute:(NSString*)api error:(NSInteger)error;
+
+- (void)rtcEngine:(RongRTCEngine *)engine didRefreshRecordingServiceStatus:(NSInteger)status;
+
+/**
+ * receive custom data from remote user
+ *
+ * @param engine The engine kit
+ * @param userId The remote user id
+ * @param streamId The stream id
+ * @param data The user defined data
+ */
+- (void)rtcEngine:(RongRTCEngine *)engine receiveStreamMessageFromUser:(NSString *)userId streamId:(NSInteger)streamId data:(NSData*)data;
+- (void)rtcEngine:(RongRTCEngine *)engine didOccurStreamMessageErrorFromUser:(NSString *)userId streamId:(NSInteger)streamId error:(NSInteger)error missed:(NSInteger)missed cached:(NSInteger)cached;
+@end
+
+
+
+
+@interface RongRTCEngine : NSObject
+
+/**
+ * Get the version of Rong SDK.
+ *
+ * @return string, sdk version
+ */
++ (NSString *)getSdkVersion;
+
+/**
+ * Get the version of Media Engine
+ *
+ * @return string, engine version
+ */
++ (NSString *)getMediaEngineVersion;
+
+
+/**
+ * Initializes the RongRtcEngineKit object.
+ *
+ * @param appKey The vendor key is issued to the application developers by Rong.
+ * @param delegate Engine delegate
+ *
+ * @return an object of RongRtcEngineKit class
+ */
++ (instancetype)sharedEngineWithAppKey:(NSString*)appKey
+ delegate:(id)delegate;
+
+
++ (void)destroy;
+
+
+/** BEGIN OF COMMON METHODS */
+
+/**
+ * Create an open UDP socket to the RongRtcEngineKit cloud service to join a channel.
+ Users in the same channel can talk to each other with same vendor key.
+ Users using different vendor keys cannot call each other.
+ The method is asynchronous.
+ *
+ * @param channelKey Channel key generated by APP using sign certificate.
+ * @param channelName Joining in the same channel indicates those clients have entered in one room.
+ * @param userId This argument is the unique ID for each member in one channel.
+ * @param joinSuccessBlock join success callback, if failure, didErrorHappend will invoke
+ *
+ * @return 0 when executed successfully, and return minus value when failed.
+ */
+- (int)joinChannelByKey:(NSString *)channelKey
+ channelName:(NSString *)channelName
+ userId:(NSString *)userId
+ joinSuccess:(void(^)(NSInteger elapsed))joinSuccessBlock;
+
+/**
+ * lets the user leave a channel, i.e., hanging up or exiting a call.
+ After joining a channel, the user must call the leaveChannel method to end the call before joining another one.
+ It is synchronous, i.e., it only returns until the call ends and all resources are released.
+ * @param leaveChannelBlock indicate the statistics of this call, from joinChannel to leaveChannel, including duration, tx bytes and rx bytes in the call.
+ *
+ * @return 0 if executed successfully, or return minus value if failed.
+ */
+- (int)leaveChannel:(void(^)(RongRtcStats* stat))leaveChannelBlock;
+
+/**
+ * Enables video mode. Switches from audio to video mode.
+ It could be called during a call and before entering a channel.
+ *
+ * @return 0 when this method is called successfully, or minus value when this method failed.
+ */
+- (int)enableVideo;
+
+/**
+ * Disable video mode. Switch from video to audio mode.
+ It could be called during a call and before entering a channel.
+ *
+ * @return 0 when this method is called successfully, or minus value when this method failed.
+ */
+- (int)disableVideo;
+
+/**
+ * start local video preview, while not sending data to server
+ *
+ * @return 0 when this method is called successfully, or minus value when this method failed.
+ */
+- (int)startPreview;
+
+/**
+ * stop local video preview
+ *
+ * @return 0 when this method is called successfully, or minus value when this method failed.
+ */
+- (int)stopPreview;
+/** END OF COMMON METHODS */
+
+/** BEGIN OF AUDIO METHODS */
+
+
+/**
+ * Enable / Disable speaker of device
+ *
+ * @param enableSpeaker YES: Switches to speakerphone. NO: Switches to headset.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setEnableSpeakerphone:(BOOL)enableSpeaker;
+
+/**
+ * test if the speakerphone is enabled or not.
+ *
+ * @return YES when speakerphone is enabled. NO when speakerphone is not enabled.
+ */
+- (BOOL)isSpeakerphoneEnabled;
+
+/**
+ * Enables to report to the application about the volume of the speakers.
+ *
+ * @param interval Specifies the time interval between two consecutive volume indications.
+ <=0: Disables volume indication.
+ >0 : The volume indication interval in milliseconds. Recommandation: >=200ms.
+ * @param smooth The smoothing factor. Recommended: 3.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)enableAudioVolumeIndication:(NSInteger)interval
+ smooth:(NSInteger)smooth;
+
+
+/**
+ * Start recording conversation to file specified by the file path.
+ *
+ * @param filePath file path to save recorded conversation.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)startAudioRecording:(NSString*)filePath;
+
+
+/**
+ * Stop conversation recording
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)stopAudioRecording;
+
+- (int)startAudioMixing:(NSString*) filePath
+ loopback:(BOOL) loopback
+ replace:(BOOL) replace
+ cycle:(NSInteger) cycle;
+- (int)stopAudioMixing;
+
+
+/**
+ * Start screen capture
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)startScreenCapture:(NSUInteger)windowId;
+
+
+/**
+ * Stop screen capture
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)stopScreenCapture;
+
+
+- (int)setScreenCaptureId:(NSUInteger)windowId;
+
+/**
+ * Mutes / Unmutes local audio.
+ *
+ * @param mute true: Mutes the local audio. false: Unmutes the local audio.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)muteLocalAudioStream:(BOOL)mute;
+
+
+/**
+ * Mutes / Unmutes all remote audio.
+ *
+ * @param mute true: Mutes all remote received audio. false: Unmutes all remote received audio.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+
+- (int)muteAllRemoteAudioStreams:(BOOL)mute;
+
+- (int)muteRemoteAudioStream:(NSUInteger)uid
+ mute:(BOOL)mute;
+
+/** END OF AUDIO METHODS */
+
+/** BEGIN OF VIDIO METHODS */
+
+/**
+ * Set up the local video view. The video canvus is initialized with video display setting. And it could be called before entering a channel.
+ *
+ * @param local the canvas is composed of view, renderMode and uid. How to initialize 'local'? please take a look at 'RongRtcVideoCanvas'
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setupLocalVideo:(RongRtcVideoCanvas*)local;
+
+
+/**
+ * Set up the remote video view. The video canvus is initialized with video display setting. It could be called after receiving the remote video streams to configure the video settings.
+ *
+ * @param remote the canvas is composed of view, renderMode and uid. How to initialize 'remote'? please take a look at 'RongRtcVideoCanvas'
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setupRemoteVideo:(RongRtcVideoCanvas*)remote;
+
+
+/**
+ * Configure display setting of local view. And it could be called mutiple times during a call.
+ *
+ * @param mode There are Hidden(1), Fit(2) and Adaptive(3) mode. Please take a look at definition of enum RongRtcRenderMode
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setLocalRenderMode:(RongRtcRenderMode) mode;
+
+
+/**
+ * Configure display setting of remote view. And it could be called mutiple times during a call.
+ *
+ * @param uid The user id of remote view.
+ * @param mode There are Hidden(1), Fit(2) and Adaptive(3) mode. Please take a look at definition of enum RongRtcRenderMode
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setRemoteRenderMode: (NSUInteger)uid
+ mode:(RongRtcRenderMode) mode;
+
+
+/**
+ * Switches between front and back cameras.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)switchCamera;
+
+/**
+ * set video profile, including resolution, fps, kbps
+ *
+ * @param profile enumeration definition about the video resolution, fps and max kbps
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setVideoProfile:(RongRtcVideoProfile)profile;
+
+
+/**
+ * Enable / disable sending local video streams to the network.
+ *
+ * @param mute YES: stop sending local video stream to the network, NO: start sending local video stream.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)muteLocalVideoStream:(BOOL)mute;
+
+
+/**
+ * Enables / disables playing all remote callers’ video streams.
+ *
+ * @param mute YES: stop playing, NO: start playing.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)muteAllRemoteVideoStreams:(BOOL)mute;
+
+/**
+ * Enable / disable a remote user's video stream
+ *
+ * @param uid The remote user id
+ * @param mute YES: discard the video stream from remote user, NO: start receiving remote video stream.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)muteRemoteVideoStream:(NSUInteger)uid
+ mute:(BOOL)mute;
+
+/** END OF VIDIO METHODS */
+
+/**
+ * Specifies the SDK output log file.
+ *
+ * @param filePath The full file path of the log file.
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setLogFile:(NSString*)filePath;
+
+/**
+ * Specifiy the log level of output
+ *
+ * @param filter The log level
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setLogFilter:(NSUInteger)filter;
+
+/**
+ * Set the role of user: such as broadcaster, audience and free(as broadcaster and audience at the same time)
+ *
+ * @param profile the role of user
+ *
+ * @return 0 when executed successfully. return minus value if failed.
+ */
+- (int)setChannelProfile:(RongRtcChannelProfile)profile;
+
+/**
+ * Specify encryption mode of AES encryption algorithm.
+ * @param [in] encryptionMode
+ * encryption mode of AES algorithm, could be one of the following:
+ * "aes-128-xts", "aes-256-xts".
+ * The default value is "aes-128-xts". specify NULL value will use default encryption mode.
+ * @return return 0 if success or an error code
+ */
+- (int)setEncryptionMode:(NSString*)encryptionMode;
+
+/**
+ * Specifying encryption secret enables built-in AES-128 encryption. Leaving channel will clear the secret specified in last channel
+ * @param [in] secret
+ * secret to enable encryption
+ * @return return 0 if success or an error code
+ */
+- (int)setEncryptionSecret:(NSString*)secret;
+
+- (int) startRecordingService:(NSString*)recordingKey;
+- (int) stopRecordingService:(NSString*)recordingKey;
+- (int) refreshRecordingServiceStatus;
+@end
+
+
diff --git a/ios-rongcallkit/framework/RongRTCEngine.framework/Info.plist b/ios-rongcallkit/framework/RongRTCEngine.framework/Info.plist
new file mode 100644
index 0000000..777f061
Binary files /dev/null and b/ios-rongcallkit/framework/RongRTCEngine.framework/Info.plist differ
diff --git a/ios-rongcallkit/framework/RongRTCEngine.framework/LICENSE b/ios-rongcallkit/framework/RongRTCEngine.framework/LICENSE
new file mode 100644
index 0000000..c01a79c
--- /dev/null
+++ b/ios-rongcallkit/framework/RongRTCEngine.framework/LICENSE
@@ -0,0 +1,15 @@
+
+ Copyright 2012 Square Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/ios-rongcallkit/framework/RongRTCEngine.framework/README.rst b/ios-rongcallkit/framework/RongRTCEngine.framework/README.rst
new file mode 100644
index 0000000..033c9dd
--- /dev/null
+++ b/ios-rongcallkit/framework/RongRTCEngine.framework/README.rst
@@ -0,0 +1,246 @@
+SocketRocket Objective-C WebSocket Client (beta)
+================================================
+A conforming WebSocket (`RFC 6455 `_)
+client library.
+
+`Test results for SocketRocket here `_.
+You can compare to what `modern browsers look like here
+`_.
+
+SocketRocket currently conforms to all ~300 of `Autobahn
+`_'s fuzzing tests (aside from
+two UTF-8 ones where it is merely *non-strict*. tests 6.4.2 and 6.4.4)
+
+Features/Design
+---------------
+- TLS (wss) support. It uses CFStream so we get this for *free*
+- Uses NSStream/CFNetworking. Earlier implementations used ``dispatch_io``,
+ however, this proved to be make TLS nearly impossible. Also I wanted this to
+ work in iOS 4.x. (SocketRocket only supports 5.0 and above now)
+- Uses ARC. It uses the 4.0 compatible subset (no weak refs).
+- Seems to perform quite well
+- Parallel architecture. Most of the work is done in background worker queues.
+- Delegate-based. Had older versions that could use blocks too, but I felt it
+ didn't blend well with retain cycles and just objective C in general.
+
+Changes
+-------
+
+v0.3.1-beta2 - 2013-01-12
+`````````````````````````
+
+- Stability fix for ``closeWithCode:reason:`` (Thanks @michaelpetrov!)
+- Actually clean up the NSStreams and remove them from their runloops
+- ``_SRRunLoopThread``'s ``main`` wasn't correctly wrapped with
+ ``@autoreleasepool``
+
+v0.3.1-beta1 - 2013-01-12
+`````````````````````````
+
+- Cleaned up GCD so OS_OBJECT_USE_OBJC_RETAIN_RELEASE is optional
+- Removed deprecated ``dispatch_get_current_queue`` in favor of ``dispatch_queue_set_specific`` and ``dispatch_get_specific``
+- Dropping support for iOS 4.0 (it may still work)
+
+
+Installing (iOS)
+----------------
+There's a few options. Choose one, or just figure it out
+
+- You can copy all the files in the SocketRocket group into your app.
+- Include SocketRocket as a subproject and use libSocketRocket
+
+ If you do this, you must add -ObjC to your "other linker flags" option
+
+- For OS X you will have to repackage make a .framework target. I will take
+ contributions. Message me if you are interested.
+
+
+Depending on how you configure your project you may need to ``#import`` either
+```` or ``"SRWebSocket.h"``
+
+Framework Dependencies
+``````````````````````
+Your .app must be linked against the following frameworks/dylibs
+
+- libicucore.dylib
+- CFNetwork.framework
+- Security.framework
+- Foundation.framework
+
+Installing (OS X)
+-----------------
+SocketRocket now has (64-bit only) OS X support. ``SocketRocket.framework``
+inside Xcode project is for OS X only. It should be identical in function aside
+from the unicode validation. ICU isn't shipped with OS X which is what the
+original implementation used for unicode validation. The workaround is much
+more rudimentary and less robust.
+
+1. Add SocketRocket.xcodeproj as either a subproject of your app or in your workspace.
+2. Add ``SocketRocket.framework`` to the link libraries
+3. If you don't have a "copy files" step for ``Framework``, create one
+4. Add ``SocketRocket.framework`` to the "copy files" step.
+
+API
+---
+The classes
+
+``SRWebSocket``
+```````````````
+The Web Socket.
+
+.. note:: ``SRWebSocket`` will retain itself between ``-(void)open`` and when it
+ closes, errors, or fails. This is similar to how ``NSURLConnection`` behaves.
+ (unlike ``NSURLConnection``, ``SRWebSocket`` won't retain the delegate)
+
+What you need to know
+
+.. code-block:: objective-c
+
+ @interface SRWebSocket : NSObject
+
+ // Make it with this
+ - (id)initWithURLRequest:(NSURLRequest *)request;
+
+ // Set this before opening
+ @property (nonatomic, assign) id delegate;
+
+ - (void)open;
+
+ // Close it with this
+ - (void)close;
+
+ // Send a UTF8 String or Data
+ - (void)send:(id)data;
+
+ @end
+
+``SRWebSocketDelegate``
+```````````````````````
+You implement this
+
+.. code-block:: objective-c
+
+ @protocol SRWebSocketDelegate
+
+ - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
+
+ @optional
+
+ - (void)webSocketDidOpen:(SRWebSocket *)webSocket;
+ - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
+ - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
+
+ @end
+
+Known Issues/Server Todo's
+--------------------------
+- Needs auth delegates (like in NSURLConnection)
+- Move the streams off the main runloop (most of the work is backgrounded uses
+ GCD, but I just haven't gotten around to moving it off the main loop since I
+ converted it from dispatch_io)
+- Re-implement server. I removed an existing implementation as well because it
+ wasn't being used and I wasn't super happy with the interface. Will revisit
+ this.
+- Separate framer and client logic. This will make it nicer when having a
+ server.
+
+Testing
+-------
+Included are setup scripts for the python testing environment. It comes
+packaged with vitualenv so all the dependencies are installed in userland.
+
+To run the short test from the command line, run::
+
+ make test
+
+To run all the tests, run::
+
+ make test_all
+
+The short tests don't include the performance tests. (the test harness is
+actually the bottleneck, not SocketRocket).
+
+The first time this is run, it may take a while to install the dependencies. It
+will be smooth sailing after that. After the test runs the makefile will open
+the results page in your browser. If nothing comes up, you failed. Working on
+making this interface a bit nicer.
+
+To run from the app, choose the ``SocketRocket`` target and run the test action
+(``cmd+u``). It runs the same thing, but makes it easier to debug. There is
+some serious pre/post hooks in the Test action. You can edit it to customize
+behavior.
+
+.. note:: Xcode only up to version 4.4 is currently supported for the test
+ harness
+
+TestChat Demo Application
+-------------------------
+SocketRocket includes a demo app, TestChat. It will "chat" with a listening
+websocket on port 9900.
+
+It's a simple project. Uses storyboard. Storyboard is sweet.
+
+
+TestChat Server
+```````````````
+We've included a small server for the chat app. It has a simple function.
+It will take a message and broadcast it to all other connected clients.
+
+We have to get some dependencies. We also want to reuse the virtualenv we made
+when we ran the tests. If you haven't run the tests yet, go into the
+SocketRocket root directory and type::
+
+ make test
+
+This will set up your `virtualenv `_.
+Now, in your terminal::
+
+ source .env/bin/activate
+ pip install git+https://github.com/tornadoweb/tornado.git
+
+In the same terminal session, start the chatroom server::
+
+ python TestChatServer/py/chatroom.py
+
+There's also a Go implementation (with the latest weekly) where you can::
+
+ cd TestChatServer/go
+ go run chatroom.go
+
+Chatting
+````````
+Now, start TestChat.app (just run the target in the Xcode project). If you had
+it started already you can hit the refresh button to reconnect. It should say
+"Connected!" on top.
+
+To talk with the app, open up your browser to `http://localhost:9000 `_ and
+start chatting.
+
+
+WebSocket Server Implementation Recommendations
+-----------------------------------------------
+SocketRocket has been used with the following libraries:
+
+- `Tornado `_
+- Go's `WebSocket package `_ or Gorilla's `version `_
+- `Autobahn `_ (using its fuzzing
+ client)
+
+The Tornado one is dirt simple and works like a charm. (`IPython notebook
+`_ uses it
+too). It's much easier to configure handlers and routes than in
+Autobahn/twisted.
+
+As far as Go's goes, it works in my limited testing. I much prefer go's
+concurrency model as well. Try it! You may like it.
+It could use some more control over things such as pings, etc., but I
+am sure it will come in time.
+
+Autobahn is a great test suite. The Python server code is good, and conforms
+well (obviously). However for me, twisted would be a deal-breaker for writing
+something new. I find it a bit too complex and heavy for a simple service. If
+you are already using twisted though, Autobahn is probably for you.
+
+Contributing
+------------
+We’re glad you’re interested in SocketRocket, and we’d love to see where you take it. Please read our `contributing guidelines `_ prior to submitting a Pull Request.
\ No newline at end of file
diff --git a/ios-rongcallkit/framework/RongRTCEngine.framework/RongRTCEngine b/ios-rongcallkit/framework/RongRTCEngine.framework/RongRTCEngine
new file mode 100644
index 0000000..5307972
Binary files /dev/null and b/ios-rongcallkit/framework/RongRTCEngine.framework/RongRTCEngine differ
diff --git a/ios-rongcallkit/framework/en.lproj/RongCloudKit.strings b/ios-rongcallkit/framework/en.lproj/RongCloudKit.strings
index 48003ad..e473147 100644
--- a/ios-rongcallkit/framework/en.lproj/RongCloudKit.strings
+++ b/ios-rongcallkit/framework/en.lproj/RongCloudKit.strings
@@ -171,7 +171,7 @@
"GroupCreated"="%@ created the group";
"GroupInvited"="%@ invited %@ to join the group";
"GroupRemoved"="%@ removed %@ from the group chat";
-"GroupByRemoved"="%@ removed %@ from the group chat";
+"GroupByRemoved"="%@ were removed from the group chat by %@";
"GroupDismiss"="%@ dismissed the group";
"GroupQuit"="%@ quitted the group";
"GroupChanged"="%@ changed the group name to \"%@\"";
@@ -229,6 +229,8 @@
"AccessRightTitle"="no access right";
"Full_Image"="Full Image";
"Preview"="Preview";
+"Max_Selected_Photos"="You can only select 9 photos at most";
+"Confirm"="Confirm";
"Location_Service"="Unable to get your location data,Please enable location service in “Settings”->“Privacy”->“Location Services” and allows the application to use location services.";
"PhotoOniCloud"="The photo has not been downloaded from the iCloud, please download the system from the album to the local post to try again.";
"SelectMentionedUser"="Select Contact";
diff --git a/ios-rongcallkit/framework/zh-Hans.lproj/RongCloudKit.strings b/ios-rongcallkit/framework/zh-Hans.lproj/RongCloudKit.strings
index adda7ac..ff8f080 100644
--- a/ios-rongcallkit/framework/zh-Hans.lproj/RongCloudKit.strings
+++ b/ios-rongcallkit/framework/zh-Hans.lproj/RongCloudKit.strings
@@ -232,6 +232,8 @@
"Location_Service"="无法获取你的位置信息,请到手机系统的[设置]->[隐私]->[定位服务]中打开定位服务,并允许应用使用定位服务。";
"PhotoOniCloud"="该照片尚未从 iCloud 下载,请从系统相册中下载到本地后重新尝试。";
"SelectMentionedUser"="选择提醒的人";
+"Max_Selected_Photos"="最多只能选择9张照片";
+"Confirm"="确定";
"ToSearch"="搜索";
"VoiceInput"="语音输入";
"Clear"="清空";