1 /*
2 * Copyright (c) 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 "movingphoto_napi.h"
17
18 #include "ext_napi_utils.h"
19 #include "movingphoto_model_ng.h"
20
21 extern const char _binary_multimedia_movingphotoview_js_start[];
22 extern const char _binary_multimedia_movingphotoview_abc_start[];
23 #if !defined(IOS_PLATFORM)
24 extern const char _binary_multimedia_movingphotoview_js_end[];
25 extern const char _binary_multimedia_movingphotoview_abc_end[];
26 #else
27 extern const char* _binary_multimedia_movingphotoview_js_end;
28 extern const char* _binary_multimedia_movingphotoview_abc_end;
29 #endif
30
31 namespace OHOS::Ace {
32 namespace {
33 static constexpr size_t MAX_ARG_NUM = 10;
34 static constexpr int32_t ARG_NUM_ONE = 1;
35 static constexpr int32_t ARG_NUM_TWO = 2;
36 static constexpr int32_t PARAM_INDEX_ZERO = 0;
37 static constexpr int32_t PARAM_INDEX_ONE = 1;
38 } // namespace
39
40 std::unique_ptr<NG::MovingPhotoModelNG> NG::MovingPhotoModelNG::instance_ = nullptr;
41 std::mutex NG::MovingPhotoModelNG::mutex_;
42
GetInstance()43 NG::MovingPhotoModelNG* NG::MovingPhotoModelNG::GetInstance()
44 {
45 if (!instance_) {
46 std::lock_guard<std::mutex> lock(mutex_);
47 if (!instance_) {
48 instance_.reset(new NG::MovingPhotoModelNG());
49 }
50 }
51 return instance_.get();
52 }
53
JsCreate(napi_env env,napi_callback_info info)54 napi_value JsCreate(napi_env env, napi_callback_info info)
55 {
56 size_t argc = MAX_ARG_NUM;
57 napi_value argv[MAX_ARG_NUM] = { nullptr };
58 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
59 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
60
61 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_object)) {
62 return ExtNapiUtils::CreateNull(env);
63 }
64
65 napi_value jsController = nullptr;
66 NG::MovingPhotoController* controller = nullptr;
67 napi_get_named_property(env, argv[0], "controller", &jsController);
68 if (ExtNapiUtils::CheckTypeForNapiValue(env, jsController, napi_object)) {
69 napi_unwrap(env, jsController, (void**)&controller);
70 }
71 NG::MovingPhotoModelNG::GetInstance()->Create(Referenced::Claim(controller));
72
73 napi_value jsData = nullptr;
74 napi_get_named_property(env, argv[0], "movingPhoto", &jsData);
75 if (!ExtNapiUtils::CheckTypeForNapiValue(env, jsData, napi_object)) {
76 return ExtNapiUtils::CreateNull(env);
77 }
78
79 napi_value jsImageAIOptions = nullptr;
80 napi_get_named_property(env, argv[0], "imageAIOptions", &jsImageAIOptions);
81 NG::MovingPhotoModelNG::GetInstance()->SetImageAIOptions(jsImageAIOptions);
82
83 napi_value jsMovingPhotoFormat = nullptr;
84 napi_get_named_property(env, argv[0], "movingPhotoFormat", &jsMovingPhotoFormat);
85 auto format = MovingPhotoFormat::UNKNOWN;
86 if (ExtNapiUtils::CheckTypeForNapiValue(env, jsMovingPhotoFormat, napi_number)) {
87 format = static_cast<MovingPhotoFormat>(ExtNapiUtils::GetCInt32(env, jsMovingPhotoFormat));
88 NG::MovingPhotoModelNG::GetInstance()->SetMovingPhotoFormat(format);
89 }
90
91 napi_value jsDynamicRangeMode = nullptr;
92 napi_get_named_property(env, argv[0], "dynamicRangeMode", &jsDynamicRangeMode);
93 auto rangeMode = DynamicRangeMode::HIGH;
94 if (ExtNapiUtils::CheckTypeForNapiValue(env, jsDynamicRangeMode, napi_number)) {
95 rangeMode = static_cast<DynamicRangeMode>(ExtNapiUtils::GetCInt32(env, jsDynamicRangeMode));
96 NG::MovingPhotoModelNG::GetInstance()->SetDynamicRangeMode(rangeMode);
97 }
98
99 napi_value getUri = nullptr;
100 napi_get_named_property(env, jsData, "getUri", &getUri);
101 if (!ExtNapiUtils::CheckTypeForNapiValue(env, getUri, napi_function)) {
102 return ExtNapiUtils::CreateNull(env);
103 }
104 napi_value imageUri;
105 napi_call_function(env, jsData, getUri, 0, nullptr, &imageUri);
106 std::string imageUriStr = ExtNapiUtils::GetStringFromValueUtf8(env, imageUri);
107 NG::MovingPhotoModelNG::GetInstance()->SetImageSrc(imageUriStr);
108
109 return ExtNapiUtils::CreateNull(env);
110 }
111
JsMuted(napi_env env,napi_callback_info info)112 napi_value JsMuted(napi_env env, napi_callback_info info)
113 {
114 size_t argc = MAX_ARG_NUM;
115 napi_value argv[MAX_ARG_NUM] = { nullptr };
116 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
117 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
118
119 bool muted = false;
120 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_boolean)) {
121 muted = ExtNapiUtils::GetBool(env, argv[0]);
122 }
123 NG::MovingPhotoModelNG::GetInstance()->SetMuted(muted);
124
125 return ExtNapiUtils::CreateNull(env);
126 }
127
JsObjectFit(napi_env env,napi_callback_info info)128 napi_value JsObjectFit(napi_env env, napi_callback_info info)
129 {
130 size_t argc = MAX_ARG_NUM;
131 napi_value argv[MAX_ARG_NUM] = { nullptr };
132 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
133 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
134
135 auto objectFit = ImageFit::COVER;
136 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_number)) {
137 objectFit = static_cast<ImageFit>(ExtNapiUtils::GetCInt32(env, argv[0]));
138 }
139 NG::MovingPhotoModelNG::GetInstance()->SetObjectFit(objectFit);
140
141 return ExtNapiUtils::CreateNull(env);
142 }
143
JsOnComplete(napi_env env,napi_callback_info info)144 napi_value JsOnComplete(napi_env env, napi_callback_info info)
145 {
146 size_t argc = MAX_ARG_NUM;
147 napi_value thisVal = nullptr;
148 napi_value argv[MAX_ARG_NUM] = { nullptr };
149 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
150 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
151 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
152 return ExtNapiUtils::CreateNull(env);
153 }
154 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
155 auto onComplete = [asyncEvent]() {
156 asyncEvent->Call(0, nullptr);
157 };
158 NG::MovingPhotoModelNG::GetInstance()->SetOnComplete(std::move(onComplete));
159 return ExtNapiUtils::CreateNull(env);
160 }
161
JsOnStart(napi_env env,napi_callback_info info)162 napi_value JsOnStart(napi_env env, napi_callback_info info)
163 {
164 size_t argc = MAX_ARG_NUM;
165 napi_value thisVal = nullptr;
166 napi_value argv[MAX_ARG_NUM] = { nullptr };
167 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
168 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
169 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
170 return ExtNapiUtils::CreateNull(env);
171 }
172 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
173 auto onStart = [asyncEvent]() {
174 asyncEvent->Call(0, nullptr);
175 };
176 NG::MovingPhotoModelNG::GetInstance()->SetOnStart(std::move(onStart));
177 return ExtNapiUtils::CreateNull(env);
178 }
179
JsOnStop(napi_env env,napi_callback_info info)180 napi_value JsOnStop(napi_env env, napi_callback_info info)
181 {
182 size_t argc = MAX_ARG_NUM;
183 napi_value thisVal = nullptr;
184 napi_value argv[MAX_ARG_NUM] = { nullptr };
185 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
186 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
187 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
188 return ExtNapiUtils::CreateNull(env);
189 }
190 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
191 auto onStop = [asyncEvent]() {
192 asyncEvent->Call(0, nullptr);
193 };
194 NG::MovingPhotoModelNG::GetInstance()->SetOnStop(std::move(onStop));
195 return ExtNapiUtils::CreateNull(env);
196 }
197
JsOnPause(napi_env env,napi_callback_info info)198 napi_value JsOnPause(napi_env env, napi_callback_info info)
199 {
200 size_t argc = MAX_ARG_NUM;
201 napi_value thisVal = nullptr;
202 napi_value argv[MAX_ARG_NUM] = { nullptr };
203 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
204 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
205 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
206 return ExtNapiUtils::CreateNull(env);
207 }
208 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
209 auto onPause = [asyncEvent]() {
210 asyncEvent->Call(0, nullptr);
211 };
212 NG::MovingPhotoModelNG::GetInstance()->SetOnPause(std::move(onPause));
213 return ExtNapiUtils::CreateNull(env);
214 }
215
JsOnFinish(napi_env env,napi_callback_info info)216 napi_value JsOnFinish(napi_env env, napi_callback_info info)
217 {
218 size_t argc = MAX_ARG_NUM;
219 napi_value thisVal = nullptr;
220 napi_value argv[MAX_ARG_NUM] = { nullptr };
221 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
222 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
223 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
224 return ExtNapiUtils::CreateNull(env);
225 }
226 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
227 auto onFinish = [asyncEvent]() {
228 asyncEvent->Call(0, nullptr);
229 };
230 NG::MovingPhotoModelNG::GetInstance()->SetOnFinish(std::move(onFinish));
231 return ExtNapiUtils::CreateNull(env);
232 }
233
JsOnError(napi_env env,napi_callback_info info)234 napi_value JsOnError(napi_env env, napi_callback_info info)
235 {
236 size_t argc = MAX_ARG_NUM;
237 napi_value thisVal = nullptr;
238 napi_value argv[MAX_ARG_NUM] = { nullptr };
239 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
240 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
241 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
242 return ExtNapiUtils::CreateNull(env);
243 }
244 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
245 auto onError = [asyncEvent]() {
246 asyncEvent->Call(0, nullptr);
247 };
248 NG::MovingPhotoModelNG::GetInstance()->SetOnError(std::move(onError));
249 return ExtNapiUtils::CreateNull(env);
250 }
251
InitView(napi_env env,napi_value exports)252 napi_value InitView(napi_env env, napi_value exports)
253 {
254 static napi_property_descriptor desc[] = {
255 DECLARE_NAPI_FUNCTION("create", JsCreate),
256 DECLARE_NAPI_FUNCTION("muted", JsMuted),
257 DECLARE_NAPI_FUNCTION("objectFit", JsObjectFit),
258 DECLARE_NAPI_FUNCTION("onComplete", JsOnComplete),
259 DECLARE_NAPI_FUNCTION("onStart", JsOnStart),
260 DECLARE_NAPI_FUNCTION("onStop", JsOnStop),
261 DECLARE_NAPI_FUNCTION("onPause", JsOnPause),
262 DECLARE_NAPI_FUNCTION("onFinish", JsOnFinish),
263 DECLARE_NAPI_FUNCTION("onError", JsOnError),
264 DECLARE_NAPI_FUNCTION("autoPlayPeriod", JsAutoPlayPeriod),
265 DECLARE_NAPI_FUNCTION("autoPlay", JsAutoPlay),
266 DECLARE_NAPI_FUNCTION("repeatPlay", JsRepeatPlay),
267 DECLARE_NAPI_FUNCTION("enableAnalyzer", JsEnableAnalyzer),
268 };
269 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
270 return exports;
271 }
272
StartPlayback(napi_env env,napi_callback_info info)273 napi_value StartPlayback(napi_env env, napi_callback_info info)
274 {
275 napi_value thisVar = nullptr;
276 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, NULL));
277 NG::MovingPhotoController* controller = nullptr;
278 napi_unwrap(env, thisVar, (void**)&controller);
279 if (controller == nullptr) {
280 return ExtNapiUtils::CreateNull(env);
281 }
282 controller->StartPlayback();
283 return ExtNapiUtils::CreateNull(env);
284 }
285
StopPlayback(napi_env env,napi_callback_info info)286 napi_value StopPlayback(napi_env env, napi_callback_info info)
287 {
288 napi_value thisVar = nullptr;
289 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, NULL));
290 NG::MovingPhotoController* controller = nullptr;
291 napi_unwrap(env, thisVar, (void**)&controller);
292 if (controller == nullptr) {
293 return ExtNapiUtils::CreateNull(env);
294 }
295 controller->StopPlayback();
296 return ExtNapiUtils::CreateNull(env);
297 }
298
RefreshMovingPhoto(napi_env env,napi_callback_info info)299 napi_value RefreshMovingPhoto(napi_env env, napi_callback_info info)
300 {
301 napi_value thisVar = nullptr;
302 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, NULL));
303 NG::MovingPhotoController* controller = nullptr;
304 napi_unwrap(env, thisVar, (void**)&controller);
305 if (controller == nullptr) {
306 return ExtNapiUtils::CreateNull(env);
307 }
308 controller->RefreshMovingPhoto();
309 return ExtNapiUtils::CreateNull(env);
310 }
311
MovingPhotoControllerConstructor(napi_env env,napi_callback_info info)312 napi_value MovingPhotoControllerConstructor(napi_env env, napi_callback_info info)
313 {
314 napi_value thisVar = nullptr;
315 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
316 auto controller = AceType::MakeRefPtr<NG::MovingPhotoController>();
317 if (controller == nullptr) {
318 return ExtNapiUtils::CreateNull(env);
319 }
320 controller->IncRefCount();
321 napi_wrap(
322 env, thisVar, AceType::RawPtr(controller),
323 [](napi_env env, void* data, void* hint) {
324 auto* controller = reinterpret_cast<NG::MovingPhotoController*>(data);
325 controller->DecRefCount();
326 },
327 nullptr, nullptr);
328 return thisVar;
329 }
330
InitController(napi_env env,napi_value exports)331 napi_value InitController(napi_env env, napi_value exports)
332 {
333 napi_value movingphotoControllerClass = nullptr;
334 napi_property_descriptor properties[] = {
335 DECLARE_NAPI_FUNCTION("startPlayback", StartPlayback),
336 DECLARE_NAPI_FUNCTION("stopPlayback", StopPlayback),
337 DECLARE_NAPI_FUNCTION("refreshMovingPhoto", RefreshMovingPhoto),
338 };
339 NAPI_CALL(env, napi_define_class(env, "MovingPhotoViewController", NAPI_AUTO_LENGTH,
340 MovingPhotoControllerConstructor, nullptr, sizeof(properties) / sizeof(*properties), properties,
341 &movingphotoControllerClass));
342 NAPI_CALL(env, napi_set_named_property(env, exports, "MovingPhotoViewController", movingphotoControllerClass));
343 return exports;
344 }
345
ExportMovingPhoto(napi_env env,napi_value exports)346 napi_value ExportMovingPhoto(napi_env env, napi_value exports)
347 {
348 InitView(env, exports);
349 InitController(env, exports);
350 return exports;
351 }
352
JsAutoPlayPeriod(napi_env env,napi_callback_info info)353 napi_value JsAutoPlayPeriod(napi_env env, napi_callback_info info)
354 {
355 size_t argc = MAX_ARG_NUM;
356 napi_value argv[MAX_ARG_NUM] = { nullptr };
357 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
358 NAPI_ASSERT(env, argc >= ARG_NUM_TWO, "Wrong number of arguments");
359
360 int64_t startTime = 0;
361 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ZERO], napi_number)) {
362 startTime = ExtNapiUtils::GetCInt64(env, argv[PARAM_INDEX_ZERO]);
363 }
364 int64_t endTime = 0;
365 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ONE], napi_number)) {
366 endTime = ExtNapiUtils::GetCInt64(env, argv[PARAM_INDEX_ONE]);
367 }
368 NG::MovingPhotoModelNG::GetInstance()->AutoPlayPeriod(startTime, endTime);
369
370 return ExtNapiUtils::CreateNull(env);
371 }
372
JsAutoPlay(napi_env env,napi_callback_info info)373 napi_value JsAutoPlay(napi_env env, napi_callback_info info)
374 {
375 size_t argc = MAX_ARG_NUM;
376 napi_value argv[MAX_ARG_NUM] = { nullptr };
377 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
378 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
379
380 bool isAutoPlay = false;
381 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ZERO], napi_boolean)) {
382 isAutoPlay = ExtNapiUtils::GetBool(env, argv[PARAM_INDEX_ZERO]);
383 }
384 NG::MovingPhotoModelNG::GetInstance()->AutoPlay(isAutoPlay);
385
386 return ExtNapiUtils::CreateNull(env);
387 }
388
JsEnableAnalyzer(napi_env env,napi_callback_info info)389 napi_value JsEnableAnalyzer(napi_env env, napi_callback_info info)
390 {
391 size_t argc = MAX_ARG_NUM;
392 napi_value argv[MAX_ARG_NUM] = { nullptr };
393 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
394 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
395
396 bool enabled = false;
397 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ZERO], napi_boolean)) {
398 enabled = ExtNapiUtils::GetBool(env, argv[PARAM_INDEX_ZERO]);
399 }
400 NG::MovingPhotoModelNG::GetInstance()->EnableAnalyzer(enabled);
401
402 return ExtNapiUtils::CreateNull(env);
403 }
404
JsRepeatPlay(napi_env env,napi_callback_info info)405 napi_value JsRepeatPlay(napi_env env, napi_callback_info info)
406 {
407 size_t argc = MAX_ARG_NUM;
408 napi_value argv[MAX_ARG_NUM] = { nullptr };
409 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
410 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
411
412 bool isRepeatPlay = false;
413 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ZERO], napi_boolean)) {
414 isRepeatPlay = ExtNapiUtils::GetBool(env, argv[PARAM_INDEX_ZERO]);
415 }
416 NG::MovingPhotoModelNG::GetInstance()->RepeatPlay(isRepeatPlay);
417
418 return ExtNapiUtils::CreateNull(env);
419 }
420
421 } // namespace OHOS::Ace
422
NAPI_multimedia_movingphotoview_GetJSCode(const char ** buf,int * bufLen)423 extern "C" __attribute__((visibility("default"))) void NAPI_multimedia_movingphotoview_GetJSCode(
424 const char** buf, int* bufLen)
425 {
426 if (buf != nullptr) {
427 *buf = _binary_multimedia_movingphotoview_js_start;
428 }
429
430 if (bufLen != nullptr) {
431 *bufLen = _binary_multimedia_movingphotoview_js_end - _binary_multimedia_movingphotoview_js_start;
432 }
433 }
434
435 // multimedia_movingphotoview JS register
NAPI_multimedia_movingphotoview_GetABCCode(const char ** buf,int * buflen)436 extern "C" __attribute__((visibility("default"))) void NAPI_multimedia_movingphotoview_GetABCCode(
437 const char** buf, int* buflen)
438 {
439 if (buf != nullptr) {
440 *buf = _binary_multimedia_movingphotoview_abc_start;
441 }
442 if (buflen != nullptr) {
443 *buflen = _binary_multimedia_movingphotoview_abc_end - _binary_multimedia_movingphotoview_abc_start;
444 }
445 }
446
447 static napi_module movingphotoModule = {
448 .nm_version = 1,
449 .nm_flags = 0,
450 .nm_filename = nullptr,
451 .nm_register_func = OHOS::Ace::ExportMovingPhoto,
452 .nm_modname = "multimedia.movingphotoview",
453 .nm_priv = ((void*)0),
454 .reserved = { 0 },
455 };
456
RegisterModuleMovingPhoto()457 extern "C" __attribute__((constructor)) void RegisterModuleMovingPhoto()
458 {
459 napi_module_register(&movingphotoModule);
460 }
461