/* * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Threading.Tasks; using System.Runtime.InteropServices; using System.Diagnostics; using System.IO; using System.Threading; using NativeDisplay = Interop.Display; using static Interop; namespace Tizen.Multimedia { /// /// Represents properties for streaming buffering time. /// /// 5 public struct PlayerBufferingTime { /// /// Initializes a new instance of the PlayerBufferingTime struct. /// /// A duration of buffering data that must be prerolled to start playback. /// Except 0 and -1, setting at least 1000 milliseconds is recommended to ensure the normal buffering operation. /// 0 : use platform default value which could be different depending on the streaming type and network status. (the initial value) /// -1 : use current value. (since 5.5) /// A duration of buffering data that must be prerolled to resume playback, /// when player is internally paused for buffering. /// Except 0 and -1, setting at least 1000 milliseconds is recommended to ensure the normal buffering operation. /// 0 : use platform default value which could be different depending on the streaming type and network status. (the initial value) /// -1 : use current value. (since 5.5) /// 0 means platform default value which could be different depending on the streaming type and network status. /// If the player state is or , /// this function will return correct time value instead of 0. (since 5.5) /// 5 public PlayerBufferingTime(int preBufferMillisecond = -1, int reBufferMillisecond = -1) { PreBufferMillisecond = preBufferMillisecond; ReBufferMillisecond = reBufferMillisecond; } /// /// Gets or sets the duration of buffering data that must be prerolled to start playback. /// /// 5 public int PreBufferMillisecond { get; set; } /// /// Gets or sets the duration of buffering data that must be prerolled to resume playback /// if player enters pause state for buffering. /// /// 5 public int ReBufferMillisecond { get; set; } } /// 3 public partial class Player { /// /// Gets the native handle of the player. /// /// An IntPtr that contains the native handle of the player. /// The player has already been disposed of. /// 3 public IntPtr Handle { get { ValidateNotDisposed(); return _handle.DangerousGetHandle(); } } #region Network configuration private string _cookie = ""; private string _userAgent = ""; private const int MinBufferingTime = -1; /// /// Gets or sets the cookie for streaming playback. /// /// To set, the player must be in the state. /// The player is not in the valid state. /// The player has already been disposed of. /// The value to set is null. /// 3 public string Cookie { get { return _cookie; } set { ValidatePlayerState(PlayerState.Idle); if (value == null) { throw new ArgumentNullException(nameof(value), "Cookie can't be null."); } NativePlayer.SetStreamingCookie(Handle, value, value.Length). ThrowIfFailed(this, "Failed to set the cookie to the player"); _cookie = value; } } /// /// Gets or sets the user agent for streaming playback. /// /// To set, the player must be in the state. /// The player is not in the valid state. /// The player has already been disposed of. /// The value to set is null. /// 3 public string UserAgent { get { return _userAgent; } set { ValidatePlayerState(PlayerState.Idle); if (value == null) { throw new ArgumentNullException(nameof(value), "UserAgent can't be null."); } NativePlayer.SetStreamingUserAgent(Handle, value, value.Length). ThrowIfFailed(this, "Failed to set the user agent to the player"); _userAgent = value; } } /// /// Gets or sets the streaming buffering time. /// /// To set, the player must be in the state. /// The player is not in the valid state. /// The player has already been disposed of. /// /// is less than -1.
/// -or-
/// is less than -1.
///
/// The required feature is not supported. /// /// 5 public PlayerBufferingTime BufferingTime { get { ValidateNotDisposed(); NativePlayer.GetStreamingBufferingTime(Handle, out var PreBuffMillisecond, out var ReBuffMillisecond). ThrowIfFailed(this, "Failed to get the buffering time of the player"); return new PlayerBufferingTime(PreBuffMillisecond, ReBuffMillisecond); } set { ValidatePlayerState(PlayerState.Idle); if (value.PreBufferMillisecond < MinBufferingTime || value.ReBufferMillisecond < MinBufferingTime) { throw new ArgumentOutOfRangeException(nameof(value), value, $"invalid range, got { value.PreBufferMillisecond }, { value.ReBufferMillisecond }."); } NativePlayer.SetStreamingBufferingTime(Handle, value.PreBufferMillisecond, value.ReBufferMillisecond). ThrowIfFailed(this, "Failed to set the buffering time of the player"); } } #endregion /// /// Gets the state of the player. /// /// The current state of the player. /// The player has already been disposed of. /// 3 public PlayerState State { get { ValidateNotDisposed(); if (IsPreparing()) { return PlayerState.Preparing; } NativePlayer.GetState(Handle, out var state). ThrowIfFailed(this, "Failed to retrieve the state of the player"); Debug.Assert(Enum.IsDefined(typeof(PlayerState), state)); return (PlayerState)state; } } /// /// Gets or sets the audio latency mode. /// /// A that specifies the mode. The default is . /// /// If the mode is , /// audio output interval can be increased, so it can keep more audio data to play. /// But, state transition like pause or resume can be more slower than default(). /// /// The player has already been disposed of. /// The value is not valid. /// 3 public AudioLatencyMode AudioLatencyMode { get { NativePlayer.GetAudioLatencyMode(Handle, out var value). ThrowIfFailed(this, "Failed to get the audio latency mode of the player"); return value; } set { ValidateNotDisposed(); ValidationUtil.ValidateEnum(typeof(AudioLatencyMode), value, nameof(value)); NativePlayer.SetAudioLatencyMode(Handle, value). ThrowIfFailed(this, "Failed to set the audio latency mode of the player"); } } /// /// Gets or sets the looping state. /// /// true if the playback is looping; otherwise, false. The default value is false. /// The player has already been disposed of. /// 3 public bool IsLooping { get { NativePlayer.IsLooping(Handle, out var value). ThrowIfFailed(this, "Failed to get the looping state of the player"); return value; } set { ValidateNotDisposed(); NativePlayer.SetLooping(Handle, value). ThrowIfFailed(this, "Failed to set the looping state of the player"); } } #region Display methods private PlayerDisplaySettings _displaySettings; /// /// Gets the display settings. /// /// A that specifies the display settings. /// 3 public PlayerDisplaySettings DisplaySettings => _displaySettings; private Display _display; private PlayerErrorCode SetDisplay(Display display) { if (display == null) { return NativeDisplay.SetDisplay(Handle, PlayerDisplayType.None, IntPtr.Zero); } return display.ApplyTo(this); } private void ReplaceDisplay(Display newDisplay) { _display?.SetOwner(null); _display = newDisplay; _display?.SetOwner(this); } /// /// Gets or sets the display. /// /// A that specifies the display. /// /// The player must be in the state.
/// The raw video feature(http://tizen.org/feature/multimedia.raw_video) is required if /// the display is created with . ///
/// The player has already been disposed of. /// The value has already been assigned to another player. /// The player is not in the valid state. /// The required feature is not supported. /// 3 public Display Display { get { return _display; } set { ValidatePlayerState(PlayerState.Idle); if (value != null && value.HasMediaView) { ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo); } if (value?.Owner != null) { if (ReferenceEquals(this, value.Owner)) { return; } throw new ArgumentException("The display has already been assigned to another."); } SetDisplay(value).ThrowIfFailed(this, "Failed to configure display of the player"); ReplaceDisplay(value); } } PlayerErrorCode IDisplayable.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject) { Debug.Assert(IsDisposed == false); Debug.Assert(Enum.IsDefined(typeof(DisplayType), type)); Debug.Assert(type != DisplayType.None); return NativeDisplay.SetDisplay(Handle, type == DisplayType.Overlay ? PlayerDisplayType.Overlay : PlayerDisplayType.Evas, evasObject); } PlayerErrorCode IDisplayable.ApplyEcoreWindow(IntPtr windowHandle) { Debug.Assert(IsDisposed == false); return NativeDisplay.SetEcoreDisplay(Handle, PlayerDisplayType.Overlay, windowHandle); } #endregion private PlayerTrackInfo _audioTrack; /// /// Gets the track info for the audio. /// /// A for audio. /// 3 public PlayerTrackInfo AudioTrackInfo { get { if (_audioTrack == null) { _audioTrack = new PlayerTrackInfo(this, StreamType.Audio); } return _audioTrack; } } private PlayerTrackInfo _subtitleTrackInfo; /// /// Gets the track info for the subtitle. /// /// A for the subtitle. /// 3 public PlayerTrackInfo SubtitleTrackInfo { get { if (_subtitleTrackInfo == null) { _subtitleTrackInfo = new PlayerTrackInfo(this, StreamType.Text); } return _subtitleTrackInfo; } } private StreamInfo _streamInfo; /// /// Gets the stream information. /// /// A for this player. /// 3 public StreamInfo StreamInfo { get { if (_streamInfo == null) { _streamInfo = new StreamInfo(this); } return _streamInfo; } } private AudioEffect _audioEffect; /// /// Gets the audio effect. /// /// http://tizen.org/feature/multimedia.custom_audio_effect /// The required feature is not supported. /// 3 public AudioEffect AudioEffect { get { if (_audioEffect == null) { throw new NotSupportedException($"The feature({PlayerFeatures.AudioEffect}) is not supported."); } return _audioEffect; } } /// /// Gets or sets the mute state. /// /// true if the player is muted; otherwise, false. /// The player has already been disposed of. /// 3 public bool Muted { get { NativePlayer.IsMuted(Handle, out var value). ThrowIfFailed(this, "Failed to get the mute state of the player"); Log.Info(PlayerLog.Tag, "get mute : " + value); return value; } set { NativePlayer.SetMute(Handle, value).ThrowIfFailed(this, "Failed to set the mute state of the player"); } } /// /// Gets or sets the current volume. /// /// Valid volume range is from 0 to 1.0, inclusive. /// The player has already been disposed of. /// /// is less than zero.
/// -or-
/// is greater than 1.0. ///
/// 3 public float Volume { get { float value = 0.0F; NativePlayer.GetVolume(Handle, out value, out value). ThrowIfFailed(this, "Failed to get the volume of the player"); return value; } set { if (value < 0F || 1.0F < value) { throw new ArgumentOutOfRangeException(nameof(value), value, $"Valid volume range is 0 <= value <= 1.0, but got { value }."); } NativePlayer.SetVolume(Handle, value, value). ThrowIfFailed(this, "Failed to set the volume of the player"); } } /// /// Gets or sets the audio-only state. /// /// true if the playback is audio-only mode; otherwise, false. The default value is false. /// The must be in the , /// , or state. /// The player is not in the valid state. /// The player has already been disposed of. /// 5 public bool IsAudioOnly { get { ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused); NativePlayer.IsAudioOnly(Handle, out var value). ThrowIfFailed(this, "Failed to get the audio-only state of the player"); return value; } set { ValidateNotDisposed(); ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused); NativePlayer.SetAudioOnly(Handle, value). ThrowIfFailed(this, "Failed to set the audio-only state of the player"); } } /// /// Gets or sets the player's replaygain state. /// /// If the replaygain status is true, replaygain is applied (if contents has a replaygain tag); /// otherwise, the replaygain is not affected by tag and properties. /// The player has already been disposed of. /// The player is not in the valid state. /// 5 public bool ReplayGain { get { ValidateNotDisposed(); NativePlayer.IsReplayGain(Handle, out var value). ThrowIfFailed(this, "Failed to get the replaygain of the player"); return value; } set { ValidateNotDisposed(); NativePlayer.SetReplayGain(Handle, value). ThrowIfFailed(this, "Failed to set the replaygain of the player"); } } private SphericalVideo _sphericalVideo; /// /// Gets the spherical video settings. /// /// 5 public SphericalVideo SphericalVideo { get { if (_sphericalVideo == null) { _sphericalVideo = new SphericalVideo(this); } return _sphericalVideo; } } private AdaptiveVariants _adaptiveVariants; /// /// Gets the adaptive variants settings. /// /// 5 public AdaptiveVariants AdaptiveVariants { get { if (_adaptiveVariants == null) { _adaptiveVariants = new AdaptiveVariants(this); } return _adaptiveVariants; } } } }