Setting since_tizen 3/4 on Tizen.NET API
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.MediaPlayer / Player / Player.Properties.cs
1 /*
2  * Copyright (c) 2016 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     /// <since_tizen> 3 </since_tizen>
28     public partial class Player
29     {
30         private void RetrieveProperties()
31         {
32             NativePlayer.GetAudioLatencyMode(Handle, out _audioLatencyMode).
33                 ThrowIfFailed("Failed to initialize the player");
34
35             NativePlayer.IsLooping(Handle, out _isLooping).ThrowIfFailed("Failed to initialize the player");
36         }
37
38         /// <summary>
39         /// Gets the native handle of the player.
40         /// </summary>
41         /// <value>An IntPtr that contains the native handle of the player.</value>
42         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
43         /// <since_tizen> 3 </since_tizen>
44         public IntPtr Handle
45         {
46             get
47             {
48                 ValidateNotDisposed();
49                 return _handle.DangerousGetHandle();
50             }
51         }
52
53         #region Network configuration
54         private string _cookie = "";
55         private string _userAgent = "";
56
57         /// <summary>
58         /// Gets or sets the cookie for streaming playback.
59         /// </summary>
60         /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
61         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
62         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
63         /// <exception cref="ArgumentNullException">The value to set is null.</exception>
64         /// <since_tizen> 3 </since_tizen>
65         public string Cookie
66         {
67             get
68             {
69                 Log.Info(PlayerLog.Tag, "get cookie : " + _cookie);
70                 return _cookie;
71             }
72             set
73             {
74                 ValidatePlayerState(PlayerState.Idle);
75
76                 if (value == null)
77                 {
78                     throw new ArgumentNullException(nameof(value), "Cookie can't be null.");
79                 }
80
81                 NativePlayer.SetStreamingCookie(Handle, value, value.Length).
82                     ThrowIfFailed("Failed to set the cookie to the player");
83
84                 _cookie = value;
85             }
86         }
87
88         /// <summary>
89         /// Gets or sets the user agent for streaming playback.
90         /// </summary>
91         /// <remarks>To set, the player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
92         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
93         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
94         /// <exception cref="ArgumentNullException">The value to set is null.</exception>
95         /// <since_tizen> 3 </since_tizen>
96         public string UserAgent
97         {
98             get
99             {
100                 Log.Info(PlayerLog.Tag, "get useragent : " + _userAgent);
101                 return _userAgent;
102             }
103             set
104             {
105                 ValidatePlayerState(PlayerState.Idle);
106
107                 if (value == null)
108                 {
109                     throw new ArgumentNullException(nameof(value), "UserAgent can't be null.");
110                 }
111
112                 NativePlayer.SetStreamingUserAgent(Handle, value, value.Length).
113                     ThrowIfFailed("Failed to set the user agent to the player");
114
115                 _userAgent = value;
116             }
117         }
118         #endregion
119
120         /// <summary>
121         /// Gets the state of the player.
122         /// </summary>
123         /// <value>The current state of the player.</value>
124         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
125         /// <since_tizen> 3 </since_tizen>
126         public PlayerState State
127         {
128             get
129             {
130                 ValidateNotDisposed();
131
132                 if (IsPreparing())
133                 {
134                     return PlayerState.Preparing;
135                 }
136
137                 NativePlayer.GetState(Handle, out var state).ThrowIfFailed("Failed to retrieve the state of the player");
138
139                 Debug.Assert(Enum.IsDefined(typeof(PlayerState), state));
140
141                 return (PlayerState)state;
142             }
143         }
144
145         private AudioLatencyMode _audioLatencyMode;
146
147         /// <summary>
148         /// Gets or sets the audio latency mode.
149         /// </summary>
150         /// <value>A <see cref="AudioLatencyMode"/> that specifies the mode. The default is <see cref="AudioLatencyMode.Mid"/>.</value>
151         /// <remarks>
152         /// If the mode is <see cref="AudioLatencyMode.High"/>,
153         /// audio output interval can be increased, so it can keep more audio data to play.
154         /// But, state transition like pause or resume can be more slower than default(<see cref="AudioLatencyMode.Mid"/>).
155         /// </remarks>
156         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
157         /// <exception cref="ArgumentException">The value is not valid.</exception>
158         /// <since_tizen> 3 </since_tizen>
159         public AudioLatencyMode AudioLatencyMode
160         {
161             get
162             {
163                 Log.Info(PlayerLog.Tag, "get audio latency mode : " + _audioLatencyMode);
164                 return _audioLatencyMode;
165             }
166             set
167             {
168                 ValidateNotDisposed();
169
170                 if (_audioLatencyMode == value)
171                 {
172                     return;
173                 }
174                 ValidationUtil.ValidateEnum(typeof(AudioLatencyMode), value);
175
176                 NativePlayer.SetAudioLatencyMode(Handle, value).
177                     ThrowIfFailed("Failed to set the audio latency mode of the player");
178
179                 _audioLatencyMode = value;
180             }
181         }
182
183         private bool _isLooping;
184
185         /// <summary>
186         /// Gets or sets the looping state.
187         /// </summary>
188         /// <value>true if the playback is looping; otherwise, false. The default value is false.</value>
189         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
190         /// <since_tizen> 3 </since_tizen>
191         public bool IsLooping
192         {
193             get
194             {
195                 Log.Info(PlayerLog.Tag, "get looping : " + _isLooping);
196                 return _isLooping;
197             }
198             set
199             {
200                 ValidateNotDisposed();
201
202                 if (_isLooping == value)
203                 {
204                     return;
205                 }
206
207                 NativePlayer.SetLooping(Handle, value).ThrowIfFailed("Failed to set the looping state of the player");
208
209                 _isLooping = value;
210             }
211         }
212
213         #region Display methods
214         /// <summary>
215         /// Gets the display settings.
216         /// </summary>
217         /// <value>A <see cref="PlayerDisplaySettings"/> that specifies the display settings.</value>
218         /// <since_tizen> 3 </since_tizen>
219         public PlayerDisplaySettings DisplaySettings { get; }
220
221         private Display _display;
222
223         private PlayerErrorCode SetDisplay(Display display)
224         {
225             if (display == null)
226             {
227                 return NativeDisplay.SetDisplay(Handle, PlayerDisplayType.None, IntPtr.Zero);
228             }
229
230             return display.ApplyTo(this);
231         }
232
233         private void ReplaceDisplay(Display newDisplay)
234         {
235             _display?.SetOwner(null);
236             _display = newDisplay;
237             _display?.SetOwner(this);
238         }
239
240         /// <summary>
241         /// Gets or sets the display.
242         /// </summary>
243         /// <value>A <see cref="Multimedia.Display"/> that specifies the display.</value>
244         /// <remarks>The player must be in the <see cref="PlayerState.Idle"/> state.</remarks>
245         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
246         /// <exception cref="ArgumentException">The value has already been assigned to another player.</exception>
247         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
248         /// <since_tizen> 3 </since_tizen>
249         public Display Display
250         {
251             get
252             {
253                 return _display;
254             }
255             set
256             {
257                 ValidatePlayerState(PlayerState.Idle);
258
259                 if (value?.Owner != null)
260                 {
261                     if (ReferenceEquals(this, value.Owner))
262                     {
263                         return;
264                     }
265
266                     throw new ArgumentException("The display has already been assigned to another.");
267                 }
268                 SetDisplay(value).ThrowIfFailed("Failed to set the display to the player");
269
270                 ReplaceDisplay(value);
271             }
272         }
273
274         PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
275         {
276             Debug.Assert(IsDisposed == false);
277
278             Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
279             Debug.Assert(type != DisplayType.None);
280
281             return NativeDisplay.SetDisplay(Handle,
282                 type == DisplayType.Overlay ? PlayerDisplayType.Overlay : PlayerDisplayType.Evas, evasObject);
283         }
284
285         PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
286         {
287             Debug.Assert(IsDisposed == false);
288
289             return NativeDisplay.SetEcoreDisplay(Handle, PlayerDisplayType.Overlay, windowHandle);
290         }
291         #endregion
292
293         private PlayerTrackInfo _audioTrack;
294
295         /// <summary>
296         /// Gets the track info for the audio.
297         /// </summary>
298         /// <value>A <see cref="PlayerTrackInfo"/> for audio.</value>
299         /// <since_tizen> 3 </since_tizen>
300         public PlayerTrackInfo AudioTrackInfo
301         {
302             get
303             {
304                 if (_audioTrack == null)
305                 {
306                     _audioTrack = new PlayerTrackInfo(this, StreamType.Audio);
307                 }
308                 return _audioTrack;
309             }
310         }
311
312         private PlayerTrackInfo _subtitleTrackInfo;
313
314         /// <summary>
315         /// Gets the track info for the subtitle.
316         /// </summary>
317         /// <value>A <see cref="PlayerTrackInfo"/> for the subtitle.</value>
318         /// <since_tizen> 3 </since_tizen>
319         public PlayerTrackInfo SubtitleTrackInfo
320         {
321             get
322             {
323                 if (_subtitleTrackInfo == null)
324                 {
325                     _subtitleTrackInfo = new PlayerTrackInfo(this, StreamType.Text);
326                 }
327                 return _subtitleTrackInfo;
328             }
329         }
330
331         private StreamInfo _streamInfo;
332
333         /// <summary>
334         /// Gets the stream information.
335         /// </summary>
336         /// <value>A <see cref="StreamInfo"/> for this player.</value>
337         /// <since_tizen> 3 </since_tizen>
338         public StreamInfo StreamInfo
339         {
340             get
341             {
342                 if (_streamInfo == null)
343                 {
344                     _streamInfo = new StreamInfo(this);
345                 }
346                 return _streamInfo;
347             }
348         }
349
350         private readonly AudioEffect _audioEffect;
351
352         /// <summary>
353         /// Gets the audio effect.
354         /// </summary>
355         /// <feature>http://tizen.org/feature/multimedia.custom_audio_effect</feature>
356         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
357         /// <since_tizen> 3 </since_tizen>
358         public AudioEffect AudioEffect
359         {
360             get
361             {
362                 if (_audioEffect == null)
363                 {
364                     throw new NotSupportedException($"The feature({Features.AudioEffect}) is not supported.");
365                 }
366
367                 return _audioEffect;
368             }
369         }
370
371         /// <summary>
372         /// Gets or sets the mute state.
373         /// </summary>
374         /// <value>true if the player is muted; otherwise, false.</value>
375         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
376         /// <since_tizen> 3 </since_tizen>
377         public bool Muted
378         {
379             get
380             {
381                 bool value = false;
382                 NativePlayer.IsMuted(Handle, out value).ThrowIfFailed("Failed to get the mute state of the player");
383
384                 Log.Info(PlayerLog.Tag, "get mute : " + value);
385
386                 return value;
387             }
388             set
389             {
390                 NativePlayer.SetMute(Handle, value).ThrowIfFailed("Failed to set the mute state of the player");
391             }
392         }
393
394         /// <summary>
395         /// Gets or sets the current volume.
396         /// </summary>
397         /// <remarks>Valid volume range is from 0 to 1.0, inclusive.</remarks>
398         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
399         /// <exception cref="ArgumentOutOfRangeException">
400         ///     <paramref name="value"/> is less than zero.<br/>
401         ///     -or-<br/>
402         ///     <paramref name="value"/> is greater than 1.0.
403         /// </exception>
404         /// <since_tizen> 3 </since_tizen>
405         public float Volume
406         {
407             get
408             {
409                 float value = 0.0F;
410                 NativePlayer.GetVolume(Handle, out value, out value).
411                     ThrowIfFailed("Failed to get the volume of the player");
412                 return value;
413             }
414             set
415             {
416                 if (value < 0F || 1.0F < value)
417                 {
418                     throw new ArgumentOutOfRangeException(nameof(value), value,
419                         $"Valid volume range is 0 <= value <= 1.0, but got { value }.");
420                 }
421
422                 NativePlayer.SetVolume(Handle, value, value).
423                     ThrowIfFailed("Failed to set the volume of the player");
424             }
425         }
426     }
427 }