[Multimedia] Fix rotation issue for portrait mode (#5105)
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia / Common / Display.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 ElmSharp;
18
19 namespace Tizen.Multimedia
20 {
21     internal enum DisplayType
22     {
23         /// <summary>
24         /// Overlay surface display.
25         /// </summary>
26         Overlay,
27
28         /// <summary>
29         ///  Evas image object surface display.
30         /// </summary>
31         Surface,
32
33         /// <summary>
34         /// This disposes off buffers.
35         /// </summary>
36         None,
37     }
38
39     internal interface IDisplayable<TError>
40     {
41         TError ApplyEvasDisplay(DisplayType type, EvasObject evasObject);
42         TError ApplyEcoreWindow(IntPtr windowHandle, Rectangle rect, Rotation rotation);
43     }
44
45     internal interface IDisplaySetter
46     {
47         TError SetDisplay<TError>(IDisplayable<TError> target);
48     }
49
50     internal class EvasDisplaySetter : IDisplaySetter
51     {
52         private readonly DisplayType _type;
53         private readonly EvasObject _target;
54
55         internal EvasDisplaySetter(DisplayType type, EvasObject target)
56         {
57             if (target == IntPtr.Zero)
58             {
59                 throw new ArgumentException("The evas object is not realized.");
60             }
61
62             _type = type;
63             _target = target;
64         }
65
66         public TError SetDisplay<TError>(IDisplayable<TError> target)
67         {
68             return target.ApplyEvasDisplay(_type, _target);
69         }
70     }
71
72     internal class EcoreDisplaySetter : IDisplaySetter
73     {
74         private readonly IntPtr _windowHandle;
75         private readonly Rectangle _rect;
76         private readonly Rotation _rotation;
77
78         internal EcoreDisplaySetter(IntPtr windowHandle, Rectangle rect, Rotation rotation)
79         {
80             _windowHandle = windowHandle;
81             _rect = rect;
82             _rotation = rotation;
83         }
84
85         public TError SetDisplay<TError>(IDisplayable<TError> target)
86         {
87             return target.ApplyEcoreWindow(_windowHandle, _rect, _rotation);
88         }
89     }
90
91     /// <summary>
92     /// Provides a means to wrap various display types.
93     /// </summary>
94     /// <seealso cref="T:Tizen.Multimedia.Player"/>
95     /// <seealso cref="T:Tizen.Multimedia.Camera"/>
96     /// <seealso cref="T:Tizen.Multimedia.Remoting.ScreenMirroring"/>
97     /// <since_tizen> 3 </since_tizen>
98     public class Display
99     {
100         private readonly IDisplaySetter _setter;
101
102         /// <summary>
103         /// Initializes a new instance of the <see cref="Display"/> class with a <see cref="MediaView"/> class.
104         /// </summary>
105         /// <param name="mediaView">A <see cref="MediaView"/> to display.</param>
106         /// <since_tizen> 3 </since_tizen>
107         [Obsolete("Deprecated in API10; Will be removed in API12")]
108         public Display(MediaView mediaView)
109         {
110             if (mediaView == null)
111             {
112                 throw new ArgumentNullException(nameof(mediaView));
113             }
114
115             _setter = new EvasDisplaySetter(DisplayType.Surface, mediaView);
116
117             HasMediaView = true;
118         }
119
120         /// <summary>
121         /// Initializes a new instance of the <see cref="Display"/> class with a <see cref="Window"/> class.
122         /// </summary>
123         /// <param name="window">A <see cref="Window"/> to display.</param>
124         /// <since_tizen> 3 </since_tizen>
125         [Obsolete("Deprecated in API10; Will be removed in API12")]
126         public Display(Window window)
127         {
128             if (window == null)
129             {
130                 throw new ArgumentNullException(nameof(window));
131             }
132
133             _setter = new EvasDisplaySetter(DisplayType.Overlay, window);
134         }
135
136         /// <summary>
137         /// Initializes a new instance of the <see cref="Display"/> class with a <see cref="NUI.Window"/> class.
138         /// </summary>
139         /// <param name="window">A <see cref="NUI.Window"/> to display.</param>
140         /// <remarks>
141         /// The <see cref="NUI.Window.BackgroundColor"/> must be <see cref="NUI.Color.Transparent"/>
142         /// for the <see cref="Display"/> to be rendered correctly.
143         /// </remarks>
144         /// <since_tizen> 3 </since_tizen>
145         public Display(NUI.Window window)
146             : this (window, false)
147         {
148         }
149
150         /// <summary>
151         /// Initializes a new instance of the <see cref="Display"/> class with a <see cref="NUI.Window"/> class.
152         /// </summary>
153         /// <param name="window">A <see cref="NUI.Window"/> to display.</param>
154         /// <param name="uiSync">A value indicates whether video and UI is in sync or not.</param>
155         /// <remarks>
156         /// The <see cref="NUI.Window.BackgroundColor"/> must be <see cref="NUI.Color.Transparent"/>
157         /// for the <see cref="Display"/> to be rendered correctly.<br/>
158         /// UI sync is only for <see cref="T:Tizen.Multimedia.Player"/> and
159         /// <see cref="T:Tizen.Multimedia.Player.DisplaySettings"/> will not work in UI sync mode.
160         /// </remarks>
161         /// <since_tizen> 9 </since_tizen>
162         public Display(NUI.Window window, bool uiSync)
163         {
164             if (window == null)
165             {
166                 throw new ArgumentNullException(nameof(window));
167             }
168
169             var windowSize = new Rectangle(window.WindowPositionSize.X, window.WindowPositionSize.Y,
170                 window.WindowPositionSize.Width, window.WindowPositionSize.Height);
171
172             _setter = new EcoreDisplaySetter(window.GetNativeWindowHandler(), windowSize, window.GetCurrentOrientation().ToMmRotation());
173
174             UiSync = uiSync;
175         }
176
177         private EvasObject EvasObject { get; }
178
179         private DisplayType Type { get; }
180
181         private object _owner;
182
183         internal bool HasMediaView { get; } = false;
184
185         internal bool UiSync { get; } = false;
186
187         internal object Owner => _owner;
188
189         internal void SetOwner(object newOwner)
190         {
191             if (_owner != null && newOwner != null)
192             {
193                 throw new ArgumentException("The display has already been assigned to another.");
194             }
195
196             _owner = newOwner;
197         }
198
199         internal TError ApplyTo<TError>(IDisplayable<TError> target)
200         {
201             return _setter.SetDisplay(target);
202         }
203     }
204
205     internal static class WindowOrientationExtension
206     {
207         internal static Tizen.Multimedia.Rotation ToMmRotation(this NUI.Window.WindowOrientation rotation)
208         {
209             switch (rotation)
210             {
211                 case NUI.Window.WindowOrientation.Portrait:
212                     return Tizen.Multimedia.Rotation.Rotate0;
213                 case NUI.Window.WindowOrientation.Landscape:
214                     return Tizen.Multimedia.Rotation.Rotate90;
215                 case NUI.Window.WindowOrientation.PortraitInverse:
216                     return Tizen.Multimedia.Rotation.Rotate180;
217                 case NUI.Window.WindowOrientation.LandscapeInverse:
218                     return Tizen.Multimedia.Rotation.Rotate270;
219                 default:
220                     break;
221             }
222
223             return Tizen.Multimedia.Rotation.Rotate90;
224         }
225     }
226 }