3862f679cc6112525ac3329fc7786960a59f02da
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Remoting / WebRTC / MediaStreamTrack.cs
1 /*
2  * Copyright (c) 2021 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
17 using System;
18 using System.Diagnostics;
19 using static Interop;
20
21 namespace Tizen.Multimedia.Remoting
22 {
23     /// <summary>
24     /// Provides the ability to control audio/video track.
25     /// </summary>
26     /// <since_tizen> 9 </since_tizen>
27     public sealed class MediaStreamTrack : IDisplayable<WebRTCErrorCode>
28     {
29         private WebRTC _webRtc;
30         private uint _trackId;
31         private Display _display;
32
33         internal MediaStreamTrack(WebRTC webRtc, MediaType type, uint trackId)
34         {
35             _webRtc = webRtc;
36             _trackId = trackId;
37             Type = type;
38         }
39
40         /// <summary>
41         /// Gets the the of media stream track.
42         /// </summary>
43         /// <value><see cref="MediaType"/></value>
44         /// <since_tizen> 9 </since_tizen>
45         public MediaType Type { get; }
46
47         private WebRTCErrorCode SetDisplay(Display display)
48             => display.ApplyTo(this);
49
50         private void ReplaceDisplay(Display newDisplay)
51         {
52             _display?.SetOwner(null);
53             _display = newDisplay;
54             _display?.SetOwner(this);
55         }
56
57         /// <summary>
58         /// Gets or sets the display to show remote video.
59         /// </summary>
60         /// <value>A <see cref="Multimedia.Display"/> that specifies the display.</value>
61         /// <remarks>
62         /// If user set video source with <see cref="TransceiverDirection.SendRecv"/>, <see cref="Display"/> must be set.<br/>
63         /// If not, the received video will fill entire screen.<br/>
64         /// If remote track, <see cref="Display"/> must be set in <see cref="WebRTC.TrackAdded"/> event.<br/>
65         /// The display is created with <see cref="MediaView"/>.
66         /// </remarks>
67         /// <exception cref="ObjectDisposedException">The WebRTC has already been disposed of.</exception>
68         /// <exception cref="ArgumentException">The value has already been assigned to another WebRTC.</exception>
69         /// <exception cref="InvalidOperationException">
70         /// The WebRTC is not called in <see cref="WebRTC.TrackAdded"/> event.
71         /// -or-<br/>
72         /// This MediaStreamTrack is not Video.
73         /// </exception>
74         /// <since_tizen> 9 </since_tizen>
75         public Display Display
76         {
77             get => _display;
78             set
79             {
80                 if (Type != MediaType.Video)
81                 {
82                     throw new InvalidOperationException("This property is only for video track.");
83                 }
84
85                 if (value == null)
86                 {
87                     throw new ArgumentNullException(nameof(value), "Display cannot be null.");
88                 }
89
90                 if (value?.Owner != null)
91                 {
92                     if (ReferenceEquals(this, value.Owner))
93                     {
94                         throw new ArgumentException("The display has already been assigned to another.");
95                     }
96                 }
97                 else
98                 {
99                     SetDisplay(value).ThrowIfFailed("Failed to configure display of the MediaStreamTrack");
100                     ReplaceDisplay(value);
101                 }
102             }
103         }
104
105         WebRTCErrorCode IDisplayable<WebRTCErrorCode>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
106         {
107             Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
108             Debug.Assert(type != DisplayType.None);
109
110             return NativeWebRTC.SetDisplay(_webRtc.Handle, _trackId,
111                 type == DisplayType.Overlay ? WebRTCDisplayType.Overlay : WebRTCDisplayType.Evas, evasObject);
112         }
113
114         WebRTCErrorCode IDisplayable<WebRTCErrorCode>.ApplyEcoreWindow(IntPtr windowHandle)
115         {
116             return NativeWebRTC.SetEcoreDisplay(_webRtc.Handle, _trackId, windowHandle);
117         }
118
119         /// <summary>
120         /// Gets or sets the display mode.
121         /// </summary>
122         /// <remarks>
123         /// This property is meaningful only in overlay or EVAS surface display type.
124         /// </remarks>
125         /// <value>A <see cref="WebRTCDisplayMode"/> that specifies the display mode.</value>
126         /// <exception cref="ArgumentException">Display mode type is incorrect.</exception>
127         /// <exception cref="InvalidOperationException"><see cref="Display"/> is not set.</exception>
128         /// <since_tizen> 9 </since_tizen>
129         public WebRTCDisplayMode DisplayMode
130         {
131             get
132             {
133                 if (Type != MediaType.Video)
134                 {
135                     throw new InvalidOperationException("This property is only for video track.");
136                 }
137
138                 NativeWebRTC.GetDisplayMode(_webRtc.Handle, _trackId, out var val).
139                     ThrowIfFailed("Failed to get WebRTC display mode");
140
141                 return val;
142             }
143             set
144             {
145                 if (Type != MediaType.Video)
146                 {
147                     throw new InvalidOperationException("This property is only for video track.");
148                 }
149
150                 ValidationUtil.ValidateEnum(typeof(WebRTCDisplayMode), value, nameof(value));
151
152                 NativeWebRTC.SetDisplayMode(_webRtc.Handle, _trackId, value).
153                     ThrowIfFailed("Failed to set WebRTC display mode.");
154             }
155         }
156
157         /// <summary>
158         /// Gets or sets the display visibility.
159         /// </summary>
160         /// <value>true if WebRTC display is visible, otherwise false.</value>
161         /// <remarks>
162         /// This property is meaningful only in overlay or EVAS surface display type.
163         /// </remarks>
164         /// <exception cref="InvalidOperationException"><see cref="Display"/> is not set.</exception>
165         /// <since_tizen> 9 </since_tizen>
166         public bool DisplayVisible
167         {
168             get
169             {
170                 if (Type != MediaType.Video)
171                 {
172                     throw new InvalidOperationException("This property is only for video track.");
173                 }
174
175                 NativeWebRTC.GetDisplayVisible(_webRtc.Handle, _trackId, out bool val).
176                     ThrowIfFailed("Failed to get visible status");
177
178                 return val;
179             }
180             set
181             {
182                 if (Type != MediaType.Video)
183                 {
184                     throw new InvalidOperationException("This property is only for video track.");
185                 }
186
187                 NativeWebRTC.SetDisplayVisible(_webRtc.Handle, _trackId, value).
188                     ThrowIfFailed("Failed to set display status.");
189             }
190         }
191
192         /// <summary>
193         /// Gets or sets the mute status of the audio track.
194         /// </summary>
195         /// <value>true if audio is muted, otherwise false. The default value is false.</value>
196         /// <exception cref="ObjectDisposedException">The WebRTC has already been disposed.</exception>
197         /// <exception cref="InvalidOperationException">This MediaStreamTrack is not Audio.</exception>
198         /// <since_tizen> 11 </since_tizen>
199         public bool Mute
200         {
201             get
202             {
203                 if (Type != MediaType.Audio)
204                 {
205                     throw new InvalidOperationException("This property is only for audio track.");
206                 }
207
208                 NativeWebRTC.GetAudioMute(_webRtc.Handle, _trackId, out bool val).
209                     ThrowIfFailed("Failed to get audio mute status");
210
211                 return val;
212             }
213             set
214             {
215                 if (Type != MediaType.Audio)
216                 {
217                     throw new InvalidOperationException("This property is only for audio track.");
218                 }
219
220                 NativeWebRTC.SetAudioMute(_webRtc.Handle, _trackId, value).
221                     ThrowIfFailed("Failed to set audio mute status.");
222             }
223         }
224
225         /// <summary>
226         /// Applies the audio stream policy to remote track.
227         /// </summary>
228         /// <param name="policy">The <see cref="AudioStreamPolicy"/> to apply.</param>
229         /// <remarks>
230         /// This must be called in <see cref="WebRTC.TrackAdded"/> event.<br/>
231         /// <br/>
232         /// <see cref="WebRTC"/> does not support all <see cref="AudioStreamType"/>.<br/>
233         /// Supported types are <see cref="AudioStreamType.Media"/>, <see cref="AudioStreamType.Voip"/>,
234         /// <see cref="AudioStreamType.MediaExternalOnly"/>.
235         /// </remarks>
236         /// <exception cref="ArgumentNullException"><paramref name="policy"/> is null.</exception>
237         /// <exception cref="InvalidOperationException">
238         /// <see cref="WebRTC.AudioFrameEncoded"/> was set.<br/>
239         /// -or-<br/>
240         /// This method was not called in <see cref="WebRTC.TrackAdded"/> event.
241         /// -or-<br/>
242         /// This MediaStreamTrack is not Audio.
243         /// </exception>
244         /// <exception cref="NotSupportedException">
245         ///     <see cref="AudioStreamType"/> of <paramref name="policy"/> is not supported on the current platform.
246         /// </exception>
247         /// <exception cref="ObjectDisposedException">
248         ///     The WebRTC has already been disposed.<br/>
249         ///     -or-<br/>
250         ///     <paramref name="policy"/> has already been disposed.
251         /// </exception>
252         /// <seealso cref="AudioStreamPolicy"/>
253         /// <seealso cref="WebRTC.TrackAdded"/>
254         /// <since_tizen> 9 </since_tizen>
255         public void ApplyAudioStreamPolicy(AudioStreamPolicy policy)
256         {
257             if (policy == null)
258             {
259                 throw new ArgumentNullException(nameof(policy));
260             }
261
262             if (Type != MediaType.Audio)
263             {
264                 throw new InvalidOperationException("This method is only for audio track.");
265             }
266
267             var ret = NativeWebRTC.SetAudioStreamPolicy(_webRtc.Handle, _trackId, policy.Handle);
268
269             if (ret == WebRTCErrorCode.InvalidArgument)
270             {
271                 throw new NotSupportedException("The specified policy is not supported on the current system.");
272             }
273
274             ret.ThrowIfFailed("Failed to set the audio stream policy to the WebRTC");
275         }
276     }
277 }