[Sensor] Add orientation sensor type
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Camera / Camera / Camera.Events.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
17 using System;
18 using System.ComponentModel;
19 using Native = Interop.Camera;
20
21 namespace Tizen.Multimedia
22 {
23     /// <summary>
24     /// This camera class provides methods to capture photos and supports setting up notifications
25     /// for state changes of capturing, previewing, focusing, and informing about the resolution and the binary format,
26     /// and functions for picture manipulations like sepia, negative, and many more.
27     /// It also notifies you when a significant picture parameter changes, (For example, focus).
28     /// </summary>
29     /// <since_tizen> 3 </since_tizen>
30     /// <feature> http://tizen.org/feature/camera </feature>
31     public partial class Camera : IDisposable, IDisplayable<CameraError>
32     {
33         /// <summary>
34         /// An event that occurs when the camera interrupt is started by the policy.
35         /// </summary>
36         /// <since_tizen> 4 </since_tizen>
37         public event EventHandler<CameraInterruptStartedEventArgs> InterruptStarted;
38         private Native.InterruptStartedCallback _interruptStartedCallback;
39
40         /// <summary>
41         /// An event that occurs when an camera is interrupted by the policy.
42         /// </summary>
43         /// <since_tizen> 3 </since_tizen>
44         public event EventHandler<CameraInterruptedEventArgs> Interrupted;
45         private Native.InterruptedCallback _interruptedCallback;
46
47         /// <summary>
48         /// An event that occurs when there is an asynchronous error.
49         /// </summary>
50         /// <since_tizen> 3 </since_tizen>
51         public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
52         private Native.ErrorCallback _errorCallback;
53
54         /// <summary>
55         /// An event that occurs when the auto focus state is changed.
56         /// </summary>
57         /// <since_tizen> 3 </since_tizen>
58         public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
59         private Native.FocusStateChangedCallback _focusStateChangedCallback;
60
61         /// <summary>
62         /// An event that occurs when a face is detected in the preview frame.
63         /// </summary>
64         /// <since_tizen> 3 </since_tizen>
65         public event EventHandler<FaceDetectedEventArgs> FaceDetected;
66         private Native.FaceDetectedCallback _faceDetectedCallback;
67
68         /// <summary>
69         /// An event that occurs during capture of an image.
70         /// </summary>
71         /// <since_tizen> 3 </since_tizen>
72         public event EventHandler<CameraCapturingEventArgs> Capturing;
73         private Native.CapturingCallback _capturingCallback;
74
75         /// <summary>
76         /// An event that occurs after the capture of the image.
77         /// </summary>
78         /// <since_tizen> 3 </since_tizen>
79         public event EventHandler<EventArgs> CaptureCompleted;
80         private Native.CaptureCompletedCallback _captureCompletedCallback;
81
82         private Native.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
83         private event EventHandler<HdrCaptureProgressEventArgs> _hdrCaptureProgress;
84         private object _hdrCaptureProgressEventLock = new object();
85
86         /// <summary>
87         /// An event that occurs when there is a change in the HDR capture progress.
88         /// Checks whether the <see cref="CameraCapabilities.IsHdrCaptureSupported"/> is supported or not before adding this EventHandler.
89         /// </summary>
90         /// <since_tizen> 3 </since_tizen>
91         /// <exception cref="NotSupportedException">In case of HDR feature is not supported.</exception>
92         public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress
93         {
94             add
95             {
96                 lock (_hdrCaptureProgressEventLock)
97                 {
98                     if (_hdrCaptureProgress == null)
99                     {
100                         RegisterHdrCaptureProgress();
101                     }
102
103                     _hdrCaptureProgress += value;
104                 }
105             }
106
107             remove
108             {
109                 lock (_hdrCaptureProgressEventLock)
110                 {
111                     _hdrCaptureProgress -= value;
112
113                     if (_hdrCaptureProgress == null)
114                     {
115                         UnregisterHdrCaptureProgress();
116                     }
117                 }
118             }
119         }
120
121         /// <summary>
122         /// An event that occurs when the camera state is changed.
123         /// </summary>
124         /// <since_tizen> 3 </since_tizen>
125         public event EventHandler<CameraStateChangedEventArgs> StateChanged;
126         private Native.StateChangedCallback _stateChangedCallback;
127
128         private static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
129         private static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
130         private static object _deviceStateChangedEventLock = new object();
131         private static int _deviceStateCallbackId;
132
133         /// <summary>
134         /// An event that occurs after the <see cref="CameraDeviceState"/> is changed.
135         /// </summary>
136         /// <since_tizen> 3 </since_tizen>
137         /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
138         /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
139         /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
140         public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
141         {
142             add
143             {
144                 lock (_deviceStateChangedEventLock)
145                 {
146                     if (_deviceStateChanged == null)
147                     {
148                         RegisterDeviceStateChangedCallback();
149                     }
150
151                     _deviceStateChanged += value;
152                 }
153             }
154
155             remove
156             {
157                 lock (_deviceStateChangedEventLock)
158                 {
159                     _deviceStateChanged -= value;
160
161                     if (_deviceStateChanged == null)
162                     {
163                         UnregisterDeviceStateChangedCallback();
164                     }
165                 }
166             }
167         }
168
169         private Native.PreviewCallback _previewCallback;
170         private event EventHandler<PreviewEventArgs> _preview;
171         private object _previewEventLock = new object();
172         /// <summary>
173         /// An event that occurs once per frame when previewing.
174         /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
175         /// </summary>
176         /// <since_tizen> 3 </since_tizen>
177         public event EventHandler<PreviewEventArgs> Preview
178         {
179             add
180             {
181                 lock (_previewEventLock)
182                 {
183                     if (_preview == null)
184                     {
185                         RegisterPreviewCallback();
186                     }
187
188                     _preview += value;
189                 }
190             }
191
192             remove
193             {
194                 lock (_previewEventLock)
195                 {
196                     _preview -= value;
197
198                     if (_preview == null)
199                     {
200                         UnregisterPreviewCallback();
201                     }
202                 }
203             }
204         }
205
206         private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
207         private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
208         private object _mediaPacketPreviewEventLock = new object();
209
210         /// <summary>
211         /// An event that occurs once per frame when previewing.
212         /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
213         /// </summary>
214         /// <since_tizen> 3 </since_tizen>
215         public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
216         {
217             add
218             {
219                 lock (_mediaPacketPreviewEventLock)
220                 {
221                     if (_mediaPacketPreview == null)
222                     {
223                         RegisterMediaPacketPreviewCallback();
224                     }
225
226                     _mediaPacketPreview += value;
227                 }
228             }
229
230             remove
231             {
232                 lock (_mediaPacketPreviewEventLock)
233                 {
234                     _mediaPacketPreview -= value;
235
236                     if (_mediaPacketPreview == null)
237                     {
238                         UnregisterMediaPacketPreviewCallback();
239                     }
240                 }
241             }
242         }
243
244         private Native.ExtraPreviewCallback _extraPreviewCallback;
245         private event EventHandler<ExtraPreviewEventArgs> _extraPreview;
246         /// <summary>
247         /// An event that occurs once per frame when previewing.
248         /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
249         /// </summary>
250         /// <since_tizen> 9 </since_tizen>
251         [EditorBrowsable(EditorBrowsableState.Never)]
252         public event EventHandler<ExtraPreviewEventArgs> ExtraPreview
253         {
254             add
255             {
256                 if (_extraPreview == null)
257                 {
258                     RegisterExtraPreviewCallback();
259                 }
260
261                 _extraPreview += value;
262             }
263
264             remove
265             {
266                 _extraPreview -= value;
267
268                 if (_extraPreview == null)
269                 {
270                     UnregisterExtraPreviewCallback();
271                 }
272             }
273         }
274
275         private void RegisterCallbacks()
276         {
277             RegisterErrorCallback();
278             RegisterFocusStateChanged();
279             RegisterInterruptStartedCallback();
280             RegisterInterruptedCallback();
281             RegisterStateChangedCallback();
282
283             //Define capturing callback
284             _capturingCallback = (main, postview, thumbnail, userData) =>
285             {
286                 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
287                     postview == IntPtr.Zero ? null : new StillImage(postview),
288                     thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
289             };
290
291             //Define captureCompleted callback
292             _captureCompletedCallback = _ =>
293             {
294                 SetState(CameraState.Captured);
295                 CaptureCompleted?.Invoke(this, EventArgs.Empty);
296             };
297         }
298
299         private void RegisterInterruptStartedCallback()
300         {
301             _interruptStartedCallback = (policy, state, _) =>
302             {
303                 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
304             };
305
306             Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback).
307                 ThrowIfFailed("Failed to set interrupt callback.");
308         }
309
310         private void RegisterInterruptedCallback()
311         {
312             _interruptedCallback = (policy, previous, current, _) =>
313             {
314                 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
315             };
316
317             Native.SetInterruptedCallback(_handle, _interruptedCallback).
318                 ThrowIfFailed("Failed to set interrupt callback.");
319         }
320
321         private void RegisterErrorCallback()
322         {
323             _errorCallback = (error, current, _) =>
324             {
325                 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
326             };
327
328             Native.SetErrorCallback(_handle, _errorCallback).
329                 ThrowIfFailed("Setting error callback failed");
330         }
331
332         private void RegisterStateChangedCallback()
333         {
334             _stateChangedCallback = (previous, current, byPolicy, _) =>
335             {
336                 SetState(current);
337                 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
338                 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
339             };
340
341             Native.SetStateChangedCallback(_handle, _stateChangedCallback).
342                 ThrowIfFailed("Failed to set state changed callback.");
343         }
344
345         private static void RegisterDeviceStateChangedCallback()
346         {
347             _deviceStateChangedCallback = (device, state, _) =>
348             {
349                 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
350             };
351
352             Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId).
353                 ThrowIfFailed("Failed to set device state changed callback.");
354
355             Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
356         }
357
358         private static void UnregisterDeviceStateChangedCallback()
359         {
360             Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId).
361                 ThrowIfFailed("Failed to unset device state changed callback.");
362
363             _deviceStateChangedCallback = null;
364             _deviceStateCallbackId = 0;
365         }
366
367         private void RegisterFocusStateChanged()
368         {
369             _focusStateChangedCallback = (state, _) =>
370             {
371                 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
372             };
373
374             Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback).
375                 ThrowIfFailed("Failed to set focus changed callback.");
376         }
377
378         private void RegisterHdrCaptureProgress()
379         {
380             _hdrCaptureProgressCallback = (percent, _) =>
381             {
382                 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
383             };
384
385             Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback).
386                 ThrowIfFailed("Failed to set Hdr capture progress callback.");
387         }
388
389         private void UnregisterHdrCaptureProgress()
390         {
391             Native.UnsetHdrCaptureProgressCallback(_handle).
392                 ThrowIfFailed("Failed to unset hdr capture progres callback.");
393
394             _hdrCaptureProgressCallback = null;
395         }
396
397         private void RegisterPreviewCallback()
398         {
399             _previewCallback = (frame, _) =>
400             {
401                 _preview?.Invoke(this,
402                     new PreviewEventArgs(new PreviewFrame(frame, ref _previewBuffer)));
403             };
404
405             Native.SetPreviewCallback(_handle, _previewCallback).
406                 ThrowIfFailed("Failed to set preview callback.");
407         }
408
409         private void UnregisterPreviewCallback()
410         {
411             Native.UnsetPreviewCallback(_handle).
412                 ThrowIfFailed("Failed to unset preview callback.");
413
414             _previewCallback = null;
415         }
416
417         private void RegisterMediaPacketPreviewCallback()
418         {
419             _mediaPacketPreviewCallback = (mediaPacket, _) =>
420             {
421                 MediaPacket packet = MediaPacket.From(mediaPacket);
422
423                 var eventHandler = _mediaPacketPreview;
424
425                 if (eventHandler != null)
426                 {
427                     eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
428                 }
429
430                 packet.Dispose();
431             };
432
433             Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback).
434                 ThrowIfFailed("Failed to set media packet preview callback.");
435         }
436
437         private void UnregisterMediaPacketPreviewCallback()
438         {
439             Native.UnsetMediaPacketPreviewCallback(_handle).
440                 ThrowIfFailed("Failed to unset media packet preview callback.");
441
442             _mediaPacketPreviewCallback = null;
443         }
444
445         private void RegisterExtraPreviewCallback()
446         {
447             _extraPreviewCallback = (frame, streamId, _) =>
448             {
449                 _extraPreview?.Invoke(this,
450                     new ExtraPreviewEventArgs(new PreviewFrame(frame, ref _previewBuffer), streamId));
451             };
452
453             Native.SetExtraPreviewCallback(_handle, _extraPreviewCallback).
454                 ThrowIfFailed("Failed to set extra preview callback.");
455         }
456
457         private void UnregisterExtraPreviewCallback()
458         {
459             Native.UnsetExtraPreviewCallback(_handle).
460                 ThrowIfFailed("Failed to unset extra preview callback.");
461
462             _extraPreviewCallback = null;
463         }
464     }
465 }