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 getUri = nullptr;
84 napi_get_named_property(env, jsData, "getUri", &getUri);
85 if (!ExtNapiUtils::CheckTypeForNapiValue(env, getUri, napi_function)) {
86 return ExtNapiUtils::CreateNull(env);
87 }
88 napi_value imageUri;
89 napi_call_function(env, jsData, getUri, 0, nullptr, &imageUri);
90 std::string imageUriStr = ExtNapiUtils::GetStringFromValueUtf8(env, imageUri);
91 NG::MovingPhotoModelNG::GetInstance()->SetImageSrc(imageUriStr);
92
93 return ExtNapiUtils::CreateNull(env);
94 }
95
JsMuted(napi_env env, napi_callback_info info)96 napi_value JsMuted(napi_env env, napi_callback_info info)
97 {
98 size_t argc = MAX_ARG_NUM;
99 napi_value argv[MAX_ARG_NUM] = { nullptr };
100 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
101 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
102
103 bool muted = false;
104 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_boolean)) {
105 muted = ExtNapiUtils::GetBool(env, argv[0]);
106 }
107 NG::MovingPhotoModelNG::GetInstance()->SetMuted(muted);
108
109 return ExtNapiUtils::CreateNull(env);
110 }
111
JsObjectFit(napi_env env, napi_callback_info info)112 napi_value JsObjectFit(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 auto objectFit = ImageFit::COVER;
120 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_number)) {
121 objectFit = static_cast<ImageFit>(ExtNapiUtils::GetCInt32(env, argv[0]));
122 }
123 NG::MovingPhotoModelNG::GetInstance()->SetObjectFit(objectFit);
124
125 return ExtNapiUtils::CreateNull(env);
126 }
127
JsOnComplete(napi_env env, napi_callback_info info)128 napi_value JsOnComplete(napi_env env, napi_callback_info info)
129 {
130 size_t argc = MAX_ARG_NUM;
131 napi_value thisVal = nullptr;
132 napi_value argv[MAX_ARG_NUM] = { nullptr };
133 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
134 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
135 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
136 return ExtNapiUtils::CreateNull(env);
137 }
138 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
139 auto onComplete = [asyncEvent]() {
140 asyncEvent->Call(0, nullptr);
141 };
142 NG::MovingPhotoModelNG::GetInstance()->SetOnComplete(std::move(onComplete));
143 return ExtNapiUtils::CreateNull(env);
144 }
145
JsOnStart(napi_env env, napi_callback_info info)146 napi_value JsOnStart(napi_env env, napi_callback_info info)
147 {
148 size_t argc = MAX_ARG_NUM;
149 napi_value thisVal = nullptr;
150 napi_value argv[MAX_ARG_NUM] = { nullptr };
151 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
152 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
153 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
154 return ExtNapiUtils::CreateNull(env);
155 }
156 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
157 auto onStart = [asyncEvent]() {
158 asyncEvent->Call(0, nullptr);
159 };
160 NG::MovingPhotoModelNG::GetInstance()->SetOnStart(std::move(onStart));
161 return ExtNapiUtils::CreateNull(env);
162 }
163
JsOnStop(napi_env env, napi_callback_info info)164 napi_value JsOnStop(napi_env env, napi_callback_info info)
165 {
166 size_t argc = MAX_ARG_NUM;
167 napi_value thisVal = nullptr;
168 napi_value argv[MAX_ARG_NUM] = { nullptr };
169 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
170 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
171 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
172 return ExtNapiUtils::CreateNull(env);
173 }
174 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
175 auto onStop = [asyncEvent]() {
176 asyncEvent->Call(0, nullptr);
177 };
178 NG::MovingPhotoModelNG::GetInstance()->SetOnStop(std::move(onStop));
179 return ExtNapiUtils::CreateNull(env);
180 }
181
JsOnPause(napi_env env, napi_callback_info info)182 napi_value JsOnPause(napi_env env, napi_callback_info info)
183 {
184 size_t argc = MAX_ARG_NUM;
185 napi_value thisVal = nullptr;
186 napi_value argv[MAX_ARG_NUM] = { nullptr };
187 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
188 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
189 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
190 return ExtNapiUtils::CreateNull(env);
191 }
192 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
193 auto onPause = [asyncEvent]() {
194 asyncEvent->Call(0, nullptr);
195 };
196 NG::MovingPhotoModelNG::GetInstance()->SetOnPause(std::move(onPause));
197 return ExtNapiUtils::CreateNull(env);
198 }
199
JsOnFinish(napi_env env, napi_callback_info info)200 napi_value JsOnFinish(napi_env env, napi_callback_info info)
201 {
202 size_t argc = MAX_ARG_NUM;
203 napi_value thisVal = nullptr;
204 napi_value argv[MAX_ARG_NUM] = { nullptr };
205 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
206 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
207 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
208 return ExtNapiUtils::CreateNull(env);
209 }
210 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
211 auto onFinish = [asyncEvent]() {
212 asyncEvent->Call(0, nullptr);
213 };
214 NG::MovingPhotoModelNG::GetInstance()->SetOnFinish(std::move(onFinish));
215 return ExtNapiUtils::CreateNull(env);
216 }
217
JsOnError(napi_env env, napi_callback_info info)218 napi_value JsOnError(napi_env env, napi_callback_info info)
219 {
220 size_t argc = MAX_ARG_NUM;
221 napi_value thisVal = nullptr;
222 napi_value argv[MAX_ARG_NUM] = { nullptr };
223 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
224 NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
225 if (!ExtNapiUtils::CheckTypeForNapiValue(env, argv[0], napi_function)) {
226 return ExtNapiUtils::CreateNull(env);
227 }
228 auto asyncEvent = std::make_shared<NapiAsyncEvent>(env, argv[0]);
229 auto onError = [asyncEvent]() {
230 asyncEvent->Call(0, nullptr);
231 };
232 NG::MovingPhotoModelNG::GetInstance()->SetOnError(std::move(onError));
233 return ExtNapiUtils::CreateNull(env);
234 }
235
InitView(napi_env env, napi_value exports)236 napi_value InitView(napi_env env, napi_value exports)
237 {
238 static napi_property_descriptor desc[] = {
239 DECLARE_NAPI_FUNCTION("create", JsCreate),
240 DECLARE_NAPI_FUNCTION("muted", JsMuted),
241 DECLARE_NAPI_FUNCTION("objectFit", JsObjectFit),
242 DECLARE_NAPI_FUNCTION("onComplete", JsOnComplete),
243 DECLARE_NAPI_FUNCTION("onStart", JsOnStart),
244 DECLARE_NAPI_FUNCTION("onStop", JsOnStop),
245 DECLARE_NAPI_FUNCTION("onPause", JsOnPause),
246 DECLARE_NAPI_FUNCTION("onFinish", JsOnFinish),
247 DECLARE_NAPI_FUNCTION("onError", JsOnError),
248 DECLARE_NAPI_FUNCTION("autoPlayPeriod", JsAutoPlayPeriod),
249 DECLARE_NAPI_FUNCTION("autoPlay", JsAutoPlay),
250 DECLARE_NAPI_FUNCTION("repeatPlay", JsRepeatPlay),
251 DECLARE_NAPI_FUNCTION("enableAnalyzer", JsEnableAnalyzer),
252 };
253 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
254 return exports;
255 }
256
StartPlayback(napi_env env, napi_callback_info info)257 napi_value StartPlayback(napi_env env, napi_callback_info info)
258 {
259 napi_value thisVar = nullptr;
260 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, NULL));
261 NG::MovingPhotoController* controller = nullptr;
262 napi_unwrap(env, thisVar, (void**)&controller);
263 if (controller == nullptr) {
264 return ExtNapiUtils::CreateNull(env);
265 }
266 controller->StartPlayback();
267 return ExtNapiUtils::CreateNull(env);
268 }
269
StopPlayback(napi_env env, napi_callback_info info)270 napi_value StopPlayback(napi_env env, napi_callback_info info)
271 {
272 napi_value thisVar = nullptr;
273 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, NULL));
274 NG::MovingPhotoController* controller = nullptr;
275 napi_unwrap(env, thisVar, (void**)&controller);
276 if (controller == nullptr) {
277 return ExtNapiUtils::CreateNull(env);
278 }
279 controller->StopPlayback();
280 return ExtNapiUtils::CreateNull(env);
281 }
282
MovingPhotoControllerConstructor(napi_env env, napi_callback_info info)283 napi_value MovingPhotoControllerConstructor(napi_env env, napi_callback_info info)
284 {
285 napi_value thisVar = nullptr;
286 NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
287 auto controller = AceType::MakeRefPtr<NG::MovingPhotoController>();
288 if (controller == nullptr) {
289 return ExtNapiUtils::CreateNull(env);
290 }
291 controller->IncRefCount();
292 napi_wrap(
293 env, thisVar, AceType::RawPtr(controller),
294 [](napi_env env, void* data, void* hint) {
295 auto* controller = reinterpret_cast<NG::MovingPhotoController*>(data);
296 controller->DecRefCount();
297 },
298 nullptr, nullptr);
299 return thisVar;
300 }
301
InitController(napi_env env, napi_value exports)302 napi_value InitController(napi_env env, napi_value exports)
303 {
304 napi_value movingphotoControllerClass = nullptr;
305 napi_property_descriptor properties[] = {
306 DECLARE_NAPI_FUNCTION("startPlayback", StartPlayback),
307 DECLARE_NAPI_FUNCTION("stopPlayback", StopPlayback),
308 };
309 NAPI_CALL(env, napi_define_class(env, "MovingPhotoViewController", NAPI_AUTO_LENGTH,
310 MovingPhotoControllerConstructor, nullptr, sizeof(properties) / sizeof(*properties), properties,
311 &movingphotoControllerClass));
312 NAPI_CALL(env, napi_set_named_property(env, exports, "MovingPhotoViewController", movingphotoControllerClass));
313 return exports;
314 }
315
ExportMovingPhoto(napi_env env, napi_value exports)316 napi_value ExportMovingPhoto(napi_env env, napi_value exports)
317 {
318 InitView(env, exports);
319 InitController(env, exports);
320 return exports;
321 }
322
JsAutoPlayPeriod(napi_env env, napi_callback_info info)323 napi_value JsAutoPlayPeriod(napi_env env, napi_callback_info info)
324 {
325 size_t argc = MAX_ARG_NUM;
326 napi_value argv[MAX_ARG_NUM] = { nullptr };
327 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
328 NAPI_ASSERT(env, argc >= ARG_NUM_TWO, "Wrong number of arguments");
329
330 int64_t startTime = 0;
331 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ZERO], napi_number)) {
332 startTime = ExtNapiUtils::GetCInt64(env, argv[PARAM_INDEX_ZERO]);
333 }
334 int64_t endTime = 0;
335 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ONE], napi_number)) {
336 endTime = ExtNapiUtils::GetCInt64(env, argv[PARAM_INDEX_ONE]);
337 }
338 NG::MovingPhotoModelNG::GetInstance()->AutoPlayPeriod(startTime, endTime);
339
340 return ExtNapiUtils::CreateNull(env);
341 }
342
JsAutoPlay(napi_env env, napi_callback_info info)343 napi_value JsAutoPlay(napi_env env, napi_callback_info info)
344 {
345 size_t argc = MAX_ARG_NUM;
346 napi_value argv[MAX_ARG_NUM] = { nullptr };
347 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
348 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
349
350 bool isAutoPlay = false;
351 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ZERO], napi_boolean)) {
352 isAutoPlay = ExtNapiUtils::GetBool(env, argv[PARAM_INDEX_ZERO]);
353 }
354 NG::MovingPhotoModelNG::GetInstance()->AutoPlay(isAutoPlay);
355
356 return ExtNapiUtils::CreateNull(env);
357 }
358
JsEnableAnalyzer(napi_env env, napi_callback_info info)359 napi_value JsEnableAnalyzer(napi_env env, napi_callback_info info)
360 {
361 size_t argc = MAX_ARG_NUM;
362 napi_value argv[MAX_ARG_NUM] = { nullptr };
363 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
364 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
365
366 bool enabled = false;
367 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ZERO], napi_boolean)) {
368 enabled = ExtNapiUtils::GetBool(env, argv[PARAM_INDEX_ZERO]);
369 }
370 NG::MovingPhotoModelNG::GetInstance()->EnableAnalyzer(enabled);
371
372 return ExtNapiUtils::CreateNull(env);
373 }
374
JsRepeatPlay(napi_env env, napi_callback_info info)375 napi_value JsRepeatPlay(napi_env env, napi_callback_info info)
376 {
377 size_t argc = MAX_ARG_NUM;
378 napi_value argv[MAX_ARG_NUM] = { nullptr };
379 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
380 NAPI_ASSERT(env, argc >= ARG_NUM_ONE, "Wrong number of arguments");
381
382 bool isRepeatPlay = false;
383 if (ExtNapiUtils::CheckTypeForNapiValue(env, argv[PARAM_INDEX_ZERO], napi_boolean)) {
384 isRepeatPlay = ExtNapiUtils::GetBool(env, argv[PARAM_INDEX_ZERO]);
385 }
386 NG::MovingPhotoModelNG::GetInstance()->RepeatPlay(isRepeatPlay);
387
388 return ExtNapiUtils::CreateNull(env);
389 }
390
391 } // namespace OHOS::Ace
392
NAPI_multimedia_movingphotoview_GetJSCode( const char** buf, int* bufLen)393 extern "C" __attribute__((visibility("default"))) void NAPI_multimedia_movingphotoview_GetJSCode(
394 const char** buf, int* bufLen)
395 {
396 if (buf != nullptr) {
397 *buf = _binary_multimedia_movingphotoview_js_start;
398 }
399
400 if (bufLen != nullptr) {
401 *bufLen = _binary_multimedia_movingphotoview_js_end - _binary_multimedia_movingphotoview_js_start;
402 }
403 }
404
405 // multimedia_movingphotoview JS register
NAPI_multimedia_movingphotoview_GetABCCode( const char** buf, int* buflen)406 extern "C" __attribute__((visibility("default"))) void NAPI_multimedia_movingphotoview_GetABCCode(
407 const char** buf, int* buflen)
408 {
409 if (buf != nullptr) {
410 *buf = _binary_multimedia_movingphotoview_abc_start;
411 }
412 if (buflen != nullptr) {
413 *buflen = _binary_multimedia_movingphotoview_abc_end - _binary_multimedia_movingphotoview_abc_start;
414 }
415 }
416
417 static napi_module movingphotoModule = {
418 .nm_version = 1,
419 .nm_flags = 0,
420 .nm_filename = nullptr,
421 .nm_register_func = OHOS::Ace::ExportMovingPhoto,
422 .nm_modname = "multimedia.movingphotoview",
423 .nm_priv = ((void*)0),
424 .reserved = { 0 },
425 };
426
RegisterModuleMovingPhoto()427 extern "C" __attribute__((constructor)) void RegisterModuleMovingPhoto()
428 {
429 napi_module_register(&movingphotoModule);
430 }
431