e180bb553dd0ff45b1633a0fcb6a0296b36ff0c5
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.MediaPlayer / Player / Player.Properties.cs
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 using System;
17 using System.Threading.Tasks;
18 using System.Runtime.InteropServices;
19 using System.Diagnostics;
20 using System.IO;
21 using System.Threading;
22 using NativeDisplay = Interop.Display;
23 using static Interop;
24
25 namespace Tizen.Multimedia
26 {
27     /// <summary>
28     /// Represents properties for streaming buffering time.
29     /// </summary>
30     /// <since_tizen> 5 </since_tizen>
31     public struct PlayerBufferingTime
32     {
33         /// <summary>
34         /// Initializes a new instance of the PlayerBufferingTime struct.
35         /// </summary>
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 depends on the streaming type and network status. It is set as the initial value of this parameter.
44         /// If the player state is <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/>,
45         /// this function will return correct time value instead of 0. (since 5.5)
46         /// -1 : use current value. (since 5.5)</param>
47         /// <since_tizen> 5 </since_tizen>
48         public PlayerBufferingTime(int preBufferMillisecond = -1, int reBufferMillisecond = -1)
49         {
50             PreBufferMillisecond = preBufferMillisecond;
51             ReBufferMillisecond = reBufferMillisecond;
52         }
53
54         /// <summary>
55         /// Gets or sets the duration of buffering data that must be prerolled to start playback.
56         /// </summary>
57         /// <since_tizen> 5 </since_tizen>
58         public int PreBufferMillisecond
59         {
60             get;
61             set;
62         }
63
64         /// <summary>
65         /// Gets or sets the duration of buffering data that must be prerolled to resume playback
66         /// if player enters pause state for buffering.
67         /// </summary>
68         /// <since_tizen> 5 </since_tizen>
69         public int ReBufferMillisecond
70         {
71             get;
72             set;
73         }
74     }
75     /// <since_tizen> 3 </since_tizen>
76     public partial class Player
77     {
78         /// <summary>
79         /// Gets the native handle of the player.
80         /// </summary>
81         /// <value>An IntPtr that contains the native handle of the player.</value>
82         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
83         /// <since_tizen> 3 </since_tizen>
84         public IntPtr Handle
85         {
86             get
87             {
88                 ValidateNotDisposed();
89                 return _handle.DangerousGetHandle();
90             }
91         }
92
93         #region Network configuration
94         private string _cookie = "";
95         private string _userAgent = "";
96         private const int MinBufferingTime = -1;
97
98         /// <summary>
99         /// Gets or sets the cookie for streaming playback.
100         /// </summary>
101         /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
102         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
103         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
104         /// <exception cref="ArgumentNullException">The value to set is null.</exception>
105         /// <since_tizen> 3 </since_tizen>
106         public string Cookie
107         {
108             get
109             {
110                 return _cookie;
111             }
112             set
113             {
114                 ValidatePlayerState(PlayerState.Idle);
115
116                 if (value == null)
117                 {
118                     throw new ArgumentNullException(nameof(value), "Cookie can't be null.");
119                 }
120
121                 NativePlayer.SetStreamingCookie(Handle, value, value.Length).
122                     ThrowIfFailed(this, "Failed to set the cookie to the player");
123
124                 _cookie = value;
125             }
126         }
127
128         /// <summary>
129         /// Gets or sets the user agent for streaming playback.
130         /// </summary>
131         /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
132         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
133         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
134         /// <exception cref="ArgumentNullException">The value to set is null.</exception>
135         /// <since_tizen> 3 </since_tizen>
136         public string UserAgent
137         {
138             get
139             {
140                 return _userAgent;
141             }
142             set
143             {
144                 ValidatePlayerState(PlayerState.Idle);
145
146                 if (value == null)
147                 {
148                     throw new ArgumentNullException(nameof(value), "UserAgent can't be null.");
149                 }
150
151                 NativePlayer.SetStreamingUserAgent(Handle, value, value.Length).
152                     ThrowIfFailed(this, "Failed to set the user agent to the player");
153
154                 _userAgent = value;
155             }
156         }
157
158         /// <summary>
159         /// Gets or sets the streaming buffering time.
160         /// </summary>
161         /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
162         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
163         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
164         /// <exception cref="ArgumentOutOfRangeException">
165         ///     <pramref name="PreBufferMillisecond"/> is less than -1.<br/>
166         ///     -or-<br/>
167         ///     <pramref name="ReBufferMillisecond"/> is less than -1.<br/>
168         /// </exception>
169         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
170         /// <seealso cref="PlayerBufferingTime"/>
171         /// <since_tizen> 5 </since_tizen>
172         public PlayerBufferingTime BufferingTime
173         {
174             get
175             {
176                 ValidateNotDisposed();
177
178                 NativePlayer.GetStreamingBufferingTime(Handle, out var PreBuffMillisecond, out var ReBuffMillisecond).
179                         ThrowIfFailed(this, "Failed to get the buffering time of the player");
180
181                 return new PlayerBufferingTime(PreBuffMillisecond, ReBuffMillisecond);
182             }
183             set
184             {
185                 ValidatePlayerState(PlayerState.Idle);
186
187                 if (value.PreBufferMillisecond < MinBufferingTime || value.ReBufferMillisecond < MinBufferingTime)
188                 {
189                     throw new ArgumentOutOfRangeException(nameof(value), value,
190                         $"invalid range, got { value.PreBufferMillisecond }, { value.ReBufferMillisecond }.");
191                 }
192
193                 NativePlayer.SetStreamingBufferingTime(Handle, value.PreBufferMillisecond, value.ReBufferMillisecond).
194                     ThrowIfFailed(this, "Failed to set the buffering time of the player");
195             }
196         }
197         #endregion
198
199         /// <summary>
200         /// Gets the state of the player.
201         /// </summary>
202         /// <value>The current state of the player.</value>
203         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
204         /// <since_tizen> 3 </since_tizen>
205         public PlayerState State
206         {
207             get
208             {
209                 ValidateNotDisposed();
210
211                 if (IsPreparing())
212                 {
213                     return PlayerState.Preparing;
214                 }
215
216                 NativePlayer.GetState(Handle, out var state).
217                     ThrowIfFailed(this, "Failed to retrieve the state of the player");
218
219                 Debug.Assert(Enum.IsDefined(typeof(PlayerState), state));
220
221                 return (PlayerState)state;
222             }
223         }
224
225         /// <summary>
226         /// Gets or sets the audio latency mode.
227         /// </summary>
228         /// <value>A <see cref="AudioLatencyMode"/> that specifies the mode. The default is <see cref="AudioLatencyMode.Mid"/>.</value>
229         /// <remarks>
230         /// If the mode is <see cref="AudioLatencyMode.High"/>,
231         /// audio output interval can be increased, so it can keep more audio data to play.
232         /// But, state transition like pause or resume can be more slower than default(<see cref="AudioLatencyMode.Mid"/>).
233         /// </remarks>
234         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
235         /// <exception cref="ArgumentException">The value is not valid.</exception>
236         /// <exception cref="NotAvailableException">
237         ///     If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
238         /// </exception>
239         /// <seealso cref="AudioOffload"/>
240         /// <since_tizen> 3 </since_tizen>
241         public AudioLatencyMode AudioLatencyMode
242         {
243             get
244             {
245                 AudioOffload.CheckDisabled();
246
247                 NativePlayer.GetAudioLatencyMode(Handle, out var value).
248                     ThrowIfFailed(this, "Failed to get the audio latency mode of the player");
249
250                 return value;
251             }
252             set
253             {
254                 ValidateNotDisposed();
255                 AudioOffload.CheckDisabled();
256
257                 ValidationUtil.ValidateEnum(typeof(AudioLatencyMode), value, nameof(value));
258
259                 NativePlayer.SetAudioLatencyMode(Handle, value).
260                     ThrowIfFailed(this, "Failed to set the audio latency mode of the player");
261             }
262         }
263
264         /// <summary>
265         /// Gets or sets the looping state.
266         /// </summary>
267         /// <value>true if the playback is looping; otherwise, false. The default value is false.</value>
268         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
269         /// <since_tizen> 3 </since_tizen>
270         public bool IsLooping
271         {
272             get
273             {
274                 NativePlayer.IsLooping(Handle, out var value).
275                     ThrowIfFailed(this, "Failed to get the looping state of the player");
276
277                 return value;
278             }
279             set
280             {
281                 ValidateNotDisposed();
282
283                 NativePlayer.SetLooping(Handle, value).
284                     ThrowIfFailed(this, "Failed to set the looping state of the player");
285             }
286         }
287
288         #region Display methods
289
290         private PlayerDisplaySettings _displaySettings;
291
292         /// <summary>
293         /// Gets the display settings.
294         /// </summary>
295         /// <value>A <see cref="PlayerDisplaySettings"/> that specifies the display settings.</value>
296         /// <since_tizen> 3 </since_tizen>
297         public PlayerDisplaySettings DisplaySettings => _displaySettings;
298
299         private Display _display;
300
301         private bool _uiSync;
302
303         private PlayerErrorCode SetDisplay(Display display)
304         {
305             if (display == null)
306             {
307                 return NativeDisplay.SetDisplay(Handle, PlayerDisplayType.None, IntPtr.Zero);
308             }
309
310             return display.ApplyTo(this);
311         }
312
313         private void ReplaceDisplay(Display newDisplay)
314         {
315             _display?.SetOwner(null);
316             _display = newDisplay;
317             _display?.SetOwner(this);
318         }
319
320         /// <summary>
321         /// Gets or sets the display.
322         /// </summary>
323         /// <value>A <see cref="Multimedia.Display"/> that specifies the display.</value>
324         /// <remarks>
325         ///     The player must be in the <see cref="PlayerState.Idle"/> state.<br/>
326         ///     The raw video feature(http://tizen.org/feature/multimedia.raw_video) is required if
327         ///     the display is created with <see cref="MediaView"/>.<br/>
328         ///     If a user wants to use video and UI sync mode, please use <see cref="Tizen.Multimedia.Display(NUI.Window, bool)"/>.(Since tizen 6.5)<br/>
329         ///     But <see cref="Tizen.Multimedia.Player.DisplaySettings"/> is not supported in UI sync mode.
330         /// </remarks>
331         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
332         /// <exception cref="ArgumentException">The value has already been assigned to another player.</exception>
333         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
334         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
335         /// <since_tizen> 3 </since_tizen>
336         public Display Display
337         {
338             get
339             {
340                 return _display;
341             }
342             set
343             {
344                 ValidatePlayerState(PlayerState.Idle);
345
346                 if (value != null && value.HasMediaView)
347                 {
348                     ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
349                 }
350
351                 if (value?.Owner != null)
352                 {
353                     if (ReferenceEquals(this, value.Owner))
354                     {
355                         return;
356                     }
357
358                     throw new ArgumentException("The display has already been assigned to another.");
359                 }
360
361                 _uiSync = value?.UiSync ?? false;
362
363                 SetDisplay(value).ThrowIfFailed(this, "Failed to configure display of the player");
364
365                 ReplaceDisplay(value);
366             }
367         }
368
369         PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
370         {
371             Debug.Assert(IsDisposed == false);
372
373             Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
374             Debug.Assert(type != DisplayType.None);
375
376             return NativeDisplay.SetDisplay(Handle,
377                 type == DisplayType.Overlay ? PlayerDisplayType.Overlay : PlayerDisplayType.Evas, evasObject);
378         }
379
380         PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
381         {
382             Debug.Assert(IsDisposed == false);
383
384             return NativeDisplay.SetEcoreDisplay(Handle,
385                 _uiSync ? PlayerDisplayType.OverlayUISync : PlayerDisplayType.Overlay, windowHandle);
386         }
387         #endregion
388
389         private PlayerTrackInfo _audioTrack;
390
391         /// <summary>
392         /// Gets the track info for the audio.
393         /// </summary>
394         /// <value>A <see cref="PlayerTrackInfo"/> for audio.</value>
395         /// <since_tizen> 3 </since_tizen>
396         public PlayerTrackInfo AudioTrackInfo
397         {
398             get
399             {
400                 if (_audioTrack == null)
401                 {
402                     _audioTrack = new PlayerTrackInfo(this, StreamType.Audio);
403                 }
404                 return _audioTrack;
405             }
406         }
407
408         private PlayerTrackInfo _subtitleTrackInfo;
409
410         /// <summary>
411         /// Gets the track info for the subtitle.
412         /// </summary>
413         /// <value>A <see cref="PlayerTrackInfo"/> for the subtitle.</value>
414         /// <since_tizen> 3 </since_tizen>
415         public PlayerTrackInfo SubtitleTrackInfo
416         {
417             get
418             {
419                 if (_subtitleTrackInfo == null)
420                 {
421                     _subtitleTrackInfo = new PlayerTrackInfo(this, StreamType.Text);
422                 }
423                 return _subtitleTrackInfo;
424             }
425         }
426
427         private StreamInfo _streamInfo;
428
429         /// <summary>
430         /// Gets the stream information.
431         /// </summary>
432         /// <value>A <see cref="StreamInfo"/> for this player.</value>
433         /// <since_tizen> 3 </since_tizen>
434         public StreamInfo StreamInfo
435         {
436             get
437             {
438                 if (_streamInfo == null)
439                 {
440                     _streamInfo = new StreamInfo(this);
441                 }
442                 return _streamInfo;
443             }
444         }
445
446         private AudioEffect _audioEffect;
447
448         /// <summary>
449         /// Gets the audio effect.
450         /// </summary>
451         /// <feature>http://tizen.org/feature/multimedia.custom_audio_effect</feature>
452         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
453         /// <since_tizen> 3 </since_tizen>
454         public AudioEffect AudioEffect
455         {
456             get
457             {
458                 if (_audioEffect == null)
459                 {
460                     throw new NotSupportedException($"The feature({PlayerFeatures.AudioEffect}) is not supported.");
461                 }
462
463                 return _audioEffect;
464             }
465         }
466
467         /// <summary>
468         /// Gets or sets the mute state.
469         /// </summary>
470         /// <value>true if the player is muted; otherwise, false.</value>
471         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
472         /// <since_tizen> 3 </since_tizen>
473         public bool Muted
474         {
475             get
476             {
477                 NativePlayer.IsMuted(Handle, out var value).
478                     ThrowIfFailed(this, "Failed to get the mute state of the player");
479
480                 Log.Info(PlayerLog.Tag, "get mute : " + value);
481
482                 return value;
483             }
484             set
485             {
486                 NativePlayer.SetMute(Handle, value).ThrowIfFailed(this, "Failed to set the mute state of the player");
487             }
488         }
489
490         /// <summary>
491         /// Gets or sets the current volume.
492         /// </summary>
493         /// <remarks>Valid volume range is from 0 to 1.0, inclusive.</remarks>
494         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
495         /// <exception cref="ArgumentOutOfRangeException">
496         ///     <paramref name="value"/> is less than zero.<br/>
497         ///     -or-<br/>
498         ///     <paramref name="value"/> is greater than 1.0.
499         /// </exception>
500         /// <since_tizen> 3 </since_tizen>
501         public float Volume
502         {
503             get
504             {
505                 float value = 0.0F;
506                 NativePlayer.GetVolume(Handle, out value, out value).
507                     ThrowIfFailed(this, "Failed to get the volume of the player");
508
509                 return value;
510             }
511             set
512             {
513                 if (value < 0F || 1.0F < value)
514                 {
515                     throw new ArgumentOutOfRangeException(nameof(value), value,
516                         $"Valid volume range is 0 <= value <= 1.0, but got { value }.");
517                 }
518
519                 NativePlayer.SetVolume(Handle, value, value).
520                     ThrowIfFailed(this, "Failed to set the volume of the player");
521             }
522         }
523
524         /// <summary>
525         /// Gets or sets the audio-only state.
526         /// </summary>
527         /// <value>true if the playback is audio-only mode; otherwise, false. The default value is false.</value>
528         /// The <see cref="Player"/> must be in the <see cref="PlayerState.Ready"/>,
529         /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
530         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
531         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
532         /// <since_tizen> 5 </since_tizen>
533         public bool IsAudioOnly
534         {
535             get
536             {
537                 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
538                 NativePlayer.IsAudioOnly(Handle, out var value).
539                     ThrowIfFailed(this, "Failed to get the audio-only state of the player");
540                 return value;
541             }
542             set
543             {
544                 ValidateNotDisposed();
545                 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
546                 NativePlayer.SetAudioOnly(Handle, value).
547                     ThrowIfFailed(this, "Failed to set the audio-only state of the player");
548             }
549         }
550
551         /// <summary>
552         /// Gets or sets the player's replaygain state.
553         /// </summary>
554         /// <value>If the replaygain status is true, replaygain is applied (if contents has a replaygain tag);
555         /// otherwise, the replaygain is not affected by tag and properties.</value>
556         /// <remarks>This function could be unavailable depending on the audio codec type.</remarks>
557         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
558         /// <exception cref="InvalidOperationException">
559         ///     The player is not in the valid state.
560         /// </exception>
561         /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
562         ///     -or-<br/>
563         ///     The function is not available depending on the audio codec type. (Since tizen 6.0)
564         /// </exception>
565         /// <seealso cref="AudioOffload"/>
566         /// <seealso cref="AudioCodecType"/>
567         /// <since_tizen> 5 </since_tizen>
568         public bool ReplayGain
569         {
570             get
571             {
572                 ValidateNotDisposed();
573                 AudioOffload.CheckDisabled();
574
575                 NativePlayer.IsReplayGain(Handle, out var value).
576                     ThrowIfFailed(this, "Failed to get the replaygain of the player");
577                 return value;
578             }
579             set
580             {
581                 ValidateNotDisposed();
582                 AudioOffload.CheckDisabled();
583
584                 NativePlayer.SetReplayGain(Handle, value).
585                     ThrowIfFailed(this, "Failed to set the replaygain of the player");
586             }
587         }
588
589         /// <summary>
590         /// Enables or disables controlling the pitch of audio.
591         /// Gets the status of controlling the pitch of audio.
592         /// </summary>
593         /// <value>The value indicating whether or not AudioPitch is enabled. The default is false.</value>
594         /// <remarks>This function is used for audio content only.
595         /// To set, the player must be in the <see cref="PlayerState.Idle"/> state.
596         /// This function could be unavailable depending on the audio codec type.</remarks>
597         /// <exception cref="InvalidOperationException">
598         ///     The player is not in the valid state.
599         /// </exception>
600         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
601         /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
602         ///     -or-<br/>
603         ///     The function is not available depending on the audio codec type. (Since tizen 6.0)
604         /// </exception>
605         /// <seealso cref="AudioPitch"/>
606         /// <seealso cref="AudioOffload"/>
607         /// <seealso cref="AudioCodecType"/>
608         /// <since_tizen> 6 </since_tizen>
609         public bool AudioPitchEnabled
610         {
611             get
612             {
613                 ValidateNotDisposed();
614                 AudioOffload.CheckDisabled();
615
616                 NativePlayer.IsAudioPitchEnabled(Handle, out var value).
617                     ThrowIfFailed(this, "Failed to get whether the audio pitch is enabled or not");
618                 return value;
619             }
620
621             set
622             {
623                 ValidateNotDisposed();
624                 AudioOffload.CheckDisabled();
625                 ValidatePlayerState(PlayerState.Idle);
626
627                 NativePlayer.SetAudioPitchEnabled(Handle, value).
628                     ThrowIfFailed(this, "Failed to enable the audio pitch of the player");
629             }
630         }
631
632         /// <summary>
633         /// Gets or sets the pitch of audio.
634         /// </summary>
635         /// <value>The audio stream pitch value. The default is 1.</value>
636         /// <remarks>Enabling pitch control could increase the CPU usage on some devices.
637         /// This function is used for audio content only.
638         /// This function could be unavailable depending on the audio codec type.</remarks>
639         /// <exception cref="InvalidOperationException">
640         ///     A pitch is not enabled.
641         /// </exception>
642         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
643         /// <exception cref="ArgumentOutOfRangeException">
644         ///     value is less than 0.5.
645         ///     -or-<br/>
646         ///     value is greater than 2.0.
647         /// </exception>
648         /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
649         ///     -or-<br/>
650         ///     The function is not available depending on the audio codec type. (Since tizen 6.0)
651         /// </exception>
652         /// <seealso cref="AudioPitchEnabled"/>
653         /// <seealso cref="AudioOffload"/>
654         /// <seealso cref="AudioCodecType"/>
655         /// <since_tizen> 6 </since_tizen>
656         public float AudioPitch
657         {
658             get
659             {
660                 ValidateNotDisposed();
661                 AudioOffload.CheckDisabled();
662
663                 if (AudioPitchEnabled == false)
664                 {
665                     throw new InvalidOperationException("An audio pitch is not enabled.");
666                 }
667
668                 NativePlayer.GetAudioPitch(Handle, out var value).
669                     ThrowIfFailed(this, "Failed to get the audio pitch");
670
671                 return value;
672             }
673
674             set
675             {
676                 ValidateNotDisposed();
677                 AudioOffload.CheckDisabled();
678
679                 if (AudioPitchEnabled == false)
680                 {
681                     throw new InvalidOperationException("An audio pitch is not enabled.");
682                 }
683
684                 if (value < 0.5F || 2.0F < value)
685                 {
686                     throw new ArgumentOutOfRangeException(nameof(value), value, "Valid value is 0.5 to 2.0");
687                 }
688
689                 NativePlayer.SetAudioPitch(Handle, value).ThrowIfFailed(this, "Failed to set the audio pitch");
690             }
691         }
692
693         /// <summary>
694         /// Gets or sets the default codec type of the audio decoder.
695         /// </summary>
696         /// <value>A <see cref="CodecType"/> specifies the type.
697         /// The default codec type could be different depending on the device capability.</value>
698         /// <remarks>
699         /// <para>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</para>
700         /// <para>If H/W audio codec type is not supported in some cases, S/W audio codec type could be used instead.</para>
701         /// <para>The availability could be changed depending on the codec capability.
702         /// If an application wants to use the H/W audio codec type as default,
703         /// The following functions should be called after the codec type is set. :<br/>
704         /// <see cref="AudioEffect.IsAvailable"/><br/>
705         /// <see cref="EnableExportingAudioData"/><br/>
706         /// <see cref="DisableExportingAudioData"/><br/>
707         /// <see cref="ReplayGain"/><br/>
708         /// <see cref="AudioPitch"/><br/>
709         /// <see cref="AudioPitchEnabled"/><br/></para>
710         /// </remarks>
711         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
712         /// <exception cref="ArgumentException">The value is not valid.</exception>
713         /// <exception cref="InvalidOperationException">
714         ///     The player is not in the valid state.
715         ///     -or-<br/>
716         ///     Operation failed; internal error.
717         /// </exception>
718         /// <exception cref="CodecNotSupportedException">The selected codec is not supported.</exception>
719         /// <since_tizen> 6 </since_tizen>
720         public CodecType AudioCodecType
721         {
722             get
723             {
724                 ValidateNotDisposed();
725
726                 NativePlayer.GetAudioCodecType(Handle, out var value).
727                     ThrowIfFailed(this, "Failed to get the type of the audio codec");
728
729                 return value;
730             }
731             set
732             {
733                 ValidateNotDisposed();
734                 ValidatePlayerState(PlayerState.Idle);
735
736                 ValidationUtil.ValidateEnum(typeof(CodecType), value, nameof(value));
737
738                 NativePlayer.SetAudioCodecType(Handle, value).
739                     ThrowIfFailed(this, "Failed to set the type of the audio codec");
740             }
741         }
742
743         private SphericalVideo _sphericalVideo;
744
745         /// <summary>
746         /// Gets the spherical video settings.
747         /// </summary>
748         /// <since_tizen> 5 </since_tizen>
749         public SphericalVideo SphericalVideo
750         {
751             get
752             {
753                 if (_sphericalVideo == null)
754                 {
755                     _sphericalVideo = new SphericalVideo(this);
756                 }
757
758                 return _sphericalVideo;
759             }
760         }
761
762         private AdaptiveVariants _adaptiveVariants;
763
764         /// <summary>
765         /// Gets the adaptive variants settings.
766         /// </summary>
767         /// <since_tizen> 5 </since_tizen>
768         public AdaptiveVariants AdaptiveVariants
769         {
770             get
771             {
772                 if (_adaptiveVariants == null)
773                 {
774                     _adaptiveVariants = new AdaptiveVariants(this);
775                 }
776
777                 return _adaptiveVariants;
778             }
779         }
780
781         private AudioOffload _audioOffload;
782
783         /// <summary>
784         /// Gets the setting for audio offload.
785         /// </summary>
786         /// <since_tizen> 6 </since_tizen>
787         public AudioOffload AudioOffload
788         {
789             get
790             {
791                 if (_audioOffload == null)
792                 {
793                     _audioOffload = new AudioOffload(this);
794                 }
795
796                 return _audioOffload;
797             }
798         }
799     }
800 }