1 /*
2  * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "camera_napi_param_parser.h"
17 #include "camera_napi_security_utils.h"
18 #include "capture_session.h"
19 #include "mode/light_painting_session_napi.h"
20 
21 namespace OHOS {
22 namespace CameraStandard {
23 using namespace std;
24 
25 thread_local napi_ref LightPaintingSessionNapi::sConstructor_ = nullptr;
26 
LightPaintingSessionNapi()27 LightPaintingSessionNapi::LightPaintingSessionNapi() : env_(nullptr), wrapper_(nullptr)
28 {
29 }
~LightPaintingSessionNapi()30 LightPaintingSessionNapi::~LightPaintingSessionNapi()
31 {
32     MEDIA_INFO_LOG("~LightPaintingSessionNapi is called");
33     if (wrapper_ != nullptr) {
34         napi_delete_reference(env_, wrapper_);
35     }
36     if (lightPaintingSession_) {
37         lightPaintingSession_ = nullptr;
38     }
39 }
LightPaintingSessionNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)40 void LightPaintingSessionNapi::LightPaintingSessionNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
41 {
42     MEDIA_INFO_LOG("LightPaintingSessionNapiDestructor is called");
43     LightPaintingSessionNapi* cameraObj = reinterpret_cast<LightPaintingSessionNapi*>(nativeObject);
44     if (cameraObj != nullptr) {
45         delete cameraObj;
46     }
47 }
Init(napi_env env,napi_value exports)48 napi_value LightPaintingSessionNapi::Init(napi_env env, napi_value exports)
49 {
50     MEDIA_INFO_LOG("Init is called");
51     napi_status status;
52     napi_value ctorObj;
53     std::vector<napi_property_descriptor> light_painting_props = {
54         DECLARE_NAPI_FUNCTION("getSupportedLightPaintingTypes", GetSupportedLightPaintings),
55         DECLARE_NAPI_FUNCTION("getLightPaintingType", GetLightPainting),
56         DECLARE_NAPI_FUNCTION("setLightPaintingType", SetLightPainting),
57         DECLARE_NAPI_FUNCTION("getSupportedLightPaintings", GetSupportedLightPaintings),
58         DECLARE_NAPI_FUNCTION("getLightPainting", GetLightPainting),
59         DECLARE_NAPI_FUNCTION("setLightPainting", SetLightPainting),
60         DECLARE_NAPI_FUNCTION("triggerLighting", TriggerLighting)
61     };
62     std::vector<std::vector<napi_property_descriptor>> descriptors = {camera_process_props,
63         color_effect_props, focus_props, manual_focus_props, zoom_props, flash_props, light_painting_props};
64     std::vector<napi_property_descriptor> light_painting_session_props =
65         CameraNapiUtils::GetPropertyDescriptor(descriptors);
66     status = napi_define_class(env, LIGHT_PAINTING_SESSION_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
67                                LightPaintingSessionNapiConstructor, nullptr,
68                                light_painting_session_props.size(),
69                                light_painting_session_props.data(), &ctorObj);
70     if (status == napi_ok) {
71         int32_t refCount = 1;
72         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
73         if (status == napi_ok) {
74             status = napi_set_named_property(env, exports, LIGHT_PAINTING_SESSION_NAPI_CLASS_NAME, ctorObj);
75             if (status == napi_ok) {
76                 return exports;
77             }
78         }
79     }
80     MEDIA_ERR_LOG("Init call Failed!");
81     return nullptr;
82 }
83 
CreateCameraSession(napi_env env)84 napi_value LightPaintingSessionNapi::CreateCameraSession(napi_env env)
85 {
86     MEDIA_INFO_LOG("CreateCameraSession is called");
87     CAMERA_SYNC_TRACE;
88     napi_status status;
89     napi_value result = nullptr;
90     napi_value constructor;
91     status = napi_get_reference_value(env, sConstructor_, &constructor);
92     if (status == napi_ok) {
93         sCameraSession_ = CameraManager::GetInstance()->CreateCaptureSession(SceneMode::LIGHT_PAINTING);
94         if (sCameraSession_ == nullptr) {
95             MEDIA_ERR_LOG("Failed to create light painting session instance");
96             napi_get_undefined(env, &result);
97             return result;
98         }
99         status = napi_new_instance(env, constructor, 0, nullptr, &result);
100         sCameraSession_ = nullptr;
101         if (status == napi_ok && result != nullptr) {
102             MEDIA_DEBUG_LOG("success to create light painting session napi instance");
103             return result;
104         } else {
105             MEDIA_ERR_LOG("Failed to create light painting session napi instance");
106         }
107     } else {
108         MEDIA_ERR_LOG("Failed to create napi reference value instance");
109     }
110     MEDIA_ERR_LOG("Failed to create light painting session napi instance last");
111     napi_get_undefined(env, &result);
112     return result;
113 }
114 
LightPaintingSessionNapiConstructor(napi_env env,napi_callback_info info)115 napi_value LightPaintingSessionNapi::LightPaintingSessionNapiConstructor(napi_env env, napi_callback_info info)
116 {
117     MEDIA_INFO_LOG("LightPaintingSessionNapiConstructor is called");
118     napi_status status;
119     napi_value result = nullptr;
120     napi_value thisVar = nullptr;
121 
122     napi_get_undefined(env, &result);
123     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
124 
125     if (status == napi_ok && thisVar != nullptr) {
126         std::unique_ptr<LightPaintingSessionNapi> obj = std::make_unique<LightPaintingSessionNapi>();
127         obj->env_ = env;
128         if (sCameraSession_ == nullptr) {
129             MEDIA_ERR_LOG("sCameraSession_ is null");
130             return result;
131         }
132         obj->lightPaintingSession_ = static_cast<LightPaintingSession*>(sCameraSession_.GetRefPtr());
133         obj->cameraSession_ = obj->lightPaintingSession_;
134         if (obj->lightPaintingSession_ == nullptr) {
135             MEDIA_ERR_LOG("lightPaintingSession_ is null");
136             return result;
137         }
138         status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
139             LightPaintingSessionNapi::LightPaintingSessionNapiDestructor, nullptr, nullptr);
140         if (status == napi_ok) {
141             obj.release();
142             return thisVar;
143         } else {
144             MEDIA_ERR_LOG("LightPaintingSessionNapi Failure wrapping js to native napi");
145         }
146     }
147     MEDIA_ERR_LOG("LightPaintingSessionNapi call Failed!");
148     return result;
149 }
150 
GetSupportedLightPaintings(napi_env env,napi_callback_info info)151 napi_value LightPaintingSessionNapi::GetSupportedLightPaintings(napi_env env, napi_callback_info info)
152 {
153     if (!CameraNapiSecurity::CheckSystemApp(env)) {
154         MEDIA_ERR_LOG("SystemApi GetSupportedLightPaintings is called!");
155         return nullptr;
156     }
157     MEDIA_INFO_LOG("GetSupportedLightPaintings is called");
158     napi_status status;
159     auto result = CameraNapiUtils::GetUndefinedValue(env);
160 
161     LightPaintingSessionNapi* lightPaintingSessionNapi = nullptr;
162     CameraNapiParamParser jsParamParser(env, info, lightPaintingSessionNapi);
163     if (lightPaintingSessionNapi->lightPaintingSession_ == nullptr) {
164         MEDIA_ERR_LOG("GetSupportedLightPaintings get native object fail");
165         CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT, "get native object fail");
166         return result;
167     }
168     status = napi_create_array(env, &result);
169     std::vector<LightPaintingType> lightPaintingTypes;
170     int32_t retCode = lightPaintingSessionNapi->lightPaintingSession_->GetSupportedLightPaintings(lightPaintingTypes);
171     if (!CameraNapiUtils::CheckError(env, retCode)) {
172         MEDIA_ERR_LOG("GetSupportedLightPaintings fail %{public}d", retCode);
173         return nullptr;
174     }
175     if (!lightPaintingTypes.empty() && status == napi_ok) {
176         for (size_t i = 0; i < lightPaintingTypes.size(); i++) {
177             int lightPaintingType = lightPaintingTypes[i];
178             napi_value value;
179             napi_create_int32(env, lightPaintingType, &value);
180             napi_set_element(env, result, i, value);
181         }
182     }
183     return result;
184 }
185 
GetLightPainting(napi_env env,napi_callback_info info)186 napi_value LightPaintingSessionNapi::GetLightPainting(napi_env env, napi_callback_info info)
187 {
188     if (!CameraNapiSecurity::CheckSystemApp(env)) {
189         MEDIA_ERR_LOG("SystemApi GetSupportedLightPaintings is called!");
190         return nullptr;
191     }
192     MEDIA_INFO_LOG("GetLightPainting is called");
193     napi_status status;
194     auto result = CameraNapiUtils::GetUndefinedValue(env);
195 
196     LightPaintingSessionNapi* lightPaintingSessionNapi = nullptr;
197     CameraNapiParamParser jsParamParser(env, info, lightPaintingSessionNapi);
198     if (lightPaintingSessionNapi->lightPaintingSession_ == nullptr) {
199         MEDIA_ERR_LOG("GetSupportedLightPaintings get native object fail");
200         CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT, "get native object fail");
201         return result;
202     }
203     LightPaintingType lightPainting;
204     int32_t retCode = lightPaintingSessionNapi->lightPaintingSession_->GetLightPainting(lightPainting);
205     if (!CameraNapiUtils::CheckError(env, retCode)) {
206         MEDIA_ERR_LOG("GetLightPainting fail %{public}d", retCode);
207     }
208     status = napi_create_int32(env, lightPainting, &result);
209     if (status != napi_ok) {
210         MEDIA_ERR_LOG("Failed to get GetLightPainting!, errorCode : %{public}d", status);
211     }
212     return result;
213 }
214 
SetLightPainting(napi_env env,napi_callback_info info)215 napi_value LightPaintingSessionNapi::SetLightPainting(napi_env env, napi_callback_info info)
216 {
217     if (!CameraNapiSecurity::CheckSystemApp(env)) {
218         MEDIA_ERR_LOG("SystemApi GetSupportedLightPaintings is called!");
219         return nullptr;
220     }
221     MEDIA_INFO_LOG("SetLightPainting is called");
222     auto result = CameraNapiUtils::GetUndefinedValue(env);
223 
224     LightPaintingSessionNapi* lightPaintingSessionNapi = nullptr;
225     int32_t lightPaintingType;
226     CameraNapiParamParser jsParamParser(env, info, lightPaintingSessionNapi, lightPaintingType);
227     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "parse parameter occur error")) {
228         MEDIA_ERR_LOG("SetLightPainting parse parameter occur error");
229         return result;
230     }
231     if (lightPaintingSessionNapi->lightPaintingSession_ == nullptr) {
232         MEDIA_ERR_LOG("SetLightPainting get native object fail");
233         CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT, "get native object fail");
234         return result;
235     }
236     lightPaintingSessionNapi->lightPaintingSession_->LockForControl();
237     MEDIA_INFO_LOG("SetLightPainting is called native");
238     int32_t retCode = lightPaintingSessionNapi->
239         lightPaintingSession_->SetLightPainting(static_cast<LightPaintingType>(lightPaintingType));
240     lightPaintingSessionNapi->lightPaintingSession_->UnlockForControl();
241     if (!CameraNapiUtils::CheckError(env, retCode)) {
242         MEDIA_ERR_LOG("SetLightPainting fail %{public}d", retCode);
243     }
244     return result;
245 }
246 
TriggerLighting(napi_env env,napi_callback_info info)247 napi_value LightPaintingSessionNapi::TriggerLighting(napi_env env, napi_callback_info info)
248 {
249     if (!CameraNapiSecurity::CheckSystemApp(env)) {
250         MEDIA_ERR_LOG("SystemApi GetSupportedLightPaintings is called!");
251         return nullptr;
252     }
253     MEDIA_INFO_LOG("TriggerLighting is called");
254     auto result = CameraNapiUtils::GetUndefinedValue(env);
255 
256     LightPaintingSessionNapi* lightPaintingSessionNapi = nullptr;
257     CameraNapiParamParser jsParamParser(env, info, lightPaintingSessionNapi);
258     if (lightPaintingSessionNapi->lightPaintingSession_ == nullptr) {
259         MEDIA_ERR_LOG("TriggerLighting get native object fail");
260         CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT, "get native object fail");
261         return result;
262     }
263     lightPaintingSessionNapi->lightPaintingSession_->LockForControl();
264     int32_t retCode = lightPaintingSessionNapi->lightPaintingSession_->TriggerLighting();
265     lightPaintingSessionNapi->lightPaintingSession_->UnlockForControl();
266     if (!CameraNapiUtils::CheckError(env, retCode)) {
267         MEDIA_ERR_LOG("TriggerLighting fail %{public}d", retCode);
268     }
269     return result;
270 }
271 } // namespace CameraStandard
272 } // namespace OHOS