[Multimedia] Modified a constructor of the Display class not to check the raw video...
[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>
245         ///     The player must be in the <see cref="PlayerState.Idle"/> state.<br/>
246         ///     The raw video feature(http://tizen.org/feature/multimedia.raw_video) is required if
247         ///     the display is created with <see cref="MediaView"/>.
248         /// </remarks>
249         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
250         /// <exception cref="ArgumentException">The value has already been assigned to another player.</exception>
251         /// <exception cref="InvalidOperationException">The player is not in the valid state.</exception>
252         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
253         /// <since_tizen> 3 </since_tizen>
254         public Display Display
255         {
256             get
257             {
258                 return _display;
259             }
260             set
261             {
262                 ValidatePlayerState(PlayerState.Idle);
263
264                 if (value != null && value.HasMediaView)
265                 {
266                     ValidationUtil.ValidateFeatureSupported(PlayerFeatures.RawVideo);
267                 }
268
269                 if (value?.Owner != null)
270                 {
271                     if (ReferenceEquals(this, value.Owner))
272                     {
273                         return;
274                     }
275
276                     throw new ArgumentException("The display has already been assigned to another.");
277                 }
278
279                 ReplaceDisplay(value);
280             }
281         }
282
283         PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
284         {
285             Debug.Assert(IsDisposed == false);
286
287             Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
288             Debug.Assert(type != DisplayType.None);
289
290             return NativeDisplay.SetDisplay(Handle,
291                 type == DisplayType.Overlay ? PlayerDisplayType.Overlay : PlayerDisplayType.Evas, evasObject);
292         }
293
294         PlayerErrorCode IDisplayable<PlayerErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
295         {
296             Debug.Assert(IsDisposed == false);
297
298             return NativeDisplay.SetEcoreDisplay(Handle, PlayerDisplayType.Overlay, windowHandle);
299         }
300         #endregion
301
302         private PlayerTrackInfo _audioTrack;
303
304         /// <summary>
305         /// Gets the track info for the audio.
306         /// </summary>
307         /// <value>A <see cref="PlayerTrackInfo"/> for audio.</value>
308         /// <since_tizen> 3 </since_tizen>
309         public PlayerTrackInfo AudioTrackInfo
310         {
311             get
312             {
313                 if (_audioTrack == null)
314                 {
315                     _audioTrack = new PlayerTrackInfo(this, StreamType.Audio);
316                 }
317                 return _audioTrack;
318             }
319         }
320
321         private PlayerTrackInfo _subtitleTrackInfo;
322
323         /// <summary>
324         /// Gets the track info for the subtitle.
325         /// </summary>
326         /// <value>A <see cref="PlayerTrackInfo"/> for the subtitle.</value>
327         /// <since_tizen> 3 </since_tizen>
328         public PlayerTrackInfo SubtitleTrackInfo
329         {
330             get
331             {
332                 if (_subtitleTrackInfo == null)
333                 {
334                     _subtitleTrackInfo = new PlayerTrackInfo(this, StreamType.Text);
335                 }
336                 return _subtitleTrackInfo;
337             }
338         }
339
340         private StreamInfo _streamInfo;
341
342         /// <summary>
343         /// Gets the stream information.
344         /// </summary>
345         /// <value>A <see cref="StreamInfo"/> for this player.</value>
346         /// <since_tizen> 3 </since_tizen>
347         public StreamInfo StreamInfo
348         {
349             get
350             {
351                 if (_streamInfo == null)
352                 {
353                     _streamInfo = new StreamInfo(this);
354                 }
355                 return _streamInfo;
356             }
357         }
358
359         private readonly AudioEffect _audioEffect;
360
361         /// <summary>
362         /// Gets the audio effect.
363         /// </summary>
364         /// <feature>http://tizen.org/feature/multimedia.custom_audio_effect</feature>
365         /// <exception cref="NotSupportedException">The required feature is not supported.</exception>
366         /// <since_tizen> 3 </since_tizen>
367         public AudioEffect AudioEffect
368         {
369             get
370             {
371                 if (_audioEffect == null)
372                 {
373                     throw new NotSupportedException($"The feature({PlayerFeatures.AudioEffect}) is not supported.");
374                 }
375
376                 return _audioEffect;
377             }
378         }
379
380         /// <summary>
381         /// Gets or sets the mute state.
382         /// </summary>
383         /// <value>true if the player is muted; otherwise, false.</value>
384         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
385         /// <since_tizen> 3 </since_tizen>
386         public bool Muted
387         {
388             get
389             {
390                 bool value = false;
391                 NativePlayer.IsMuted(Handle, out value).ThrowIfFailed("Failed to get the mute state of the player");
392
393                 Log.Info(PlayerLog.Tag, "get mute : " + value);
394
395                 return value;
396             }
397             set
398             {
399                 NativePlayer.SetMute(Handle, value).ThrowIfFailed("Failed to set the mute state of the player");
400             }
401         }
402
403         /// <summary>
404         /// Gets or sets the current volume.
405         /// </summary>
406         /// <remarks>Valid volume range is from 0 to 1.0, inclusive.</remarks>
407         /// <exception cref="ObjectDisposedException">The player has already been disposed of.</exception>
408         /// <exception cref="ArgumentOutOfRangeException">
409         ///     <paramref name="value"/> is less than zero.<br/>
410         ///     -or-<br/>
411         ///     <paramref name="value"/> is greater than 1.0.
412         /// </exception>
413         /// <since_tizen> 3 </since_tizen>
414         public float Volume
415         {
416             get
417             {
418                 float value = 0.0F;
419                 NativePlayer.GetVolume(Handle, out value, out value).
420                     ThrowIfFailed("Failed to get the volume of the player");
421                 return value;
422             }
423             set
424             {
425                 if (value < 0F || 1.0F < value)
426                 {
427                     throw new ArgumentOutOfRangeException(nameof(value), value,
428                         $"Valid volume range is 0 <= value <= 1.0, but got { value }.");
429                 }
430
431                 NativePlayer.SetVolume(Handle, value, value).
432                     ThrowIfFailed("Failed to set the volume of the player");
433             }
434         }
435     }
436 }