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 /// <param name="reBufferMillisecond">A duration of buffering data that must be prerolled to resume playback
38 /// if player enters pause state for buffering.</param>
39 /// <since_tizen> 5 </since_tizen>
40 public PlayerBufferingTime(int preBufferMillisecond, int reBufferMillisecond)
42 PreBufferMillisecond = preBufferMillisecond;
43 ReBufferMillisecond = reBufferMillisecond;
47 /// Gets or sets the duration of buffering data that must be prerolled to start playback
49 /// <since_tizen> 5 </since_tizen>
50 public int PreBufferMillisecond
57 /// Gets or sets the duration of buffering data that must be prerolled to resume playback
58 /// if player enters pause state for buffering.
60 /// <since_tizen> 5 </since_tizen>
61 public int ReBufferMillisecond
67 /// <since_tizen> 3 </since_tizen>
68 public partial class Player
71 /// Gets the native handle of the player.
73 /// <value>An IntPtr that contains the native handle of the player.</value>
74 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
75 /// <since_tizen> 3 </since_tizen>
80 ValidateNotDisposed();
81 return _handle.DangerousGetHandle();
85 #region Network configuration
86 private string _cookie = "";
87 private string _userAgent = "";
90 /// Gets or sets the cookie for streaming playback.
92 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
93 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
94 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
95 /// <exception cref="ArgumentNullException">The value to set is null.</exception>
96 /// <since_tizen> 3 </since_tizen>
105 ValidatePlayerState(PlayerState.Idle);
109 throw new ArgumentNullException(nameof(value), "Cookie can't be null.");
112 NativePlayer.SetStreamingCookie(Handle, value, value.Length).
113 ThrowIfFailed(this, "Failed to set the cookie to the player");
120 /// Gets or sets the user agent for streaming playback.
122 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
123 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
124 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
125 /// <exception cref="ArgumentNullException">The value to set is null.</exception>
126 /// <since_tizen> 3 </since_tizen>
127 public string UserAgent
135 ValidatePlayerState(PlayerState.Idle);
139 throw new ArgumentNullException(nameof(value), "UserAgent can't be null.");
142 NativePlayer.SetStreamingUserAgent(Handle, value, value.Length).
143 ThrowIfFailed(this, "Failed to set the user agent to the player");
150 /// Gets or sets the streaming buffering time.
152 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
153 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
154 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
155 /// <exception cref="ArgumentOutOfRangeException">
156 /// <pramref name="PreBufferMillisecond"/> is less than 0.<br/>
158 /// <pramref name="ReBufferMillisecond"/> is less than 0.<br/>
160 /// <seealso cref="PlayerBufferingTime"/>
161 /// <since_tizen> 5 </since_tizen>
162 public PlayerBufferingTime BufferingTime
166 ValidateNotDisposed();
168 NativePlayer.GetStreamingBufferingTime(Handle, out var PreBuffMillisecond, out var ReBuffMillisecond).
169 ThrowIfFailed(this, "Failed to get the buffering time of the player");
171 return new PlayerBufferingTime(PreBuffMillisecond, ReBuffMillisecond);
175 ValidatePlayerState(PlayerState.Idle);
177 if (value.PreBufferMillisecond < 0 || value.ReBufferMillisecond < 0)
179 throw new ArgumentOutOfRangeException("invalid range");
182 NativePlayer.SetStreamingBufferingTime(Handle, value.PreBufferMillisecond, value.ReBufferMillisecond).
183 ThrowIfFailed(this, "Failed to set the buffering time of the player");
189 /// Gets the state of the player.
191 /// <value>The current state of the player.</value>
192 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
193 /// <since_tizen> 3 </since_tizen>
194 public PlayerState State
198 ValidateNotDisposed();
202 return PlayerState.Preparing;
205 NativePlayer.GetState(Handle, out var state).
206 ThrowIfFailed(this, "Failed to retrieve the state of the player");
208 Debug.Assert(Enum.IsDefined(typeof(PlayerState), state));
210 return (PlayerState)state;
215 /// Gets or sets the audio latency mode.
217 /// <value>A <see cref="AudioLatencyMode"/> that specifies the mode. The default is <see cref="AudioLatencyMode.Mid"/>.</value>
219 /// If the mode is <see cref="AudioLatencyMode.High"/>,
220 /// audio output interval can be increased, so it can keep more audio data to play.
221 /// But, state transition like pause or resume can be more slower than default(<see cref="AudioLatencyMode.Mid"/>).
223 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
224 /// <exception cref="ArgumentException">The value is not valid.</exception>
225 /// <since_tizen> 3 </since_tizen>
226 public AudioLatencyMode AudioLatencyMode
230 NativePlayer.GetAudioLatencyMode(Handle, out var value).
231 ThrowIfFailed(this, "Failed to get the audio latency mode of the player");
237 ValidateNotDisposed();
239 ValidationUtil.ValidateEnum(typeof(AudioLatencyMode), value, nameof(value));
241 NativePlayer.SetAudioLatencyMode(Handle, value).
242 ThrowIfFailed(this, "Failed to set the audio latency mode of the player");
247 /// Gets or sets the looping state.
249 /// <value>true if the playback is looping; otherwise, false. The default value is false.</value>
250 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
251 /// <since_tizen> 3 </since_tizen>
252 public bool IsLooping
256 NativePlayer.IsLooping(Handle, out var value).
257 ThrowIfFailed(this, "Failed to get the looping state of the player");
263 ValidateNotDisposed();
265 NativePlayer.SetLooping(Handle, value).
266 ThrowIfFailed(this, "Failed to set the looping state of the player");
270 #region Display methods
272 private PlayerDisplaySettings _displaySettings;
275 /// Gets the display settings.
277 /// <value>A <see cref="PlayerDisplaySettings"/> that specifies the display settings.</value>
278 /// <since_tizen> 3 </since_tizen>
279 public PlayerDisplaySettings DisplaySettings => _displaySettings;
281 private Display _display;
283 private PlayerErrorCode SetDisplay(Display display)
287 return NativeDisplay.SetDisplay(Handle, PlayerDisplayType.None, IntPtr.Zero);
290 return display.ApplyTo(this);
293 private void ReplaceDisplay(Display newDisplay)
295 _display?.SetOwner(null);
296 _display = newDisplay;
297 _display?.SetOwner(this);
301 /// Gets or sets the display.
303 /// <value>A <see cref="Multimedia.Display"/> that specifies the display.</value>
305 /// The player must be in the <see cref="PlayerState.Idle"/> state.<br/>
306 /// The raw video feature(http://tizen.org/feature/multimedia.raw_video) is required if
307 /// the display is created with <see cref="MediaView"/>.
309 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
310 /// <exception cref="ArgumentException">The value has already been assigned to another player.</exception>
311 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
312 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
313 /// <since_tizen> 3 </since_tizen>
314 public Display Display
322 ValidatePlayerState(PlayerState.Idle);
324 if (value != null && value.HasMediaView)
326 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
329 if (value?.Owner != null)
331 if (ReferenceEquals(this, value.Owner))
336 throw new ArgumentException("The display has already been assigned to another.");
339 SetDisplay(value).ThrowIfFailed(this, "Failed to configure display of the player");
341 ReplaceDisplay(value);
345 PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
347 Debug.Assert(IsDisposed == false);
349 Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
350 Debug.Assert(type != DisplayType.None);
352 return NativeDisplay.SetDisplay(Handle,
353 type == DisplayType.Overlay ? PlayerDisplayType.Overlay : PlayerDisplayType.Evas, evasObject);
356 PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
358 Debug.Assert(IsDisposed == false);
360 return NativeDisplay.SetEcoreDisplay(Handle, PlayerDisplayType.Overlay, windowHandle);
364 private PlayerTrackInfo _audioTrack;
367 /// Gets the track info for the audio.
369 /// <value>A <see cref="PlayerTrackInfo"/> for audio.</value>
370 /// <since_tizen> 3 </since_tizen>
371 public PlayerTrackInfo AudioTrackInfo
375 if (_audioTrack == null)
377 _audioTrack = new PlayerTrackInfo(this, StreamType.Audio);
383 private PlayerTrackInfo _subtitleTrackInfo;
386 /// Gets the track info for the subtitle.
388 /// <value>A <see cref="PlayerTrackInfo"/> for the subtitle.</value>
389 /// <since_tizen> 3 </since_tizen>
390 public PlayerTrackInfo SubtitleTrackInfo
394 if (_subtitleTrackInfo == null)
396 _subtitleTrackInfo = new PlayerTrackInfo(this, StreamType.Text);
398 return _subtitleTrackInfo;
402 private StreamInfo _streamInfo;
405 /// Gets the stream information.
407 /// <value>A <see cref="StreamInfo"/> for this player.</value>
408 /// <since_tizen> 3 </since_tizen>
409 public StreamInfo StreamInfo
413 if (_streamInfo == null)
415 _streamInfo = new StreamInfo(this);
421 private AudioEffect _audioEffect;
424 /// Gets the audio effect.
426 /// <feature>http://tizen.org/feature/multimedia.custom_audio_effect</feature>
427 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
428 /// <since_tizen> 3 </since_tizen>
429 public AudioEffect AudioEffect
433 if (_audioEffect == null)
435 throw new NotSupportedException($"The feature({PlayerFeatures.AudioEffect}) is not supported.");
443 /// Gets or sets the mute state.
445 /// <value>true if the player is muted; otherwise, false.</value>
446 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
447 /// <since_tizen> 3 </since_tizen>
452 NativePlayer.IsMuted(Handle, out var value).
453 ThrowIfFailed(this, "Failed to get the mute state of the player");
455 Log.Info(PlayerLog.Tag, "get mute : " + value);
461 NativePlayer.SetMute(Handle, value).ThrowIfFailed(this, "Failed to set the mute state of the player");
466 /// Gets or sets the current volume.
468 /// <remarks>Valid volume range is from 0 to 1.0, inclusive.</remarks>
469 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
470 /// <exception cref="ArgumentOutOfRangeException">
471 /// <paramref name="value"/> is less than zero.<br/>
473 /// <paramref name="value"/> is greater than 1.0.
475 /// <since_tizen> 3 </since_tizen>
481 NativePlayer.GetVolume(Handle, out value, out value).
482 ThrowIfFailed(this, "Failed to get the volume of the player");
488 if (value < 0F || 1.0F < value)
490 throw new ArgumentOutOfRangeException(nameof(value), value,
491 $"Valid volume range is 0 <= value <= 1.0, but got { value }.");
494 NativePlayer.SetVolume(Handle, value, value).
495 ThrowIfFailed(this, "Failed to set the volume of the player");
500 /// Gets or sets the audio-only state.
502 /// <value>true if the playback is audio-only mode; otherwise, false. The default value is false.</value>
503 /// The <see cref="Player"/> must be in the <see cref="PlayerState.Ready"/>,
504 /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
505 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
506 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
507 /// <since_tizen> 5 </since_tizen>
508 public bool IsAudioOnly
512 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
513 NativePlayer.IsAudioOnly(Handle, out var value).
514 ThrowIfFailed(this, "Failed to get the audio-only state of the player");
519 ValidateNotDisposed();
520 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
521 NativePlayer.SetAudioOnly(Handle, value).
522 ThrowIfFailed(this, "Failed to set the audio-only state of the player");
527 /// Gets or sets the player's replaygain state.
529 /// <value>If the replaygain status is true, replaygain is applied (if contents has a replaygain tag);
530 /// otherwise, the replaygain isn't affected by tag and properties.</value>
531 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
532 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
533 /// <since_tizen> 5 </since_tizen>
534 public bool ReplayGain
538 ValidateNotDisposed();
539 NativePlayer.IsReplayGain(Handle, out var value).
540 ThrowIfFailed(this, "Failed to get the replaygain of the player");
545 ValidateNotDisposed();
546 NativePlayer.SetReplayGain(Handle, value).
547 ThrowIfFailed(this, "Failed to set the replaygain of the player");
551 private SphericalVideo _sphericalVideo;
554 /// Gets the spherical video settings.
556 /// <since_tizen> 5 </since_tizen>
557 public SphericalVideo SphericalVideo
561 if (_sphericalVideo == null)
563 _sphericalVideo = new SphericalVideo(this);
566 return _sphericalVideo;
570 private AdaptiveVariants _adaptiveVariants;
573 /// Gets the adaptive variants settings.
575 /// <since_tizen> 5 </since_tizen>
576 public AdaptiveVariants AdaptiveVariants
580 if (_adaptiveVariants == null)
582 _adaptiveVariants = new AdaptiveVariants(this);
585 return _adaptiveVariants;