using System.IO;
using System.Threading;
using static Interop;
+using System.ComponentModel;
namespace Tizen.Multimedia
{
- static internal class PlayerLog
+ internal static class PlayerLog
{
internal const string Tag = "Tizen.Multimedia.Player";
- internal const string Enter = "[ENTER]";
- internal const string Leave = "[LEAVE]";
}
/// <summary>
/// Provides the ability to control media playback.
/// </summary>
/// <remarks>
- /// The Player provides functions to play a media content.
+ /// The player provides functions to play a media content.
/// It also provides functions to adjust the configurations of the player such as playback rate, volume, looping etc.
/// Note that only one video player can be played at one time.
/// </remarks>
private PlayerHandle _handle;
/// <summary>
- /// Initialize a new instance of the Player class.
+ /// Initializes a new instance of the <see cref="Player"/> class.
/// </summary>
+ /// <since_tizen> 3 </since_tizen>
public Player()
{
NativePlayer.Create(out _handle).ThrowIfFailed("Failed to create player");
RetrieveProperties();
- if (Features.IsSupported(Features.AudioEffect))
+ if (Features.IsSupported(PlayerFeatures.AudioEffect))
{
_audioEffect = new AudioEffect(this);
}
- if (Features.IsSupported(Features.RawVideo))
+ if (Features.IsSupported(PlayerFeatures.RawVideo))
{
RegisterVideoFrameDecodedCallback();
}
/// <summary>
/// Releases all resources used by the current instance.
/// </summary>
+ /// <since_tizen> 3 </since_tizen>
public void Dispose()
{
Dispose(true);
#region Methods
/// <summary>
- /// Gets the streaming download Progress.
+ /// Gets the streaming download progress.
/// </summary>
/// <returns>The <see cref="DownloadProgress"/> containing current download progress.</returns>
/// <remarks>The player must be in the <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/> state.</remarks>
/// <exception cref="InvalidOperationException">
- /// The player is not streaming.\n
- /// -or-\n
+ /// The player is not streaming.<br/>
+ /// -or-<br/>
/// The player is not in the valid state.
/// </exception>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
+ /// <since_tizen> 3 </since_tizen>
public DownloadProgress GetDownloadProgress()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
ValidatePlayerState(PlayerState.Playing, PlayerState.Paused);
int start = 0;
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="ArgumentException"><paramref name="path"/> is an empty string.</exception>
/// <exception cref="FileNotFoundException">The specified path does not exist.</exception>
- /// <exception cref="ArgumentNullException">The path is null.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
+ /// <since_tizen> 3 </since_tizen>
public void SetSubtitle(string path)
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
ValidateNotDisposed();
if (path == null)
NativePlayer.SetSubtitlePath(Handle, path).
ThrowIfFailed("Failed to set the subtitle path to the player");
-
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
/// <summary>
/// <remarks>The player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
+ /// <since_tizen> 3 </since_tizen>
public void ClearSubtitle()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
ValidatePlayerState(PlayerState.Idle);
NativePlayer.SetSubtitlePath(Handle, null).
ThrowIfFailed("Failed to clear the subtitle of the player");
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
/// <summary>
/// <remarks>The player must be in the <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/> state.</remarks>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">
- /// The player is not in the valid state.\n
- /// -or-\n
+ /// The player is not in the valid state.<br/>
+ /// -or-<br/>
/// No subtitle is set.
/// </exception>
/// <seealso cref="SetSubtitle(string)"/>
+ /// <since_tizen> 3 </since_tizen>
public void SetSubtitleOffset(int offset)
{
ValidatePlayerState(PlayerState.Playing, PlayerState.Paused);
}
err.ThrowIfFailed("Failed to the subtitle offset of the player");
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
private void Prepare()
/// <summary>
/// Called when the <see cref="Prepare"/> is invoked.
/// </summary>
+ /// <since_tizen> 3 </since_tizen>
protected virtual void OnPreparing()
{
RegisterEvents();
/// <exception cref="InvalidOperationException">No source is set.</exception>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
+ /// <since_tizen> 3 </since_tizen>
public virtual Task PrepareAsync()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
if (_source == null)
{
throw new InvalidOperationException("No source is set.");
ValidatePlayerState(PlayerState.Idle);
+ SetDisplay(_display).ThrowIfFailed("Failed to configure display of the player");
+
OnPreparing();
var completionSource = new TaskCompletionSource<bool>();
completionSource.TrySetException(e);
}
});
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
return completionSource.Task;
}
/// Unprepares the player.
/// </summary>
/// <remarks>
- /// The most recently used source is reset and no longer associated with the player. Playback is no longer possible.
+ /// The most recently used source is reset and is no longer associated with the player. Playback is no longer possible.
/// If you want to use the player again, you have to set a source and call <see cref="PrepareAsync"/> again.
/// <para>
- /// The player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/> state.
+ /// The player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
/// It has no effect if the player is already in the <see cref="PlayerState.Idle"/> state.
/// </para>
/// </remarks>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
+ /// <since_tizen> 3 </since_tizen>
public virtual void Unprepare()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
if (State == PlayerState.Idle)
{
Log.Warn(PlayerLog.Tag, "idle state already");
/// Called after the <see cref="Player"/> is unprepared.
/// </summary>
/// <seealso cref="Unprepare"/>
+ /// <since_tizen> 3 </since_tizen>
protected virtual void OnUnprepared()
{
_source?.DetachFrom(this);
/// </summary>
/// <remarks>
/// The player must be in the <see cref="PlayerState.Ready"/> or <see cref="PlayerState.Paused"/> state.
- /// It has no effect if the player is already in the <see cref="PlayerState.Playing"/> state.\n
- /// \n
+ /// It has no effect if the player is already in the <see cref="PlayerState.Playing"/> state.<br/>
+ /// <br/>
/// Sound can be mixed with other sounds if you don't control the stream focus using <see cref="ApplyAudioStreamPolicy"/>.
/// </remarks>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <seealso cref="Pause"/>
/// <seealso cref="PlaybackCompleted"/>
/// <seealso cref="ApplyAudioStreamPolicy"/>
+ /// <since_tizen> 3 </since_tizen>
public virtual void Start()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
if (State == PlayerState.Playing)
{
Log.Warn(PlayerLog.Tag, "playing state already");
ValidatePlayerState(PlayerState.Ready, PlayerState.Paused);
NativePlayer.Start(Handle).ThrowIfFailed("Failed to start the player");
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
/// <summary>
- /// Stops playing media content.
+ /// Stops playing the media content.
/// </summary>
/// <remarks>
/// The player must be in the <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/> state.
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
/// <seealso cref="Start"/>
/// <seealso cref="Pause"/>
+ /// <since_tizen> 3 </since_tizen>
public virtual void Stop()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
if (State == PlayerState.Ready)
{
Log.Warn(PlayerLog.Tag, "ready state already");
ValidatePlayerState(PlayerState.Paused, PlayerState.Playing);
NativePlayer.Stop(Handle).ThrowIfFailed("Failed to stop the player");
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
/// <summary>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
/// <seealso cref="Start"/>
+ /// <since_tizen> 3 </since_tizen>
public virtual void Pause()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
if (State == PlayerState.Paused)
{
Log.Warn(PlayerLog.Tag, "pause state already");
ValidatePlayerState(PlayerState.Playing);
NativePlayer.Pause(Handle).ThrowIfFailed("Failed to pause the player");
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
private MediaSource _source;
/// <remarks>The player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">
- /// The player is not in the valid state.\n
- /// -or-\n
+ /// The player is not in the valid state.<br/>
+ /// -or-<br/>
/// It is not able to assign the source to the player.
/// </exception>
/// <seealso cref="PrepareAsync"/>
+ /// <since_tizen> 3 </since_tizen>
public void SetSource(MediaSource source)
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
ValidatePlayerState(PlayerState.Idle);
if (source != null)
}
_source = source;
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
/// <summary>
- /// Captures a video frame asynchronously.
+ /// Captures a video frame, asynchronously.
/// </summary>
/// <returns>A task that represents the asynchronous capture operation.</returns>
/// <feature>http://tizen.org/feature/multimedia.raw_video</feature>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
/// <exception cref="NotSupportedException">The required feature is not supported.</exception>
+ /// <since_tizen> 3 </since_tizen>
public async Task<CapturedFrame> CaptureVideoAsync()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
-
- ValidationUtil.ValidateFeatureSupported(Features.RawVideo);
+ ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
ValidatePlayerState(PlayerState.Playing, PlayerState.Paused);
/// <summary>
/// Gets the play position in milliseconds.
/// </summary>
- /// <remarks>The player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/> state.</remarks>
+ /// <remarks>The player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/>,
+ /// or <see cref="PlayerState.Paused"/> state.</remarks>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
/// <seealso cref="SetPlayPositionAsync(int, bool)"/>
+ /// <since_tizen> 3 </since_tizen>
public int GetPlayPosition()
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
ValidatePlayerState(PlayerState.Ready, PlayerState.Paused, PlayerState.Playing);
int playPosition = 0;
private void SetPlayPosition(int milliseconds, bool accurate,
NativePlayer.SeekCompletedCallback cb)
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
var ret = NativePlayer.SetPlayPosition(Handle, milliseconds, accurate, cb, IntPtr.Zero);
//Note that we assume invalid param error is returned only when the position value is invalid.
/// <param name="position">The value indicating a desired position in milliseconds.</param>
/// <param name="accurate">The value indicating whether the operation performs with accuracy.</param>
/// <remarks>
- /// <para>The player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/> state.</para>
+ /// <para>The player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/>,
+ /// or <see cref="PlayerState.Paused"/> state.</para>
/// <para>If the <paramref name="accurate"/> is true, the play position will be adjusted as the specified <paramref name="position"/> value,
/// but this might be considerably slow. If false, the play position will be a nearest keyframe position.</para>
/// </remarks>
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
/// <exception cref="ArgumentOutOfRangeException">The specified position is not valid.</exception>
/// <seealso cref="GetPlayPosition"/>
+ /// <since_tizen> 3 </since_tizen>
public async Task SetPlayPositionAsync(int position, bool accurate)
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
- var taskCompletionSource = new TaskCompletionSource<bool>();
+ var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
bool immediateResult = _source is MediaStreamSource;
await taskCompletionSource.Task;
}
-
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
/// <summary>
- /// Sets playback rate.
+ /// Sets the playback rate.
/// </summary>
/// <param name="rate">The value for the playback rate. Valid range is -5.0 to 5.0, inclusive.</param>
/// <remarks>
- /// <para>The player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/> state.</para>
+ /// <para>The player must be in the <see cref="PlayerState.Ready"/>, <see cref="PlayerState.Playing"/>,
+ /// or <see cref="PlayerState.Paused"/> state.</para>
/// <para>The sound will be muted, when the playback rate is under 0.0 or over 2.0.</para>
/// </remarks>
/// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
/// <exception cref="InvalidOperationException">
- /// The player is not in the valid state.\n
- /// -or-\n
+ /// The player is not in the valid state.<br/>
+ /// -or-<br/>
/// Streaming playback.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
- /// <paramref name="rate"/> is less than 5.0.\n
- /// -or-\n
- /// <paramref name="rate"/> is greater than 5.0.\n
- /// -or-\n
+ /// <paramref name="rate"/> is less than 5.0.<br/>
+ /// -or-<br/>
+ /// <paramref name="rate"/> is greater than 5.0.<br/>
+ /// -or-<br/>
/// <paramref name="rate"/> is zero.
/// </exception>
+ /// <since_tizen> 3 </since_tizen>
public void SetPlaybackRate(float rate)
{
- Log.Debug(PlayerLog.Tag, PlayerLog.Enter);
if (rate < -5.0F || 5.0F < rate || rate == 0.0F)
{
throw new ArgumentOutOfRangeException(nameof(rate), rate, "Valid range is -5.0 to 5.0 (except 0.0)");
ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
NativePlayer.SetPlaybackRate(Handle, rate).ThrowIfFailed("Failed to set the playback rate.");
- Log.Debug(PlayerLog.Tag, PlayerLog.Leave);
}
/// <summary>
/// </summary>
/// <param name="policy">The <see cref="AudioStreamPolicy"/> to apply.</param>
/// <remarks>
- /// The player must be in the <see cref="PlayerState.Idle"/> state.\n
- /// \n
- /// <see cref="Player"/> does not support all <see cref="AudioStreamType"/>.\n
+ /// The player must be in the <see cref="PlayerState.Idle"/> state.<br/>
+ /// <br/>
+ /// <see cref="Player"/> does not support all <see cref="AudioStreamType"/>.<br/>
/// Supported types are <see cref="AudioStreamType.Media"/>, <see cref="AudioStreamType.System"/>,
/// <see cref="AudioStreamType.Alarm"/>, <see cref="AudioStreamType.Notification"/>,
/// <see cref="AudioStreamType.Emergency"/>, <see cref="AudioStreamType.VoiceInformation"/>,
/// <see cref="AudioStreamType.RingtoneVoip"/> and <see cref="AudioStreamType.MediaExternalOnly"/>.
/// </remarks>
/// <exception cref="ObjectDisposedException">
- /// The player has already been disposed of.\n
- /// -or-\n
+ /// The player has already been disposed of.<br/>
+ /// -or-<br/>
/// <paramref name="policy"/> has already been disposed of.
/// </exception>
/// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
/// <see cref="AudioStreamType"/> of <paramref name="policy"/> is not supported by <see cref="Player"/>.
/// </exception>
/// <seealso cref="AudioStreamPolicy"/>
+ /// <since_tizen> 3 </since_tizen>
public void ApplyAudioStreamPolicy(AudioStreamPolicy policy)
{
if (policy == null)
/// <summary>
/// This method supports the product infrastructure and is not intended to be used directly from application code.
/// </summary>
+ /// <since_tizen> 4 </since_tizen>
+ [EditorBrowsable(EditorBrowsableState.Never)]
protected static Exception GetException(int errorCode, string message) =>
((PlayerErrorCode)errorCode).GetException(message);
}