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.Diagnostics;
18 using NativeDisplay = Interop.Display;
21 namespace Tizen.Multimedia
24 /// Represents properties for streaming buffering time.
26 /// <since_tizen> 5 </since_tizen>
27 public struct PlayerBufferingTime
30 /// Initializes a new instance of the PlayerBufferingTime struct.
32 /// <param name="preBufferMillisecond">A duration of buffering data that must be prerolled to start playback.</param>
33 /// Except 0 and -1, setting at least 1000 milliseconds is recommended to ensure the normal buffering operation.
34 /// 0 : use platform default value which could be different depending on the streaming type and network status. (the initial value)
35 /// -1 : use current value. (since 5.5)
36 /// <param name="reBufferMillisecond">A duration of buffering data that must be prerolled to resume playback,
37 /// when player is internally paused for buffering.
38 /// Except 0 and -1, setting at least 1000 milliseconds is recommended to ensure the normal buffering operation.
39 /// 0 : use platform default value, which depends on the streaming type and network status. It is set as the initial value of this parameter.
40 /// If the player state is <see cref="PlayerState.Playing"/> or <see cref="PlayerState.Paused"/>,
41 /// this function will return correct time value instead of 0. (since 5.5)
42 /// -1 : use current value. (since 5.5)</param>
43 /// <since_tizen> 5 </since_tizen>
44 public PlayerBufferingTime(int preBufferMillisecond = -1, int reBufferMillisecond = -1)
46 PreBufferMillisecond = preBufferMillisecond;
47 ReBufferMillisecond = reBufferMillisecond;
51 /// Gets or sets the duration of buffering data that must be prerolled to start playback.
53 /// <since_tizen> 5 </since_tizen>
54 public int PreBufferMillisecond
61 /// Gets or sets the duration of buffering data that must be prerolled to resume playback
62 /// if player enters pause state for buffering.
64 /// <since_tizen> 5 </since_tizen>
65 public int ReBufferMillisecond
71 /// <since_tizen> 3 </since_tizen>
72 public partial class Player
75 /// Gets the native handle of the player.
77 /// <value>An IntPtr that contains the native handle of the player.</value>
78 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
79 /// <since_tizen> 3 </since_tizen>
84 ValidateNotDisposed();
85 return _handle.DangerousGetHandle();
89 #region Network configuration
90 private string _cookie = "";
91 private string _userAgent = "";
92 private const int MinBufferingTime = -1;
95 /// Gets or sets the cookie for streaming playback.
97 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
98 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
99 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
100 /// <exception cref="ArgumentNullException">The value to set is null.</exception>
101 /// <since_tizen> 3 </since_tizen>
110 ValidatePlayerState(PlayerState.Idle);
114 throw new ArgumentNullException(nameof(value), "Cookie can't be null.");
117 NativePlayer.SetStreamingCookie(Handle, value, value.Length).
118 ThrowIfFailed(this, "Failed to set the cookie to the player");
125 /// Gets or sets the user agent for streaming playback.
127 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
128 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
129 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
130 /// <exception cref="ArgumentNullException">The value to set is null.</exception>
131 /// <since_tizen> 3 </since_tizen>
132 public string UserAgent
140 ValidatePlayerState(PlayerState.Idle);
144 throw new ArgumentNullException(nameof(value), "UserAgent can't be null.");
147 NativePlayer.SetStreamingUserAgent(Handle, value, value.Length).
148 ThrowIfFailed(this, "Failed to set the user agent to the player");
155 /// Gets or sets the streaming buffering time.
157 /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
158 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
159 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
160 /// <exception cref="ArgumentOutOfRangeException">
161 /// <pramref name="PreBufferMillisecond"/> is less than -1.<br/>
163 /// <pramref name="ReBufferMillisecond"/> is less than -1.<br/>
165 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
166 /// <seealso cref="PlayerBufferingTime"/>
167 /// <since_tizen> 5 </since_tizen>
168 public PlayerBufferingTime BufferingTime
172 ValidateNotDisposed();
174 NativePlayer.GetStreamingBufferingTime(Handle, out var PreBuffMillisecond, out var ReBuffMillisecond).
175 ThrowIfFailed(this, "Failed to get the buffering time of the player");
177 return new PlayerBufferingTime(PreBuffMillisecond, ReBuffMillisecond);
181 ValidatePlayerState(PlayerState.Idle);
183 if (value.PreBufferMillisecond < MinBufferingTime || value.ReBufferMillisecond < MinBufferingTime)
185 throw new ArgumentOutOfRangeException(nameof(value), value,
186 $"invalid range, got { value.PreBufferMillisecond }, { value.ReBufferMillisecond }.");
189 NativePlayer.SetStreamingBufferingTime(Handle, value.PreBufferMillisecond, value.ReBufferMillisecond).
190 ThrowIfFailed(this, "Failed to set the buffering time of the player");
196 /// Gets the state of the player.
198 /// <value>The current state of the player.</value>
199 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
200 /// <since_tizen> 3 </since_tizen>
201 public PlayerState State
205 ValidateNotDisposed();
209 return PlayerState.Preparing;
212 NativePlayer.GetState(Handle, out var state).
213 ThrowIfFailed(this, "Failed to retrieve the state of the player");
215 Debug.Assert(Enum.IsDefined(typeof(PlayerState), state));
217 return (PlayerState)state;
222 /// Gets or sets the audio latency mode.
224 /// <value>A <see cref="AudioLatencyMode"/> that specifies the mode. The default is <see cref="AudioLatencyMode.Mid"/>.</value>
226 /// If the mode is <see cref="AudioLatencyMode.High"/>,
227 /// audio output interval can be increased, so it can keep more audio data to play.
228 /// But, state transition like pause or resume can be more slower than default(<see cref="AudioLatencyMode.Mid"/>).
230 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
231 /// <exception cref="ArgumentException">The value is not valid.</exception>
232 /// <exception cref="NotAvailableException">
233 /// If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
235 /// <seealso cref="AudioOffload"/>
236 /// <since_tizen> 3 </since_tizen>
237 public AudioLatencyMode AudioLatencyMode
241 AudioOffload.CheckDisabled();
243 NativePlayer.GetAudioLatencyMode(Handle, out var value).
244 ThrowIfFailed(this, "Failed to get the audio latency mode of the player");
250 ValidateNotDisposed();
251 AudioOffload.CheckDisabled();
253 ValidationUtil.ValidateEnum(typeof(AudioLatencyMode), value, nameof(value));
255 NativePlayer.SetAudioLatencyMode(Handle, value).
256 ThrowIfFailed(this, "Failed to set the audio latency mode of the player");
261 /// Gets or sets the looping state.
263 /// <value>true if the playback is looping; otherwise, false. The default value is false.</value>
264 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
265 /// <since_tizen> 3 </since_tizen>
266 public bool IsLooping
270 NativePlayer.IsLooping(Handle, out var value).
271 ThrowIfFailed(this, "Failed to get the looping state of the player");
277 ValidateNotDisposed();
279 NativePlayer.SetLooping(Handle, value).
280 ThrowIfFailed(this, "Failed to set the looping state of the player");
284 #region Display methods
286 private PlayerDisplaySettings _displaySettings;
289 /// Gets the display settings.
291 /// <value>A <see cref="PlayerDisplaySettings"/> that specifies the display settings.</value>
292 /// <since_tizen> 3 </since_tizen>
293 public PlayerDisplaySettings DisplaySettings => _displaySettings;
295 private Display _display;
297 private bool _uiSync;
299 private PlayerErrorCode SetDisplay(Display display)
303 return NativeDisplay.SetDisplay(Handle, PlayerDisplayType.None, IntPtr.Zero);
306 return display.ApplyTo(this);
309 private void ReplaceDisplay(Display newDisplay)
311 _display?.SetOwner(null);
312 _display = newDisplay;
313 _display?.SetOwner(this);
317 /// Gets or sets the display.
319 /// <value>A <see cref="Multimedia.Display"/> that specifies the display.</value>
321 /// The player must be in the <see cref="PlayerState.Idle"/> state.<br/>
322 /// The raw video feature(http://tizen.org/feature/multimedia.raw_video) is required if
323 /// the display is created with <see cref="MediaView"/>.<br/>
324 /// 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/>
325 /// But <see cref="Tizen.Multimedia.Player.DisplaySettings"/> is not supported in UI sync mode.
327 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
328 /// <exception cref="ArgumentException">The value has already been assigned to another player.</exception>
329 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
330 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
331 /// <since_tizen> 3 </since_tizen>
332 public Display Display
340 ValidatePlayerState(PlayerState.Idle);
342 if (value != null && value.HasMediaView)
344 ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
347 if (value?.Owner != null)
349 if (ReferenceEquals(this, value.Owner))
354 throw new ArgumentException("The display has already been assigned to another.");
357 _uiSync = value?.UiSync ?? false;
359 SetDisplay(value).ThrowIfFailed(this, "Failed to configure display of the player");
361 ReplaceDisplay(value);
365 PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
367 Debug.Assert(IsDisposed == false);
369 Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
370 Debug.Assert(type != DisplayType.None);
372 return NativeDisplay.SetDisplay(Handle,
373 type == DisplayType.Overlay ? PlayerDisplayType.Overlay : PlayerDisplayType.Evas, evasObject);
376 PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
378 Debug.Assert(IsDisposed == false);
380 return NativeDisplay.SetEcoreDisplay(Handle,
381 _uiSync ? PlayerDisplayType.OverlayUISync : PlayerDisplayType.Overlay, windowHandle);
385 private PlayerTrackInfo _audioTrack;
388 /// Gets the track info for the audio.
390 /// <value>A <see cref="PlayerTrackInfo"/> for audio.</value>
391 /// <since_tizen> 3 </since_tizen>
392 public PlayerTrackInfo AudioTrackInfo
396 if (_audioTrack == null)
398 _audioTrack = new PlayerTrackInfo(this, StreamType.Audio);
404 private PlayerTrackInfo _subtitleTrackInfo;
407 /// Gets the track info for the subtitle.
409 /// <value>A <see cref="PlayerTrackInfo"/> for the subtitle.</value>
410 /// <since_tizen> 3 </since_tizen>
411 public PlayerTrackInfo SubtitleTrackInfo
415 if (_subtitleTrackInfo == null)
417 _subtitleTrackInfo = new PlayerTrackInfo(this, StreamType.Text);
419 return _subtitleTrackInfo;
423 private StreamInfo _streamInfo;
426 /// Gets the stream information.
428 /// <value>A <see cref="StreamInfo"/> for this player.</value>
429 /// <since_tizen> 3 </since_tizen>
430 public StreamInfo StreamInfo
434 if (_streamInfo == null)
436 _streamInfo = new StreamInfo(this);
442 private AudioEffect _audioEffect;
445 /// Gets the audio effect.
447 /// <feature>http://tizen.org/feature/multimedia.custom_audio_effect</feature>
448 /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
449 /// <since_tizen> 3 </since_tizen>
450 public AudioEffect AudioEffect
454 if (_audioEffect == null)
456 throw new NotSupportedException($"The feature({PlayerFeatures.AudioEffect}) is not supported.");
464 /// Gets or sets the mute state.
466 /// <value>true if the player is muted; otherwise, false.</value>
467 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
468 /// <since_tizen> 3 </since_tizen>
473 NativePlayer.IsMuted(Handle, out var value).
474 ThrowIfFailed(this, "Failed to get the mute state of the player");
476 Log.Info(PlayerLog.Tag, "get mute : " + value);
482 NativePlayer.SetMute(Handle, value).ThrowIfFailed(this, "Failed to set the mute state of the player");
487 /// Gets or sets the current volume.
489 /// <remarks>Valid volume range is from 0 to 1.0, inclusive.</remarks>
490 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
491 /// <exception cref="ArgumentOutOfRangeException">
492 /// <paramref name="value"/> is less than zero.<br/>
494 /// <paramref name="value"/> is greater than 1.0.
496 /// <since_tizen> 3 </since_tizen>
502 NativePlayer.GetVolume(Handle, out value, out value).
503 ThrowIfFailed(this, "Failed to get the volume of the player");
509 if (value < 0F || 1.0F < value)
511 throw new ArgumentOutOfRangeException(nameof(value), value,
512 $"Valid volume range is 0 <= value <= 1.0, but got { value }.");
515 NativePlayer.SetVolume(Handle, value, value).
516 ThrowIfFailed(this, "Failed to set the volume of the player");
521 /// Gets or sets the audio-only state.
523 /// <value>true if the playback is audio-only mode; otherwise, false. The default value is false.</value>
524 /// The <see cref="Player"/> must be in the <see cref="PlayerState.Ready"/>,
525 /// <see cref="PlayerState.Playing"/>, or <see cref="PlayerState.Paused"/> state.
526 /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
527 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
528 /// <since_tizen> 5 </since_tizen>
529 public bool IsAudioOnly
533 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
534 NativePlayer.IsAudioOnly(Handle, out var value).
535 ThrowIfFailed(this, "Failed to get the audio-only state of the player");
540 ValidateNotDisposed();
541 ValidatePlayerState(PlayerState.Ready, PlayerState.Playing, PlayerState.Paused);
542 NativePlayer.SetAudioOnly(Handle, value).
543 ThrowIfFailed(this, "Failed to set the audio-only state of the player");
548 /// Gets or sets the player's replaygain state.
550 /// <value>If the replaygain status is true, replaygain is applied (if contents has a replaygain tag);
551 /// otherwise, the replaygain is not affected by tag and properties.</value>
552 /// <remarks>This function could be unavailable depending on the audio codec type.</remarks>
553 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
554 /// <exception cref="InvalidOperationException">
555 /// The player is not in the valid state.
557 /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
559 /// The function is not available depending on the audio codec type. (Since tizen 6.0)
561 /// <seealso cref="AudioOffload"/>
562 /// <seealso cref="AudioCodecType"/>
563 /// <since_tizen> 5 </since_tizen>
564 public bool ReplayGain
568 ValidateNotDisposed();
569 AudioOffload.CheckDisabled();
571 NativePlayer.IsReplayGain(Handle, out var value).
572 ThrowIfFailed(this, "Failed to get the replaygain of the player");
577 ValidateNotDisposed();
578 AudioOffload.CheckDisabled();
580 NativePlayer.SetReplayGain(Handle, value).
581 ThrowIfFailed(this, "Failed to set the replaygain of the player");
586 /// Enables or disables controlling the pitch of audio.
587 /// Gets the status of controlling the pitch of audio.
589 /// <value>The value indicating whether or not AudioPitch is enabled. The default is false.</value>
590 /// <remarks>This function is used for audio content only.
591 /// To set, the player must be in the <see cref="PlayerState.Idle"/> state.
592 /// This function could be unavailable depending on the audio codec type.</remarks>
593 /// <exception cref="InvalidOperationException">
594 /// The player is not in the valid state.
596 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
597 /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
599 /// The function is not available depending on the audio codec type. (Since tizen 6.0)
601 /// <seealso cref="AudioPitch"/>
602 /// <seealso cref="AudioOffload"/>
603 /// <seealso cref="AudioCodecType"/>
604 /// <since_tizen> 6 </since_tizen>
605 public bool AudioPitchEnabled
609 ValidateNotDisposed();
610 AudioOffload.CheckDisabled();
612 NativePlayer.IsAudioPitchEnabled(Handle, out var value).
613 ThrowIfFailed(this, "Failed to get whether the audio pitch is enabled or not");
619 ValidateNotDisposed();
620 AudioOffload.CheckDisabled();
621 ValidatePlayerState(PlayerState.Idle);
623 NativePlayer.SetAudioPitchEnabled(Handle, value).
624 ThrowIfFailed(this, "Failed to enable the audio pitch of the player");
629 /// Gets or sets the pitch of audio.
631 /// <value>The audio stream pitch value. The default is 1.</value>
632 /// <remarks>Enabling pitch control could increase the CPU usage on some devices.
633 /// This function is used for audio content only.
634 /// This function could be unavailable depending on the audio codec type.</remarks>
635 /// <exception cref="InvalidOperationException">
636 /// A pitch is not enabled.
638 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
639 /// <exception cref="ArgumentOutOfRangeException">
640 /// value is less than 0.5.
642 /// value is greater than 2.0.
644 /// <exception cref="NotAvailableException">If audio offload is enabled by calling <see cref="AudioOffload.IsEnabled"/>. (Since tizen 6.0)
646 /// The function is not available depending on the audio codec type. (Since tizen 6.0)
648 /// <seealso cref="AudioPitchEnabled"/>
649 /// <seealso cref="AudioOffload"/>
650 /// <seealso cref="AudioCodecType"/>
651 /// <since_tizen> 6 </since_tizen>
652 public float AudioPitch
656 ValidateNotDisposed();
657 AudioOffload.CheckDisabled();
659 if (AudioPitchEnabled == false)
661 throw new InvalidOperationException("An audio pitch is not enabled.");
664 NativePlayer.GetAudioPitch(Handle, out var value).
665 ThrowIfFailed(this, "Failed to get the audio pitch");
672 ValidateNotDisposed();
673 AudioOffload.CheckDisabled();
675 if (AudioPitchEnabled == false)
677 throw new InvalidOperationException("An audio pitch is not enabled.");
680 if (value < 0.5F || 2.0F < value)
682 throw new ArgumentOutOfRangeException(nameof(value), value, "Valid value is 0.5 to 2.0");
685 NativePlayer.SetAudioPitch(Handle, value).ThrowIfFailed(this, "Failed to set the audio pitch");
690 /// Gets or sets the default codec type of the audio decoder.
692 /// <value>A <see cref="CodecType"/> specifies the type.
693 /// The default codec type could be different depending on the device capability.</value>
695 /// <para>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</para>
696 /// <para>If H/W audio codec type is not supported in some cases, S/W audio codec type could be used instead.</para>
697 /// <para>The availability could be changed depending on the codec capability.
698 /// If an application wants to use the H/W audio codec type as default,
699 /// The following functions should be called after the codec type is set. :<br/>
700 /// <see cref="AudioEffect.IsAvailable"/><br/>
701 /// <see cref="EnableExportingAudioData"/><br/>
702 /// <see cref="DisableExportingAudioData"/><br/>
703 /// <see cref="ReplayGain"/><br/>
704 /// <see cref="AudioPitch"/><br/>
705 /// <see cref="AudioPitchEnabled"/><br/></para>
707 /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
708 /// <exception cref="ArgumentException">The value is not valid.</exception>
709 /// <exception cref="InvalidOperationException">
710 /// The player is not in the valid state.
712 /// Operation failed; internal error.
714 /// <exception cref="CodecNotSupportedException">The selected codec is not supported.</exception>
715 /// <since_tizen> 6 </since_tizen>
716 public CodecType AudioCodecType
720 ValidateNotDisposed();
722 NativePlayer.GetAudioCodecType(Handle, out var value).
723 ThrowIfFailed(this, "Failed to get the type of the audio codec");
729 ValidateNotDisposed();
730 ValidatePlayerState(PlayerState.Idle);
732 ValidationUtil.ValidateEnum(typeof(CodecType), value, nameof(value));
734 NativePlayer.SetAudioCodecType(Handle, value).
735 ThrowIfFailed(this, "Failed to set the type of the audio codec");
740 /// Gets or sets the codec type of the video decoder.
742 /// <value>A <see cref="CodecType"/> specifies the type.
743 /// The default codec type could be different depending on the device capability.</value>
745 /// <para>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</para>
746 /// <para>If H/W video codec type is not supported in some cases, S/W video codec type could be used instead.</para>
747 /// <para>The availability could be changed depending on the codec capability.</para>
749 /// <exception cref="ObjectDisposedException">The player has already been disposed.</exception>
750 /// <exception cref="ArgumentException">The value is not valid.</exception>
751 /// <exception cref="InvalidOperationException">
752 /// The player is not in the valid state.
754 /// Operation failed; internal error.
756 /// <exception cref="CodecNotSupportedException">The selected codec is not supported.</exception>
757 /// <since_tizen> 11 </since_tizen>
758 public CodecType VideoCodecType
762 ValidateNotDisposed();
764 NativePlayer.GetVideoCodecType(Handle, out var value).
765 ThrowIfFailed(this, "Failed to get the type of the video codec");
771 ValidateNotDisposed();
772 ValidatePlayerState(PlayerState.Idle);
774 ValidationUtil.ValidateEnum(typeof(CodecType), value, nameof(value));
776 NativePlayer.SetVideoCodecType(Handle, value).
777 ThrowIfFailed(this, "Failed to set the type of the video codec");
781 private SphericalVideo _sphericalVideo;
784 /// Gets the spherical video settings.
786 /// <since_tizen> 5 </since_tizen>
787 public SphericalVideo SphericalVideo
791 if (_sphericalVideo == null)
793 _sphericalVideo = new SphericalVideo(this);
796 return _sphericalVideo;
800 private AdaptiveVariants _adaptiveVariants;
803 /// Gets the adaptive variants settings.
805 /// <since_tizen> 5 </since_tizen>
806 public AdaptiveVariants AdaptiveVariants
810 if (_adaptiveVariants == null)
812 _adaptiveVariants = new AdaptiveVariants(this);
815 return _adaptiveVariants;
819 private AudioOffload _audioOffload;
822 /// Gets the setting for audio offload.
824 /// <since_tizen> 6 </since_tizen>
825 public AudioOffload AudioOffload
829 if (_audioOffload == null)
831 _audioOffload = new AudioOffload(this);
834 return _audioOffload;