/// <summary> /// Register a unique schema for <c>OAuth</c> redirect handler. The caller needs to ensure that the schema is unique. /// If the schema is already registered the function will return an error. The handler /// will be called once the authorization procedure has been completed. /// The caller should register two schema callbacks. The first will be for /// authorization redirect and the second schema will in case the user cancels /// the authentication. /// </summary> /// <param name="schema">A unique string that will match the redirect uri schema</param> /// <param name="callback">MLDispatch <c>OAuth</c> callback function</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if the new schema has been registered correctly. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if SecureBrowserWindow privilege is denied. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if the operation failed with an unspecified error. /// MLResult.Result will be <c>MLResult.Code.SchemaAlreadyRegistered</c> if the schema already is registered. /// MLResult.Result will be <c>MLResult.Code.Dispatch*</c> if a dispatch specific error occurred. /// </returns> public static MLResult OAuthRegisterSchema(string schema, ref OAuthHandler callback) { try { NativeBindings.OAuthCallbacksNative newSchema = NativeBindings.OAuthCallbacksNative.Create(); newSchema.OnReplyComplete = OAuthOnReplyNative; int newID = uniqueID + 1; MLResult.Code resultCode = NativeBindings.MLDispatchOAuthRegisterSchemaEx(schema, ref newSchema, new IntPtr(newID)); if (MLResult.IsOK(resultCode)) { OAuthPair newEntry = new OAuthPair(schema, callback); oAuthCallbacks.Add(newID, newEntry); uniqueID = newID; } return(MLResult.Create(resultCode)); } catch (System.DllNotFoundException) { MLPluginLog.Error(DllNotFoundExceptionError); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, DllNotFoundExceptionError)); } catch (System.EntryPointNotFoundException) { MLPluginLog.Error("MLDispatch API symbols not found"); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLDispatch API symbols not found")); } }
/// <summary> /// Gets the offset position/rotation values and the PCF of the current Perception root. /// </summary> /// <param name="offsetPosition">Stores the value of the current offset from the root's position.</param> /// <param name="offsetRotation">Stores the value of the current offset from the root's rotation.</param> /// <param name="pcf">Stores the reference to the current root PCF.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if operation completed successfully. /// MLResult.Result will be <c>MLResult.Code.MLPerceptionNotStarted</c> if unable to retrieve the Perception System. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error. /// </returns> public static MLResult GetPerceptionRoot(out Vector3 offsetPosition, out Quaternion offsetRotation, out PCF pcf) { offsetPosition = Vector3.zero; offsetRotation = Quaternion.identity; pcf = new PCF(new MagicLeapNativeBindings.MLCoordinateFrameUID()); if (MLPersistentCoordinateFrames.IsValidInstance()) { try { MLResult.Code resultCode = NativeBindings.MLPerceptionGetRootCoordinateFrame(out MagicLeapNativeBindings.MLCoordinateFrameUID cfuid, out MagicLeapNativeBindings.MLTransform mlTransform); if (MLResult.IsOK(resultCode)) { offsetPosition = MLConvert.ToUnity(mlTransform.Position); offsetRotation = MLConvert.ToUnity(mlTransform.Rotation); return(MLResult.Create(MLResult.Code.Ok)); } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.GetPerceptionRoot failed. Reason: {0}", MLResult.CodeToString(resultCode)); return(MLResult.Create(resultCode)); } } catch (EntryPointNotFoundException) { MLPluginLog.Error("MLPersistentCoordinateFrames.GetPerceptionRoot failed. Reason: API symbols not found."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.GetPerceptionRoot failed. Reason: API symbols not found.")); } } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.GetPerceptionRoot failed. Reason: No Instance for MLPersistentCoordinateFrames."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.GetPerceptionRoot failed. Reason: No Instance for MLPersistentCoordinateFrames.")); } }
/// <summary> /// GetClientCredentials is a blocking function that accesses the cloud and /// returns a MLTokenAgentClientCredentials structure containing the users credentials and /// tokens for a particular service (Audience). /// The library deduces the Audience being requested from the name of the calling service. /// </summary> /// <param name="clientCredentials">Reference to the clientCredentials object.</param> /// <param name="credentials">Reference to the credentials struct of the clientCredentials object.</param> /// <param name="tokens">Reference to the tokens struct of the clientCredentials object.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if successful. /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if failed due to internal invalid input parameter. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to internal error. /// MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if failed to allocate memory. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing. /// MLResult.Result will be <c>MLResult.Code.TokenAgent*</c> if a token specific failure occurred during the operation. /// </returns> public static MLResult.Code GetClientCredentials(MLTokenAgent.ClientCredentials clientCredentials, ref MLTokenAgent.Credentials credentials, ref MLTokenAgent.Tokens tokens) { try { IntPtr clientCredentialsPtr = clientCredentialsPtrMap.ContainsKey(clientCredentials) ? clientCredentialsPtrMap[clientCredentials] : IntPtr.Zero; MLResult.Code resultCode = MLTokenAgent.NativeBindings.MLTokenAgentGetClientCredentials(ref clientCredentialsPtr); if (MLResult.IsOK(resultCode)) { clientCredentialsPtrMap.Remove(clientCredentials); clientCredentialsPtrMap.Add(clientCredentials, clientCredentialsPtr); MLTokenAgent.NativeBindings.ClientCredentialsNative clientCredentialsNative = (MLTokenAgent.NativeBindings.ClientCredentialsNative)Marshal.PtrToStructure(clientCredentialsPtr, typeof(MLTokenAgent.NativeBindings.ClientCredentialsNative)); credentials = clientCredentialsNative.Credentials; tokens = clientCredentials.Tokens; } else { credentials = new Credentials(); tokens = new Tokens(); } return(resultCode); } catch (EntryPointNotFoundException) { MLPluginLog.Error("MLTokenAgent.NativeBindings.GetClientCredentials failed. Reason: API symbols not found."); return(MLResult.Code.UnspecifiedFailure); } }
/// <summary> /// Invokes the MLTokenAgentGetClientCredentials() function asynchronously (in a different thread). /// </summary> /// <param name="clientCredentials">Reference to the clientCredentials object.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if the operation completed successfully. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if the operation failed with an unspecified error. /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if the profile or out_future were 0 (null). /// MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if the operation failed to allocate memory. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if the caller does not have the ClientCredentialsRead privilege. /// MLResult.Result will be <c>MLResult.Code.TokenAgent*</c> if a token specific failure occurred during the operation. /// </returns> public static MLResult.Code RequestClientCredentialsAsync(MLTokenAgent.ClientCredentials clientCredentials) { IntPtr clientCredentialsFuturePtr = clientCredentialsFuturePtrMap.ContainsKey(clientCredentials) ? clientCredentialsFuturePtrMap[clientCredentials] : IntPtr.Zero; try { MLResult.Code resultCode = MLTokenAgent.NativeBindings.MLTokenAgentGetClientCredentialsAsync(ref clientCredentialsFuturePtr); if (MLResult.IsOK(resultCode)) { clientCredentialsFuturePtrMap.Remove(clientCredentials); clientCredentialsFuturePtrMap.Add(clientCredentials, clientCredentialsFuturePtr); } else if (resultCode == MLResult.Code.PrivilegeDenied) { MLPluginLog.Warning("MLTokenAgent.NativeBindings.RequestClientCredentialsAsync failed. Reason: Caller does not have IdentityRead Privilege."); } else { MLPluginLog.ErrorFormat("MLTokenAgent.NativeBindings.RequestClientCredentialsAsync failed. Reason: {0}", resultCode); } return(resultCode); } catch (EntryPointNotFoundException) { MLPluginLog.Error("MLTokenAgent.NativeBindings.RequestClientCredentialsAsync failed. Reason: API symbols not found."); return(MLResult.Code.UnspecifiedFailure); } }
/// <summary> /// Handles when a request queries client credentials. /// </summary> public void ProcessRequest() { if (this.request == null) { return; } switch (this.request.RequestState) { case Request.State.REQUEST_CREDENTIALS: this.RequestClientCredentialsAsync(); break; case Request.State.LISTENING_CREDENTIALS: this.ListenClientCredentialsResponse(); break; case Request.State.DONE: this.request?.Callback?.Invoke(MLResult.Create(this.request.ResultCode)); // Removes the clientCredentials object if something when wrong with the request. if (!MLResult.IsOK(this.request.ResultCode)) { this.request = null; MLTokenAgent.RemoveClientCredentials(this); } this.request = null; break; default: break; } }
/// <summary> /// Used to safely make native calls. /// </summary> /// <param name="resultCode">MLResult.Code enum that the wrappedPlatformCall should set.</param> /// <param name="platformFunctionName">Name of the function for the log to print on failure.</param> /// <param name="wrappedPlatformCall">Anonymous function for making your native call that you should set resultCode with.</param> /// <param name="successCase">Predicate delegate for determining when a call was successful.</param> /// <param name="checkInstance">Determines if this call should check for a valid instance before running.</param> protected static void PlatformInvoke(out MLResult.Code resultCode, string platformFunctionName, Action wrappedPlatformCall, Predicate <MLResult.Code> successCase = null, bool checkInstance = true) { resultCode = MLResult.Code.UnspecifiedFailure; if (checkInstance && !IsValidInstance()) { MLPluginLog.ErrorFormat("{0} failed. Reason: {1} API has no valid instance.", platformFunctionName, typeof(T).Name); return; } try { wrappedPlatformCall?.Invoke(); bool success = successCase != null?successCase(resultCode) : MLResult.IsOK(resultCode); if (!success) { MLPluginLog.ErrorFormat("{0} failed. Reason: {1}", platformFunctionName, MLResult.CodeToString(resultCode)); } } catch (DllNotFoundException) { MLPluginLog.ErrorFormat("{0} failed. Reason: {1} API is currently available only on device.", platformFunctionName, typeof(T).Name); resultCode = MLResult.Code.APIDLLNotFound; } catch (EntryPointNotFoundException) { MLPluginLog.ErrorFormat("{0} failed. Reason: {1} API symbols not found.", platformFunctionName, typeof(T).Name); resultCode = MLResult.Code.APISymbolsNotFound; } }
/// <summary> /// Updates the state of the PCF. /// </summary> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if operation completed successfully. /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if failed due to an invalid input parameter. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if there was a lack of privileges. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error. /// MLResult.Result will be <c>MLResult.Code.PassableWorldLowMapQuality</c> if map quality is too low for content persistence. Continue building the map. /// MLResult.Result will be <c>MLResult.Code.PassableWorldNotFound</c> if the passed CFUID is not available. /// MLResult.Result will be <c>MLResult.Code.PassableWorldUnableToLocalize</c> if currently unable to localize into any map. Continue building the map. /// </returns> private MLResult UpdateState() { if (MLPersistentCoordinateFrames.IsValidInstance()) { try { NativeBindings.FrameStateNative nativeState = NativeBindings.FrameStateNative.Create(); MLResult.Code resultCode = NativeBindings.MLPersistentCoordinateFramesGetFrameState(MLPersistentCoordinateFrames._instance.nativeTracker, in this.cfuid, ref nativeState); if (!MLResult.IsOK(resultCode)) { MLPluginLog.ErrorFormat("PCF.UpdateState failed to get frame state. Reason: {0}", MLResult.CodeToString(resultCode)); return(MLResult.Create(resultCode, string.Format("PCF.UpdateState failed to get frame state. Reason: {0}", MLResult.CodeToString(resultCode)))); } this.FrameState = nativeState.Data(); return(MLResult.Create(resultCode)); } catch (EntryPointNotFoundException) { MLPluginLog.Error("PCF.UpdateState failed. Reason: API symbols not found."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "PCF.UpdateState failed. Reason: API symbols not found.")); } } else { MLPluginLog.ErrorFormat("PCF.UpdateState failed. Reason: No Instance for MLPersistentCoordinateFrames."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "PCF.UpdateState failed. Reason: No Instance for MLPersistentCoordinateFrames.")); } }
/// <summary> /// Fetches client credentials, can be used with a callback or as a blocking call. /// </summary> /// <param name="callback">The callback to notify when the CurrentRequest is complete.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if the operation completed successfully. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if the operation failed with an unspecified error. /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if the out_credentials was 0 (null). /// MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if the operation failed to allocate memory. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if the caller does not have the ClientCredentialsRead privilege. /// MLResult.Result will be <c>MLResult.Code.TokenAgent*</c> if a token specific failure occurred during the operation. /// </returns> public MLResult Fetch(MLTokenAgent.ClientCredentials.Request.RequestAttibutesDelegate callback = null) { if (callback == null) { MLResult.Code resultCode = MLTokenAgent.NativeBindings.GetClientCredentials(this, ref this.credentials, ref this.tokens); if (!MLResult.IsOK(resultCode)) { MLPluginLog.ErrorFormat("MLTokenAgent.Fetch failed. Reason: {0}", MLResult.CodeToString(resultCode)); } return(MLResult.Create(resultCode)); } else { this.CurrentRequest = new Request { Callback = callback, ResultCode = MLResult.Code.Pending, RequestState = Request.State.REQUEST_CREDENTIALS }; MLTokenAgent.AddClientCredentials(this); return(MLResult.Create(MLResult.Code.Ok)); } }
/// <summary> /// Apply any changes made to the MLCamera.GeneralSettings properties. /// </summary> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if successful. /// MLResult.Result will be <c>MLResult.Code.MediaGenericUnexpectedNull</c> if failed to connect to camera characteristic due to null pointer. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to internal error. /// MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if failed to allocate memory. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing. /// </returns> public MLResult Apply() { MLResult.Code resultCode; if (this.SensorInfoExposureTimeRange.IsDirty) { ulong cameraCharacteristicsHandle = MagicLeapNativeBindings.InvalidHandle; resultCode = MLCameraNativeBindings.MLCameraGetCameraCharacteristics(ref cameraCharacteristicsHandle); if (!MLResult.IsOK(resultCode)) { MLResult result = MLResult.Create(resultCode); MLPluginLog.ErrorFormat("MLCamera.GeneralSettings.Apply failed to get camera characteristics for MLCamera while applying. Reason: {0}", result); return(result); } long[] sensorExposureTimeRange = new long[2]; sensorExposureTimeRange[0] = this.SensorInfoExposureTimeRange.Minimum; sensorExposureTimeRange[1] = this.SensorInfoExposureTimeRange.Maximum; resultCode = MLCameraNativeBindings.MLCameraMetadataSetSensorInfoExposureTimeRange(cameraCharacteristicsHandle, sensorExposureTimeRange); if (!MLResult.IsOK(resultCode)) { MLResult result = MLResult.Create(resultCode); MLPluginLog.ErrorFormat("MLCamera.GeneralSettings.Apply failed to set sensor exposure time range. Reason: {0}", result); return(result); } } return(MLResult.Create(MLResult.Code.Ok)); }
/// <summary> /// Called by MLAPISingleton on destruction /// </summary> /// <param name="isSafeToAccessManagedObjects">Used for cleanup</param> protected override void CleanupAPI(bool isSafeToAccessManagedObjects) { if (Native.MagicLeapNativeBindings.MLHandleIsValid(this.registerHandle)) { MLResult.Code resultCode = NativeBindings.MLConnectionsRegistrationShutdown(this.registerHandle); if (!MLResult.IsOK(resultCode)) { MLPluginLog.ErrorFormat("MLConnections.Stop failed in CleapupAPI() to shutdown registration to receive invites. Reason: {0}", MLResult.CodeToString(resultCode)); } } // Shutdown should only be called if Startup was successful. if (this.sendInviteHasStarted) { MLResult.Code shutdownResultCode = NativeBindings.MLConnectionsShutdown(); if (!MLResult.IsOK(shutdownResultCode)) { MLPluginLog.ErrorFormat("MLConnections.Stop failed in CleapupAPI() to deinitialize all resources used for sending an invite. Reason: {0}", MLResult.CodeToString(shutdownResultCode)); } } this.registerHandle = Native.MagicLeapNativeBindings.InvalidHandle; this.activeRequest = false; this.sendInviteHasStarted = false; }
/// <summary> /// Initialized a given appDefinedVideoSource object and sets it's callbacks. /// </summary> /// <param name="appDefinedVideoSource">The AppDefinedVideoSource object to initialize.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if the connection was successfully created. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if necessary privilege is missing. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to other internal error. /// </returns> public static MLResult.Code InitializeAppDefinedVideoSource(MLWebRTC.AppDefinedVideoSource appDefinedVideoSource) { #if PLATFORM_LUMIN appDefinedVideoSource.TrackType = Type.Video; appDefinedVideoSource.IsLocal = true; appDefinedVideoSource.gcHandle = GCHandle.Alloc(appDefinedVideoSource); IntPtr gcHandlePtr = GCHandle.ToIntPtr(appDefinedVideoSource.gcHandle); ulong appDefinedVideoSourceHandle = MagicLeapNativeBindings.InvalidHandle; NativeBindings.MLWebRTCAppDefinedSourceEventCallbacks callbacks = NativeBindings.MLWebRTCAppDefinedSourceEventCallbacks.Create(gcHandlePtr); MLResult.Code resultCode = NativeBindings.MLWebRTCSourceCreateAppDefinedVideoSource(in callbacks, out appDefinedVideoSourceHandle); appDefinedVideoSource.Handle = appDefinedVideoSourceHandle; if (!MLResult.IsOK(resultCode)) { appDefinedVideoSource.gcHandle.Free(); } return(resultCode); #else appDefinedVideoSource = null; return(MLResult.Code.Ok); #endif }
private static MLResult.Code CreateRemoteConnection(MLWebRTC.IceServer[] iceServers, IntPtr proxyConfig, out PeerConnection connection) { #if PLATFORM_LUMIN connection = new PeerConnection(); // Converts into native ice server structs MLWebRTCConnectionIceServer[] nativeIceServers = new MLWebRTCConnectionIceServer[iceServers.Length]; for (int i = 0; i < iceServers.Length; ++i) { nativeIceServers[i].Data = iceServers[i]; } IntPtr arrayPtr = Marshal.AllocHGlobal(Marshal.SizeOf <MLWebRTCConnectionIceServer>() * nativeIceServers.Length); IntPtr walkPtr = arrayPtr; for (int i = 0; i < nativeIceServers.Length; ++i) { Marshal.StructureToPtr(nativeIceServers[i], walkPtr, false); walkPtr = new IntPtr(walkPtr.ToInt64() + Marshal.SizeOf <MLWebRTCConnectionIceServer>()); } NativeBindings.MLWebRTCConnectionConfig config = new NativeBindings.MLWebRTCConnectionConfig(); config.IceServers = arrayPtr; config.NumIceServers = (uint)nativeIceServers.Length; config.ProxyConfig = proxyConfig; NativeBindings.MLWebRTCConnectionEventCallbacks callbacks = new NativeBindings.MLWebRTCConnectionEventCallbacks(); callbacks.OnError = NativeBindings.OnError; callbacks.OnConnected = NativeBindings.OnConnected; callbacks.OnDisconnected = NativeBindings.OnDisconnected; callbacks.OnLocalOfferCreated = NativeBindings.OnLocalOfferCreated; callbacks.OnLocalAnswerCreated = NativeBindings.OnLocalAnswerCreated; callbacks.OnLocalIceCandidateFound = NativeBindings.OnLocalIceCandidateFound; callbacks.OnIceGatheringCompleted = NativeBindings.OnIceGatheringCompleted; callbacks.OnTrackRemoved = NativeBindings.OnTrackRemoved; callbacks.OnTrackAdded = NativeBindings.OnTrackAdded; callbacks.OnDataChannelReceived = NativeBindings.OnDataChannelReceived; connection.gcHandle = GCHandle.Alloc(connection); IntPtr gcHandlePtr = GCHandle.ToIntPtr(connection.gcHandle); callbacks.Context = gcHandlePtr; ulong connectionHandle = MagicLeapNativeBindings.InvalidHandle; MLResult.Code resultCode = NativeBindings.MLWebRTCConnectionCreate(in config, in callbacks, out connectionHandle); Marshal.FreeHGlobal(arrayPtr); if (!MLResult.IsOK(resultCode)) { connection.gcHandle.Free(); return(resultCode); } connection.Handle = connectionHandle; return(resultCode); #else connection = null; return(MLResult.Code.Ok); #endif }
/// <summary> /// Sets the localization status based on if PCFs can currently be found /// </summary> private void SetLocalizationStatus() { if (MLPersistentCoordinateFrames.IsValidInstance()) { try { MLResult result = MLResult.Create(MLResult.Code.Ok); uint numPCFs = 0; MLResult.Code resultCode = NativeBindings.MLPersistentCoordinateFrameGetCount(MLPersistentCoordinateFrames._instance.nativeTracker, ref numPCFs); if (!MLResult.IsOK(resultCode)) { if (resultCode == MLResult.Code.PassableWorldLowMapQuality || resultCode == MLResult.Code.PassableWorldUnableToLocalize) { MLPluginLog.WarningFormat("Map quality not sufficient enough for MLPersistentCoordinateFrames.SetLocalizationStatus. Reason: {0}", MLResult.CodeToString(resultCode)); } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.SetLocalizationStatus failed. Reason: {0}", MLResult.IsOK(resultCode) ? "No PCFs could be found." : MLResult.CodeToString(resultCode)); } result = MLResult.Create(resultCode, string.Format("MLPersistentCoordinateFrames.SetLocalizationStatus failed. Reason: {0}", MLResult.IsOK(resultCode) ? "No PCFs could be found." : MLResult.CodeToString(resultCode))); } bool foundPCFs = result.IsOk && numPCFs > 0; if (!MLPersistentCoordinateFrames.IsLocalized && foundPCFs) { MLPersistentCoordinateFrames.IsLocalized = true; MLPersistentCoordinateFrames.OnLocalized?.Invoke(IsLocalized); } else if (MLPersistentCoordinateFrames.IsLocalized && !foundPCFs) { List <PCF> allPCFs = new List <PCF>(MLPersistentCoordinateFrames._instance.mapAllPCFs.Values); MLPersistentCoordinateFrames._instance.mapTrackedPCFs.Clear(); MLPersistentCoordinateFrames._instance.mapAllPCFs.Clear(); MLPersistentCoordinateFrames.IsLocalized = false; foreach (PCF pcf in allPCFs) { pcf.Update(); } MLPersistentCoordinateFrames._instance.mapUpdatedPCFsThisFrame.Clear(); MLPersistentCoordinateFrames.OnLocalized?.Invoke(MLPersistentCoordinateFrames.IsLocalized); } } catch (EntryPointNotFoundException) { MLPluginLog.Error("MLPersistentCoordinateFrames.SetLocalizationStatus failed. Reason: API symbols not found."); } } else { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.SetLocalizationStatus failed. Reason: No Instance for MLPersistentCoordinateFrames."); } }
/// <summary> /// Checks native code results for failure. /// </summary> /// <param name="resultCode"> The result of the native function call. </param> /// <param name="functionName"> The name of the native function. </param> /// <param name="successCase"> /// Predicate delegate for determining when a call was successful. /// Defaults to a check against <c>MLResult.IsOK(resultCode)</c>. /// </param> /// <param name="showError"> /// Should the default error message be displayed /// if the <c>resultCode</c> is not expected? /// </param> /// <returns> /// <c>true</c> if the result of <c>successCase</c> matches <c>resultCode</c>. /// <c>false</c> otherwise. /// </returns> protected static bool DidNativeCallSucceed(MLResult.Code resultCode, string functionName = "A native function", Predicate <MLResult.Code> successCase = null, bool showError = true) { bool success = successCase != null?successCase(resultCode) : MLResult.IsOK(resultCode); if (!success && showError) { MLPluginLog.ErrorFormat($"{functionName} in the Magic Leap API failed. Reason: {MLResult.CodeToString(resultCode)} "); } return(success); }
/// <summary> /// Request the list of detected found objects. /// Callback will never be called while request is still pending. /// </summary> /// <param name="callback"> /// Callback used to report query results. /// Callback MLResult code will never be <c>MLResult.Code.Pending</c>. /// </param> /// <returns> /// MLResult.Result inside callback will be <c>MLResult.Code.Ok</c> if successful. /// MLResult.Result inside callback will be <c>MLResult.Code.InvalidParam</c> if failed due to invalid input parameter. /// MLResult.Result inside callback will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to internal error. /// </returns> public static MLResult GetUniqueObjectLabelsAsync(OnGetUniqueObjectLabelsDelegate callback) { MLThreadDispatch.ScheduleWork(() => { string[] labels; MLResult result = MLResult.Create(MLResult.Code.Ok); if (MLFoundObjects.IsValidInstance()) { MLResult.Code resultCode = NativeBindings.MLFoundObjectGetAvailableLabelsCount(_instance.handle, out uint labelCount); result = MLResult.Create(resultCode); labels = new string[labelCount]; if (MLResult.IsOK(resultCode)) { for (uint i = 0; i < labelCount; ++i) { resultCode = NativeBindings.MLFoundObjectGetUniqueLabel(_instance.handle, i, 20, out string label); if (MLResult.IsOK(resultCode)) { labels[i] = label; } else { MLPluginLog.ErrorFormat("MLFoundObjects.GetUniqueObjectLabels failed getting a unique label. Reason: {0}", MLResult.CodeToString(resultCode)); result = MLResult.Create(MLResult.Code.UnspecifiedFailure, string.Format("MLFoundObjects.GetUniqueObjectLabels failed getting a unique label. Reason: {0}", MLResult.CodeToString(resultCode))); } } } else { MLPluginLog.ErrorFormat("MLFoundObjects.GetUniqueObjectLabels failed getting the unique label count. Reason: {0}", MLResult.CodeToString(resultCode)); result = MLResult.Create(MLResult.Code.UnspecifiedFailure, string.Format("MLFoundObjects.GetUniqueObjectLabels failed getting the unique label count. Reason: {0}", MLResult.CodeToString(resultCode))); } } else { labels = new string[0]; MLPluginLog.ErrorFormat("MLFoundObjects.GetUniqueObjectLabelsAsync failed. Reason: No Instance for MLFoundObjects."); result = MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLFoundObjects.GetUniqueObjectLabelsAsync failed. Reason: No Instance for MLFoundObjects"); } MLThreadDispatch.ScheduleMain(() => { callback?.Invoke(result, labels); }); return(true); }); return(MLResult.Create(MLResult.Code.Ok)); }
/// <summary> /// Queries a profile for a list of attribute values asynchronously. /// </summary> private void RequestAttributeValuesAsync() { MLResult.Code resultCode = MLIdentity.NativeBindings.RequestAttributeValuesAsync(this, ref this.attributes); if (MLResult.IsOK(resultCode)) { this.request.RequestState = Request.State.LISTENING_ATTRIB_VALUES; } else { MLPluginLog.WarningFormat("MLIdentity.Profile.RequestAttributeValuesAsync failed request for attribute values async. Reason: {0}", MLResult.CodeToString(resultCode)); this.request.RequestState = Request.State.DONE; } }
/// <summary> /// Instance.settings setter. /// If called with the same value while a settings update operation is in progress, /// nothing will happen. /// </summary> public static async Task SetSettingsAsync(Settings value) { if (futureSettingsValue.Equals(value)) { return; } futureSettingsValue = value; if (MLResult.IsOK((await MLBarcodeScannerSettingsUpdate(value)).Result)) { Instance.settings = value; } }
/// <summary> /// Called by MLAPISingleton to start the API /// </summary> /// <returns> /// <para>MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if the registration resource allocation failed.</para> /// <para>MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if a given argument is invalid.</para> /// <para>MLResult.Result will be <c>MLResult.Code.Ok</c> if successfully initialized.</para> /// <para>MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if there was an unexpected failure.</para> /// <para>MLResult.Result will be <c>MLResult.Code.ConnectionsAlreadyRegistered</c> if this is a duplicate registration.</para> /// <para>MLResult.Result will be <c>MLResult.Code.ConnectionsNetworkFailure</c> if communication to the network failed.</para> /// <para>MLResult.Result will be <c>MLResult.Code.ConnectionsSystemFailure</c> if there was system failure.</para> /// </returns> protected override MLResult StartAPI() { MLResult.Code resultCode = NativeBindings.MLConnectionsRegistrationStartup(ref _instance.registerHandle); if (!MLResult.IsOK(resultCode) || !Native.MagicLeapNativeBindings.MLHandleIsValid(_instance.registerHandle)) { MLResult resultError = MLResult.Create(resultCode); MLPluginLog.ErrorFormat("MLConnections.Start failed in StartAPI() to register to receive invites. Handle is invalid or Reason: {0}", resultError); return(resultError); } NativeBindings.InviteCallbacks connectionCallbacks = NativeBindings.InviteCallbacks.Create(); resultCode = NativeBindings.MLConnectionsRegisterForInvite(_instance.registerHandle, connectionCallbacks, IntPtr.Zero); if (!MLResult.IsOK(resultCode)) { MLResult resultError = MLResult.Create(resultCode); MLPluginLog.ErrorFormat("MLConnections.Start failed in StartAPI() to set callbacks. Reason: {0}", resultError); return(resultError); } else { if (_instance.activeRequest) { // This check is just precautionary, but it should never happen. MLPluginLog.WarningFormat("MLConnections.Start allowed multiple active registrations."); } Instance.activeRequest = true; } resultCode = NativeBindings.MLConnectionsStartup(); if (!MLResult.IsOK(resultCode)) { MLPluginLog.ErrorFormat("MLConnections.Start failed in StartAPI() to initialize resources for sending an invite. Reason: {0}", MLResult.CodeToString(resultCode)); } else { _instance.sendInviteHasStarted = true; } return(MLResult.Create(resultCode)); }
/// <summary> /// Destroys the native Hand Meshing client. /// </summary> private void DestroyNativeTracker() { if (!MagicLeapNativeBindings.MLHandleIsValid(this.nativeTracker)) { return; } MLResult.Code result = NativeBindings.MLHandMeshingDestroyClient(ref this.nativeTracker); if (!MLResult.IsOK(result)) { MLPluginLog.ErrorFormat("MLHandMeshing.DestroyNativeTracker failed to destroy native hand tracker. Reason: {0}", result); } this.nativeTracker = MagicLeapNativeBindings.InvalidHandle; }
/// <summary> /// Queries for the client credentials of this user. /// </summary> private void RequestClientCredentialsAsync() { MLResult.Code resultCode = MLTokenAgent.NativeBindings.RequestClientCredentialsAsync(this); if (MLResult.IsOK(resultCode)) { this.request.ResultCode = MLResult.Code.Pending; this.request.RequestState = MLTokenAgent.ClientCredentials.Request.State.LISTENING_CREDENTIALS; } else { this.request.ResultCode = resultCode; this.request.RequestState = MLTokenAgent.ClientCredentials.Request.State.DONE; } }
/// <summary> /// Listens for a list of attribute values previously requested by RequestAttributeValuesAsync. /// </summary> private void ListenAttributeValuesResponse() { MLResult.Code resultCode = MLIdentity.NativeBindings.ListenAttributeValuesResponse(this, ref this.attributes); if (MLResult.IsOK(resultCode)) { this.request.RequestState = Request.State.DONE; } else if (!MLResult.IsPending(resultCode)) { MLPluginLog.ErrorFormat("MLIdentity.Profile.ListenAttributeValuesResponse failed to retrieve attribute values. Reason: {0}", resultCode); this.request.RequestState = Request.State.DONE; } this.request.ResultCode = resultCode; }
/// <summary> /// Listens for client credentials previously requested by RequestClientCredentialsAsync. /// </summary> private void ListenClientCredentialsResponse() { MLResult.Code resultCode = MLTokenAgent.NativeBindings.ListenClientCredentialsResponse(this, ref this.credentials, ref this.tokens); if (MLResult.IsOK(resultCode)) { this.request.RequestState = Request.State.DONE; } else if (!MLResult.IsPending(resultCode)) { MLPluginLog.ErrorFormat("MLIdentity.clientCredentials.ListenAttributeNamesResponse failed to retrieve attribute names. Reason: {0}", resultCode); this.request.RequestState = Request.State.DONE; } this.request.ResultCode = resultCode; }
/// <summary> /// Updates the settings of the found objects tracker. /// </summary> /// <param name="newSettings">The new settings to update the found objects tracker with.</param> /// <param name="callback">The callback to invoke when the settings have been updated or failed doing so.</param> /// <returns> /// MLResult.Result inside callback will be <c>MLResult.Code.Ok</c> if successful. /// MLResult.Result inside callback will be <c>MLResult.Code.InvalidParam</c> if failed due to invalid input parameter. /// MLResult.Result inside callback will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to internal error. /// </returns> public static MLResult UpdateSettingsAsync(Settings newSettings, OnUpdateSettingsDelegate callback = null) { MLResult result = MLResult.Create(MLResult.Code.Ok); MLThreadDispatch.ScheduleWork(() => { if (MLFoundObjects.IsValidInstance()) { NativeBindings.Settings settingsNative = new NativeBindings.Settings(); settingsNative.Data = newSettings; MLResult.Code resultCode = NativeBindings.MLFoundObjectTrackerUpdateSettings(_instance.handle, in settingsNative); if (MLResult.IsOK(resultCode)) { MLThreadDispatch.ScheduleMain(() => { result = MLResult.Create(resultCode); _instance.settings = newSettings; callback?.Invoke(result, _instance.settings); }); } else { MLPluginLog.ErrorFormat("MLFoundObjects.UpdateSettingsAsync failed to update settings. Reason: {0}", MLResult.CodeToString(resultCode)); result = MLResult.Create(MLResult.Code.UnspecifiedFailure, string.Format("MLFoundObjects.UpdateSettingsAsync failed to update settings. Reason: {0}", MLResult.CodeToString(resultCode))); MLThreadDispatch.ScheduleMain(() => { callback?.Invoke(result, _instance.settings); }); } } else { MLPluginLog.ErrorFormat("MLFoundObjects.GetObjects failed. Reason: No Instance for MLFoundObjects"); result = MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLFoundObjects.GetFoundObjects failed. Reason: No Instance for MLFoundObjects"); MLThreadDispatch.ScheduleMain(() => { callback?.Invoke(result, _instance.settings); }); } return(true); }); return(result); }
/// <summary> /// Creates an initialized Track object. /// Recommended to use app defined video sources in production, with sample sources provided /// as MLCameraVideoSource and MLMRCameraVideoSource in the UnityEngine.XR.MagicLeap namespace /// since those sources provide more information about and control over various error cases and /// handle special cases like app pause/resume and device standby/reality/active. /// </summary> /// <param name="videoType">The type of video source to use.</param> /// <param name="result">The MLResult object of the inner platform call(s).</param> /// <param name="inputContext">The InputContext object to start the MLMRCamera API with.</param> /// <returns> An initialized Track object.</returns> public static Track CreateVideoTrack(VideoType videoType, out MLResult result, MLMRCamera.InputContext?inputContext = null, string trackId = "") { Track track = null; ulong handle = MagicLeapNativeBindings.InvalidHandle; MLResult.Code resultCode = MLResult.Code.Ok; switch (videoType) { case VideoType.MLCamera: { resultCode = Source.NativeBindings.MLWebRTCSourceCreateLocalSourceForCamera(out handle); DidNativeCallSucceed(resultCode, "MLWebRTCSourceCreateLocalSourceForCamera"); break; } case VideoType.MLMRCamera: { MLMRCamera.NativeBindings.InputContextNative inputContextNative = new MLMRCamera.NativeBindings.InputContextNative { Data = inputContext ?? MLMRCamera.InputContext.Create() }; resultCode = Source.NativeBindings.MLWebRTCSourceCreateLocalSourceForMRCamera(in inputContextNative, out handle); DidNativeCallSucceed(resultCode, "MLWebRTCSourceCreateLocalSourceForMRCamera"); break; } } if (!MLResult.IsOK(resultCode)) { result = MLResult.Create(resultCode); return(track); } track = new Track(trackId) { Handle = handle, TrackType = Type.Video, IsLocal = true, }; MLWebRTC.Instance.localTracks.Add(track); result = MLResult.Create(resultCode); return(track); }
/// <summary> /// Create a new found object native tracker. /// </summary> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if successful. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to internal error. /// </returns> private MLResult CreateTracker() { try { MLResult.Code resultCode = NativeBindings.MLFoundObjectTrackerCreate(out _instance.handle); if (!MLResult.IsOK(resultCode)) { MLPluginLog.ErrorFormat("MLFoundObjects.CreateTracker failed to initialize native tracker. Reason: {0}", resultCode); } return(MLResult.Create(resultCode)); } catch (System.EntryPointNotFoundException) { MLPluginLog.Error("MLFoundObjects.CreateTracker failed. Reason: API symbols not found"); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLFoundObjects.CreateTracker failed. Reason: API symbols not found")); } }
/// <summary> /// Queries a profile for a list of attribute names asynchronously. /// </summary> private void RequestAttributeNamesAsync() { MLResult.Code resultCode = MLIdentity.NativeBindings.RequestAttributeNamesAsync(this, this.requestAttributes, ref this.attributes); if (MLResult.IsOK(resultCode)) { this.request.ResultCode = MLResult.Code.Pending; this.request.RequestState = (this.requestAttributes != null && this.requestAttributes.Length > 0) ? MLIdentity.Profile.Request.State.REQUEST_ATTRIB_VALUES : MLIdentity.Profile.Request.State.LISTENING_ATTRIB_NAMES; } else { MLPluginLog.WarningFormat("MLIdentity.Profile.RequestAttributeNamesAsync failed request for attribute names async. Reason: {0}", MLResult.CodeToString(resultCode)); this.request.ResultCode = resultCode; this.request.RequestState = MLIdentity.Profile.Request.State.DONE; } }
/// <summary> /// Updates the tracking status of the PCF based on the current and last MLResult /// received when querying for the PCF's pose. /// </summary> /// <param name="oldCode">The MLResult from the previous pose query.</param> /// <param name="newCode">The MLResult from the current pose query.</param> /* ----------------------------------------- * OldCode | NewCode | Event * ------------------------------------------|---------|--------------- * Pending | Ok | Create * !Ok & !Pending | Ok | Regain * Ok & (poseChanged || stateChanged) | Ok | Update * Ok & !(poseChanged || stateChanged) | Ok | Stable * Ok | !Ok | Lost * ----------------------------------------- */ private void OnCurrentResultChanged(MLResult.Code oldCode, MLResult.Code newCode) { if (MLResult.IsOK(newCode)) { if (oldCode == MLResult.Code.Pending) { this.UpdateStatus(Status.Created); } else if (!MLResult.IsOK(oldCode)) { foreach (IBinding binding in this.bindings) { binding.Regain(); } this.UpdateStatus(Status.Regained); } else if (this.poseChanged || this.stateChanged) { foreach (IBinding binding in this.bindings) { binding.Update(); } this.UpdateStatus(Status.Updated); this.poseChanged = false; this.stateChanged = false; } else { this.UpdateStatus(Status.Stable); } } else { foreach (IBinding binding in this.bindings) { binding.Lost(); } this.UpdateStatus(Status.Lost); } }
/// <summary> /// Starts the Persistent Coordinate Frames API. /// Initializes the PCF tracker. /// </summary> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if the PCF tracker could be created successfully. /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if the tracker to initialize was null. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if there were any missing privileges. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if failed due to an internal error. /// </returns> protected override MLResult StartAPI() { try { MLResult.Code resultCode = NativeBindings.MLPersistentCoordinateFrameTrackerCreate(ref _instance.nativeTracker); if (!MLResult.IsOK(resultCode)) { MLPluginLog.ErrorFormat("MLPersistentCoordinateFrames.StartAPI failed to create PCF tracker. Reason: {0}", MLResult.CodeToString(resultCode)); return(MLResult.Create(resultCode, "MLPersistentCoordinateFrames.StartAPI failed to create PCF tracker.")); } return(MLResult.Create(resultCode)); } catch (EntryPointNotFoundException) { MLPluginLog.Error("MLPersistentCoordinateFrames.StartAPI failed. Reason: API symbols not found."); return(MLResult.Create(MLResult.Code.UnspecifiedFailure, "MLPersistentCoordinateFrames.StartAPI failed. Reason: API symbols not found.")); } }
/// <summary> /// Having made a call to MLTokenAgentGetClientCredentialsAsync(), the user can call MLTokenAgentGetClientCredentialsWait() /// to detect whether the asynchronous call completed and if so, to retrieve the credentials in out_credentials. /// </summary> /// <param name="clientCredentials">Reference to the clientCredentials object.</param> /// <param name="credentials">Reference to the credentials struct of the clientCredentials object.</param> /// <param name="tokens">Reference to the tokens struct of the clientCredentials object.</param> /// <returns> /// MLResult.Result will be <c>MLResult.Code.Ok</c> if the operation completed successfully before the timeout elapsed. /// MLResult.Result will be <c>MLResult.Code.Pending</c> if the timeout elapsed before the asynchronous call completed. /// MLResult.Result will be <c>MLResult.Code.UnspecifiedFailure</c> if the operation failed with an unspecified error. /// MLResult.Result will be <c>MLResult.Code.InvalidParam</c> if the future or out_credentials were 0 (null). /// MLResult.Result will be <c>MLResult.Code.AllocFailed</c> if the operation failed to allocate memory. /// MLResult.Result will be <c>MLResult.Code.PrivilegeDenied</c> if the caller does not have the ClientCredentialsRead privilege. /// MLResult.Result will be <c>MLResult.Code.TokenAgent*</c> if a token specific failure occurred during the operation. /// </returns> public static MLResult.Code ListenClientCredentialsResponse(MLTokenAgent.ClientCredentials clientCredentials, ref MLTokenAgent.Credentials credentials, ref MLTokenAgent.Tokens tokens) { try { IntPtr clientCredentialsPtr = clientCredentialsPtrMap.ContainsKey(clientCredentials) ? clientCredentialsPtrMap[clientCredentials] : IntPtr.Zero; IntPtr clientCredentialsFuturePtr = clientCredentialsFuturePtrMap.ContainsKey(clientCredentials) ? clientCredentialsFuturePtrMap[clientCredentials] : IntPtr.Zero; if (clientCredentialsFuturePtr == IntPtr.Zero) { MLPluginLog.Warning("MLTokenAgent.NativeBindings.ListenClientCredentialsResponse failed because a valid future pointer could not be found with the passed request."); return(MLResult.Code.UnspecifiedFailure); } //// Attempt to get data if available, 0 is passed as a timeout to immediately return and never wait for results. MLResult.Code resultCode = MLTokenAgent.NativeBindings.MLTokenAgentGetClientCredentialsWait(clientCredentialsFuturePtr, 0, ref clientCredentialsPtr); // If it succeeded, copy any modifications made to the profile in unmanaged memory by the Identity API to managed memory. if (MLResult.IsOK(resultCode)) { clientCredentialsFuturePtrMap.Remove(clientCredentials); clientCredentialsPtrMap.Remove(clientCredentials); clientCredentialsPtrMap.Add(clientCredentials, clientCredentialsPtr); MLTokenAgent.NativeBindings.ClientCredentialsNative clientCredentialsNative = (MLTokenAgent.NativeBindings.ClientCredentialsNative)Marshal.PtrToStructure(clientCredentialsPtr, typeof(MLTokenAgent.NativeBindings.ClientCredentialsNative)); credentials = clientCredentialsNative.Credentials; tokens = clientCredentials.Tokens; } else { credentials = new Credentials(); tokens = new Tokens(); } return(resultCode); } catch (EntryPointNotFoundException) { MLPluginLog.Error("MLTokenAgent.NativeBindings.ListenClientCredentialsResponse failed. Reason: API symbols not found."); return(MLResult.Code.UnspecifiedFailure); } }
/// <summary> /// Handles when a request queries the attribute names. /// </summary> public void ProcessRequest() { if (this.request == null) { return; } switch (this.request.RequestState) { case Request.State.REQUEST_ATTRIB_NAMES: this.RequestAttributeNamesAsync(); break; case Request.State.LISTENING_ATTRIB_NAMES: this.ListenAttributeNamesResponse(); break; case Request.State.REQUEST_ATTRIB_VALUES: this.RequestAttributeValuesAsync(); break; case Request.State.LISTENING_ATTRIB_VALUES: this.ListenAttributeValuesResponse(); break; case Request.State.DONE: this.request?.Callback?.Invoke(MLResult.Create(this.request.ResultCode)); //// Removes the profile if something when wrong with the request. if (!MLResult.IsOK(this.request.ResultCode)) { this.request = null; MLIdentity.RemoveProfile(this); } this.request = null; break; default: break; } }