06dc9cf69f6e84714ba5ac2a873ff06a60d7c60f
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Capture.cs
1 using System.Diagnostics;
2 using System;
3 using System.Drawing;
4 /*
5  * Copyright(c) 2020 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 namespace Tizen.NUI
22 {
23     using global::System;
24     using global::System.ComponentModel;
25     using global::System.Runtime.InteropServices;
26     using global::System.ComponentModel;
27     using Tizen.NUI.BaseComponents;
28
29     /// <summary>
30     /// Capture snapshots the current scene and save as a file.
31     /// Applications should follow the example below to create capture :
32     /// <code>
33     /// Capture capture = new Capture();
34     /// </code>
35     /// If required, you can also subscribe Finished event :
36     /// <code>
37     /// capture.Finished += onCaptureFinished;
38     /// </code>
39     /// At the subcribed event handler, user can know whether capture finish succeeded state.
40     /// <code>
41     /// private void onCaptureFinished(object sender, CaptureFinishedEventArgs e)
42     /// {
43     ///   if(e.Success) { //capture success, do something. }
44     ///   else { //capture failure, do something. }
45     /// }
46     /// </code>
47     /// </summary>
48     [EditorBrowsable(EditorBrowsableState.Never)]
49     public class Capture : BaseHandle
50     {
51         /// <summary>
52         /// Create an Capture.
53         /// </summary>
54         [EditorBrowsable(EditorBrowsableState.Never)]
55         public Capture() : this(Interop.Capture.New(), true)
56         {
57             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
58         }
59
60         internal Capture(IntPtr cPtr, bool cMemoryOwn) : base(Interop.Capture.Upcast(cPtr), cMemoryOwn)
61         {
62         }
63
64         /// <summary>
65         /// Dispose
66         /// </summary>
67         /// <param name="type"></param>
68         [EditorBrowsable(EditorBrowsableState.Never)]
69         protected override void Dispose(DisposeTypes type)
70         {
71             if (disposed)
72             {
73                 return;
74             }
75
76             if (type == DisposeTypes.Explicit)
77             {
78                 //Called by User
79                 //Release your own managed resources here.
80                 //You should release all of your own disposable objects here.
81             }
82
83             base.Dispose(type);
84         }
85
86         /// This will not be public opened.
87         [EditorBrowsable(EditorBrowsableState.Never)]
88         protected override void ReleaseSwigCPtr(HandleRef swigCPtr)
89         {
90             Interop.Capture.Delete(swigCPtr);
91         }
92
93         /// <summary>
94         /// Start capture and save the image as a file.
95         /// </summary>
96         /// <param name="source">source View or Layer to be used for capture.</param>
97         /// <param name="size">captured size.</param>
98         /// <param name="path">image file path to be saved as a file.
99         /// If path is empty string, the captured result is not be saved as a file.</param>
100         /// <param name="color">background color of captured scene.</param>
101         /// <exception cref="InvalidOperationException">This exception can be due to the invalid size values, of when width or height is lower than zero.</exception>
102         /// <exception cref="ArgumentNullException">This exception is due to the path is null.</exception>
103         [EditorBrowsable(EditorBrowsableState.Never)]
104         public void Start(Container source, Size size, string path, Color color)
105         {
106             if (size.Width <= 0 || size.Height <=0)
107             {
108                 throw new InvalidOperationException("size should larger than zero");
109             }
110             else if (null == path)
111             {
112                 throw new ArgumentNullException("path should not be null");
113             }
114
115             if (source is View || source is Layer)
116             {
117                 Interop.Capture.Start1(swigCPtr, source.SwigCPtr, new Vector2(size.Width, size.Height).SwigCPtr, path, new Vector4(color.R, color.G, color.B, color.A).SwigCPtr);
118
119                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
120             }
121         }
122
123         /// <summary>
124         /// Start capture and save the image as a file.
125         /// </summary>
126         /// <remarks>
127         /// Background color of captured scene is transparent.
128         /// </remarks>
129         /// <param name="source">source View or Layer to be used for capture.</param>
130         /// <param name="size">captured size.</param>
131         /// <param name="path">image file path to be saved as a file.
132         /// If path is empty string, the captured result is not be saved as a file.</param>
133         /// <exception cref="InvalidOperationException">This exception can be due to the invalid size values, of when width or height is lower than zero.</exception>
134         /// <exception cref="ArgumentNullException">This exception is due to the path is null.</exception>
135         [EditorBrowsable(EditorBrowsableState.Never)]
136         public void Start(Container source, Size size, string path)
137         {
138             if (size.Width <= 0 || size.Height <=0)
139             {
140                 throw new InvalidOperationException("size should larger than zero");
141             }
142             else if (null == path)
143             {
144                 throw new ArgumentNullException("path should not be null");
145             }
146             
147             if (source is View || source is Layer)
148             {
149                 Interop.Capture.Start2(swigCPtr, source.SwigCPtr, new Vector2(size.Width, size.Height).SwigCPtr, path);
150
151                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
152             }
153         }
154
155         private void onFinished(IntPtr data, int state)
156         {
157             if (data != IntPtr.Zero)
158             {
159                 var arg = new CaptureFinishedEventArgs();
160                 // dali native definition :
161                 // enum class FinishState
162                 // {
163                 //   SUCCEEDED, ///< Succeeded in saving the result after capture
164                 //   FAILED     ///< Failed to capture by time out or to save the result
165                 // };
166                 arg.Success = (state == 0) ? true : false;
167                 finishedEventHandler?.Invoke(this, arg);
168             }
169         }
170
171         private CaptureSignal finishedSignal;
172         private delegate void finishedCallbackType(IntPtr data, int state);
173         private finishedCallbackType finishedCallback;
174         private EventHandler<CaptureFinishedEventArgs> finishedEventHandler;
175
176         /// <summary>
177         /// For subscribing Finished event sent by this class.
178         /// </summary>
179         [EditorBrowsable(EditorBrowsableState.Never)]
180         public event EventHandler<CaptureFinishedEventArgs> Finished
181         {
182             add
183             {
184                 if (finishedEventHandler == null && disposed == false)
185                 {
186                     finishedSignal = new CaptureSignal(Interop.Capture.Get(swigCPtr), false);
187                     finishedCallback = onFinished;
188                     finishedSignal.Connect(finishedCallback);
189                 }
190                 finishedEventHandler += value;
191             }
192             remove
193             {
194                 finishedEventHandler -= value;
195
196                 if (finishedEventHandler == null && finishedSignal?.Empty() == false)
197                 {
198                     finishedCallback = onFinished;
199                     finishedSignal.Disconnect(finishedCallback);
200                 }
201             }
202         }
203
204         /// <summary>
205         /// Get NativeImageSource that is saved captured image.
206         /// </summary>
207         /// <returns>NativeImageSource that is saved captured image.</returns>
208         [EditorBrowsable(EditorBrowsableState.Never)]
209         public NativeImageSource GetNativeImageSource()
210         {
211             Tizen.Log.Debug("NUI", $"GetNativeImageSource()");
212             return new NativeImageSource(Interop.Capture.GetNativeImageSourcePtr(swigCPtr), true);
213         }
214
215         /// <summary>
216         /// Generate captured image's Url
217         /// </summary>
218         /// <returns>The Url string representing this captured image source</returns>
219         [EditorBrowsable(EditorBrowsableState.Never)]
220         public string GenerateUrl()
221         {
222             string url = "";
223             url = Interop.Capture.GenerageUrl(swigCPtr);
224             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
225             return url;
226         }
227
228     }
229
230     /// <summary>
231     /// CaptureFinishedEventArgs
232     /// </summary>
233     [EditorBrowsable(EditorBrowsableState.Never)]
234     public class CaptureFinishedEventArgs : EventArgs
235     {
236         /// <summary>
237         /// Status of saving the result after capture.
238         /// </summary>
239         /// <value>
240         /// true when succeeded in saving the result after capture.
241         /// false when failed to capture by time out or to save the result.
242         /// </value>
243         public bool Success { get; internal set; }
244     }
245
246     internal class CaptureSignal : Disposable
247     {
248         internal CaptureSignal(IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
249         {
250         }
251
252         protected override void ReleaseSwigCPtr(HandleRef swigCPtr)
253         {
254             if (swigCMemOwn)
255             {
256                 Interop.Capture.DeleteSignal(swigCPtr);
257             }
258         }
259
260         public bool Empty()
261         {
262             bool ret = Interop.Capture.SignalEmpty(swigCPtr);
263             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
264             return ret;
265         }
266
267         public uint GetConnectionCount()
268         {
269             uint ret = Interop.Capture.SignalGetConnectionCount(swigCPtr);
270             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
271             return ret;
272         }
273
274         public void Connect(Delegate func)
275         {
276             IntPtr ip = Marshal.GetFunctionPointerForDelegate<Delegate>(func);
277             {
278                 Interop.Capture.SignalConnect(swigCPtr, new HandleRef(this, ip));
279                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
280             }
281         }
282
283         public void Disconnect(Delegate func)
284         {
285             IntPtr ip = Marshal.GetFunctionPointerForDelegate<Delegate>(func);
286             {
287                 Interop.Capture.SignalDisconnect(swigCPtr, new HandleRef(this, ip));
288                 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
289             }
290         }
291
292         public void Emit(Capture src, bool success)
293         {
294             Interop.Capture.SignalEmit(swigCPtr, src.SwigCPtr, (success ? 0 : 1));
295             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
296         }
297     }
298 }