1 /*
2  * Copyright (c) 2021-2022 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 "mode/mode_manager_napi.h"
17 
18 #include "camera_napi_object_types.h"
19 #include "input/camera_manager_napi.h"
20 #include "input/camera_napi.h"
21 #include "napi/native_common.h"
22 
23 namespace OHOS {
24 namespace CameraStandard {
25 using namespace std;
26 thread_local napi_ref ModeManagerNapi::sConstructor_ = nullptr;
27 thread_local uint32_t ModeManagerNapi::modeManagerTaskId = MODE_MANAGER_TASKID;
28 
29 namespace {
GetCameraDeviceFromNapiCameraInfoObj(napi_env env,napi_value napiCameraInfoObj)30 sptr<CameraDevice> GetCameraDeviceFromNapiCameraInfoObj(napi_env env, napi_value napiCameraInfoObj)
31 {
32     napi_value napiCameraId = nullptr;
33     if (napi_get_named_property(env, napiCameraInfoObj, "cameraId", &napiCameraId) != napi_ok) {
34         return nullptr;
35     }
36     std::string cameraId = CameraNapiUtils::GetStringArgument(env, napiCameraId);
37     return CameraManager::GetInstance()->GetCameraDeviceFromId(cameraId);
38 }
39 }
40 
ModeManagerNapi()41 ModeManagerNapi::ModeManagerNapi() : env_(nullptr)
42 {
43     MEDIA_DEBUG_LOG("ModeManagerNapi::ModeManagerNapi is called");
44 }
45 
~ModeManagerNapi()46 ModeManagerNapi::~ModeManagerNapi()
47 {
48     MEDIA_DEBUG_LOG("~ModeManagerNapi is called");
49 }
50 
51 // Constructor callback
ModeManagerNapiConstructor(napi_env env,napi_callback_info info)52 napi_value ModeManagerNapi::ModeManagerNapiConstructor(napi_env env, napi_callback_info info)
53 {
54     MEDIA_DEBUG_LOG("ModeManagerNapiConstructor is called");
55     napi_status status;
56     napi_value result = nullptr;
57     napi_value thisVar = nullptr;
58 
59     napi_get_undefined(env, &result);
60     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
61 
62     if (status == napi_ok && thisVar != nullptr) {
63         std::unique_ptr<ModeManagerNapi> obj = std::make_unique<ModeManagerNapi>();
64         obj->env_ = env;
65         obj->modeManager_ = CameraManager::GetInstance();
66         if (obj->modeManager_ == nullptr) {
67             MEDIA_ERR_LOG("Failure wrapping js to native napi, obj->modeManager_ null");
68             return result;
69         }
70         status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
71                            ModeManagerNapi::ModeManagerNapiDestructor, nullptr, nullptr);
72         if (status == napi_ok) {
73             obj.release();
74             return thisVar;
75         } else {
76             MEDIA_ERR_LOG("Failure wrapping js to native napi");
77         }
78     }
79     MEDIA_ERR_LOG("ModeManagerNapiConstructor call Failed!");
80     return result;
81 }
82 
ModeManagerNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)83 void ModeManagerNapi::ModeManagerNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
84 {
85     MEDIA_DEBUG_LOG("ModeManagerNapiDestructor is called");
86     ModeManagerNapi* camera = reinterpret_cast<ModeManagerNapi*>(nativeObject);
87     if (camera != nullptr) {
88         delete camera;
89     }
90 }
91 
Init(napi_env env,napi_value exports)92 napi_value ModeManagerNapi::Init(napi_env env, napi_value exports)
93 {
94     MEDIA_DEBUG_LOG("Init is called");
95     napi_status status;
96     napi_value ctorObj;
97     napi_property_descriptor mode_mgr_properties[] = {
98         DECLARE_NAPI_FUNCTION("getSupportedModes", GetSupportedModes),
99         DECLARE_NAPI_FUNCTION("getSupportedOutputCapability", GetSupportedOutputCapability),
100         DECLARE_NAPI_FUNCTION("createCaptureSession", CreateCameraSessionInstance),
101     };
102 
103     status = napi_define_class(env, MODE_MANAGER_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
104                                ModeManagerNapiConstructor, nullptr,
105                                sizeof(mode_mgr_properties) / sizeof(mode_mgr_properties[PARAM0]),
106                                mode_mgr_properties, &ctorObj);
107     if (status == napi_ok) {
108         int32_t refCount = 1;
109         if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
110             status = napi_set_named_property(env, exports, MODE_MANAGER_NAPI_CLASS_NAME, ctorObj);
111             if (status == napi_ok) {
112                 return exports;
113             }
114         }
115     }
116     MEDIA_ERR_LOG("Init call Failed!");
117     return nullptr;
118 }
119 
CreateModeManager(napi_env env)120 napi_value ModeManagerNapi::CreateModeManager(napi_env env)
121 {
122     MEDIA_INFO_LOG("CreateModeManager is called");
123     napi_status status;
124     napi_value result = nullptr;
125     napi_value ctor;
126 
127     status = napi_get_reference_value(env, sConstructor_, &ctor);
128     if (status == napi_ok) {
129         status = napi_new_instance(env, ctor, 0, nullptr, &result);
130         if (status == napi_ok) {
131             return result;
132         } else {
133             MEDIA_ERR_LOG("New instance could not be obtained");
134         }
135     }
136     napi_get_undefined(env, &result);
137     MEDIA_ERR_LOG("CreateModeManager call Failed!");
138     return result;
139 }
140 
CreateCameraSessionInstance(napi_env env,napi_callback_info info)141 napi_value ModeManagerNapi::CreateCameraSessionInstance(napi_env env, napi_callback_info info)
142 {
143     MEDIA_INFO_LOG("CreateCameraSessionInstance is called");
144     napi_status status;
145     napi_value result = nullptr;
146     size_t argc = ARGS_ONE;
147     napi_value argv[ARGS_ONE];
148     napi_value thisVar = nullptr;
149 
150     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
151 
152     napi_get_undefined(env, &result);
153 
154     ModeManagerNapi* modeManagerNapi = nullptr;
155     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&modeManagerNapi));
156     if (status != napi_ok || modeManagerNapi == nullptr) {
157         MEDIA_ERR_LOG("napi_unwrap failure!");
158         return nullptr;
159     }
160 
161     int32_t jsModeName;
162     napi_get_value_int32(env, argv[PARAM0], &jsModeName);
163     MEDIA_INFO_LOG("ModeManagerNapi::CreateCameraSessionInstance mode = %{public}d", jsModeName);
164     switch (jsModeName) {
165         case JsSceneMode::JS_CAPTURE:
166             result = PhotoSessionNapi::CreateCameraSession(env);
167             break;
168         case JsSceneMode::JS_VIDEO:
169             result = VideoSessionNapi::CreateCameraSession(env);
170             break;
171         case JsSceneMode::JS_PORTRAIT:
172             result = PortraitSessionNapi::CreateCameraSession(env);
173             break;
174         case JsSceneMode::JS_NIGHT:
175             result = NightSessionNapi::CreateCameraSession(env);
176             break;
177         case JS_SECURE_CAMERA:
178             result = SecureCameraSessionNapi::CreateCameraSession(env);
179             break;
180         case JsSceneMode::JS_PANORAMA_PHOTO:
181             result = PanoramaSessionNapi::CreateCameraSession(env);
182             break;
183         default:
184             MEDIA_ERR_LOG("ModeManagerNapi::CreateCameraSessionInstance mode = %{public}d not supported", jsModeName);
185             break;
186     }
187     return result;
188 }
189 
CreateSceneModeJSArray(napi_env env,napi_status status,std::vector<SceneMode> nativeArray)190 static napi_value CreateSceneModeJSArray(napi_env env, napi_status status,
191     std::vector<SceneMode> nativeArray)
192 {
193     MEDIA_DEBUG_LOG("CreateSceneModeJSArray is called");
194     napi_value jsArray = nullptr;
195     napi_value item = nullptr;
196 
197     if (nativeArray.empty()) {
198         MEDIA_ERR_LOG("nativeArray is empty");
199     }
200 
201     status = napi_create_array(env, &jsArray);
202     if (status == napi_ok) {
203         for (size_t i = 0; i < nativeArray.size(); i++) {
204             napi_create_int32(env, nativeArray[i], &item);
205             if (napi_set_element(env, jsArray, i, item) != napi_ok) {
206                 MEDIA_ERR_LOG("Failed to create profile napi wrapper object");
207                 return nullptr;
208             }
209         }
210     }
211     return jsArray;
212 }
213 
GetSupportedModes(napi_env env,napi_callback_info info)214 napi_value ModeManagerNapi::GetSupportedModes(napi_env env, napi_callback_info info)
215 {
216     MEDIA_INFO_LOG("GetSupportedModes is called");
217     napi_status status;
218     napi_value result = nullptr;
219     size_t argc = ARGS_ONE;
220     napi_value argv[ARGS_ONE];
221     napi_value thisVar = nullptr;
222     napi_value jsResult = nullptr;
223     ModeManagerNapi* modeManagerNapi = nullptr;
224     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
225 
226     napi_get_undefined(env, &result);
227     sptr<CameraDevice> cameraInfo = GetCameraDeviceFromNapiCameraInfoObj(env, argv[PARAM0]);
228     if (cameraInfo == nullptr) {
229         MEDIA_ERR_LOG("Could not able to read cameraId argument!");
230         return result;
231     }
232 
233     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&modeManagerNapi));
234     if (status == napi_ok && modeManagerNapi != nullptr) {
235         std::vector<SceneMode> modeObjList = modeManagerNapi->modeManager_->GetSupportedModes(cameraInfo);
236         MEDIA_INFO_LOG("ModeManagerNapi::GetSupportedModes size=[%{public}zu]", modeObjList.size());
237         jsResult = CreateSceneModeJSArray(env, status, modeObjList);
238         if (status == napi_ok) {
239             return jsResult;
240         } else {
241             MEDIA_ERR_LOG("Failed to get modeObjList!, errorCode : %{public}d", status);
242         }
243     } else {
244         MEDIA_ERR_LOG("GetSupportedModes call Failed!");
245     }
246     return result;
247 }
248 
GetSupportedOutputCapability(napi_env env,napi_callback_info info)249 napi_value ModeManagerNapi::GetSupportedOutputCapability(napi_env env, napi_callback_info info)
250 {
251     MEDIA_INFO_LOG("GetSupportedOutputCapability is called");
252     napi_status status;
253 
254     napi_value result = nullptr;
255     size_t argc = ARGS_TWO;
256     napi_value argv[ARGS_TWO] = {0};
257     napi_value thisVar = nullptr;
258     ModeManagerNapi* modeManagerNapi = nullptr;
259 
260     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
261 
262     napi_get_undefined(env, &result);
263     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&modeManagerNapi));
264     if (status != napi_ok || modeManagerNapi == nullptr) {
265         MEDIA_ERR_LOG("napi_unwrap() failure!");
266         return result;
267     }
268 
269     sptr<CameraDevice> cameraInfo = GetCameraDeviceFromNapiCameraInfoObj(env, argv[PARAM0]);
270     if (cameraInfo == nullptr) {
271         MEDIA_ERR_LOG("Could not able to read cameraId argument!");
272         return result;
273     }
274 
275     int32_t sceneMode;
276     napi_get_value_int32(env, argv[PARAM1], &sceneMode);
277     MEDIA_INFO_LOG("ModeManagerNapi::GetSupportedOutputCapability mode = %{public}d", sceneMode);
278 
279     sptr<CameraOutputCapability> outputCapability = nullptr;
280     auto cameraManager = CameraManager::GetInstance();
281     switch (sceneMode) {
282         case JS_CAPTURE:
283             outputCapability = cameraManager->GetSupportedOutputCapability(cameraInfo, SceneMode::CAPTURE);
284             break;
285         case JS_VIDEO:
286             outputCapability = cameraManager->GetSupportedOutputCapability(cameraInfo, SceneMode::VIDEO);
287             break;
288         case JS_PORTRAIT:
289             outputCapability = cameraManager->GetSupportedOutputCapability(cameraInfo, SceneMode::PORTRAIT);
290             break;
291         case JS_NIGHT:
292             outputCapability = cameraManager->GetSupportedOutputCapability(cameraInfo, SceneMode::NIGHT);
293             break;
294         case JS_SECURE_CAMERA:
295             outputCapability = cameraManager->GetSupportedOutputCapability(cameraInfo, SceneMode::SECURE);
296             break;
297         default:
298             MEDIA_ERR_LOG("ModeManagerNapi::CreateCameraSessionInstance mode = %{public}d not supported", sceneMode);
299             break;
300     }
301     if (outputCapability != nullptr) {
302         result = CameraNapiObjCameraOutputCapability(*outputCapability).GenerateNapiValue(env);
303     }
304     return result;
305 }
306 } // namespace CameraStandard
307 } // namespace OHOS
308