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