[MediaPlayer] Add API to be able to cancel preparing it (#944)
authornam <36914158+aferin@users.noreply.github.com>
Wed, 31 Jul 2019 07:02:56 +0000 (16:02 +0900)
committerGitHub <noreply@github.com>
Wed, 31 Jul 2019 07:02:56 +0000 (16:02 +0900)
src/Tizen.Multimedia.MediaPlayer/Interop/Interop.Player.cs
src/Tizen.Multimedia.MediaPlayer/Player/Player.Events.cs
src/Tizen.Multimedia.MediaPlayer/Player/Player.cs

index 8c0cf7af0159c5dc123718c0daff2986df7d9bdb..fc70274c0733b24ec3611e9e7f22c61fada8cc46 100644 (file)
@@ -75,6 +75,10 @@ internal static partial class Interop
         [DllImport(Libraries.Player, EntryPoint = "player_prepare")]
         internal static extern PlayerErrorCode Prepare(IntPtr player);
 
+        [DllImport(Libraries.Player, EntryPoint = "player_prepare_async")]
+        internal static extern PlayerErrorCode PrepareAsync(IntPtr player, PrepareCallback callback,
+            IntPtr userData = default(IntPtr));
+
         [DllImport(Libraries.Player, EntryPoint = "player_unprepare")]
         internal static extern PlayerErrorCode Unprepare(IntPtr player);
 
index ed9f3dc0b355be7b83126e0efead56e156394e14..e7ba765c828aa7af7bd36098d78c7210a5805663 100644 (file)
@@ -74,6 +74,8 @@ namespace Tizen.Multimedia
         public event EventHandler<BufferingProgressChangedEventArgs> BufferingProgressChanged;
         private NativePlayer.BufferingProgressCallback _bufferingProgressCallback;
 
+        private NativePlayer.PrepareCallback _prepareCallback;
+
         internal event EventHandler<MediaStreamBufferStatusChangedEventArgs> MediaStreamAudioBufferStatusChanged;
         private NativePlayer.MediaStreamBufferStatusCallback _mediaStreamAudioBufferStatusChangedCallback;
 
index 27e77d4be3b6f9a932bebeb4ccccaf57a302e831..8d35953a7b11e1dee72a4d6ce4e14244bde772a6 100644 (file)
@@ -345,6 +345,75 @@ namespace Tizen.Multimedia
                 TaskScheduler.Default);
         }
 
+        /// <summary>
+        /// Prepares the cancellable media player for playback, asynchronously.
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token to cancel preparing.</param>
+        /// <seealso cref="CancellationToken"/>
+        /// <returns>A 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 of.</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();
+            }
+        }
+
         /// <summary>
         /// Unprepares the player.
         /// </summary>