[Camera] Hide CDM interface from user (#3146)
[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         /// <summary>
276         /// An event that occurs when there is a change in the camera device list.
277         /// </summary>
278         /// <since_tizen> 9 </since_tizen>
279         [EditorBrowsable(EditorBrowsableState.Never)]
280         public event EventHandler<CameraDeviceListChangedEventArgs> CameraDeviceListChanged;
281
282         private void RegisterCallbacks()
283         {
284             RegisterErrorCallback();
285             RegisterFocusStateChanged();
286             RegisterInterruptStartedCallback();
287             RegisterInterruptedCallback();
288             RegisterStateChangedCallback();
289
290             //Define capturing callback
291             _capturingCallback = (main, postview, thumbnail, userData) =>
292             {
293                 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
294                     postview == IntPtr.Zero ? null : new StillImage(postview),
295                     thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
296             };
297
298             //Define captureCompleted callback
299             _captureCompletedCallback = _ =>
300             {
301                 SetState(CameraState.Captured);
302                 CaptureCompleted?.Invoke(this, EventArgs.Empty);
303             };
304         }
305
306         private void RegisterInterruptStartedCallback()
307         {
308             _interruptStartedCallback = (policy, state, _) =>
309             {
310                 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
311             };
312
313             Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback).
314                 ThrowIfFailed("Failed to set interrupt callback.");
315         }
316
317         private void RegisterInterruptedCallback()
318         {
319             _interruptedCallback = (policy, previous, current, _) =>
320             {
321                 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
322             };
323
324             Native.SetInterruptedCallback(_handle, _interruptedCallback).
325                 ThrowIfFailed("Failed to set interrupt callback.");
326         }
327
328         private void RegisterErrorCallback()
329         {
330             _errorCallback = (error, current, _) =>
331             {
332                 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
333             };
334
335             Native.SetErrorCallback(_handle, _errorCallback).
336                 ThrowIfFailed("Setting error callback failed");
337         }
338
339         private void RegisterStateChangedCallback()
340         {
341             _stateChangedCallback = (previous, current, byPolicy, _) =>
342             {
343                 SetState(current);
344                 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
345                 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
346             };
347
348             Native.SetStateChangedCallback(_handle, _stateChangedCallback).
349                 ThrowIfFailed("Failed to set state changed callback.");
350         }
351
352         private static void RegisterDeviceStateChangedCallback()
353         {
354             _deviceStateChangedCallback = (device, state, _) =>
355             {
356                 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
357             };
358
359             Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId).
360                 ThrowIfFailed("Failed to set device state changed callback.");
361
362             Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
363         }
364
365         private static void UnregisterDeviceStateChangedCallback()
366         {
367             Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId).
368                 ThrowIfFailed("Failed to unset device state changed callback.");
369
370             _deviceStateChangedCallback = null;
371             _deviceStateCallbackId = 0;
372         }
373
374         private void RegisterFocusStateChanged()
375         {
376             _focusStateChangedCallback = (state, _) =>
377             {
378                 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
379             };
380
381             Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback).
382                 ThrowIfFailed("Failed to set focus changed callback.");
383         }
384
385         private void RegisterHdrCaptureProgress()
386         {
387             _hdrCaptureProgressCallback = (percent, _) =>
388             {
389                 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
390             };
391
392             Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback).
393                 ThrowIfFailed("Failed to set Hdr capture progress callback.");
394         }
395
396         private void UnregisterHdrCaptureProgress()
397         {
398             Native.UnsetHdrCaptureProgressCallback(_handle).
399                 ThrowIfFailed("Failed to unset hdr capture progres callback.");
400
401             _hdrCaptureProgressCallback = null;
402         }
403
404         private void RegisterPreviewCallback()
405         {
406             _previewCallback = (frame, _) =>
407             {
408                 _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
409             };
410
411             Native.SetPreviewCallback(_handle, _previewCallback).
412                 ThrowIfFailed("Failed to set preview callback.");
413         }
414
415         private void UnregisterPreviewCallback()
416         {
417             Native.UnsetPreviewCallback(_handle).
418                 ThrowIfFailed("Failed to unset preview callback.");
419
420             _previewCallback = null;
421         }
422
423         private void RegisterMediaPacketPreviewCallback()
424         {
425             _mediaPacketPreviewCallback = (mediaPacket, _) =>
426             {
427                 MediaPacket packet = MediaPacket.From(mediaPacket);
428
429                 var eventHandler = _mediaPacketPreview;
430
431                 if (eventHandler != null)
432                 {
433                     eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
434                 }
435
436                 packet.Dispose();
437             };
438
439             Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback).
440                 ThrowIfFailed("Failed to set media packet preview callback.");
441         }
442
443         private void UnregisterMediaPacketPreviewCallback()
444         {
445             Native.UnsetMediaPacketPreviewCallback(_handle).
446                 ThrowIfFailed("Failed to unset media packet preview callback.");
447
448             _mediaPacketPreviewCallback = null;
449         }
450
451         private void RegisterExtraPreviewCallback()
452         {
453             _extraPreviewCallback = (frame, streamId, _) =>
454             {
455                 _extraPreview?.Invoke(this, new ExtraPreviewEventArgs(new PreviewFrame(frame), streamId));
456             };
457
458             Native.SetExtraPreviewCallback(_handle, _extraPreviewCallback).
459                 ThrowIfFailed("Failed to set extra preview callback.");
460         }
461
462         private void UnregisterExtraPreviewCallback()
463         {
464             Native.UnsetPreviewCallback(_handle).
465                 ThrowIfFailed("Failed to unset preview callback.");
466
467             _extraPreviewCallback = null;
468         }
469     }
470 }