/// <summary> /// Prepares the cancelable media player for playback, asynchronously. /// </summary> /// <param name="cancellationToken">The cancellation token to cancel preparing.</param> /// <seealso cref="CancellationToken"/> /// <returns>The task that represents the asynchronous prepare operation.</returns> /// <remarks>To prepare the player, the player must be in the <see cref="PlayerState.Idle"/> state, /// and a source must be set. /// The state must be <see cref="PlayerState.Preparing"/> to cancel preparing. /// When preparing is cancelled, a state will be changed to <see cref="PlayerState.Idle"/> from <see cref="PlayerState.Preparing"/>.</remarks> /// <exception cref="ObjectDisposedException">The player has already been disposed.</exception> /// <exception cref="InvalidOperationException"> /// Operation failed; internal error. /// -or-<br/> /// The player is not in the valid state. /// </exception> /// <seealso cref="PrepareAsync()"/> /// <seealso cref="Unprepare()"/> /// <since_tizen> 6 </since_tizen> public virtual async Task PrepareAsync(CancellationToken cancellationToken) { ValidateNotDisposed(); var taskCompletionSource = new TaskCompletionSource <bool>(); if (_source == null) { throw new InvalidOperationException("No source is set."); } ValidatePlayerState(PlayerState.Idle); OnPreparing(); SetPreparing(); // register a callback to handle cancellation token anytime it occurs cancellationToken.Register(() => { ValidatePlayerState(PlayerState.Preparing); // a user can get the state before finally block is called. ClearPreparing(); Log.Warn(PlayerLog.Tag, $"preparing will be cancelled."); NativePlayer.Unprepare(Handle).ThrowIfFailed(this, "Failed to unprepare the player"); taskCompletionSource.TrySetCanceled(); }); _prepareCallback = _ => { Log.Warn(PlayerLog.Tag, $"prepared callback is called."); taskCompletionSource.TrySetResult(true); }; try { NativePlayer.PrepareAsync(Handle, _prepareCallback, IntPtr.Zero). ThrowIfFailed(this, "Failed to prepare the player"); await taskCompletionSource.Task.ConfigureAwait(false); } finally { ClearPreparing(); } }