From 6eb915c129fc90c6f4c82ae097dd6ffad5239efc Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 25 Jan 2021 14:28:30 +0800 Subject: +scripts --- Client/Assets/Scripts/Apollo/AndroidBridge.meta | 5 + .../Apollo/AndroidBridge/QGameKitAndroidBridge.cs | 1018 ++++++++++++++++ .../AndroidBridge/QGameKitAndroidBridge.cs.meta | 8 + Client/Assets/Scripts/Apollo/ApolloManager.cs | 558 +++++++++ Client/Assets/Scripts/Apollo/ApolloManager.cs.meta | 8 + Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs | 1241 ++++++++++++++++++++ .../Assets/Scripts/Apollo/ApolloVoice_lib.cs.meta | 8 + Client/Assets/Scripts/Apollo/BroadcastManager.cs | 338 ++++++ .../Assets/Scripts/Apollo/BroadcastManager.cs.meta | 8 + Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs | 612 ++++++++++ .../Assets/Scripts/Apollo/CApolloVoiceSys.cs.meta | 8 + Client/Assets/Scripts/Apollo/QGameExceptions.cs | 134 +++ .../Assets/Scripts/Apollo/QGameExceptions.cs.meta | 8 + Client/Assets/Scripts/Apollo/QGameKit.cs | 606 ++++++++++ Client/Assets/Scripts/Apollo/QGameKit.cs.meta | 8 + Client/Assets/Scripts/Apollo/iOSBridge.meta | 5 + .../Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs | 111 ++ .../Apollo/iOSBridge/QGameKitiOSBridge.cs.meta | 8 + .../Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs | 552 +++++++++ .../Apollo/iOSBridge/QGameUtilsJSON.cs.meta | 8 + 20 files changed, 5252 insertions(+) create mode 100644 Client/Assets/Scripts/Apollo/AndroidBridge.meta create mode 100644 Client/Assets/Scripts/Apollo/AndroidBridge/QGameKitAndroidBridge.cs create mode 100644 Client/Assets/Scripts/Apollo/AndroidBridge/QGameKitAndroidBridge.cs.meta create mode 100644 Client/Assets/Scripts/Apollo/ApolloManager.cs create mode 100644 Client/Assets/Scripts/Apollo/ApolloManager.cs.meta create mode 100644 Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs create mode 100644 Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs.meta create mode 100644 Client/Assets/Scripts/Apollo/BroadcastManager.cs create mode 100644 Client/Assets/Scripts/Apollo/BroadcastManager.cs.meta create mode 100644 Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs create mode 100644 Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs.meta create mode 100644 Client/Assets/Scripts/Apollo/QGameExceptions.cs create mode 100644 Client/Assets/Scripts/Apollo/QGameExceptions.cs.meta create mode 100644 Client/Assets/Scripts/Apollo/QGameKit.cs create mode 100644 Client/Assets/Scripts/Apollo/QGameKit.cs.meta create mode 100644 Client/Assets/Scripts/Apollo/iOSBridge.meta create mode 100644 Client/Assets/Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs create mode 100644 Client/Assets/Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs.meta create mode 100644 Client/Assets/Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs create mode 100644 Client/Assets/Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs.meta (limited to 'Client/Assets/Scripts/Apollo') diff --git a/Client/Assets/Scripts/Apollo/AndroidBridge.meta b/Client/Assets/Scripts/Apollo/AndroidBridge.meta new file mode 100644 index 00000000..14525c6e --- /dev/null +++ b/Client/Assets/Scripts/Apollo/AndroidBridge.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 3597e05c7359f6d498161935df762d7c +folderAsset: yes +DefaultImporter: + userData: diff --git a/Client/Assets/Scripts/Apollo/AndroidBridge/QGameKitAndroidBridge.cs b/Client/Assets/Scripts/Apollo/AndroidBridge/QGameKitAndroidBridge.cs new file mode 100644 index 00000000..91f084a2 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/AndroidBridge/QGameKitAndroidBridge.cs @@ -0,0 +1,1018 @@ +#if !DISABLE_PLUGIN + +#if UNITY_ANDROID && !UNITY_EDITOR + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System; +using System.Threading; + +public class QGameKitAndroidBridge : MonoBehaviour { + private static string gameID; + private static string wnsID; + private static QGameKit.CaptureType myCaptureType; + private int grabFrameRate = 20; + private static QGameKit.Environment sdkEnvironmentType; + private static QGameKitAndroidBridge singletonInstance = null; + + private static AndroidJavaObject playerActivityContext = null; + private static IntPtr constructorMethodID = IntPtr.Zero; + private static IntPtr setupMethodID = IntPtr.Zero; + private static IntPtr tearDownMethodID = IntPtr.Zero; + private static IntPtr resetMethodID = IntPtr.Zero; + private static IntPtr startLiveBroadcastMethodID = IntPtr.Zero; + private static IntPtr frameUpdatedMethodID = IntPtr.Zero; + private static IntPtr stopLiveBroadcastMethodID = IntPtr.Zero; + private static IntPtr enterLiveHallMethodID = IntPtr.Zero; + private static IntPtr enterLiveHallInGameMethodID = IntPtr.Zero; + private static IntPtr updateUserAccountMethodID = IntPtr.Zero; + private static IntPtr getLiveBroadcastStatusMethodID = IntPtr.Zero; + private static IntPtr getErrorCodeMethodID = IntPtr.Zero; + private static IntPtr isLiveBroadcastSupportedMethodID = IntPtr.Zero; + private static IntPtr getVersionNameMethodID = IntPtr.Zero; + private static IntPtr showCameraMethodID = IntPtr.Zero; + private static IntPtr hideCameraMethodID = IntPtr.Zero; + private static IntPtr setEnvironmentTypeMethodID = IntPtr.Zero; + private static IntPtr getLiveFrameRateMethodID = IntPtr.Zero; + private static IntPtr doOnCreateMethodID = IntPtr.Zero; + private static IntPtr doOnResumeMethodID = IntPtr.Zero; + private static IntPtr doOnPauseMethodID = IntPtr.Zero; + private static IntPtr doOnDestroyMethodID = IntPtr.Zero; + private static IntPtr doOnBackPressedMethodID = IntPtr.Zero; + private static IntPtr notifyUserAccountMethodID = IntPtr.Zero; + private static IntPtr setUserAccountListenerMethodID = IntPtr.Zero; + private static IntPtr setCommentReceiveDelegateMethodID = IntPtr.Zero; + private static IntPtr setLogDelegateMethodID = IntPtr.Zero; + private static IntPtr setLiveStatusChangedDelegateMethodID = IntPtr.Zero; + private static IntPtr setShareListenerMethodID = IntPtr.Zero; + private static IntPtr setErrorCodeDelegateMethodID = IntPtr.Zero; + private static IntPtr setWebViewStatusChangedDelegateMethodID = IntPtr.Zero; + private static IntPtr isSupportCameraMethodID = IntPtr.Zero; + private static IntPtr shareLiveBroadcastMethodID = IntPtr.Zero; + private static IntPtr isSupportLiveHallMethodID = IntPtr.Zero; + private static IntPtr setDanmakuEnabledMethodID = IntPtr.Zero; + private static IntPtr showDanmakuMethodID = IntPtr.Zero; + private static IntPtr hideDanmakuMethodID = IntPtr.Zero; + + private IntPtr androidBridge = IntPtr.Zero; + private float startTime = 0.0f; + private float nextCaptureTime = 0.0f; + private float frameInterval = 0.0f; + + public bool isRunning { get; private set; } + + + + private static QGameKit.UserAccountDelegate userAccountDelegate; + + + + + /** + 初始化入口 + 这里自动创建gameobj 并挂载组件 必须调用且仅能调用一次 + */ + public static QGameKitAndroidBridge Setup(string gameId, string wnsId, QGameKit.CaptureType captureType, QGameKit.UserAccountDelegate accountDelegate, QGameKit.Environment environmentType) + { + if(singletonInstance != null) + { + return singletonInstance; + } + + gameID = gameId; + wnsID = wnsId; + myCaptureType = captureType; + userAccountDelegate = accountDelegate; + sdkEnvironmentType = environmentType; + GameObject sdkObject = new GameObject("QGameKitAndroidBridge"); + + DontDestroyOnLoad(sdkObject); + + singletonInstance = sdkObject.AddComponent(); + + singletonInstance.initSDK(); + + return singletonInstance; + } + + private void initSDK() + { + // Search for our class + IntPtr classID = AndroidJNI.FindClass("com/tencent/qgame/livesdk/bridge/Unity3D"); + + // Search for it's contructor + constructorMethodID = AndroidJNI.GetMethodID(classID, "", "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;IIII)V"); + if (constructorMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find UnityBridge constructor."); + return; + } + + setupMethodID = AndroidJNI.GetMethodID(classID, "setup", "(Lcom/tencent/qgame/livesdk/bridge/UserAccountListener;)Z"); + if (setupMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setup() method."); + return; + } + + tearDownMethodID = AndroidJNI.GetMethodID(classID, "tearDown", "()V"); + if (tearDownMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find tearDown() method."); + return; + } + + resetMethodID = AndroidJNI.GetMethodID(classID, "reset", "()Z"); + if (resetMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find reset() method."); + return; + } + + startLiveBroadcastMethodID = AndroidJNI.GetMethodID(classID, "startLiveBroadcast", "(Ljava/lang/String;Ljava/lang/String;)Z"); + if (startLiveBroadcastMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find startLiveBroadcast() method."); + return; + } + + stopLiveBroadcastMethodID = AndroidJNI.GetMethodID(classID, "stopLiveBroadcast", "()Z"); + if (stopLiveBroadcastMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find stopLiveBroadcast() method."); + return; + } + + frameUpdatedMethodID = AndroidJNI.GetMethodID(classID, "frameUpdated", "()V"); + if (frameUpdatedMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find frameUpdated() method."); + return; + } + + enterLiveHallMethodID = AndroidJNI.GetMethodID(classID, "enterLiveHall", "(Landroid/content/Context;)V"); + if (enterLiveHallMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find enterLiveHall() method."); + return; + } + + enterLiveHallInGameMethodID = AndroidJNI.GetMethodID(classID, "enterLiveHallInGame", "(Landroid/content/Context;)V"); + if (enterLiveHallInGameMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find enterLiveHallInGameMethodID() method."); + return; + } + + updateUserAccountMethodID = AndroidJNI.GetMethodID(classID, "updateUserAccount", "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + if (updateUserAccountMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find updateUserAccount() method."); + return; + } + + getLiveBroadcastStatusMethodID = AndroidJNI.GetMethodID(classID, "getLiveBroadcastStatus", "()I"); + if (getLiveBroadcastStatusMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find getLiveBroadcastStatus() method."); + return; + } + + getErrorCodeMethodID = AndroidJNI.GetMethodID(classID, "getErrorCode", "()I"); + if (getErrorCodeMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find getErrorCode() method."); + return; + } + + setUserAccountListenerMethodID = AndroidJNI.GetMethodID(classID, "setUserAccountListener", "(Lcom/tencent/qgame/livesdk/bridge/UserAccountListener;)V"); + if (setUserAccountListenerMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setUserAccountListener() method."); + return; + } + + setCommentReceiveDelegateMethodID = AndroidJNI.GetMethodID(classID, "setCommentReceiveListener", "(Lcom/tencent/qgame/livesdk/bridge/CommentReceiveListener;)V"); + if (setCommentReceiveDelegateMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setCommentReceiveListener() method."); + return; + } + + setLogDelegateMethodID = AndroidJNI.GetMethodID(classID, "setLogListener", "(Lcom/tencent/qgame/livesdk/bridge/LogListener;)V"); + if (setLogDelegateMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setLogListener() method."); + return; + } + + setLiveStatusChangedDelegateMethodID = AndroidJNI.GetMethodID(classID, "setLiveStatusChangedListener", "(Lcom/tencent/qgame/live/listener/OnLiveStatusChangedListener;)V"); + if (setLiveStatusChangedDelegateMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setLiveStatusChangedListener() method."); + return; + } + + setShareListenerMethodID = AndroidJNI.GetMethodID(classID, "setShareListener", "(Lcom/tencent/qgame/livesdk/bridge/ShareListener;)V"); + if (setShareListenerMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setShareListener() method."); + return; + } + + setErrorCodeDelegateMethodID = AndroidJNI.GetMethodID(classID, "setErrorCodeListener", "(Lcom/tencent/qgame/live/listener/ErrorCodeListener;)V"); + if (setErrorCodeDelegateMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setErrorCodeDelegateMethodID() method."); + return; + } + + setWebViewStatusChangedDelegateMethodID = AndroidJNI.GetMethodID(classID, "setWebViewStatusChangedListener", "(Lcom/tencent/qgame/livesdk/bridge/WebViewStatusChangedListener;)V"); + if (setWebViewStatusChangedDelegateMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setWebViewStatusChangedListener() method."); + return; + } + + isLiveBroadcastSupportedMethodID = AndroidJNI.GetMethodID(classID, "isLiveBroadcastSupported", "()Z"); + if (isLiveBroadcastSupportedMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find isLiveBroadcastSupportedMethodID() method."); + return; + } + + getVersionNameMethodID = AndroidJNI.GetMethodID(classID, "getVersionName", "()Ljava/lang/String;"); + if (getVersionNameMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find getVersionNameMethodID() method."); + return; + } + + showCameraMethodID = AndroidJNI.GetMethodID(classID, "showCamera", "()Z"); + if (showCameraMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find showCameraMethodID() method."); + return; + } + + hideCameraMethodID = AndroidJNI.GetMethodID(classID, "hideCamera", "()V"); + if (hideCameraMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find hideCameraMethodID() method."); + return; + } + + setEnvironmentTypeMethodID = AndroidJNI.GetMethodID(classID, "setEnvironmentType", "(I)V"); + if (setEnvironmentTypeMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setEnvironmentTypeMethodID() method"); + return; + } + + getLiveFrameRateMethodID = AndroidJNI.GetMethodID(classID, "getLiveFrameRate", "()I"); + if (getLiveFrameRateMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find getLiveFrameRate() method"); + return; + } + + notifyUserAccountMethodID = AndroidJNI.GetMethodID(classID, "notifyUserAccountUpdate", "()V"); + if (notifyUserAccountMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find notifyUserAccountMethodID() method."); + return; + } + + doOnCreateMethodID = AndroidJNI.GetMethodID(classID, "doOnCreate", "()V"); + if (doOnCreateMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find doOnCreate() method"); + return; + } + doOnResumeMethodID = AndroidJNI.GetMethodID(classID, "doOnResume", "()V"); + if (doOnResumeMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find doOnResume() method"); + return; + } + doOnPauseMethodID = AndroidJNI.GetMethodID(classID, "doOnPause", "()V"); + if (doOnPauseMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find doOnPause() method"); + return; + } + doOnDestroyMethodID = AndroidJNI.GetMethodID(classID, "doOnDestroy", "()V"); + if (doOnDestroyMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find doOnDestroy() method"); + return; + } + doOnBackPressedMethodID = AndroidJNI.GetMethodID(classID, "doOnBackPressed", "()Z"); + if (doOnBackPressedMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find doOnBackPressed() method"); + return; + } + isSupportCameraMethodID = AndroidJNI.GetMethodID(classID, "isSupportCamera", "()Z"); + if (isSupportCameraMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find isSupportCamera() method"); + return; + } + shareLiveBroadcastMethodID = AndroidJNI.GetMethodID(classID, "shareLiveBroadcast", "()V"); + if (shareLiveBroadcastMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find shareLiveBroadcast() method"); + return; + } + + isSupportLiveHallMethodID = AndroidJNI.GetMethodID(classID, "isSupportLiveHall", "()Z"); + if (isSupportLiveHallMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find isSupportLiveHall() method"); + return; + } + + setDanmakuEnabledMethodID = AndroidJNI.GetMethodID(classID, "setDanmakuEnabled", "(Z)V"); + if (setDanmakuEnabledMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find setDanmakuEnabled() method"); + return; + } + + showDanmakuMethodID = AndroidJNI.GetMethodID(classID, "showDanmaku", "()V"); + if (showDanmakuMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find showDanmaku() method"); + return; + } + + hideDanmakuMethodID = AndroidJNI.GetMethodID(classID, "hideDanmaku", "()V"); + if (hideDanmakuMethodID == IntPtr.Zero) + { + Debug.LogError("Can't find hideDanmaku() method"); + return; + } + + // Create Unity bridge object + jvalue[] constructorParameters = AndroidJNIHelper.CreateJNIArgArray(new object[] { + getActivityContext(), gameID, wnsID, Screen.width, Screen.height, Convert.ToInt32(myCaptureType), Convert.ToInt32(sdkEnvironmentType) + }); + IntPtr local_capturingObject = AndroidJNI.NewObject(classID, constructorMethodID, constructorParameters); + if (local_capturingObject == IntPtr.Zero) + { + Debug.LogError("--- Can't create Unity bridge object."); + return; + } + // Keep a global reference to it + androidBridge = AndroidJNI.NewGlobalRef(local_capturingObject); + AndroidJNI.DeleteLocalRef(local_capturingObject); + + AndroidJNI.DeleteLocalRef(classID); + + Debug.Log("--- grabFrameRate = " + grabFrameRate); + frameInterval = 1.0f / grabFrameRate; + Debug.Log("--- 1.0f / grabFrameRate = " + frameInterval); + startTime = Time.time; + + isRunning = false; + if (myCaptureType == 0) + { + if (userAccountDelegate != null) + { + SetUserAccountDelegate(userAccountDelegate); + } + Debug.Log("CaptureType is zero, give up setup"); + return; + } + if (setup()) + { + Debug.Log("Native setup success."); + } + else + { + Debug.LogError("Native setup failed!"); + } + } + + void Awake() { + + } + void Start() { + + + } + + + void Update() + { + if (isRunning) { + float elapsedTime = Time.time - startTime; + //Debug.Log("elapsedTime=" + elapsedTime); + if (elapsedTime >= frameInterval) { + CaptureFrame(); + startTime = Time.time; + //Debug.Log("CaptureFrame()"); + } + } + } + + private void SetEnvironmentType(QGameKit.Environment environmentType) { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, cann't get setEnvironemtType!"); + return; + } + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + (int) environmentType + }); + AndroidJNI.CallVoidMethod(androidBridge, setEnvironmentTypeMethodID, args); + } + + public bool IsLiveBroadcastSupported() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, cann't get liveBroadcast support!"); + return false; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallBooleanMethod(androidBridge, isLiveBroadcastSupportedMethodID, args); + } + + private bool setup() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, setup failed!"); + return false; + } + UserAccountCallback callback = new UserAccountCallback(userAccountDelegate); + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + callback + }); + return AndroidJNI.CallBooleanMethod(androidBridge, setupMethodID, args); + } + + public void TearDown() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, tear down failed!"); + return ; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, tearDownMethodID, args); + } + + public bool Reset() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, reset failed!"); + return false; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallBooleanMethod(androidBridge, resetMethodID, args); + } + + public bool StartLiveBroadcast(string title, string description) + { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("Start Live Broadcast failed because bridge object is null!"); + return false; + } + + nextCaptureTime = 0.0f; + + jvalue[] args = new jvalue[2]; + args[0].l = AndroidJNI.NewStringUTF(title); + args[1].l = AndroidJNI.NewStringUTF(description); + if (AndroidJNI.CallBooleanMethod(androidBridge, startLiveBroadcastMethodID, args)) { + Debug.Log("Start Live Broadcast success"); + grabFrameRate = GetLiveFrameRate(); + frameInterval = 1.0f / grabFrameRate; + Debug.Log("--- grabFrameRate = " + grabFrameRate); + Debug.Log("--- 1.0f / grabFrameRate = " + frameInterval); + return true; + } + Debug.LogError("Native Start Live Broadcast failed!"); + return false; + } + + public bool StopLiveBroadcast() + { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, stop liveBroadcast failed!"); + return false; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallBooleanMethod(androidBridge, stopLiveBroadcastMethodID, args); + } + + public void EnterLiveHall() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, enter LiveHall failed!"); + return ; + } + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + getActivityContext() + }); + AndroidJNI.CallVoidMethod(androidBridge, enterLiveHallMethodID, args); + } + + public void EnterLiveHallInGame() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, enter LiveHallInGame failed!"); + return; + } + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object[] { + getActivityContext() + }); + AndroidJNI.CallVoidMethod(androidBridge, enterLiveHallInGameMethodID, args); + } + + public void UpdateUserAccount(QGameKit.UserAccount account) { + if (androidBridge == IntPtr.Zero || null == account) { + Debug.LogError("Update user account failed because bridge object or account is null!"); + return ; + } + + jvalue[] args = new jvalue[4]; + int platform = 0; + if (QGameKit.LoginPlatform.QQ == account.platform) { + platform = 1; + } else if (QGameKit.LoginPlatform.WeChat == account.platform) { + platform = 2; + } + args[0].i = platform; + args[1].l = AndroidJNI.NewStringUTF(account.appId); + args[2].l = AndroidJNI.NewStringUTF(account.id); + args[3].l = AndroidJNI.NewStringUTF(account.token); + AndroidJNI.CallVoidMethod(androidBridge, updateUserAccountMethodID, args); + } + + public void UpdateUserAccount() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, UpdateUserAccount down failed!"); + return ; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, notifyUserAccountMethodID, args); + } + + public void CaptureFrame() + { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, captureFrame failed!"); + return; + } + StartCoroutine(CaptureScreen()); + } + + private IEnumerator CaptureScreen() { + yield return new WaitForEndOfFrame(); + + //float start = Time.time; + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, frameUpdatedMethodID, args); + //float delta = Time.time - start; + //Debug.Log("CaptureFrame cost=" + delta); + } + + private static AndroidJavaObject getActivityContext () + { + if (playerActivityContext == null) { + AndroidJavaClass actClass = new AndroidJavaClass ("com.unity3d.player.UnityPlayer"); + if (actClass == null) { + Debug.LogError ("Get UnityPlayer Class failed"); + return null; + } + playerActivityContext = actClass.GetStatic ("currentActivity"); + if (playerActivityContext == null) { + Debug.LogError ("get context failed"); + return null; + } + } + return playerActivityContext; + } + + public class UserAccountCallback : AndroidJavaProxy + { + private QGameKit.UserAccountDelegate accountDelegate; + public UserAccountCallback(QGameKit.UserAccountDelegate mDelegate) : base("com.tencent.qgame.livesdk.bridge.UserAccountListener"){ + accountDelegate = mDelegate; + } + AndroidJavaObject getUserAccount() { + //Debug.Log("getUserAccount Thread " + Thread.CurrentThread.Name); + QGameKit.UserAccount account = accountDelegate(); + AndroidJavaObject javaAccount = new AndroidJavaObject("com.tencent.qgame.livesdk.webview.Account"); + javaAccount.Set("openId", account.id); + javaAccount.Set("accessToken", account.token); + javaAccount.Set("loginType", (int)account.platform); + javaAccount.Set("appId", account.appId); + return javaAccount; + } + } + public void SetUserAccountDelegate(QGameKit.UserAccountDelegate accountDelegate) { + + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, setUserAccountDelegate failed!"); + return; + } + UserAccountCallback callback = new UserAccountCallback(accountDelegate); + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + callback + }); + AndroidJNI.CallVoidMethod(androidBridge, setUserAccountListenerMethodID, args); + } + + public QGameKit.LiveStatus GetLiveBroadcastStatus() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, cann't getLiveBroadcastStatus!"); + return QGameKit.LiveStatus.Unknown; + } + jvalue[] args = new jvalue[0]; + int state = AndroidJNI.CallIntMethod(androidBridge, getLiveBroadcastStatusMethodID, args); + return getStateById(state); + } + + public int GetErrorCode() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, getErrorCode failed!"); + return 0; + } + jvalue[] args = new jvalue[0]; + int error = AndroidJNI.CallIntMethod(androidBridge, getErrorCodeMethodID, args); + return error; + } + + public class CommentReceiveCallback : AndroidJavaProxy + { + private QGameKit.CommentReceiveDelegate commentDelegate; + public CommentReceiveCallback(QGameKit.CommentReceiveDelegate mDelegate ) : base("com.tencent.qgame.livesdk.bridge.CommentReceiveListener"){ + commentDelegate = mDelegate; + } + void onCommentReceive(AndroidJavaObject comments) { + List commentList = new List(); + int size = comments.Call("size"); + for (int i = 0; i < size; i++) { + AndroidJavaObject javaObject = comments.Call("get", i); + QGameKit.LiveComment comment = new QGameKit.LiveComment(); + comment.type = (QGameKit.CommentType)javaObject.Get("msgType"); + comment.nick = javaObject.Get("nick"); + comment.content = javaObject.Get("msgContent"); + //unity 5.0以下不能直接传long + string msgTimeStr = javaObject.Call("msgTime2String"); + comment.timestamp = long.Parse(msgTimeStr); + commentList.Add(comment); + } + commentDelegate(commentList); + } + } + + public void SetCommentReceiveDelegete(QGameKit.CommentReceiveDelegate commentDelegate) { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, setCommentReceiveDelegate failed!"); + return ; + } + CommentReceiveCallback callback = new CommentReceiveCallback(commentDelegate); + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + callback + }); + AndroidJNI.CallVoidMethod(androidBridge, setCommentReceiveDelegateMethodID, args); + } + + public class LogCallback : AndroidJavaProxy + { + private QGameKit.LogDelegate logDelegate; + public LogCallback(QGameKit.LogDelegate mDelegate) : base("com.tencent.qgame.livesdk.bridge.LogListener") { + logDelegate = mDelegate; + } + void log(string msg) { + logDelegate(msg); + } + } + + public void SetLogDelegate(QGameKit.LogDelegate logDelegate) { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, setLogDelegate failed!"); + return ; + } + LogCallback callback = new LogCallback(logDelegate); + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + callback + }); + AndroidJNI.CallVoidMethod(androidBridge, setLogDelegateMethodID, args); + } + + public class LiveStatusChangedCallback : AndroidJavaProxy + { + private QGameKit.LiveStatusChangedDelegate liveStatusChangedDelegate; + private QGameKitAndroidBridge mBridge; + public LiveStatusChangedCallback(QGameKitAndroidBridge bridge, QGameKit.LiveStatusChangedDelegate mDelegate) : base("com/tencent/qgame/live/listener/OnLiveStatusChangedListener") { + liveStatusChangedDelegate = mDelegate; + mBridge = bridge; + } + + void onLiveStatusChanged(int stateId) { + Debug.Log ("Live status change to: " + stateId); + QGameKit.LiveStatus status = mBridge.getStateById(stateId); + switch (status) { + case QGameKit.LiveStatus.LiveStarting: + mBridge.isRunning = true; + Debug.Log("Start CaptureFrame"); + break; + + case QGameKit.LiveStatus.LivePaused: + case QGameKit.LiveStatus.LiveStopping: + mBridge.isRunning = false; + break; + + case QGameKit.LiveStatus.Error: + mBridge.isRunning = false; + break; + } + liveStatusChangedDelegate(status); + } + } + + public void SetLiveStatusChangedDelegate(QGameKit.LiveStatusChangedDelegate liveDelegate) { + + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, setLiveStatusChangedDelegate failed!"); + return ; + } + LiveStatusChangedCallback callback = new LiveStatusChangedCallback(this, liveDelegate); + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + callback + }); + AndroidJNI.CallVoidMethod(androidBridge, setLiveStatusChangedDelegateMethodID, args); + } + + public class ShareDelegateCallback : AndroidJavaProxy + { + private QGameKit.ShareDelegate shareDelegate; + public ShareDelegateCallback(QGameKit.ShareDelegate mDelegate) : base("com.tencent.qgame.livesdk.bridge.ShareListener") { + shareDelegate = mDelegate; + } + void share(AndroidJavaObject javaObject) { + QGameKit.ShareContent share = new QGameKit.ShareContent(); + share.fopenId = javaObject.Get("fopenId"); + share.title = javaObject.Get("title"); + share.description = javaObject.Get("description"); + share.targetUrl = javaObject.Get("targetUrl"); + share.imageUrl = javaObject.Get("imageUrl"); + shareDelegate(share); + } + } + + public void SetShareDelegate(QGameKit.ShareDelegate shareDelegate) { + + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, setShareDelegate failed!"); + return ; + } + ShareDelegateCallback callback = new ShareDelegateCallback(shareDelegate); + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + callback + }); + AndroidJNI.CallVoidMethod(androidBridge, setShareListenerMethodID, args); + } + + public class ErrorCodeCallback : AndroidJavaProxy + { + private QGameKit.ErrorCodeListenerDelegate errorCodeDelegate; + public ErrorCodeCallback(QGameKit.ErrorCodeListenerDelegate mDelegate) : base("com/tencent/qgame/live/listener/ErrorCodeListener") { + errorCodeDelegate = mDelegate; + } + void onResult(int errorCode, String errorMessage) { + errorCodeDelegate(errorCode, errorMessage); + } + } + + public void SetErrorCodeDelegate(QGameKit.ErrorCodeListenerDelegate errorDelegate) { + + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, setErrorCodeDelegate failed!"); + return ; + } + ErrorCodeCallback callback = new ErrorCodeCallback(errorDelegate); + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object [] { + callback + }); + AndroidJNI.CallVoidMethod(androidBridge, setErrorCodeDelegateMethodID, args); + } + + public class WebViewStatusChangedCallback : AndroidJavaProxy + { + private QGameKit.WebViewStatusChangedDelegate webviewStatusChangedDelegate; + public WebViewStatusChangedCallback(QGameKit.WebViewStatusChangedDelegate mDelegate) : base("com.tencent.qgame.livesdk.bridge.WebViewStatusChangedListener") + { + webviewStatusChangedDelegate = mDelegate; + } + + void onWebViewStatusChanged(int status) + { + webviewStatusChangedDelegate((QGameKit.WebViewStatus) status); + } + } + + public void SetWebViewStatusChangedDelegate(QGameKit.WebViewStatusChangedDelegate webviewDelegate) + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, setLiveStatusChangedDelegate failed!"); + return; + } + WebViewStatusChangedCallback callback = new WebViewStatusChangedCallback(webviewDelegate); + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object[] { + callback + }); + AndroidJNI.CallVoidMethod(androidBridge, setWebViewStatusChangedDelegateMethodID, args); + } + + public string GetVersionName() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, getVersionName failed!"); + return null; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallStringMethod(androidBridge, getVersionNameMethodID, args); + } + + public void ShareLiveBroadcast() { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, ShareLiveBroadcast failed!"); + return; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, shareLiveBroadcastMethodID, args); + } + + private int GetLiveFrameRate() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, getLiveFrameRate failed!"); + return 20; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallIntMethod(androidBridge, getLiveFrameRateMethodID, args); + } + + public bool ShowCamera() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, showCamera faile!"); + return false; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallBooleanMethod(androidBridge, showCameraMethodID, args); + } + + public void HideCamera() { + if (androidBridge == IntPtr.Zero) { + Debug.LogError("androidBridge is null, hideCamera failed!"); + return ; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, hideCameraMethodID, args); + } + + public void DoOnCreate() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, onCreate failed!"); + return; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, doOnCreateMethodID, args); + } + + public void DoOnResume() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, onResume failed!"); + return; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, doOnResumeMethodID, args); + } + public void DoOnPause() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, onPause failed!"); + return; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, doOnPauseMethodID, args); + } + public void DoOnDestroy() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, onDestory failed!"); + return; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, doOnDestroyMethodID, args); + } + public bool DoOnBackPressed() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, onBackPressed failed!"); + return false; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallBooleanMethod(androidBridge, doOnBackPressedMethodID, args); + } + + public bool IsSupportCamera() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, IsSupportCamera failed!"); + return false; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallBooleanMethod(androidBridge, isSupportCameraMethodID, args); + } + + public bool IsSupportLiveHall() + { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, IsSupportLiveHall failed!"); + return false; + } + jvalue[] args = new jvalue[0]; + return AndroidJNI.CallBooleanMethod(androidBridge, isSupportLiveHallMethodID, args); + } + + public void SetDanmakuEnabled(bool enable) { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, setDanmakuEnabled failed!"); + return; + } + jvalue[] args = AndroidJNIHelper.CreateJNIArgArray(new object[] { + enable + }); + AndroidJNI.CallVoidMethod(androidBridge, setDanmakuEnabledMethodID, args); + } + + public void ShowDanmaku() { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, ShowDanmaku failed!"); + return; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, showDanmakuMethodID, args); + } + + public void HideDanmaku() { + if (androidBridge == IntPtr.Zero) + { + Debug.LogError("androidBridge is null, HideDanmaku failed!"); + return; + } + jvalue[] args = new jvalue[0]; + AndroidJNI.CallVoidMethod(androidBridge, hideDanmakuMethodID, args); + } + + private void JavaMessage(string message) + { + Debug.Log("message " + message); + + } + + private QGameKit.LiveStatus getStateById(int id) { + switch (id) { + case 1: // Uninit + return (QGameKit.LiveStatus.Uninitialized); + case 2: // Prepared + return (QGameKit.LiveStatus.Prepared); + case 3: // Starting + return (QGameKit.LiveStatus.LiveStarting); + case 4: // Started + return (QGameKit.LiveStatus.LiveStarted); + case 5: // Paused + return (QGameKit.LiveStatus.LivePaused); + case 6: // Resume + return (QGameKit.LiveStatus.LiveResume); + case 7: // Stopping + return (QGameKit.LiveStatus.LiveStopping); + case 8: // Stopped + return (QGameKit.LiveStatus.LiveStopped); + case 9: // Error + return (QGameKit.LiveStatus.Error); + } + return QGameKit.LiveStatus.Unknown; + } +} + +#endif + +#endif \ No newline at end of file diff --git a/Client/Assets/Scripts/Apollo/AndroidBridge/QGameKitAndroidBridge.cs.meta b/Client/Assets/Scripts/Apollo/AndroidBridge/QGameKitAndroidBridge.cs.meta new file mode 100644 index 00000000..b4d3b3d0 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/AndroidBridge/QGameKitAndroidBridge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cc31e4ac25dfe9e4daf15b7b3e33717b +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Client/Assets/Scripts/Apollo/ApolloManager.cs b/Client/Assets/Scripts/Apollo/ApolloManager.cs new file mode 100644 index 00000000..b5c26887 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/ApolloManager.cs @@ -0,0 +1,558 @@ +#if !DISABLE_PLUGIN +using UnityEngine; +using System.Collections; +using System; +using XUtliPoolLib; +//using com.tencent.gsdk; +using System.IO; +using System.Text; + +public class ApolloManager : MonoBehaviour, IApolloManager +{ +#if APOLLO + private static CApolloVoiceSys ApolloVoiceMgr = null; + static bool m_bCreateEngine = false; + private string mAppID = string.Empty; + private string mOpenID = string.Empty; +#endif + + private bool _openMusic = true; + private bool _openSpeak = true; + + + + public static ApolloManager sington = null; + public static byte[] m_strFileID = new byte[1024]; + + + void Awake() + { + sington = this; + } + + void OnDestroy() + { + sington = null; + } + + void Start() + { + // InitGSDK("1105309683"); + } + + /// + /// sdk speak表示打开或者关闭其他玩家说话 + /// + public bool openMusic + { + get { return _openMusic; } + set + { + _openMusic = value; +#if APOLLO + ApolloVoiceErr VoiceErr = value ? (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._OpenSpeaker() + : (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._CloseSpeaker(); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog(string.Format("openMusic Succ {0}", value)); + } + else + { + string text = string.Format("openMusic Err is {0}", VoiceErr); + Debug.Log(text); + } +#endif + } + } + + + /// + /// sdk music代表打开或者关闭自己说话 + /// + public bool openSpeak + { + get { return _openSpeak; } + set + { + _openSpeak = value; +#if APOLLO + ApolloVoiceErr VoiceErr = value ? (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._OpenMic() + : (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._CloseMic(); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog(string.Format("openSpeak Succ {0}", value)); + } + else + { + string text = string.Format("openSpeak Err is {0}", VoiceErr); + Debug.Log(text); + } +#endif + } + } + + + public void Init(int platf, string openid) + { +#if APOLLO + mAppID = "guest100023"; +#if UNITY_EDITOR + mAppID = "1105309683"; + openid = "63662733"; +#endif + if (platf == 3) mAppID = "1105309683"; + else if (platf == 4) mAppID = "wxfdab5af74990787a"; + mOpenID = openid; + + //SetGSDKUserName(platf, openid); + + + if (ApolloVoiceMgr != null) + { + Debug.Log("ApolloVoiceMgr Created"); + } + else + { + ApolloVoiceMgr = new CApolloVoiceSys(); + ApolloVoiceMgr.SysInitial(); + } + if (ApolloVoiceMgr != null) + { + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._CreateApolloVoiceEngine(mAppID, openid); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog("CreateApolloVoiceEngine Succ"); + } + else + { + string text = string.Format("CreateApolloVoiceEngine Err is {0}", VoiceErr); + Debug.Log(text); + } + } +#if Publish + ApolloVoiceMgr.CallApolloVoiceSDK._EnableLog(false); +#endif + +#endif + } + + + public void SetRealtimeMode() + { +#if APOLLO + if (ApolloVoiceMgr != null) + { + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._SetMode(0); + + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog("apollo _SetMode Succ"); + } + else + { + string text = string.Format("apollo _SetMode Err is {0}", VoiceErr); + Debug.Log(text); + } + } +#endif + } + + + public void Capture(bool capture) + { +#if APOLLO&&!UNITY_EDITOR && !UNITY_STANDALONE_WIN + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._CaptureMicrophone(capture); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + Debug.Log("apollo capture Succ"); + } + else + { + string text = string.Format("apollo capture Err is {0}", VoiceErr); + Debug.Log(text); + } +#endif + } + + + /// + /// 禁止成员声音 + /// + /// + /// + public void ForbitMember(int memberId, bool bEnable) + { +#if APOLLO + if (ApolloVoiceMgr != null) + { + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._ForbidMemberVoice(memberId, bEnable); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog("ForbitMember Succ"); + } + else + { + string text = string.Format("ForbitMember Err is {0}", VoiceErr); + Debug.Log(text); + } + } +#endif + } + + /// + /// 获取说话成员信息 + /// + /// + /// + public int[] GetMembersState(ref int size) + { + int[] memberState = new int[32]; +#if APOLLO + size = ApolloManager.ApolloVoiceMgr.CallApolloVoiceSDK._GetMemberState(memberState); +#endif + return memberState; + } + + /// + /// 加入小房间 + /// + public void JoinRoom(string url1, string url2, string url3, Int64 roomId, Int64 roomKey, short memberId) + { +#if APOLLO + if (string.IsNullOrEmpty(mOpenID)) { Debug.LogError("openid is nil"); return; } + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._JoinRoom(url1, url2, url3, roomId, roomKey, memberId, mOpenID, 45000); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog(string.Format("JoinRoom Succ {0} {1} {2} {3} {4} {5}", roomId, roomKey, memberId, url1, url2, url3)); + } + else + { + string text = string.Format("JoinRoom Err is {0}", VoiceErr); + Debug.Log(text); + } +#endif + } + + /// + /// 加入大房间 + /// + /// 大房间url + /// 0 主播(最多五人), 1 观众 + /// 后台传递过来的业务ID + public void JoinBigRoom(string urls, int role, uint busniessID, Int64 roomid, Int64 roomkey, short memberid) + { +#if APOLLO + if (string.IsNullOrEmpty(mOpenID)) { Debug.LogError("openid is nil"); return; } + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._JoinBigRoom(urls, role, busniessID, roomid, roomkey, memberid, mOpenID, 45000); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog(string.Format("_JoinBigRoom Succ {0} {1} {2} {3} {4} {5}", roomid, roomkey, urls, role, busniessID, memberid)); + } + else + { + string text = string.Format("_JoinBigRoom Err is {0}", VoiceErr); + Debug.Log(text); + } +#endif + } + + + public bool GetJoinRoomResult() + { + bool isInRoom = false; +#if APOLLO + if (ApolloVoiceMgr != null) + { + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._GetJoinRoomResult(); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_JOIN_SUCC) + { + isInRoom = true; + XDebug.singleton.AddLog("Apollo GetJoinRoomResult Succ"); + } + else + { + string text = string.Format("Apollo GetJoinRoomResult is {0}", VoiceErr); + Debug.Log(text); + } + } +#endif + return isInRoom; + } + + + public bool GetJoinRoomBigResult() + { + bool isInRoom = false; +#if APOLLO + if (ApolloVoiceMgr != null) + { + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._GetJoinRoomBigResult(); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_JOIN_SUCC) + { + isInRoom = true; + XDebug.singleton.AddLog("Apollo _GetJoinRoomBigResult Succ"); + } + else + { + string text = string.Format("Apollo _GetJoinRoomBigResult is {0}", VoiceErr); + XDebug.singleton.AddLog(text); + } + } +#endif + return isInRoom; + } + + + /// + /// 退出小房间 + /// + /// + /// + public void QuitRoom(Int64 roomId, short memberId) + { +#if APOLLO + if (string.IsNullOrEmpty(mOpenID)) { Debug.LogError("openid is nil"); return; } + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._QuitRoom(roomId, memberId, mOpenID); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog(string.Format("QuitRoom Succ {0} {1}", roomId, memberId)); + } + else + { + string text = string.Format("QuitRoom Err is {0}", VoiceErr); + XDebug.singleton.AddLog(text); + } +#endif + } + + /// + /// 退出大房间 + /// + public void QuitBigRoom() + { +#if APOLLO + if (string.IsNullOrEmpty(mOpenID)) { Debug.LogError("openid is nil"); return; } + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._QuitBigRoom(); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog(string.Format("QuitBigRoom!")); + } + else + { + string text = string.Format("QuitBigRoom Err is {0}", VoiceErr); + XDebug.singleton.AddLog(text); + } +#endif + } + + + /// + /// 获取麦克音量 + /// + public int GetSpeakerVolume() + { +#if APOLLO + if (ApolloVoiceMgr != null) + { + return ApolloVoiceMgr.CallApolloVoiceSDK._GetMicLevel(); + } +#endif + return 100; + } + + + /// + /// 设置背景音乐的大小 + /// + /// + public void SetMusicVolum(int nVol) + { +#if APOLLO + if (ApolloVoiceMgr != null) + { + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._SetSpeakerVolume(nVol); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog(string.Format("SetMusicVolum Succ {0}", nVol)); + } + else + { + string text = string.Format("SetMusicVolum Err is {0}", VoiceErr); + XDebug.singleton.AddLog(text); + } + } +#endif + } + + + void OnApplicationPause(bool pause) + { +#if APOLLO + XDebug.singleton.AddLog("apollo puase: " + pause + " mgr: " + (ApolloVoiceMgr != null)); + if (ApolloVoiceMgr != null) + { + if (pause) + { + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._Pause(); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + XDebug.singleton.AddLog(string.Format("OnApplicationPause pause true Succ")); + } + else + { + string text = string.Format("OnApplicationPause Err is {0}", VoiceErr); + Debug.Log(text); + } + } + else + { + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._Resume(); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + m_bCreateEngine = true; + Debug.Log(string.Format("OnApplicationPause pause false Succ")); + } + else + { + string text = string.Format("OnApplicationPause Err is {0}", VoiceErr); + Debug.Log(text); + } + } + } +#endif + } + + + + public int InitApolloEngine(int ip1, int ip2, int ip3, int ip4, byte[] key, int len) + { +#if APOLLO + //int res = ApolloVoiceMgr.CallApolloVoiceSDK._SetMode(2); + //if (res != 0) + // return res; + + ApolloVoiceMgr.CallApolloVoiceSDK._SetServiceInfo(ip1, ip2, ip3, ip4, 80, 60000); + return ApolloVoiceMgr.CallApolloVoiceSDK._SetAuthkey(key, len); +#else + return 0; +#endif + } + + + public int StartRecord(string filename) + { +#if APOLLO + string path = Application.persistentDataPath + "/" + filename; + return ApolloVoiceMgr.CallApolloVoiceSDK._StartRecord(path); +#else + return 0; +#endif + } + + public int StopApolloRecord() + { +#if APOLLO + return ApolloVoiceMgr != null ? ApolloVoiceMgr.CallApolloVoiceSDK._StopRecord(true) : 0; +#else + return 0; +#endif + } + + public int GetApolloUploadStatus() + { +#if APOLLO + return ApolloVoiceMgr != null ? ApolloVoiceMgr.CallApolloVoiceSDK._GetVoiceUploadState() : 0; +#else + return 0; +#endif + } + + public int UploadRecordFile(string filename) + { +#if APOLLO +#if UNITY_EDITOR + string path = Application.persistentDataPath + "/record.sound"; + return 0; +#else + string path = Application.persistentDataPath + "/" + filename; + byte[] filebyte = File.ReadAllBytes(path); + return ApolloVoiceMgr.CallApolloVoiceSDK._SendRecFile(path); +#endif + +#else + return 0; +#endif + } + public string GetFileID() + { +#if APOLLO + ApolloVoiceErr VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._GetVoiceUploadState(); + + if (VoiceErr != ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + return ""; + } + + VoiceErr = (ApolloVoiceErr)ApolloVoiceMgr.CallApolloVoiceSDK._GetFileID(m_strFileID); + if (VoiceErr == ApolloVoiceErr.APOLLO_VOICE_SUCC) + { + return Encoding.Default.GetString(m_strFileID); + } + else + { + return ""; + } +#else + return ""; +#endif + } + + public int GetMicLevel() + { +#if APOLLO + return ApolloVoiceMgr != null ? ApolloVoiceMgr.CallApolloVoiceSDK._GetMicLevel() : 0; +#else + return 0; +#endif + } + + public int StartPlayVoice(string filepath) + { +#if APOLLO + return ApolloVoiceMgr != null ? ApolloVoiceMgr.CallApolloVoiceSDK._PlayFile(filepath) : 0; +#else + return 0; +#endif + } + + public int StopPlayVoice() + { +#if APOLLO + return ApolloVoiceMgr != null ? ApolloVoiceMgr.CallApolloVoiceSDK._StopPlayFile() : 0; +#else + return 0; +#endif + } + + public int SetApolloMode(int mode) + { +#if APOLLO + return ApolloVoiceMgr != null ? ApolloVoiceMgr.CallApolloVoiceSDK._SetMode(mode) : 0; +#else + return 0; +#endif + } +} +#endif diff --git a/Client/Assets/Scripts/Apollo/ApolloManager.cs.meta b/Client/Assets/Scripts/Apollo/ApolloManager.cs.meta new file mode 100644 index 00000000..d6592a99 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/ApolloManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 770421b5fede8d84cb2a96df10783908 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs b/Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs new file mode 100644 index 00000000..012504b7 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs @@ -0,0 +1,1241 @@ +using UnityEngine; +using System.Runtime.InteropServices; +using System; +using System.Text; + +#if UNITY_ANDROID || UNITY_STANDALONE_WIN || UNITY_IPHONE +public class ApolloVoice_lib : IApolloVoice +{ + private static bool bInit = false; + +#if UNITY_ANDROID + private static AndroidJavaClass mApolloVoice = null; +#endif + + + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceCreateEngine([MarshalAs(UnmanagedType.LPArray)] string appID, [MarshalAs(UnmanagedType.LPArray)] string openID); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceDestoryEngine(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceJoinRoom([MarshalAs(UnmanagedType.LPArray)] string url1, [MarshalAs(UnmanagedType.LPArray)]string url2,[MarshalAs(UnmanagedType.LPArray)] string url3, Int64 roomId, Int64 roomKey, short memberId, [MarshalAs(UnmanagedType.LPArray)] string openId, int nTimeOut); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetJoinRoomResult(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceQuitRoom(Int64 roomId, short memberId, [MarshalAs(UnmanagedType.LPArray)] byte [] OpenId); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceOpenMic(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceCloseMic(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceOpenSpeaker(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceCloseSpeaker(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoicePause(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceResume(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetMemberState(int[] memberState, int nSize); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetMemberCount(int nCount); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceStartRecord([MarshalAs(UnmanagedType.LPArray)] string strFullPath, bool bOptim); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceStopRecord(bool bAutoSend, bool bOptim); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetFileID(byte[] filekey, int nSize); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetAppReportInfo([MarshalAs(UnmanagedType.LPArray)] string reportInfo); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSendRecFile([MarshalAs(UnmanagedType.LPArray)] string strFullPath); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceDownloadFile([MarshalAs(UnmanagedType.LPArray)] string strFullPath, [MarshalAs(UnmanagedType.LPArray)] string strFileID, bool bAutoPlay); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoicePlayFile([MarshalAs(UnmanagedType.LPArray)] string strFullPath); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceForbidMemberVoice(int nMemberId, bool bEnable); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetMode(int nMode); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloGetMicLevel(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetSpeakerVolume(int nvol); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetPhoneMode(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetSpeakerLevel(); +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern uint ApolloVoiceGetOfflineFileSize(); +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern float ApolloVoiceGetOfflineFileTime(); + + +// big room + +#if UNITY_IPHONE +[DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN +[DllImport("apollo_voice")] +#endif +private static extern int ApolloVoiceJoinBigRoom([MarshalAs(UnmanagedType.LPArray)] string urls,int role, UInt32 businessID , Int64 roomId, Int64 roomKey, short memberId, [MarshalAs(UnmanagedType.LPArray)] string openId, int nTimeOut); + + +#if UNITY_IPHONE +[DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN +[DllImport("apollo_voice")] +#endif +private static extern int ApolloVoiceGetJoinBigRoomResult(); + +#if UNITY_IPHONE +[DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN +[DllImport("apollo_voice")] +#endif +private static extern int ApolloVoiceQuitBigRoom(); + +#if UNITY_IPHONE +[DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN +[DllImport("apollo_voice")] +#endif +private static extern int ApolloVoiceSetAudience([MarshalAs(UnmanagedType.LPArray)] int [] audience, int count); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetBGMPath([MarshalAs(UnmanagedType.LPArray)] string path); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceStartBGMPlay(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceStopBGMPlay(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoicePauseBGMPlay(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceResumeBGMPlay(); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceEnableNativeBGMPlay(bool bEnable); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetBGMVol(int nvol); + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetBGMPlayState(); + + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetRegion(int region); + + public void Init() + { + + ApolloVoiceLog("apollo voice android sdk init ok!"); + + } + + public int _CreateApolloVoiceEngine(string appID, string openID) + { + ApolloVoiceLog("ApolloVoiceC# API: _CreateApolloVoiceEngine"); + int nRet = ApolloVoiceCreateEngine(appID, openID); + if (0 == nRet) + { + bInit = true; + } + + ApolloVoiceLog("ApolloVoiceC# API: _CreateApolloVoiceEngine nRet=" + nRet); + return nRet; + } + + public int _DestoryApolloVoiceEngine() + { + ApolloVoiceLog("ApolloVoiceC# API: _DestoryApolloVoiceEngine"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + bInit = false; + int nRet = ApolloVoiceDestoryEngine(); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _DestoryApolloVoiceEngine Failed nRet=" + nRet); + return nRet; + } + + public int _JoinRoom(string url1, string url2, string url3, Int64 roomId, Int64 roomKey, short memberId, string OpenId, int nTimeOut) + { + ApolloVoiceLog("ApolloVoiceC# API: _JoinRoom"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + /* + byte[] byteUrl1 = System.Text.Encoding.UTF8.GetBytes(url1); + byte[] byteUrl2 = System.Text.Encoding.UTF8.GetBytes(url2); + byte[] byteUrl3 = System.Text.Encoding.UTF8.GetBytes(url3); + + byte[] byteOpenId = System.Text.Encoding.UTF8.GetBytes(OpenId); + */ + int nRet = ApolloVoiceJoinRoom(url1, url2, url3, roomId, roomKey, memberId, OpenId, nTimeOut); + if (0 == nRet) + { + //ApolloVoiceDelegate.m_RealtimeFuncCall[0] = 1; + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _JoinRoom Failed nRet=" + nRet); + return nRet; + } + + public int _JoinBigRoom(string urls, int role, UInt32 busniessID, Int64 roomId, Int64 roomKey, short memberId, string OpenId, int nTimeOut) + { + ApolloVoiceLog("ApolloVoiceC# API: _JoinBigRoom"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceJoinBigRoom(urls,role, busniessID, roomId, roomKey, memberId, OpenId, nTimeOut); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _JoinBigRoom Failed nRet=" + nRet); + return nRet; + + } + + public int _GetJoinRoomBigResult() + { + ApolloVoiceLog("ApolloVoiceC# API: _GetJoinRoomBigResult"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + return ApolloVoiceGetJoinBigRoomResult(); + } + + public int _QuitBigRoom() + { + ApolloVoiceLog("ApolloVoiceC# API: _QuitBigRoom"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceQuitBigRoom(); + return nRet; + + } + + public int _GetJoinRoomResult() + { + ApolloVoiceLog("ApolloVoiceC# API: _GetJoinRoomResult"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + return ApolloVoiceGetJoinRoomResult(); + } + + + public int _QuitRoom(Int64 roomId, short memberId, String OpenId) + { + ApolloVoiceLog("ApolloVoiceC# API: _QuitRoom"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + + byte[] byteOpenId = System.Text.Encoding.ASCII.GetBytes(OpenId); + int nRet = ApolloVoiceQuitRoom(roomId, memberId, byteOpenId); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _QuitRoom Failed nRet=" + nRet); + + return nRet; + } + + public int _OpenMic() + { + ApolloVoiceLog("ApolloVoiceC# API: _OpenMic"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + + int nRet = ApolloVoiceOpenMic(); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _OpenMic Failed nRet=" + nRet); + return nRet; + } + + public int _CloseMic() + { + ApolloVoiceLog("ApolloVoiceC# API: _CloseMic"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + + + int nRet = ApolloVoiceCloseMic(); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _CloseMic Failed nRet=" + nRet); + return nRet; + } + + public int _OpenSpeaker() + { + ApolloVoiceLog("ApolloVoiceC# API: _OpenSpeaker"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceOpenSpeaker(); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _OpenSpeaker Failed nRet=" + nRet); + + return nRet; + } + + public int _CloseSpeaker() + { + ApolloVoiceLog("ApolloVoiceC# API: _ClosenSpeaker"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceCloseSpeaker(); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _CloseSpeaker Failed nRet=" + nRet); + return nRet; + } + + public int _Resume() + { + ApolloVoiceLog("ApolloVoiceC# API: _Resume"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceResume(); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _Resume Failed nRet=" + nRet); + return nRet; + } + + public int _Pause() + { + ApolloVoiceLog("ApolloVoiceC# API: _Pause"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoicePause(); + if (0 == nRet) + { + return 0; + } + ApolloVoiceLog("ApolloVoiceC# API: _Pause Failed nRet=" + nRet); + return nRet; + } + + /* + Get Member State, the audioengine return format is : memberId +'#' + memberState + '#' + memberId + '#' + memberState + * memberId and memberState is string format + */ + public int _GetMemberState(int[] memberState) + { + // ApolloVoiceLog("ApolloVoiceC# API: _GetMemberState"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nSize = memberState.Length; + + //StringBuilder strmemberState = new StringBuilder(nSize * 4); + //c++ clear the buffer, + int nRet = ApolloVoiceGetMemberState(memberState, nSize); + if( nRet > 0) + { + for(int i = 0; i < nRet; ++i) + { + ApolloVoiceLog("GetMemberState Result " + memberState[i]); + } + } + + + return nRet; + } + + public int _StartRecord(string strFullPath) + { + ApolloVoiceLog("ApolloVoiceC# API: _StartRecord"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceStartRecord(strFullPath, false); + + return nRet; + } + + public int _StopRecord(bool bAutoSend) + { + ApolloVoiceLog("ApolloVoiceC# API: _StopRecord"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + + int nRet = ApolloVoiceStopRecord(bAutoSend, false); + + return nRet; + } + +#if UNITY_IPHONE + public int _StartRecord(string strFullPath, bool bOptim) + { + ApolloVoiceLog("ApolloVoiceC# API: _StartRecord"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceStartRecord(strFullPath, bOptim); + + return nRet; + } + + public int _StopRecord(bool bAutoSend, bool bOptim) + { + ApolloVoiceLog("ApolloVoiceC# API: _StopRecord"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + + int nRet = ApolloVoiceStopRecord(bAutoSend, bOptim); + + return nRet; + } +#endif + + public int _SetMemberCount(int nCount) + { + ApolloVoiceLog("ApolloVoiceC# API: _SetMemberCount"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + + int nRet = ApolloVoiceSetMemberCount(nCount); + + return nRet; + } + + public int _GetFileID(byte [] fileKey) + { + ApolloVoiceLog("ApolloVoiceC# API: _GetFileKey"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nSize = fileKey.Length; + int nRet = ApolloVoiceGetFileID(fileKey, nSize); + ApolloVoiceLog("fileID buffer size " + nSize + " fileID = " + Encoding.Default.GetString(fileKey)); + + return nRet; + } + + public int _SetAppReportInfo(string reportInfo) + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceSetAppReportInfo(reportInfo); + return nRet; + } + + public int _SendRecFile(string strFullPath) + { + ApolloVoiceLog("ApolloVoiceC# API: _SendRecFile"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + //ApolloVoiceDelegate.m_OfflineFuncCall[0] = 1; + return ApolloVoiceSendRecFile(strFullPath); + } + + public int _PlayFile(string strFullPath) + { + ApolloVoiceLog("ApolloVoiceC# API: _PlayFile"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + //ApolloVoiceDelegate.m_OfflineFuncCall[2] = 1; + return ApolloVoicePlayFile(strFullPath); + } + + public int _DownloadVoiceFile(string strFullPath, string strFileID, bool bAutoPlay) + { + ApolloVoiceLog("ApolloVoiceC# API: _DownloadVoiceFile"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + //ApolloVoiceDelegate.m_OfflineFuncCall[1] = 1; + return ApolloVoiceDownloadFile(strFullPath, strFileID, bAutoPlay); + } + + public int _ForbidMemberVoice(int nMemberId, bool bEnable) + { + ApolloVoiceLog("ApolloVoiceC# API: _ForbidMemberVoice"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceForbidMemberVoice(nMemberId, bEnable); + } + + public int _SetMode(int nMode) + { + ApolloVoiceLog("ApolloVoiceC# API: _SetMode"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceSetMode(nMode); + } + + public int _GetMicLevel() + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloGetMicLevel(); + } + + public int _SetSpeakerVolume(int nVol) + { + ApolloVoiceLog("ApolloVoiceC# API: _SetSpeakerVolume"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceSetSpeakerVolume(nVol); + } + + public int _GetSpeakerLevel() + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + return ApolloVoiceGetSpeakerLevel(); + } + + public uint _GetOfflineFileSize() + { + if(!bInit) + { + return 0; + } + return (uint)ApolloVoiceGetOfflineFileSize(); + } + public float _GetOfflineFileTime() + { + if(!bInit) + { + return 0; + } + return ApolloVoiceGetOfflineFileTime(); + } + + public int _SetBGMPath(string path) + { + ApolloVoiceLog("ApolloVoiceC# API: _SetBGMPath"); + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceSetBGMPath(path); + } + public int _StartBGMPlay() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceStartBGMPlay(); + } + public int _StopBGMPlay() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceStopBGMPlay(); + } + public int _PauseBGMPlay() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoicePauseBGMPlay(); + } + public int _ResumeBGMPlay() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceResumeBGMPlay(); + } + public int _EnableNativeBGMPlay(bool bEnable) + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceEnableNativeBGMPlay(bEnable); + + } + public int _SetBGMVol(int nvol) + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceSetBGMVol(nvol); + } + + public int _GetBGMPlayState() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceGetBGMPlayState(); + + + } + public int _SetAudience(int []audience) + { + return ApolloVoiceSetAudience (audience, audience.Length); + } + + public int _SetRegion(ApolloVoiceRegion region) + { + ApolloVoiceLog("ApolloVoiceC# API: _SetRegion"); + if (!bInit) + { + return 0; + } + + int nRet = ApolloVoiceSetRegion((int)region); + return nRet; + } + +//-----------------------------------------HTTP Upload/Download----------------------------- +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetServiceInfo(int nIP0, int nIP1, int nIP2, int nIP3, int nPort, int nTimeout); + + public int _SetServiceInfo(int nIP0, int nIP1, int nIP2, int nIP3, int nPort, int nTimeout) + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceSetServiceInfo(nIP0, nIP1, nIP2, nIP3, nPort, nTimeout); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetAuthkey([MarshalAs(UnmanagedType.LPArray)] byte[] strAuthkey, int nLength); + + public int _SetAuthkey(byte[] strAuthkey, int nLength) + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceSetAuthkey(strAuthkey, nLength); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetDownloadState(); + + public int _GetVoiceDownloadState() + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceGetDownloadState(); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetUploadState(); + + public int _GetVoiceUploadState() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceGetUploadState(); + } + +#if UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] + private static extern int ApolloVoiceTestMic(); +#endif + + public int _TestMic() + { +#if UNITY_ANDROID || UNITY_STANDALONE_WIN + ApolloVoiceLog("ApolloVoiceC# API: _TestMic"); + if (!bInit) + { + return 0; + } + + return ApolloVoiceTestMic(); +#else + return 0; +#endif + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetPlayFileState(); + + public int _GetPlayFileState() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceGetPlayFileState(); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceStopPlayFile(); + public int _StopPlayFile() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceStopPlayFile(); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetSubBID([MarshalAs(UnmanagedType.LPArray)] string cszSubBID, int nLength); + + public int _SetSubBID(string strSubBID) + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceSetSubBID(strSubBID, strSubBID.Length); + } + +/////////////////////////////////////////////////////////////////////////////// +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceEncodeWAVFileForPESQ([MarshalAs(UnmanagedType.LPArray)] string strSrcFile,[MarshalAs(UnmanagedType.LPArray)] string strDstFile); + + public int _EncodeWAVFile(string strSrcFile, string strDstFile) + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceEncodeWAVFileForPESQ(strSrcFile, strDstFile); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceDecodeToWAVEFile([MarshalAs(UnmanagedType.LPArray)] string strSrcFile,[MarshalAs(UnmanagedType.LPArray)] string strDstFile); + + public int _DecodeWAVFile(string strSrcFile, string strDstFile) + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceDecodeToWAVEFile(strSrcFile, strDstFile); + } +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetWAVEFileProcessedState(); + + public int _GetWAVEFileProcessedState() + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceGetWAVEFileProcessedState(); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceEnableLog(bool bEnable); + + public int _EnableLog(bool bEnable) + { + if(!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceEnableLog(bEnable); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceSetCodec(int mode, int codec); + + public int _SetCodec(int mode, int codec) + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + return ApolloVoiceSetCodec( mode, codec ); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceDownloadMusicFile([MarshalAs(UnmanagedType.LPArray)] string strUrl, [MarshalAs(UnmanagedType.LPArray)] string strPath, int nTimeout); + + public int _DownMusicFile(string strUrl, string strPath, int nTimeout) + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + return ApolloVoiceDownloadMusicFile(strUrl, strPath, nTimeout); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceGetDownloadMusicFileState(); + + public int _GetDownloadMusicFileState() + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceGetDownloadMusicFileState(); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVocieSetAnchorUsed(bool bEnable); + public int _SetAnchorUsed(bool bEnable) + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVocieSetAnchorUsed(bEnable); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern float ApolloVoiceGetLostRate(); + public float _GetLostRate() + { + return ApolloVoiceGetLostRate(); + } + +// #if UNITY_IPHONE +// [DllImport("__Internal")] +// #elif UNITY_ANDROID || UNITY_STANDALONE_WIN +// [DllImport("apollo_voice")] +// #endif +// private static extern int ApolloVoiceEnableCaptureMicrophone(bool bEnable); +// public int _EnableCaptureMicrophone(bool bEnable) +// { +// if (!bInit) +// { +// return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; +// } +// return ApolloVoiceEnableCaptureMicrophone(bEnable); +// } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceQuitDownloadMusicFile(); + + public int _QuitDownMusicFile() + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + return ApolloVoiceQuitDownloadMusicFile(); + } + + [System.Diagnostics.Conditional("DEBUG_VOICE")] + private void ApolloVoiceLog(string logStr) + { + Debug.Log(logStr); + } + + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN + [DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceCaptureMicrophone(bool bEnable); + public int _CaptureMicrophone(bool bEnable) + { + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceCaptureMicrophone(bEnable); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN +[DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceEnableSoftAec(bool bEnable); + + public int _EnableSoftAec(bool bEnable) + { + ApolloVoiceLog("ApolloVoiceC# API: _EnableSoftAecIOS"); + if (!bInit) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + + int nRet = ApolloVoiceEnableSoftAec(bEnable); + + return nRet; + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN +[DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceInvoke(uint nCmd, uint nParam1, uint nParam2, [MarshalAs(UnmanagedType.LPArray)] int[] pOutput); + + public int _Invoke(uint nCmd, uint nParam1, uint nParam2, int[] pOutput) + { + ApolloVoiceLog("ApolloVoiceC# API: _Invoke"); + if( !bInit ) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceInvoke(nCmd, nParam1, nParam2, pOutput); + } + +#if UNITY_IPHONE + [DllImport("__Internal")] +#elif UNITY_ANDROID || UNITY_STANDALONE_WIN +[DllImport("apollo_voice")] +#endif + private static extern int ApolloVoiceEnableSpeakerOn(bool bEnable); + + public int _SetSpeakerOn(bool bEnable) + { + ApolloVoiceLog("ApolloVoiceC# API: _SetSpeakerOn"); + if( !bInit ) + { + return (int)ApolloVoiceErr.APOLLO_VOICE_STATE_ERR; + } + return ApolloVoiceEnableSpeakerOn(bEnable); + } + +} +#endif diff --git a/Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs.meta b/Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs.meta new file mode 100644 index 00000000..c8407d69 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/ApolloVoice_lib.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c7b3c32600dcf064995ba3056407c641 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Client/Assets/Scripts/Apollo/BroadcastManager.cs b/Client/Assets/Scripts/Apollo/BroadcastManager.cs new file mode 100644 index 00000000..6bf7427b --- /dev/null +++ b/Client/Assets/Scripts/Apollo/BroadcastManager.cs @@ -0,0 +1,338 @@ +#if !DISABLE_PLUGIN + + +using System.Collections.Generic; +using System.Text; +using UnityEngine; +using XUtliPoolLib; + +public class BroadcastManager : MonoBehaviour, IBroardcast +{ + + + private static string m_token = "", m_openId = "", m_appid = ""; + private static QGameKit.LoginPlatform m_platf = QGameKit.LoginPlatform.QQ; + private static GameObject m_gameobject; + private static QGameKit.ShareContent m_shareContent; +#if BROADCAST + private bool isConfigOpen = true; + private static bool enableDanku = false; +#endif + + /// + /// 初始化 + /// + public void ToStart() + { +#if BROADCAST + QGameKit.CaptureType captureType = QGameKit.CaptureType.AudioApolloVoice | QGameKit.CaptureType.VideoCapture; +#if Release || Publish + QGameKit.Setup("1105309683", "203090", captureType, UserAccountDelegate, QGameKit.Environment.Release); +#else + QGameKit.Setup("1105309683", "203090", captureType, UserAccountDelegate, QGameKit.Environment.Release); +#endif + if (!enableDanku) + { + QGameKit.SetDanmakuEnabled(true); + enableDanku = true; + } + QGameKit.SetLogDelegate(LogDelegate); + QGameKit.SetCommentReceiveDelegate(CommentReceiveDelegate); + QGameKit.SetLiveStatusDelegate(LiveStatusChangedDelegate); + QGameKit.SetShareDelegate(ShareDelegate); + QGameKit.SetErrorCodeDelegate(ErrorCodeListenerDelegate); +#endif + } + + + void OnDestroy() + { + TearDown(); + } + + + /// + /// qgamekit很多回调都是在多线程里实现的 + /// 不能直接在回调中调用unity的API + /// + private void Update() + { + if (m_gameobject != null && m_shareContent != null) + { + DoSahre(); + m_shareContent = null; + } + } + + + public static QGameKit.UserAccount UserAccountDelegate() + { + QGameKit.UserAccount account = new QGameKit.UserAccount(); + account.platform = m_platf; // QGameKit.LoginPlatform.WeChat + account.appId = m_appid; // ⼿手Q或微信开放平台申请登录能⼒力时分配的 AppID + account.id = m_openId; // 请赋值为⼿手Q或微信登录后获得的 OpenID + account.token = m_token; // 请赋值为⼿手Q或微信登录后获得的AccessToken + // Debug.Log("UserAccountDelegate platf: " + m_platf + " openid: " + m_openId + " token: " + m_token); + return account; // 将⽤用户信息返回给 SDK + } + + + public bool IsBroadState() + { +#if BROADCAST + return true && isConfigOpen; +#else + return false; +#endif + } + + public bool ShowCamera(bool show) + { + Debug.Log("showcamera:" + show); +#if BROADCAST + if (QGameKit.IsSupportCamera() && isConfigOpen) + { + if (show) + { + return QGameKit.ShowCamera(); + } + else + { + QGameKit.HideCamera(); + return true; + } + } + else + { + Hotfix.LuaShowSystemTip("系统版本太低,不支持开启摄像头"); + return false; + } +#else + return false; +#endif + } + + public void SetAccount(int platf, string openid, string token) + { +#if BROADCAST + m_gameobject = gameObject; + int open = PlayerPrefs.GetInt("BroadcastOpen"); + isConfigOpen = open == 1; + if (isConfigOpen) + { + m_openId = openid; + m_token = token; + if (platf == 3) + { + m_platf = QGameKit.LoginPlatform.QQ; + m_appid = "1105309683"; + } + else if (platf == 4) + { + m_platf = QGameKit.LoginPlatform.WeChat; + m_appid = "wxfdab5af74990787a"; + } + else + { + m_platf = QGameKit.LoginPlatform.Guest; + m_appid = "1105309683"; + } + ToStart(); + } +#endif + } + + + /// + /// 反初始化 + /// + public void TearDown() + { +#if BROADCAST + if (isConfigOpen && !string.IsNullOrEmpty(m_openId)) + { + Debug.Log("tear down!"); + QGameKit.TearDown(); + } +#endif + } + + /// + /// 开始直播 + /// + public void StartLiveBroadcast(string title, string desc) + { +#if BROADCAST + if (isConfigOpen) + { + Debug.Log("Start live broadcast"); + QGameKit.LiveStatus code = (QGameKit.LiveStatus)QGameKit.GetErrorCode(); + if (code == QGameKit.LiveStatus.Error) + { + QGameKit.Reset(); + } + QGameKit.StartLiveBroadcast(title, desc); + } +#endif + } + + + /// + /// 停止直播 + /// + public void StopBroadcast() + { +#if BROADCAST + if (isConfigOpen) + { + Debug.Log("stop live broadcast!"); + QGameKit.StopLiveBroadcast(); + } +#endif + } + + /// + /// 获取当前状态 + /// + public int GetState() + { +#if BROADCAST + if (isConfigOpen) + { + QGameKit.LiveStatus code = (QGameKit.LiveStatus)QGameKit.GetErrorCode(); + Debug.Log("GetState " + code); + return (int)code; + } + else return 0; +#else + return 0; +#endif + } + + + /// + /// 进入直播大厅 + /// + public void EnterHall() + { +#if BROADCAST + if (isConfigOpen) + { + Debug.Log("Hall"); + QGameKit.EnterLiveHall(); + } +#endif + } + + // 游戏监听并处理状态变化 + public static void LiveStatusChangedDelegate(QGameKit.LiveStatus newState) + { + // Debug.Log("live status: " + newState); + if (m_uiUtility == null || m_uiUtility.Deprecated) + m_uiUtility = XInterfaceMgr.singleton.GetInterface(XCommon.singleton.XHash("IUiUtility")); + if (newState == QGameKit.LiveStatus.LiveStarting || newState == QGameKit.LiveStatus.LiveStarted) + { + m_uiUtility.StartBroadcast(true); + ApolloManager.sington.Capture(true); + } + else if (newState == QGameKit.LiveStatus.LiveStopping || newState == QGameKit.LiveStatus.LiveStopped) + { + m_uiUtility.StartBroadcast(false); + ApolloManager.sington.Capture(false); + } + } + + public static void ErrorCodeListenerDelegate(int errorCode, string errorMessage) + { + // Debug.Log("ErrorCodeListenerDelegate...errorCode=" + errorCode + ", errorMessage=" + errorMessage); + } + + public static void LogDelegate(string log) + { + Debug.Log(log); + } + + static IUiUtility m_uiUtility; + public static void CommentReceiveDelegate(List comments) + { + //if (m_uiUtility == null || m_uiUtility.Deprecated) + // m_uiUtility = XInterfaceMgr.singleton.GetInterface(XCommon.singleton.XHash("IUiUtility")); + //for (int i = 0; i < comments.Count; i++) + //{ + // // Debug.Log("comment index " + i); + // QGameKit.LiveComment comment = comments[i]; + // if (m_uiUtility != null) m_uiUtility.PushBarrage(UTF8String(comment.nick), UTF8String(comment.content)); + + //} + } + + + public static string UTF8String(string input) + { + UTF8Encoding utf8 = new UTF8Encoding(); + return utf8.GetString(utf8.GetBytes(input)); + } + + public static void ShareDelegate(QGameKit.ShareContent shareContent) + { + //Debug.Log("ShareContent title " + shareContent.title); + m_shareContent = shareContent; + } + + + private void DoSahre() + { + XPlatform platf = m_gameobject.GetComponent(); + Dictionary jsondata = new Dictionary(); + jsondata["scene"] = "Session"; + jsondata["targetUrl"] = m_shareContent.targetUrl; + jsondata["imageUrl"] = m_shareContent.imageUrl; + jsondata["title"] = m_shareContent.title; + jsondata["description"] = m_shareContent.description; + jsondata["summary"] = ""; + string json = MiniJSON.Json.Serialize(jsondata); + platf.SendGameExData("share_send_to_struct_qq", json); + } + + +#if UNITY_EDITOR + void OnGUI() + { +#if BROADCAST_TEST + if (GUI.Button(new Rect(20, 20, 140, 60), "Start")) + { + StartLiveBroadcast("龙之谷dragonnest", "I just want to test for broadcast..."); + } + if (GUI.Button(new Rect(20, 100, 140, 60), "Stop")) + { + StopBroadcast(); + } + if (GUI.Button(new Rect(20, 180, 140, 60), "Reset")) + { + Debug.Log("reset live broadcast!"); + QGameKit.Reset(); + } + if (GUI.Button(new Rect(20, 260, 140, 60), "Hall")) + { + EnterHall(); + } + if (GUI.Button(new Rect(20, 340, 140, 60), "HallInGame")) + { + Debug.Log("HallInGame"); + QGameKit.EnterLiveHallInGame(); + } + if (GUI.Button(new Rect(20, 420, 140, 60), "State")) + { + GetState(); + } + if (GUI.Button(new Rect(20, 500, 140, 60), "TearDown")) + { + TearDown(); + } +#endif + } +#endif + +} + +#endif diff --git a/Client/Assets/Scripts/Apollo/BroadcastManager.cs.meta b/Client/Assets/Scripts/Apollo/BroadcastManager.cs.meta new file mode 100644 index 00000000..70f63bba --- /dev/null +++ b/Client/Assets/Scripts/Apollo/BroadcastManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a2281fdd0bbdd544fba63d355c4a52de +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs b/Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs new file mode 100644 index 00000000..71ef82db --- /dev/null +++ b/Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs @@ -0,0 +1,612 @@ +using UnityEngine; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; + +#region interface about platform call + +public enum ApolloVoiceRegion { + // REGION_CHINA = 156, + REGION_CHINA = 1888, + REGION_TAIWAN = 158, + REGION_HONGKONG = 344, + REGION_USA = 840, + REGION_THAILAND = 764, + REGION_INDIA = 356, + REGION_VIETNAM = 704, + REGION_GERMANY = 276, + REGION_BRAZIL = 76, + REGION_MALAYSIA = 458, + REGION_KOREA= 410, +}; + +public enum ApolloVoiceErr +{ + APOLLO_VOICE_SUCC = 0, + APOLLO_VOICE_NONE = 1, + APOLLO_VOICE_UNKNOWN = 3, + APOLLO_VOICE_STATE_ERR = 4, + APOLLO_VOICE_CREATE_ERR = 5, + APOLLO_VOICE_IN_ROOM = 6, + APOLLO_VOICE_PATH_NULL = 7, + APOLLO_VOICE_PATH_ACCESS = 8, + APOLLO_VOICE_UPLOAD = 9, + APOLLO_VOICE_DOWNLOAD = 10, + APOLLO_VOICE_HTTP_BUSY = 11, + APOLLO_VOICE_RECORDING = 12, + APOLLO_VOICE_OPENID = 13, + APOLLO_VOICE_AUDIENCE = 14, + + APOLLO_VOICE_JOIN_TIMEOUT = 50, + APOLLO_VOICE_JOIN_SUCC = 51, + APOLLO_VOICE_JOIN_NOTIN = 52, + APOLLO_VOICE_JOIN_FAIL = 53, + APOLLO_VOICE_JOIN_URL = 54, + + APOLLO_VOICE_NET_TIMEOUT = 121, + + APOLLO_VOICE_PERMISSION_MIC = 200, + APOLLO_VOICE_SPEAKER = 201, + APOLLO_VOICE_EMPTY_AUTHKEY = 202, + APOLLO_VOICE_EMPTY_FILE = 203, + APOLLO_VOICE_EMPTY_OPENID = 204, + APOLLO_VOICE_EMPTY_FILE_ID = 205, + + APOLLO_VOICE_TVE_CREATE = 300, + APOLLO_VOICE_TVE_NULL = 301, + APOLLO_VOICE_TVE_STOP = 302, + APOLLO_VOICE_TVE_INIT = 303, + APOLLO_VOICE_TVE_START = 304, + APOLLO_VOICE_TVE_CREATE_NTFY = 305, + APOLLO_VOICE_TVE_FILEKEY_NULL = 306, + APOLLO_VOICE_TVE_BUF_NULL = 307, + APOLLO_VOICE_TVE_PLAYSOUND = 308, + APOLLO_VOICE_TVE_FORBID = 309, + APOLLO_VOICE_CHANGE_MODE = 310, + + APOLLO_VOICE_CDNV_CREATE = 400, + APOLLO_VOICE_CDNV_NULL = 401, + APOLLO_VOICE_CDNV_QUIT = 402, + APOLLO_VOICE_CDNV_CREATE_NTFY = 403, + APOLLO_VOICE_HTTP_ERROR_DATA = 404, + APOLLO_VOICE_HTTP_BADPARAM = 405, + + APOLLO_VOICE_PARAM_NULL = 406, + APOLLO_VOICE_STOP_PLAY_FILE = 407, + APOLLO_VOICE_CDNV_URL = 408, + + APOLLO_VOICE_PAUSED = 409, + APOLLO_VOICE_WRONG_MODE = 410, + APOLLO_VOICE_RECORD_FILE_FAILED = 411, + APOLLO_VOICE_CLOSE_MIC = 412, + APOLLO_VOICE_FILE_OPERATION = 413, + APOLLO_VOICE_HTTP_INIT = 414, + APOLLO_VOICE_HTTP_GET = 415, +} + +public enum ApolloVoiceRole +{ + ANCHOR = 1, + AUDIENCE = 2, +} + +public enum ApolloVoiceMode +{ + REALTIME_VOICE = 0, //实时语音 + OFFLINE_VOICE = 1, //离线语音 + STT_VOICE = 2, //离线转文字语音 +} + +public interface IApolloVoice +{ + #region BasicFunctions + + /** + * Init Environment. + * @result: 0 for succ, otherwise failed + */ + void Init(); + + /** + * Create Apollo Voice Engine. + * @param appID: The project appID + * @param openID: the user's openID + * @result: 0 for succ, otherwise failed + */ + int _CreateApolloVoiceEngine(string appID, string openID = null); + + /** + * Destory Apollo Voice Engine. + * @result: 0 for succ, otherwise failed + */ + int _DestoryApolloVoiceEngine(); + + /** + * Set Engine work mode. + * @param nMode: 0 for realtime chat, 1 for offline file record, 2 for STT(Sound To Text). + * @result: 0 for succ, otherwise failed + */ + int _SetMode(int nMode); + + /** + * Pause the voice engine(while App switch to background, you need call this function). + * @result: 0 for succ, otherwise failed + */ + int _Pause(); + + /** + * Resume the voice engine(while App switch back to foreground, you need call this function). + * @result: 0 for succ, otherwise failed + */ + int _Resume(); + + /** + * Set the codec for VoiceEngine. + * default: realtime use opus, offline use Speex + * default codec is good enough, unless you have other requirement, you should never change the codec + * @param mode: 0 for realtime, 1 for offline + * @param codec: the codec you need to use in current mode + * QT_CODEC_PCM = 4097, + QT_CODEC_SPEEX_MONO = 4098, + QT_CODEC_SPEEX_MS = 4098, + QT_CODEC_CELT_0_11_1 = 4099, + QT_CODEC_SPEEX_ST = 4100, + QT_CODED_SPEEX_IS = 4101, + QT_CODEC_OPUS_1_1_0 = 4102, + QT_CODEC_SILK_1_0_8 = 4103, + QT_CODEC_AMRWB = 4104, + QT_CODEC_AMRWBPLUS = 4105, + QT_CODEC_EAACPLUS = 4106, + QT_CODEC_TEST = 4107, + QT_CODEC_G718 = 4108, + QT_CODEC_AMR_NB = 4109, + QT_CODEC_MP3 = 4110, + * @result: 0 for succ, otherwise failed + */ + int _SetCodec(int mode, int codec); + + /** + * Get latest Voice Frame Level captured by Mic. + * @result: the captured mic volume, the range is 0 - 0x0FFFF + */ + int _GetMicLevel(); + + /** + * Set the Amplification factor of speaker volume. + * @param nVol: On Mobile Platform, 0 is Silence, Max is 800 times. On Windows platform, the range is + * set speaker's volume directly, the range is 0 - 100 + * @result: 0 for succ, otherwise failed + */ + int _SetSpeakerVolume(int nVol); + + /** + * Get the Amplification factor of voice. + * @result: the enlargement times + */ + int _GetSpeakerLevel(); + + /** + * Open Or Close VoiceEngine's Log. + * @param bEnable: true for enable, false for disable + * @result: 0 for succ, otherwise failed + */ + int _EnableLog(bool bEnable); + + /** + * Test Mic is enable or not. + * @result: 0 for succ, APOLLO_VOICE_RECORDING for recording now, otherwise failed + */ + int _TestMic(); + +// /** +// * enable or disable capture microphone +// */ +// int _EnableCaptureMicrophone(bool bEnable + /** + * + */ + int _CaptureMicrophone(bool bEnable); + #endregion + + + #region Functions For RealtimeVoice Only + /** + * Join CDN Small Voice Room(Only Support up to 20 members in one room, generally used for 5V5 Scenes, + * Only Support 5 people talking at the same time). + * @param url1,url2,url3: CDN address + * @param roomid: voice room ID, + * @param memberid: user'id in voice room + * @param roomKey: user' roomkey in voice room + * @param openid: user's login id + * @param nTimeout: the max join room time + * @result: 0 represent function executed succ(does not mean join succ), otherwise failed + */ + int _JoinRoom(string url1, string url2, string url3, Int64 roomId, Int64 roomKey, short memberId, string OpenId, int nTimeOut); + + /** + * Get JoinRoom Result. + * @param nMode: 0 for realtime chat, 1 for offline file record, 2 for STT(Sound To Text) + * @result: 0 for succ, otherwise failed + */ + int _GetJoinRoomResult(); + + /** + * Quit VoiceRoom. + * @param roomId: user's roomid + * @param memberId: user's memberid + * @param openid: user's login id + * @result: 0 for succ, otherwise failed + */ + int _QuitRoom(Int64 roomId, short memberId, string OpenId); + + /** + * Join CDN Big Voice Room(Used for thousands of people playing in one room at the same time, Still Only Support 5 people talking + * at the same time). + * @param urls: CDN address + * @param role: Players role, 0 for anchor(up to 5 people), 1 for audience(no limits) + * @param busniessID: the busniessID for this project + * @param memberid: user'id in voice room + * @param roomKey: user' roomkey in voice room + * @param openid: user's login id + * @param nTimeout: the max join room time + * @result: 0 represent function executed succ(does not mean join succ), otherwise failed + */ + int _JoinBigRoom(string urls, int role, UInt32 busniessID, Int64 roomId, Int64 roomKey, short memberId, string OpenId, int nTimeOut); + + /** + * Get JoinRoom Result. + * @param nMode: 0 for realtime chat, 1 for offline file record, 2 for STT(Sound To Text) + * @result: 0 for succ, other failed; + */ + int _GetJoinRoomBigResult(); + + /** + * Quit Big Voice Room. + * @result: 0 for succ, otherwise failed + */ + int _QuitBigRoom(); + + /** + * Open Mic. + * @result: 0 for succ, otherwise failed + */ + int _OpenMic(); + + /** + * Close Mic. + * @result: 0 for succ, otherwise failed + */ + int _CloseMic(); + + /** + * Open Speaker. + * @result: 0 for succ, otherwise failed + */ + int _OpenSpeaker(); + + /** + * Close Speaker. + * @result: 0 for succ, otherwise failed + */ + int _CloseSpeaker(); + + /* + * Get member Speaking State. + * @param memberState: the format is: MemberID(4 Byte) | State (4 Byte)|MemberID (4 Byte)| State(4 Byte)...... + * state : 1 for speaking ,0 for not speaking right now + * @result: 0 for succ, otherwise failed + */ + int _GetMemberState(int [] memberState); + + /** + * Set room member count. + * @param nCount: the num of member + * @result: 0 for succ, otherwise failed + */ + int _SetMemberCount(int nCount); + + #region BGM Play + /** + * Set the BGM path. + * @param path: the BGM path + * @result: 0 for succ, otherwise failed + */ + int _SetBGMPath(string path); + + /** + * Start playing BGM. + * @result: 0 for succ, otherwise failed + */ + int _StartBGMPlay(); + + /** + * Stop playing BGM. + * @result: 0 for succ, otherwise failed + */ + int _StopBGMPlay(); + + /** + * Pause playing BGM. + * @result: 0 for succ, otherwise failed + */ + int _PauseBGMPlay(); + + /** + * Resume playing BGM. + * @result: 0 for succ, otherwise failed + */ + int _ResumeBGMPlay(); + + /* + * get BGM play state. + * @ param: pState:0 for playing , + * 1 for stop + */ + + int _GetBGMPlayState(); + + /** + * You can hear the bgm in your own device. + * @param bEnable: default is true, and you can not set false currently + * @result: 0 for succ, otherwise failed + */ + int _EnableNativeBGMPlay(bool bEnable); + + /** + * Set BGM Playing volume. + * @param nvol:which want set volume of BGM Playing. + * @result: 0 for succ, otherwise failed + */ + int _SetBGMVol(int nvol); + + /** + * Download music file + */ + int _DownMusicFile(string strUrl, string strPath, int nTimeout); + + /** + * get music file download state + * result: reference ApolloVoiceErr + */ + int _GetDownloadMusicFileState(); + + /** + * quit download music file + */ + int _QuitDownMusicFile(); + #endregion + + #endregion + + #region Functions For Offline Voice Only + /** + * Start record. + * @param strFullPath: the place to restore your local record file + * @result: 0 for succ, otherwise failed + */ + int _StartRecord(string strFullPath); +#if UNITY_IPHONE + /** + * Start record. + * @param strFullPath: the place to restore your local record file + * @param bOptim: record audio do not enter voip mode, may record BGM + * @result: 0 for succ, otherwise failed + */ + int _StartRecord(string strFullPath, bool bOptim); + + /** + * Stop record. + * @param bAutoSend: decide whether auto send local file to server + * @result: 0 for succ, otherwise failed + */ + int _StopRecord(bool bAutoSend, bool bOptim); +#endif + + /** + * Stop record. + * @param bAutoSend: decide whether auto send local file to server + * @result: 0 for succ, otherwise failed + */ + int _StopRecord(bool bAutoSend); + + /** + * Get last file ID. + * @param fileKey: the latest upload file key + * @result: 0 for succ, otherwise failed + */ + int _GetFileID(byte [] fileKey); + + /** + * send rec file. + * @param strFullPath: local record file stored place + * @result: 0 for succ, otherwise failed + */ + int _SendRecFile(string strFullPath); + + /** + * Set app report info. + * @param reportInfo: qos report info,call after SetMode + * @result: 0 for succ, otherwise failed + */ + int _SetAppReportInfo(string reportInfo); + + /** + * play rec file. + * @param strFullPath: local record file stored place + * @result: 0 for succ, otherwise failed + */ + int _PlayFile(string strFullPath); + + /** + * download voice file. + * @param strFullPath: local record file stored place + * @param strFileID: latest uploaded file id + * @param bAutoPlay: Currently unimplemented! It should be false + * @result: 0 for succ, otherwise failed + */ + int _DownloadVoiceFile(string strFullPath, string strFileID, bool bAutoPlay); + + /** + * forbid one's voice. + * @param nMemberId: the member id + * @param bEnable: true for disable one's speaking, false for enable + * @result: 0 for succ, otherwise failed + */ + int _ForbidMemberVoice(int nMemberId, bool bEnable); + + /** + * Set Offline Voice Server info. + * @param nIP0, nIP1, nIP2, nIP3: the OfflineVoice server url, you can get all of it from game server + * @param nPort: ip port + * @param nTimeout: the unit is ms + * @result: 0 for succ, otherwise failed + */ + int _SetServiceInfo(int nIP0, int nIP1, int nIP2, int nIP3, int nPort, int nTimeout); + + /** + * Set Authkey info. + * @param strAuthkey: the authkey + * @param nLength: the length of authkey + * @result: 0 for succ, otherwise failed + */ + int _SetAuthkey(byte[] strAuthkey, int nLength); + + /** + * Get the State of _DownloadVoiceFile + * you should loop it while the result is APOLLO_VOICE_HTTP_BUSY or APOLLO_VOICE_SUCC. + * @result: 0 for succ, + * APOLLO_VOICE_HTTP_BUSY is still download + * Otherwise is failed + */ + int _GetVoiceDownloadState(); + + /** + * Get the State of _SendRecFile + * you should loop it while the result is APOLLO_VOICE_HTTP_BUSY or APOLLO_VOICE_SUCC. + * @result: 0 for succ, + * APOLLO_VOICE_HTTP_BUSY is still download + * Otherwise is failed + */ + int _GetVoiceUploadState(); + + /** + * Get Latest Recording File Time. + * @result: The file time length + */ + float _GetOfflineFileTime(); + + /** + * Get Latest Recording File Size. + * @result: The file Size + */ + uint _GetOfflineFileSize(); + + /** + * Decide whether is playing file now. + * @result: 0 is idle or play finished, 1 is playing + */ + int _GetPlayFileState(); + + /** + * Stop playing file immediately. + * @result: 0 for succ, otherwise failed + */ + int _StopPlayFile(); + + /** + * Only selected audience can receive voice(used for small room). + * @param audience: A member id list who can receive voice + * @result: 0 for succ, otherwise failed + */ + int _SetAudience(int []audience); + + /** + * Unused Now. + * @result: 0 for succ, otherwise failed + */ + int _SetSubBID(string strSubBID); + + /** + * Query Lost Rate for Voice Package + * @result: rate + */ + float _GetLostRate(); + +//#if UNITY_STANDALONE_WIN + int _SetAnchorUsed(bool bEnable); +//#endif + /** + * enable or disable software aec mode; + * default: software aec is disabled; + */ + int _EnableSoftAec(bool bEnable); + + /** + * Set which region to deploy + */ + int _SetRegion(ApolloVoiceRegion region); + #endregion + + #region Reserved function + + /* + * reserved function for special function + * @param: nCmd command for invoke + * @param: nParam1 command's parameter + * @param: nParam2 command's parameter + * @param: pOutput command's buffer for output + * @return S_OK; + */ + int _Invoke(uint nCmd, uint nParam1, uint nParam2, int[] pOutput); + + + int _SetSpeakerOn(bool bEnable); + #endregion +} +#endregion + + +class CApolloVoiceSys +{ + private IApolloVoice m_CallApolloVoiceSDK = null; + + public IApolloVoice CallApolloVoiceSDK + { + get + { + return m_CallApolloVoiceSDK; + } + } + + public void SysInitial() + { +#if UNITY_STANDALONE_OSX + m_CallApolloVoiceSDK = null; +#elif UNITY_EDITOR || UNITY_STANDALONE_WIN + m_CallApolloVoiceSDK = new ApolloVoice_lib(); +#elif UNITY_IPHONE + m_CallApolloVoiceSDK = new ApolloVoice_lib(); +#elif UNITY_ANDROID + m_CallApolloVoiceSDK = new ApolloVoice_lib(); +#endif + if (null == m_CallApolloVoiceSDK) + { + Debug.Log("apollo voice sdk init error!"); + return; + } + + Debug.Log("apollo voice sdk init!"); + m_CallApolloVoiceSDK.Init(); +// InitVoiceDelegate(); + } + +// private void InitVoiceDelegate() +// { +// GameObject VoiceDelegate = new GameObject("VoiceDelegate"); +// VoiceDelegate.AddComponent(); +// ApolloVoiceDelegate.SetVoiceEngine(m_CallApolloVoiceSDK); +// } +} + diff --git a/Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs.meta b/Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs.meta new file mode 100644 index 00000000..04767d28 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/CApolloVoiceSys.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 198a8d92c5d5e004ea4f94cfe43acb3f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Client/Assets/Scripts/Apollo/QGameExceptions.cs b/Client/Assets/Scripts/Apollo/QGameExceptions.cs new file mode 100644 index 00000000..5f24b84d --- /dev/null +++ b/Client/Assets/Scripts/Apollo/QGameExceptions.cs @@ -0,0 +1,134 @@ +#if !DISABLE_PLUGIN + +using System; +using System.Collections; +using UnityEngine; + +public class ExceptionUtils +{ + private static Hashtable hashTable = new Hashtable(128); + + public static void initValues() + { + Debug.Log("initValues()..."); + // 后台逻辑错误 + hashTable.Add(361001, "系统内部错误"); + hashTable.Add(361002, "推流地址申请失败"); + hashTable.Add(361003, "推流地址续期失败"); + hashTable.Add(361004, "节目开播失败"); + hashTable.Add(361005, "节目结束失败"); + hashTable.Add(361006, "uid不合法"); + hashTable.Add(361007, "appid不合法"); + hashTable.Add(361008, "获取当前节目信息失败"); + hashTable.Add(361009, "该节目id不是待直播状态"); + hashTable.Add(361010, "该节目id不是正在直播状态"); + hashTable.Add(361011, "查询用户角色失败"); + hashTable.Add(361012, "game_id不合法"); + hashTable.Add(361013, "平台同时在线数达到上限阈值, 暂时不能新开播"); + hashTable.Add(-361014, "请求超时"); + hashTable.Add(361015, "参数无效"); + hashTable.Add(361016, "拉取配置失败"); + hashTable.Add(361017, "无效的登录态类型(非手Q)"); + hashTable.Add(361018, "用户权限不足(被封禁)"); + hashTable.Add(361019, "不在白名单"); + + // 推流SDK警告 + hashTable.Add(1101, "网络状况不佳:上行带宽太小,上传数据受阻"); + hashTable.Add(1102, "网络断连, 已启动自动重连 (自动重连连续失败超过三次会放弃)"); + hashTable.Add(1103, "硬编码启动失败,采用软编码"); + hashTable.Add(3001, "RTMP -DNS解析失败(会触发重试流程)"); + hashTable.Add(3002, "RTMP服务器连接失败(会触发重试流程)"); + hashTable.Add(3003, "RTMP服务器握手失败(会触发重试流程)"); + + // 推流SDK错误 + hashTable.Add(-1301, "打开摄像头失败"); + hashTable.Add(-1302, "打开麦克风失败"); + hashTable.Add(-1303, "视频编码失败"); + hashTable.Add(-1304, "音频编码失败"); + hashTable.Add(-1305, "不支持的视频分辨率"); + hashTable.Add(-1306, "不支持的音频采样率"); + hashTable.Add(-1307, "网络断连,且经三次抢救无效,可以放弃治疗,更多重试请自行重启推流"); + + // wns错误 + hashTable.Add(1, "密码错误"); + hashTable.Add(2, "请输入验证码"); + hashTable.Add(3, "长时间未操作,请重新登录"); + hashTable.Add(4, "请输入正确验证码"); + hashTable.Add(5, "请输入正确用户名/密码"); + hashTable.Add(6, "请输入正确用户名/密码"); + hashTable.Add(7, "账号异常,请登录QQ安全中心查看详情"); + hashTable.Add(8, "无法识别的第三方"); + hashTable.Add(9, "网络繁忙,请稍后重试"); + hashTable.Add(10, "网络繁忙,请稍后重试"); + hashTable.Add(11, "网络繁忙,请稍后重试"); + hashTable.Add(12, "请输入正确用户名/密码"); + hashTable.Add(14, "网络繁忙,请稍后重试"); + hashTable.Add(15, "密码已过期,请重新登录"); + hashTable.Add(16, "长时间未操作,请重新登录"); + hashTable.Add(18, "请输入正确用户名/密码"); + hashTable.Add(32, "您的帐号长期未登录已经冻结,建议您到http://zc.qq.com 申请一个新号码使用。"); + hashTable.Add(33, "您的帐号由于存在安全风险,已启用临时登录限制,解除限制后即可正常登录。解除地址:\nhttp://aq.qq.com/xz"); + hashTable.Add(40, "您的帐号暂被冻结,请点击http://aq.qq.com/007查看详情"); + hashTable.Add(41, "您的QQ号码服务已到期,\n请尽快点击http://haoma.qq.com/expire/续费。\n固定电话拨打16885886可快捷续费"); + hashTable.Add(42, "您的帐号已锁定,解锁请查看http://aq.qq.com/mp?id=1&source_id=2040"); + hashTable.Add(43, "请输入正确用户名/密码"); + hashTable.Add(44, "请输入正确用户名/密码"); + hashTable.Add(48, "账号异常,请登录QQ安全中心查看详情"); + hashTable.Add(113, "账号异常,请登录QQ安全中心查看详情"); + hashTable.Add(128, "账号异常,请登录QQ安全中心查看详情"); + hashTable.Add(129, "网络繁忙,请稍后重试"); + hashTable.Add(154, "网络繁忙,请稍后重试"); + hashTable.Add(130, "请输入正确用户名/密码"); + hashTable.Add(131, "请输入正确用户名/密码"); + hashTable.Add(132, "网络繁忙,请稍后重试"); + hashTable.Add(133, "网络繁忙,请稍后重试"); + hashTable.Add(134, "网络繁忙,请稍后重试"); + hashTable.Add(160, "请输入短信验证码"); + hashTable.Add(161, "请输入短信验证码"); + hashTable.Add(162, "请输入短信验证码"); + hashTable.Add(163, "请输入短信验证码"); + hashTable.Add(901, "Quick verification mode does not support the operation"); + hashTable.Add(256, "网络繁忙,请稍后重试"); + hashTable.Add(263, "网络繁忙,请稍后重试"); + hashTable.Add(264, "请输入正确用户名/密码"); + hashTable.Add(272, "密码票据丢失或格式错误"); + hashTable.Add(513, "当前网络不可用,请检查网络设置"); + hashTable.Add(514, "网络超时,请稍后重试"); + hashTable.Add(515, "网络超时,请稍后重试"); + hashTable.Add(516, "当前网络不可用,请检查网络设置"); + hashTable.Add(517, "网络繁忙,请稍后重试"); + hashTable.Add(518, "网络繁忙,请稍后重试"); + hashTable.Add(519, "当前网络不可用,请检查网络设置"); + hashTable.Add(521, "网络繁忙,请稍后重试"); + hashTable.Add(522, "网络繁忙,请稍后重试"); + hashTable.Add(526, "网络繁忙,请稍后重试"); + hashTable.Add(527, "网络繁忙,请稍后重试"); + hashTable.Add(528, "操作超时,请稍后重试"); + hashTable.Add(532, "网络连接不可用,请重新连接"); + hashTable.Add(1907, "密码已修改,请重新输入密码"); + hashTable.Add(4001, "该号码异常,存在安全风险,请定期修改密码"); + hashTable.Add(4011, "该网络异常,请一段时间后再试"); + hashTable.Add(4021, "该版本异常,请更新到最新版本"); + hashTable.Add(4031, "该操作已过期"); + hashTable.Add(583, ""); + hashTable.Add(585, "登录态异常,请重新登录"); + hashTable.Add(601, "解包失败"); + } + + public static String getErroMessage(int errorCode) + { + if (hashTable.Keys.Count == 0) + { + initValues(); + } + if (hashTable.ContainsKey(errorCode)) + { + Debug.Log(hashTable[errorCode].ToString()); + return hashTable[errorCode].ToString(); + } + return ""; + } + +} + +#endif \ No newline at end of file diff --git a/Client/Assets/Scripts/Apollo/QGameExceptions.cs.meta b/Client/Assets/Scripts/Apollo/QGameExceptions.cs.meta new file mode 100644 index 00000000..21257767 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/QGameExceptions.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 17c42a6c3ef96ad43aaac009a88c54e5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Client/Assets/Scripts/Apollo/QGameKit.cs b/Client/Assets/Scripts/Apollo/QGameKit.cs new file mode 100644 index 00000000..e469dbb7 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/QGameKit.cs @@ -0,0 +1,606 @@ +#if !DISABLE_PLUGIN + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +public class QGameKit { + + public enum CaptureType { + AudioCapture = 1 << 0, //采集麦克风声音 + AudioApolloVoice = 1 << 1, //Apollo Voice组件提供声音 + AudioCustom = 1 << 2, //自定义声音数据 + VideoCapture = 1 << 3, //SDK录制视频数据 + VideoCustom = 1 << 4, //自定义视频数据 + } + + public enum LoginPlatform { + Guest, + QQ, + WeChat, + } + + public enum LiveStatus { + Unknown, // 未知状态(在获取状态过程中发生了错误) + Uninitialized, // 尚未初始化 + Prepared, // 已准备好 + LiveStarting, // 直播开启中 + LiveStarted, // 直播已开始 + LivePaused, // 直播已暂停 + LiveResume, // 暂停恢复中 + LiveStopping, // 直播结束中 + LiveStopped, // 直播已结束 + Error // 直播过程出错 + } + + public enum CommentType { + Normal, // 普通消息 + System, // 系统消息 + Anchor, // 主播消息 + RoomManager, // 房管消息 + LiveManager, // 直播管理员消息 + SuperManager, // 超管消息 + Edit, // 小编消息 + Gift, // 礼物消息 + Welcome, // 用户进入消息 + Vip, // VIP 用户消息 + LoginVisitor // 登录用户消息 + } + + public enum Environment { + Release, //正式环境 + Debug //测试环境 + } + + public enum WebViewStatus + { + Open, + Closed, + SmallWindow, + FullScreen + } + + // 用户登录信息 + public class UserAccount { + public LoginPlatform platform; + public string appId; // AppID:手Q或微信分享的AppID,必填 + public string id; // openId:手Q或微信登录的Open ID,必填 + public string token; // accessToken:必填 + + public string phoneNum; // 可选: Phone number + public long expires; // 可选: expires timestamp(ms) + } + + // 直播评论信息 + public class LiveComment { + public CommentType type; // 评论类型 + public string nick; // 用户昵称 + public string content; // 评论内容 + public long timestamp; // 评论的产生时间 + } + + public class ShareContent { + public string fopenId; // 可选:若指定则直接发起后端分享,否则拉起手Q/微信分享 + public string title; // 分享标题 + public string description; // 分享描述 + public string targetUrl; // 分享链接 + public string imageUrl; // 分享消息缩略图 URL + } + + + public delegate UserAccount UserAccountDelegate(); // 用户信息委托:SDK 需要用户登录态时会回调委托,游戏应返回有效的用户信息 + public delegate void CommentReceiveDelegate(List comments); // 直播评论委托:直播过程中SDK会定时调用委托并将评论传入 + public delegate void LogDelegate(string log); // SDK日志落入游戏日志记录体系 Delegate,可选择使用 + public delegate void LiveStatusChangedDelegate(LiveStatus newState); // 直播状态变化委托,SDK通过它将直播状态变化通知游戏 + public delegate void ShareDelegate(ShareContent shareContent); // 分享委托,SDK通过委托调用游戏分享能力 + public delegate void ErrorCodeListenerDelegate(int errorCode, string errorMessage); // 直播过程中的错误监听委托 + public delegate void WebViewStatusChangedDelegate(WebViewStatus status); //直播大厅在游戏中时,状态回调 + + public static LiveStatus liveStatus = LiveStatus.Uninitialized; + + #if !UNITY_EDITOR + #if UNITY_ANDROID + private static QGameKitAndroidBridge QGameKitObj; // Android Native 桥接对象 + #elif UNITY_IPHONE + private static QGameKitiOSBridge QGameKitObj; // iOS Native 桥接对象iOS 的桥接对象 + #endif + #endif + // 初始化SDK,状态流转:Uninitialized -> Prepared,直播过程中出现任何错误会导致状态流转到 Error + // 参数 gameId 为企鹅电竞为游戏分配的唯一标识,accountDelegate 为用户信息回调,SDK会调用该委托获取游戏的用户登录态信息 + + public static bool Setup(string gameId, string wnsAppId, CaptureType captureType, UserAccountDelegate accountDelegate, Environment env) { + #if UNITY_ANDROID && !UNITY_EDITOR + QGameKitObj = QGameKitAndroidBridge.Setup(gameId, wnsAppId, captureType, accountDelegate, env); + if (null == QGameKitObj) + { + Debug.LogError("QGameKitObj init failed!"); + return false; + } + #elif UNITY_IPHONE && !UNITY_EDITOR + QGameKitObj = QGameKitiOSBridge.Setup (); + QGameKitObj.accountDelegate = accountDelegate; + _QGameSetup (gameId, wnsAppId, (int)captureType, (int)env); + #endif + + UserAccount account = accountDelegate(); + UpdateUserAccount(account); + + liveStatus = LiveStatus.Prepared; + return true; + } + + // 反初始化,状态流转:Setup -> Uninitialized + public static void TearDown() { + #if UNITY_ANDROID && !UNITY_EDITOR + QGameKitObj.TearDown(); + #endif + liveStatus = LiveStatus.Uninitialized; + } + + // 使用之前已配置的信息重新 Setup,状态流转:Error/LiveStopped -> Setup + public static bool Reset() { + #if UNITY_ANDROID && !UNITY_EDITOR + return QGameKitObj.Reset(); + #endif + + #if UNITY_IOS && !UNITY_EDITOR + return _QGameReset(); + #endif + liveStatus = LiveStatus.Prepared; + return false; + } + + // 游戏每帧刷新时调用通知 SDK 采集画面 + public static void FrameUpdated() { + #if UNITY_ANDROID && !UNITY_EDITOR + QGameKitObj.CaptureFrame(); + #endif + } + + // 进入直播大厅 + public static void EnterLiveHall() { + #if UNITY_IPHONE && !UNITY_EDITOR + _QGameEnterLiveHall (); + #endif + + #if UNITY_ANDROID && !UNITY_EDITOR + QGameKitObj.EnterLiveHall (); + #endif + } + + public static void DisabledLiveHall() { + #if UNITY_IPHONE && !UNITY_EDITOR + _QGameDisabledLiveHall (); + #endif + + #if UNITY_ANDROID && !UNITY_EDITOR + #endif + } + + // 进入直播大厅 + public static void EnterLiveHallInGame() { + #if UNITY_IPHONE && !UNITY_EDITOR + _QGameEnterLiveHall (); + #endif + + #if UNITY_ANDROID && !UNITY_EDITOR + QGameKitObj.EnterLiveHallInGame (); + #endif + } + + // 开始直播,状态流转:Setup -> LiveStarted + public static bool StartLiveBroadcast(string title, string description) { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj.StartLiveBroadcast(title, description)) + { + return true; + } else { + Debug.LogError("StartLiveBroadcast failed!"); + return false; + } + #endif + + #if UNITY_IPHONE && !UNITY_EDITOR + return _QGameStartLiveBroadcast (title, description); + #endif + + return false; + } + + // 结束直播,状态流转:LiveStarted -> LiveStopped + public static bool StopLiveBroadcast() { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj.StopLiveBroadcast()) + { + return true; + } else { + Debug.LogError("StopLiveBroadcast failed!"); + return false; + } + #endif + + #if UNITY_IPHONE && !UNITY_EDITOR + return _QGameStopLiveBroadcast (); + #endif + + return false; + } + + // 暂定直播,状态流转:LiveStarted -> LivePaused + public static void PauseLiveBroadcast() { + Debug.LogError("PauseLiveBroadcast unsupported yet!"); + } + + // 恢复直播,状态流转:LivePaused -> LiveStarted + public static void ResumeLiveBroadcast() { + Debug.LogError("ResumeLiveBroadcast unsupported yet!"); + } + + //分享直播 + public static void ShareLiveBroadcast() { + #if UNITY_ANDROID && !UNITY_EDITOR + QGameKitObj.ShareLiveBroadcast(); + #elif UNITY_IOS && !UNITY_EDITOR + _QGameShareLiveBroadcast(); + #endif + } + + // 获取当前直播状态 + public static LiveStatus GetLiveBroadcastStatus() { + #if UNITY_ANDROID && !UNITY_EDITOR + return QGameKitObj.GetLiveBroadcastStatus(); + #endif + + #if UNITY_IOS && !UNITY_EDITOR + return (LiveStatus)_QGameGetLiveBroadcastStatus (); + #endif + return LiveStatus.LiveStopped; + } + + // 获取当前直播状态 + public static int GetErrorCode() { + #if UNITY_ANDROID && !UNITY_EDITOR + return QGameKitObj.GetErrorCode(); + #elif UNITY_IOS && !UNITY_EDITOR + return _QGameGetErrorCode(); + #endif + return 0; + } + + // 主动更新用户信息(游戏里用户注销重新登录后主动调用) + public static void UpdateUserAccount(UserAccount account) { + #if UNITY_ANDROID && !UNITY_EDITOR + QGameKitObj.UpdateUserAccount(account); + #elif UNITY_IOS && !UNITY_EDITOR + _QGameUpdateUserAccount(account.appId, account.id, account.token, (int)account.platform); + #endif + } + + // 切换帐号时通知调用 + public static void UpdateUserAccount() { + #if UNITY_ANDROID && !UNITY_EDITOR + QGameKitObj.UpdateUserAccount(); + #endif + } + + // 往当前自己的直播发送评论 + public static void SendComment(LiveComment comment) { + Debug.LogError("SendComment unsupported yet!"); + } + + // 设置直播评论 Delegate + public static void SetCommentReceiveDelegate(CommentReceiveDelegate commentDelegate) { + #if !UNITY_EDITOR + #if UNITY_ANDROID + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.SetCommentReceiveDelegete(commentDelegate); + # elif UNITY_IPHONE + QGameKitObj.commentDelegate = commentDelegate; + #endif + #endif + } + + // 设置日志委托,让SDK的日志有机会跟随游戏的日志落地 + public static void SetLogDelegate(LogDelegate logDelegate) { + #if !UNITY_EDITOR + #if UNITY_ANDROID + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.SetLogDelegate(logDelegate); + # elif UNITY_IPHONE + QGameKitObj.logDelegate = logDelegate; + #endif + #endif + + } + + // 设置分享委托,让 SDK 能够使用游戏的分享能力 + public static void SetShareDelegate(ShareDelegate shareDelegate) { + #if !UNITY_EDITOR + #if UNITY_ANDROID + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.SetShareDelegate(shareDelegate); + #elif UNITY_IPHONE + QGameKitObj.shareDelegate = shareDelegate; + _QGameSetShareDelegateEnabled(shareDelegate != null ? true : false); + #endif + #endif + } + + // 设置弹幕面板是否启用,默认不启用 + public static void SetDanmakuEnabled(bool enabled) { + #if !UNITY_EDITOR + #if UNITY_ANDROID + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.SetDanmakuEnabled(enabled); + #elif UNITY_IPHONE + _QGameSetDanmakuEnabled(enabled); + #endif + #endif + } + + //Android弹幕面板会遮挡分享 这里添加显示隐藏的接口 + public static void ShowDanmaku() { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return; + } + QGameKitObj.ShowDanmaku(); + #endif + } + + public static void HideDanmaku() { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return; + } + QGameKitObj.HideDanmaku(); + #endif + } + + // 游戏通知 SDK 发起分享的结果,result = 0 为分享成功否则为失败 + public static void SetShareResult(ShareContent content, int result) { + } + + // 设置直播状态 Delegate,如果游戏需要实时获得直播状态请注册 delegate + public static void SetLiveStatusDelegate(LiveStatusChangedDelegate liveStatusDelegate) { + #if !UNITY_EDITOR + #if UNITY_ANDROID + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.SetLiveStatusChangedDelegate(liveStatusDelegate); + # elif UNITY_IPHONE + QGameKitObj.liveStatusDelegate = liveStatusDelegate; + #endif + #endif + } + + public static void SetErrorCodeDelegate(ErrorCodeListenerDelegate errorCodeDelegate) { + #if !UNITY_EDITOR + #if UNITY_ANDROID + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.SetErrorCodeDelegate(errorCodeDelegate); + #elif UNITY_IPHONE + QGameKitObj.errorCodeDelegate = errorCodeDelegate; + #endif + #endif + } + + public static void SetWebViewStatusChangedDelegate(WebViewStatusChangedDelegate webviewDelegate) + { + #if !UNITY_EDITOR + #if UNITY_ANDROID + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.SetWebViewStatusChangedDelegate(webviewDelegate); + #elif UNITY_IPHONE + #endif + #endif + } + public static bool IsLiveBroadcastSupported() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return false; + } + return QGameKitObj.IsLiveBroadcastSupported(); + #endif + return true; + } + + public static string GetVersionName() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return null; + } + return QGameKitObj.GetVersionName(); + #endif + return null; + } + + public static bool ShowCamera() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return false; + } + return QGameKitObj.ShowCamera(); + #endif + return false; + } + + public static void HideCamera() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.HideCamera(); + #endif + + } + + public static void DoOnResume() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.DoOnResume(); + #endif + } + + public static void DoOnPause() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.DoOnPause(); + #endif + } + + public static void DoOnDestroy() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return ; + } + QGameKitObj.DoOnDestroy(); + #endif + } + + public static bool DoOnBackPressed() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return false; + } + return QGameKitObj.DoOnBackPressed(); + #endif + return false; + } + + public static bool IsSupportCamera() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return false; + } + return QGameKitObj.IsSupportCamera(); + #endif + return false; + } + + public static bool IsSupportLiveHall() + { + #if UNITY_ANDROID && !UNITY_EDITOR + if (QGameKitObj == null) + { + Debug.LogError("QGameKitObj is null!"); + return false; + } + return QGameKitObj.IsSupportLiveHall(); + #endif + return true; + } + +#if UNITY_IPHONE && !UNITY_EDITOR + [DllImport ("__Internal")] + private static extern void _QGameSetup(string gameId, string wnsAppId, int captureType, int env); + + [DllImport ("__Internal")] + private static extern void _QGameTearDown(); + + [DllImport ("__Internal")] + private static extern bool _QGameReset(); + + [DllImport ("__Internal")] + private static extern void _QGameEnterLiveHall(); + + [DllImport ("__Internal")] + private static extern bool _QGameStartLiveBroadcast(string title, string description); + + [DllImport ("__Internal")] + private static extern bool _QGameStopLiveBroadcast(); + + [DllImport ("__Internal")] + private static extern void _QGamePauseLiveBroadcast(); + + [DllImport ("__Internal")] + private static extern void _QGameResumeLiveBroadcast(); + + [DllImport ("__Internal")] + private static extern void _QGameUpdateUserAccount(string appId, string openId, string accessToken, int loginType); + + [DllImport ("__Internal")] + private static extern int _QGameGetErrorCode(); + + [DllImport ("__Internal")] + private static extern int _QGameGetLiveBroadcastStatus(); + + [DllImport ("__Internal")] + private static extern void _QGameShareLiveBroadcast(); + + [DllImport ("__Internal")] + private static extern void _QGameDisabledLiveHall(); + + [DllImport ("__Internal")] + private static extern void _QGameSetShareDelegateEnabled(bool enabled); + + [DllImport ("__Internal")] + private static extern void _QGameSetDanmakuEnabled(bool enabled); +#endif +} + + +#endif diff --git a/Client/Assets/Scripts/Apollo/QGameKit.cs.meta b/Client/Assets/Scripts/Apollo/QGameKit.cs.meta new file mode 100644 index 00000000..343a4880 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/QGameKit.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c0c74cdaa20744047be5221577a0d863 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Client/Assets/Scripts/Apollo/iOSBridge.meta b/Client/Assets/Scripts/Apollo/iOSBridge.meta new file mode 100644 index 00000000..c09ffcef --- /dev/null +++ b/Client/Assets/Scripts/Apollo/iOSBridge.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 6275a9f64d1045f4aa4f8f6f57040b26 +folderAsset: yes +DefaultImporter: + userData: diff --git a/Client/Assets/Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs b/Client/Assets/Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs new file mode 100644 index 00000000..a30b5e18 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs @@ -0,0 +1,111 @@ +#if !DISABLE_PLUGIN + +#if UNITY_IOS && !UNITY_EDITOR +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.IO; +using System; +using System.Threading; +using QGameUtils; + +public class QGameKitiOSBridge : MonoBehaviour { + + private static QGameKitiOSBridge singletonInstance = null; + public QGameKit.UserAccountDelegate accountDelegate; + public QGameKit.CommentReceiveDelegate commentDelegate; + public QGameKit.LogDelegate logDelegate; + public QGameKit.LiveStatusChangedDelegate liveStatusDelegate; + public QGameKit.ShareDelegate shareDelegate; + public QGameKit.ErrorCodeListenerDelegate errorCodeDelegate; + + public static QGameKitiOSBridge Setup() + { + if(singletonInstance != null) + { + return singletonInstance; + } + + GameObject sdkObject = new GameObject("QGameKitiOSBridge"); + DontDestroyOnLoad(sdkObject); + singletonInstance = sdkObject.AddComponent(); + + return singletonInstance; + } + + private void DidReceivedGetUserAccountRequest() + { + QGameKit.UserAccount account = accountDelegate(); + QGameKit.UpdateUserAccount (account); + } + + private void DidReceivedComments(string data) + { + if (commentDelegate == null) { + return; + } + + List comments = new List(); + List array = Json.Deserialize(data) as List; + + foreach(var item in array) { + IDictionary itemDict = (IDictionary)item; + QGameKit.LiveComment comment = new QGameKit.LiveComment(); + comment.type = (QGameKit.CommentType)(Int32.Parse((string)itemDict["type"])); + comment.nick = (string)itemDict["nick"]; + comment.content = (string)itemDict["content"]; + comment.timestamp = Int64.Parse((string)itemDict["timestamp"]); + comments.Add(comment); + } + this.commentDelegate(comments); + } + + private void DidReceivedLog(string log) + { + if (logDelegate == null) { + return; + } + logDelegate (log); + } + + private void DidReceivedLiveStatusChanged(string liveStatus) + { + if (liveStatusDelegate == null) { + return; + } + + QGameKit.LiveStatus status = (QGameKit.LiveStatus)int.Parse(liveStatus); + liveStatusDelegate (status); + } + + private void DidReceivedShareContent(string content) + { + if (shareDelegate == null) { + Debug.Log ("Share Delegate Null"); + return; + } + + QGameKit.ShareContent shareContent = new QGameKit.ShareContent(); + var data = Json.Deserialize(content) as Dictionary; + shareContent.title = data["title"].ToString(); + shareContent.description = data["description"].ToString(); + shareContent.targetUrl = data["targetUrl"].ToString(); + shareContent.imageUrl = data["imageUrl"].ToString(); + shareDelegate(shareContent); + } + + private void DidReceivedError(string error) + { + if (errorCodeDelegate == null) { + Debug.Log ("Error Delegate Null"); + return; + } + + var data = Json.Deserialize(error) as Dictionary; + errorCodeDelegate (int.Parse (data["errorCode"]), data["errorMessage"]); + } +} +#endif + +#endif diff --git a/Client/Assets/Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs.meta b/Client/Assets/Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs.meta new file mode 100644 index 00000000..3dd5f8f2 --- /dev/null +++ b/Client/Assets/Scripts/Apollo/iOSBridge/QGameKitiOSBridge.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a10a8ee33966b924ea167527bbefc5dc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Client/Assets/Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs b/Client/Assets/Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs new file mode 100644 index 00000000..2a56689c --- /dev/null +++ b/Client/Assets/Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs @@ -0,0 +1,552 @@ +#if !DISABLE_PLUGIN +/* + * Copyright (c) 2013 Calvin Rien + * + * Based on the JSON parser by Patrick van Bergen + * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html + * + * Simplified it so that it doesn't throw exceptions + * and can be used in Unity iPhone with maximum code stripping. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace QGameUtils { + // Example usage: + // + // using UnityEngine; + // using System.Collections; + // using System.Collections.Generic; + // using MiniJSON; + // + // public class MiniJSONTest : MonoBehaviour { + // void Start () { + // var jsonString = "{ \"array\": [1.44,2,3], " + + // "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + + // "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + + // "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + + // "\"int\": 65536, " + + // "\"float\": 3.1415926, " + + // "\"bool\": true, " + + // "\"null\": null }"; + // + // var dict = Json.Deserialize(jsonString) as Dictionary; + // + // Debug.Log("deserialized: " + dict.GetType()); + // Debug.Log("dict['array'][0]: " + ((List) dict["array"])[0]); + // Debug.Log("dict['string']: " + (string) dict["string"]); + // Debug.Log("dict['float']: " + (double) dict["float"]); // floats come out as doubles + // Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs + // Debug.Log("dict['unicode']: " + (string) dict["unicode"]); + // + // var str = Json.Serialize(dict); + // + // Debug.Log("serialized: " + str); + // } + // } + + /// + /// This class encodes and decodes JSON strings. + /// Spec. details, see http://www.json.org/ + /// + /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. + /// All numbers are parsed to doubles. + /// + public static class Json { + /// + /// Parses the string json into a value + /// + /// A JSON string. + /// An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false + public static object Deserialize(string json) { + // save the string for debug information + if (json == null) { + return null; + } + + return Parser.Parse(json); + } + + sealed class Parser : IDisposable { + const string WORD_BREAK = "{}[],:\""; + + public static bool IsWordBreak(char c) { + return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1; + } + + enum TOKEN { + NONE, + CURLY_OPEN, + CURLY_CLOSE, + SQUARED_OPEN, + SQUARED_CLOSE, + COLON, + COMMA, + STRING, + NUMBER, + TRUE, + FALSE, + NULL + }; + + StringReader json; + + Parser(string jsonString) { + json = new StringReader(jsonString); + } + + public static object Parse(string jsonString) { + using (var instance = new Parser(jsonString)) { + return instance.ParseValue(); + } + } + + public void Dispose() { + json.Dispose(); + json = null; + } + + Dictionary ParseObject() { + Dictionary table = new Dictionary(); + + // ditch opening brace + json.Read(); + + // { + while (true) { + switch (NextToken) { + case TOKEN.NONE: + return null; + case TOKEN.COMMA: + continue; + case TOKEN.CURLY_CLOSE: + return table; + default: + // name + string name = ParseString(); + if (name == null) { + return null; + } + + // : + if (NextToken != TOKEN.COLON) { + return null; + } + // ditch the colon + json.Read(); + + // value + table[name] = ParseValue(); + break; + } + } + } + + List ParseArray() { + List array = new List(); + + // ditch opening bracket + json.Read(); + + // [ + var parsing = true; + while (parsing) { + TOKEN nextToken = NextToken; + + switch (nextToken) { + case TOKEN.NONE: + return null; + case TOKEN.COMMA: + continue; + case TOKEN.SQUARED_CLOSE: + parsing = false; + break; + default: + object value = ParseByToken(nextToken); + + array.Add(value); + break; + } + } + + return array; + } + + object ParseValue() { + TOKEN nextToken = NextToken; + return ParseByToken(nextToken); + } + + object ParseByToken(TOKEN token) { + switch (token) { + case TOKEN.STRING: + return ParseString(); + case TOKEN.NUMBER: + return ParseNumber(); + case TOKEN.CURLY_OPEN: + return ParseObject(); + case TOKEN.SQUARED_OPEN: + return ParseArray(); + case TOKEN.TRUE: + return true; + case TOKEN.FALSE: + return false; + case TOKEN.NULL: + return null; + default: + return null; + } + } + + string ParseString() { + StringBuilder s = new StringBuilder(); + char c; + + // ditch opening quote + json.Read(); + + bool parsing = true; + while (parsing) { + + if (json.Peek() == -1) { + parsing = false; + break; + } + + c = NextChar; + switch (c) { + case '"': + parsing = false; + break; + case '\\': + if (json.Peek() == -1) { + parsing = false; + break; + } + + c = NextChar; + switch (c) { + case '"': + case '\\': + case '/': + s.Append(c); + break; + case 'b': + s.Append('\b'); + break; + case 'f': + s.Append('\f'); + break; + case 'n': + s.Append('\n'); + break; + case 'r': + s.Append('\r'); + break; + case 't': + s.Append('\t'); + break; + case 'u': + var hex = new char[4]; + + for (int i=0; i< 4; i++) { + hex[i] = NextChar; + } + + s.Append((char) Convert.ToInt32(new string(hex), 16)); + break; + } + break; + default: + s.Append(c); + break; + } + } + + return s.ToString(); + } + + object ParseNumber() { + string number = NextWord; + + if (number.IndexOf('.') == -1 && number.IndexOf('E') == -1 && number.IndexOf('e') == -1) { + long parsedInt; + Int64.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedInt); + return parsedInt; + } + + double parsedDouble; + Double.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedDouble); + return parsedDouble; + } + + void EatWhitespace() { + while (Char.IsWhiteSpace(PeekChar)) { + json.Read(); + + if (json.Peek() == -1) { + break; + } + } + } + + char PeekChar { + get { + return Convert.ToChar(json.Peek()); + } + } + + char NextChar { + get { + return Convert.ToChar(json.Read()); + } + } + + string NextWord { + get { + StringBuilder word = new StringBuilder(); + + while (!IsWordBreak(PeekChar)) { + word.Append(NextChar); + + if (json.Peek() == -1) { + break; + } + } + + return word.ToString(); + } + } + + TOKEN NextToken { + get { + EatWhitespace(); + + if (json.Peek() == -1) { + return TOKEN.NONE; + } + + switch (PeekChar) { + case '{': + return TOKEN.CURLY_OPEN; + case '}': + json.Read(); + return TOKEN.CURLY_CLOSE; + case '[': + return TOKEN.SQUARED_OPEN; + case ']': + json.Read(); + return TOKEN.SQUARED_CLOSE; + case ',': + json.Read(); + return TOKEN.COMMA; + case '"': + return TOKEN.STRING; + case ':': + return TOKEN.COLON; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + return TOKEN.NUMBER; + } + + switch (NextWord) { + case "false": + return TOKEN.FALSE; + case "true": + return TOKEN.TRUE; + case "null": + return TOKEN.NULL; + } + + return TOKEN.NONE; + } + } + } + + /// + /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string + /// + /// A Dictionary<string, object> / List<object> + /// A JSON encoded string, or null if object 'json' is not serializable + public static string Serialize(object obj) { + return Serializer.Serialize(obj); + } + + sealed class Serializer { + StringBuilder builder; + + Serializer() { + builder = new StringBuilder(); + } + + public static string Serialize(object obj) { + var instance = new Serializer(); + + instance.SerializeValue(obj); + + return instance.builder.ToString(); + } + + void SerializeValue(object value) { + IList asList; + IDictionary asDict; + string asStr; + + if (value == null) { + builder.Append("null"); + } else if ((asStr = value as string) != null) { + SerializeString(asStr); + } else if (value is bool) { + builder.Append((bool) value ? "true" : "false"); + } else if ((asList = value as IList) != null) { + SerializeArray(asList); + } else if ((asDict = value as IDictionary) != null) { + SerializeObject(asDict); + } else if (value is char) { + SerializeString(new string((char) value, 1)); + } else { + SerializeOther(value); + } + } + + void SerializeObject(IDictionary obj) { + bool first = true; + + builder.Append('{'); + + foreach (object e in obj.Keys) { + if (!first) { + builder.Append(','); + } + + SerializeString(e.ToString()); + builder.Append(':'); + + SerializeValue(obj[e]); + + first = false; + } + + builder.Append('}'); + } + + void SerializeArray(IList anArray) { + builder.Append('['); + + bool first = true; + + for (int i=0; i= 32) && (codepoint <= 126)) { + builder.Append(c); + } else { + builder.Append("\\u"); + builder.Append(codepoint.ToString("x4")); + } + break; + } + } + + builder.Append('\"'); + } + + void SerializeOther(object value) { + // NOTE: decimals lose precision during serialization. + // They always have, I'm just letting you know. + // Previously floats and doubles lost precision too. + if (value is float) { + builder.Append(((float) value).ToString("R", System.Globalization.CultureInfo.InvariantCulture)); + } else if (value is int + || value is uint + || value is long + || value is sbyte + || value is byte + || value is short + || value is ushort + || value is ulong) { + builder.Append(value); + } else if (value is double + || value is decimal) { + builder.Append(Convert.ToDouble(value).ToString("R", System.Globalization.CultureInfo.InvariantCulture)); + } else { + SerializeString(value.ToString()); + } + } + } + } +} + +#endif diff --git a/Client/Assets/Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs.meta b/Client/Assets/Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs.meta new file mode 100644 index 00000000..ed9a0c7d --- /dev/null +++ b/Client/Assets/Scripts/Apollo/iOSBridge/QGameUtilsJSON.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 66d30201ecde99a48bc94ac54ddc113e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: -- cgit v1.1-26-g67d0