2 * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 using System.Threading.Tasks;
18 using System.Runtime.InteropServices;
19 using System.Diagnostics;
21 using System.Threading;
22 using NativeDisplay = Interop.Display;
25 namespace Tizen.Multimedia
28 /// Represents properties for streaming buffering time.
30 /// <since_tizen> 5 </since_tizen>
31 public struct PlayerBufferingTime
34 /// Initializes a new instance of the PlayerBufferingTime struct.
36 /// <param name="preBufferMillisecond">A duration of buffering data that must be prerolled to start playback.</param>
37 /// Except 0 and -1, setting at least 1000 milliseconds is recommended to ensure the normal buffering operation.
38 /// 0 : use platform default value which could be different depending on the streaming type and network status. (the initial value)
39 /// -1 : use current value. (since 5.5)
40 /// <param name="reBufferMillisecond">A duration of buffering data that must be prerolled to resume playback,
41 /// when player is internally paused for buffering.
42 /// Except 0 and -1, setting at least 1000 milliseconds is recommended to ensure the normal buffering operation.
43 /// 0 : use platform default value which could be different depending on the streaming type and network status. (the initial value)
44 /// -1 : use current value. (since 5.5)
45 /// <para>0 means platform default value which could be different depending on the streaming type and network status.
46 /// If the player state is <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/>,
47 /// this function will return correct time value instead of 0. (since 5.5)</para></param>
48 /// <since_tizen> 5 </since_tizen>
49 public PlayerBufferingTime(int preBufferMillisecond = -1, int reBufferMillisecond = -1)
51 PreBufferMillisecond = preBufferMillisecond;
52 ReBufferMillisecond = reBufferMillisecond;
56 /// Gets or sets the duration of buffering data that must be prerolled to start playback.
58 /// <since_tizen> 5 </since_tizen>
59 public int PreBufferMillisecond
66 /// Gets or sets the duration of buffering data that must be prerolled to resume playback
67 /// if player enters pause state for buffering.
69 /// <since_tizen> 5 </since_tizen>
70 public int ReBufferMillisecond
76 /// <since_tizen> 3 </since_tizen>
77 public partial class Player
80 /// Gets the native handle of the player.
82 /// <value>An IntPtr that contains the native handle of the player.</value>
83 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
84 /// <since_tizen> 3 </since_tizen>
89 ValidateNotDisposed();
90 return _handle.DangerousGetHandle();
94 #region Network configuration
95 private string _cookie = "";
96 private string _userAgent = "";
97 private const int MinBufferingTime = -1;
100 /// Gets or sets the cookie for streaming playback.
102 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
103 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
104 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
105 /// <exception cref="ArgumentNullException">The value to set is null.</exception>
106 /// <since_tizen> 3 </since_tizen>
115 ValidatePlayerState(PlayerState.Idle);
119 throw new ArgumentNullException(nameof(value), "Cookie can't be null.");
122 NativePlayer.SetStreamingCookie(Handle, value, value.Length).
123 ThrowIfFailed(this, "Failed to set the cookie to the player");
130 /// Gets or sets the user agent for streaming playback.
132 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
133 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
134 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
135 /// <exception cref="ArgumentNullException">The value to set is null.</exception>
136 /// <since_tizen> 3 </since_tizen>
137 public string UserAgent
145 ValidatePlayerState(PlayerState.Idle);
149 throw new ArgumentNullException(nameof(value), "UserAgent can't be null.");
152 NativePlayer.SetStreamingUserAgent(Handle, value, value.Length).
153 ThrowIfFailed(this, "Failed to set the user agent to the player");
160 /// Gets or sets the streaming buffering time.
162 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
163 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
164 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
165 /// <exception cref="ArgumentOutOfRangeException">
166 /// <pramref name="PreBufferMillisecond"/> is less than -1.<br/>
168 /// <pramref name="ReBufferMillisecond"/> is less than -1.<br/>
170 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
171 /// <seealso cref="PlayerBufferingTime"/>
172 /// <since_tizen> 5 </since_tizen>
173 public PlayerBufferingTime BufferingTime
177 ValidateNotDisposed();
179 NativePlayer.GetStreamingBufferingTime(Handle, out var PreBuffMillisecond, out var ReBuffMillisecond).
180 ThrowIfFailed(this, "Failed to get the buffering time of the player");
182 return new PlayerBufferingTime(PreBuffMillisecond, ReBuffMillisecond);
186 ValidatePlayerState(PlayerState.Idle);
188 if (value.PreBufferMillisecond < MinBufferingTime || value.ReBufferMillisecond < MinBufferingTime)
190 throw new ArgumentOutOfRangeException(nameof(value), value,
191 $"invalid range, got { value.PreBufferMillisecond }, { value.ReBufferMillisecond }.");
194 NativePlayer.SetStreamingBufferingTime(Handle, value.PreBufferMillisecond, value.ReBufferMillisecond).
195 ThrowIfFailed(this, "Failed to set the buffering time of the player");
201 /// Gets the state of the player.
203 /// <value>The current state of the player.</value>
204 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
205 /// <since_tizen> 3 </since_tizen>
206 public PlayerState State
210 ValidateNotDisposed();
214 return PlayerState.Preparing;
217 NativePlayer.GetState(Handle, out var state).
218 ThrowIfFailed(this, "Failed to retrieve the state of the player");
220 Debug.Assert(Enum.IsDefined(typeof(PlayerState), state));
222 return (PlayerState)state;
227 /// Gets or sets the audio latency mode.
229 /// <value>A <see cref="AudioLatencyMode"/> that specifies the mode. The default is <see cref="AudioLatencyMode.Mid"/>.</value>
231 /// If the mode is <see cref="AudioLatencyMode.High"/>,
232 /// audio output interval can be increased, so it can keep more audio data to play.
233 /// But, state transition like pause or resume can be more slower than default(<see cref="AudioLatencyMode.Mid"/>).
235 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
236 /// <exception cref="ArgumentException">The value is not valid.</exception>
237 /// <since_tizen> 3 </since_tizen>
238 public AudioLatencyMode AudioLatencyMode
242 NativePlayer.GetAudioLatencyMode(Handle, out var value).
243 ThrowIfFailed(this, "Failed to get the audio latency mode of the player");
249 ValidateNotDisposed();
251 ValidationUtil.ValidateEnum(typeof(AudioLatencyMode), value, nameof(value));
253 NativePlayer.SetAudioLatencyMode(Handle, value).
254 ThrowIfFailed(this, "Failed to set the audio latency mode of the player");
259 /// Gets or sets the looping state.
261 /// <value>true if the playback is looping; otherwise, false. The default value is false.</value>
262 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
263 /// <since_tizen> 3 </since_tizen>
264 public bool IsLooping
268 NativePlayer.IsLooping(Handle, out var value).
269 ThrowIfFailed(this, "Failed to get the looping state of the player");
275 ValidateNotDisposed();
277 NativePlayer.SetLooping(Handle, value).
278 ThrowIfFailed(this, "Failed to set the looping state of the player");
282 #region Display methods
284 private PlayerDisplaySettings _displaySettings;
287 /// Gets the display settings.
289 /// <value>A <see cref="PlayerDisplaySettings"/> that specifies the display settings.</value>
290 /// <since_tizen> 3 </since_tizen>
291 public PlayerDisplaySettings DisplaySettings => _displaySettings;
293 private Display _display;
295 private PlayerErrorCode SetDisplay(Display display)
299 return NativeDisplay.SetDisplay(Handle, PlayerDisplayType.None, IntPtr.Zero);
302 return display.ApplyTo(this);
305 private void ReplaceDisplay(Display newDisplay)
307 _display?.SetOwner(null);
308 _display = newDisplay;
309 _display?.SetOwner(this);
313 /// Gets or sets the display.
315 /// <value>A <see cref="Multimedia.Display"/> that specifies the display.</value>
317 /// The player must be in the <see cref="PlayerState.Idle"/> state.<br/>
318 /// The raw video feature(http://tizen.org/feature/multimedia.raw_video) is required if
319 /// the display is created with <see cref="MediaView"/>.
321 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
322 /// <exception cref="ArgumentException">The value has already been assigned to another player.</exception>
323 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
324 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
325 /// <since_tizen> 3 </since_tizen>
326 public Display Display
334 ValidatePlayerState(PlayerState.Idle);
336 if (value != null && value.HasMediaView)
338 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
341 if (value?.Owner != null)
343 if (ReferenceEquals(this, value.Owner))
348 throw new ArgumentException("The display has already been assigned to another.");
351 SetDisplay(value).ThrowIfFailed(this, "Failed to configure display of the player");
353 ReplaceDisplay(value);
357 PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
359 Debug.Assert(IsDisposed == false);
361 Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
362 Debug.Assert(type != DisplayType.None);
364 return NativeDisplay.SetDisplay(Handle,
365 type == DisplayType.Overlay ? PlayerDisplayType.Overlay : PlayerDisplayType.Evas, evasObject);
368 PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
370 Debug.Assert(IsDisposed == false);
372 return NativeDisplay.SetEcoreDisplay(Handle, PlayerDisplayType.Overlay, windowHandle);
376 private PlayerTrackInfo _audioTrack;
379 /// Gets the track info for the audio.
381 /// <value>A <see cref="PlayerTrackInfo"/> for audio.</value>
382 /// <since_tizen> 3 </since_tizen>
383 public PlayerTrackInfo AudioTrackInfo
387 if (_audioTrack == null)
389 _audioTrack = new PlayerTrackInfo(this, StreamType.Audio);
395 private PlayerTrackInfo _subtitleTrackInfo;
398 /// Gets the track info for the subtitle.
400 /// <value>A <see cref="PlayerTrackInfo"/> for the subtitle.</value>
401 /// <since_tizen> 3 </since_tizen>
402 public PlayerTrackInfo SubtitleTrackInfo
406 if (_subtitleTrackInfo == null)
408 _subtitleTrackInfo = new PlayerTrackInfo(this, StreamType.Text);
410 return _subtitleTrackInfo;
414 private StreamInfo _streamInfo;
417 /// Gets the stream information.
419 /// <value>A <see cref="StreamInfo"/> for this player.</value>
420 /// <since_tizen> 3 </since_tizen>
421 public StreamInfo StreamInfo
425 if (_streamInfo == null)
427 _streamInfo = new StreamInfo(this);
433 private AudioEffect _audioEffect;
436 /// Gets the audio effect.
438 /// <feature>http://tizen.org/feature/multimedia.custom_audio_effect</feature>
439 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
440 /// <since_tizen> 3 </since_tizen>
441 public AudioEffect AudioEffect
445 if (_audioEffect == null)
447 throw new NotSupportedException($"The feature({PlayerFeatures.AudioEffect}) is not supported.");
455 /// Gets or sets the mute state.
457 /// <value>true if the player is muted; otherwise, false.</value>
458 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
459 /// <since_tizen> 3 </since_tizen>
464 NativePlayer.IsMuted(Handle, out var value).
465 ThrowIfFailed(this, "Failed to get the mute state of the player");
467 Log.Info(PlayerLog.Tag, "get mute : " + value);
473 NativePlayer.SetMute(Handle, value).ThrowIfFailed(this, "Failed to set the mute state of the player");
478 /// Gets or sets the current volume.
480 /// <remarks>Valid volume range is from 0 to 1.0, inclusive.</remarks>
481 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
482 /// <exception cref="ArgumentOutOfRangeException">
483 /// <paramref name="value"/> is less than zero.<br/>
485 /// <paramref name="value"/> is greater than 1.0.
487 /// <since_tizen> 3 </since_tizen>
493 NativePlayer.GetVolume(Handle, out value, out value).
494 ThrowIfFailed(this, "Failed to get the volume of the player");
500 if (value < 0F || 1.0F < value)
502 throw new ArgumentOutOfRangeException(nameof(value), value,
503 $"Valid volume range is 0 <= value <= 1.0, but got { value }.");
506 NativePlayer.SetVolume(Handle, value, value).
507 ThrowIfFailed(this, "Failed to set the volume of the player");
512 /// Gets or sets the audio-only state.
514 /// <value>true if the playback is audio-only mode; otherwise, false. The default value is false.</value>
515 /// The <see cref="Player"/> must be in the <see cref="PlayerState.Ready"/>,
516 /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
517 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
518 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
519 /// <since_tizen> 5 </since_tizen>
520 public bool IsAudioOnly
524 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
525 NativePlayer.IsAudioOnly(Handle, out var value).
526 ThrowIfFailed(this, "Failed to get the audio-only state of the player");
531 ValidateNotDisposed();
532 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
533 NativePlayer.SetAudioOnly(Handle, value).
534 ThrowIfFailed(this, "Failed to set the audio-only state of the player");
539 /// Gets or sets the player's replaygain state.
541 /// <value>If the replaygain status is true, replaygain is applied (if contents has a replaygain tag);
542 /// otherwise, the replaygain is not affected by tag and properties.</value>
543 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
544 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
545 /// <since_tizen> 5 </since_tizen>
546 public bool ReplayGain
550 ValidateNotDisposed();
551 NativePlayer.IsReplayGain(Handle, out var value).
552 ThrowIfFailed(this, "Failed to get the replaygain of the player");
557 ValidateNotDisposed();
558 NativePlayer.SetReplayGain(Handle, value).
559 ThrowIfFailed(this, "Failed to set the replaygain of the player");
563 private SphericalVideo _sphericalVideo;
566 /// Gets the spherical video settings.
568 /// <since_tizen> 5 </since_tizen>
569 public SphericalVideo SphericalVideo
573 if (_sphericalVideo == null)
575 _sphericalVideo = new SphericalVideo(this);
578 return _sphericalVideo;
582 private AdaptiveVariants _adaptiveVariants;
585 /// Gets the adaptive variants settings.
587 /// <since_tizen> 5 </since_tizen>
588 public AdaptiveVariants AdaptiveVariants
592 if (_adaptiveVariants == null)
594 _adaptiveVariants = new AdaptiveVariants(this);
597 return _adaptiveVariants;