1 /*
2 * Copyright (c) 2023 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 "system_tone_player_napi.h"
17
18 #include "system_sound_log.h"
19 #include "common_napi.h"
20
21 namespace {
22 /* Constants for array index */
23 const int32_t PARAM0 = 0;
24 const int32_t PARAM1 = 1;
25
26 /* Constants for array size */
27 const int32_t ARGS_ONE = 1;
28 const int32_t ARGS_TWO = 2;
29
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "SystemTonePlayerNapi"};
31 }
32
33 namespace OHOS {
34 namespace Media {
35 thread_local napi_ref SystemTonePlayerNapi::sConstructor_ = nullptr;
36 std::shared_ptr<SystemTonePlayer> SystemTonePlayerNapi::sSystemTonePlayer_ = nullptr;
37
SystemTonePlayerNapi()38 SystemTonePlayerNapi::SystemTonePlayerNapi() : env_(nullptr) {}
39
40 SystemTonePlayerNapi::~SystemTonePlayerNapi() = default;
41
Init(napi_env env,napi_value exports)42 napi_value SystemTonePlayerNapi::Init(napi_env env, napi_value exports)
43 {
44 napi_status status;
45 napi_value ctorObj;
46 int32_t refCount = 1;
47
48 napi_property_descriptor system_tone_player_prop[] = {
49 DECLARE_NAPI_FUNCTION("getTitle", GetTitle),
50 DECLARE_NAPI_FUNCTION("prepare", Prepare),
51 DECLARE_NAPI_FUNCTION("start", Start),
52 DECLARE_NAPI_FUNCTION("stop", Stop),
53 DECLARE_NAPI_FUNCTION("release", Release),
54 DECLARE_NAPI_FUNCTION("setAudioVolumeScale", SetAudioVolumeScale),
55 DECLARE_NAPI_FUNCTION("getAudioVolumeScale", GetAudioVolumeScale),
56 DECLARE_NAPI_FUNCTION("getSupportedHapticsFeatures", GetSupportedHapticsFeatures),
57 DECLARE_NAPI_FUNCTION("setHapticsFeature", SetHapticsFeature),
58 DECLARE_NAPI_FUNCTION("getHapticsFeature", GetHapticsFeature),
59 };
60
61 status = napi_define_class(env, SYSTEM_TONE_PLAYER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
62 SystemTonePlayerNapiConstructor, nullptr, sizeof(system_tone_player_prop) / sizeof(system_tone_player_prop[0]),
63 system_tone_player_prop, &ctorObj);
64 if (status == napi_ok) {
65 if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
66 status = napi_set_named_property(env, exports, SYSTEM_TONE_PLAYER_NAPI_CLASS_NAME.c_str(), ctorObj);
67 if (status == napi_ok) {
68 return exports;
69 }
70 }
71 }
72
73 return nullptr;
74 }
75
SystemTonePlayerNapiConstructor(napi_env env,napi_callback_info info)76 napi_value SystemTonePlayerNapi::SystemTonePlayerNapiConstructor(napi_env env, napi_callback_info info)
77 {
78 napi_status status;
79 napi_value result = nullptr;
80 napi_value thisVar = nullptr;
81
82 napi_get_undefined(env, &result);
83 status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
84 if (status == napi_ok && thisVar != nullptr) {
85 std::unique_ptr<SystemTonePlayerNapi> obj = std::make_unique<SystemTonePlayerNapi>();
86 if (obj != nullptr) {
87 ObjectRefMap<SystemTonePlayerNapi>::Insert(obj.get());
88 obj->env_ = env;
89 if (obj->sSystemTonePlayer_ != nullptr) {
90 obj->systemTonePlayer_ = move(obj->sSystemTonePlayer_);
91 } else {
92 MEDIA_LOGE("Failed to create sSystemTonePlayer_ instance.");
93 return result;
94 }
95
96 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
97 SystemTonePlayerNapi::SystemTonePlayerNapiDestructor, nullptr, nullptr);
98 if (status == napi_ok) {
99 obj.release();
100 return thisVar;
101 } else {
102 ObjectRefMap<SystemTonePlayerNapi>::Erase(obj.get());
103 MEDIA_LOGE("Failed to wrap the native system tone player object with JS.");
104 }
105 }
106 }
107
108 return result;
109 }
110
SystemTonePlayerNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)111 void SystemTonePlayerNapi::SystemTonePlayerNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
112 {
113 SystemTonePlayerNapi *systemTonePlayerHelper = reinterpret_cast<SystemTonePlayerNapi*>(nativeObject);
114 if (systemTonePlayerHelper != nullptr) {
115 ObjectRefMap<SystemTonePlayerNapi>::DecreaseRef(systemTonePlayerHelper);
116 }
117 }
118
GetSystemTonePlayerInstance(napi_env env,std::shared_ptr<SystemTonePlayer> & systemTonePlayer)119 napi_value SystemTonePlayerNapi::GetSystemTonePlayerInstance(napi_env env,
120 std::shared_ptr<SystemTonePlayer> &systemTonePlayer)
121 {
122 napi_status status;
123 napi_value result = nullptr;
124 napi_value ctor;
125
126 status = napi_get_reference_value(env, sConstructor_, &ctor);
127 if (status == napi_ok) {
128 sSystemTonePlayer_ = systemTonePlayer;
129 status = napi_new_instance(env, ctor, 0, nullptr, &result);
130 if (status == napi_ok) {
131 return result;
132 } else {
133 MEDIA_LOGE("GetSystemTonePlayerInstance: New instance could not be obtained.");
134 }
135 }
136
137 napi_get_undefined(env, &result);
138 return result;
139 }
140
CommonAsyncCallbackComplete(napi_env env,napi_status status,void * data)141 void SystemTonePlayerNapi::CommonAsyncCallbackComplete(napi_env env, napi_status status, void* data)
142 {
143 auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
144 napi_value callback = nullptr;
145 napi_value retVal = nullptr;
146 napi_value result[2] = {};
147
148 napi_get_undefined(env, &result[PARAM1]);
149 if (!context->status) {
150 napi_get_undefined(env, &result[PARAM0]);
151 } else {
152 napi_value message = nullptr;
153 napi_create_string_utf8(env, "Error: Operation is not supported or failed", NAPI_AUTO_LENGTH, &message);
154 napi_create_error(env, nullptr, message, &result[PARAM0]);
155 }
156
157 if (context->deferred) {
158 if (!context->status) {
159 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
160 } else {
161 napi_reject_deferred(env, context->deferred, result[PARAM0]);
162 }
163 } else {
164 napi_get_reference_value(env, context->callbackRef, &callback);
165 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
166 napi_delete_reference(env, context->callbackRef);
167 }
168 napi_delete_async_work(env, context->work);
169
170 delete context;
171 context = nullptr;
172 }
173
GetTitleAsyncCallbackComplete(napi_env env,napi_status status,void * data)174 void SystemTonePlayerNapi::GetTitleAsyncCallbackComplete(napi_env env, napi_status status, void *data)
175 {
176 auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
177 napi_value getTitleCallback = nullptr;
178 napi_value retVal = nullptr;
179 napi_value result[2] = {};
180
181 if (!context->status) {
182 napi_get_undefined(env, &result[PARAM0]);
183 napi_create_string_utf8(env, context->title.c_str(), NAPI_AUTO_LENGTH, &result[PARAM1]);
184 } else {
185 napi_value message = nullptr;
186 napi_create_string_utf8(env, "GetTitle Error: Operation is not supported or failed",
187 NAPI_AUTO_LENGTH, &message);
188 napi_create_error(env, nullptr, message, &result[PARAM0]);
189 napi_get_undefined(env, &result[PARAM1]);
190 }
191
192 if (context->deferred) {
193 if (!context->status) {
194 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
195 } else {
196 napi_reject_deferred(env, context->deferred, result[PARAM0]);
197 }
198 } else {
199 napi_get_reference_value(env, context->callbackRef, &getTitleCallback);
200 napi_call_function(env, nullptr, getTitleCallback, ARGS_TWO, result, &retVal);
201 napi_delete_reference(env, context->callbackRef);
202 }
203 napi_delete_async_work(env, context->work);
204
205 delete context;
206 context = nullptr;
207 }
208
GetTitle(napi_env env,napi_callback_info info)209 napi_value SystemTonePlayerNapi::GetTitle(napi_env env, napi_callback_info info)
210 {
211 napi_value result = nullptr;
212 napi_value resource = nullptr;
213 size_t argc = ARGS_ONE;
214 napi_value argv[ARGS_ONE] = {0};
215 napi_value thisVar = nullptr;
216 const int32_t refCount = 1;
217
218 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
219 napi_get_undefined(env, &result);
220 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result, "GetTitle: napi_get_cb_info failed");
221
222 NAPI_ASSERT(env, argc <= ARGS_ONE, "GetTitle: requires 1 parameter maximum");
223 std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
224 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
225 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
226 if (argc == ARGS_ONE) {
227 napi_valuetype valueType = napi_undefined;
228 napi_typeof(env, argv[PARAM0], &valueType);
229 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
230 "GetTitle: the param type is not napi_function");
231 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
232 } else {
233 napi_create_promise(env, &asyncContext->deferred, &result);
234 }
235
236 napi_create_string_utf8(env, "GetTitle", NAPI_AUTO_LENGTH, &resource);
237 status = napi_create_async_work(env, nullptr, resource,
238 [](napi_env env, void *data) {
239 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
240 auto obj = reinterpret_cast<SystemTonePlayerNapi*>(context->objectInfo);
241 ObjectRefMap objectGuard(obj);
242 auto *napiSystemTonePlayer = objectGuard.GetPtr();
243 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
244 MEDIA_LOGE("The system tone player is nullptr!");
245 context->status = MSERR_INVALID_STATE;
246 return;
247 }
248 context->title = napiSystemTonePlayer->systemTonePlayer_->GetTitle();
249 context->status = MSERR_OK;
250 },
251 GetTitleAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
252 if (status != napi_ok) {
253 MEDIA_LOGE("GetTitle: Failed to get create async work");
254 napi_get_undefined(env, &result);
255 } else {
256 napi_queue_async_work(env, asyncContext->work);
257 asyncContext.release();
258 }
259 }
260
261 return result;
262 }
263
Prepare(napi_env env,napi_callback_info info)264 napi_value SystemTonePlayerNapi::Prepare(napi_env env, napi_callback_info info)
265 {
266 napi_status status;
267 napi_value result = nullptr;
268 napi_value resource = nullptr;
269 size_t argc = ARGS_ONE;
270 napi_value argv[ARGS_ONE] = {0};
271 napi_value thisVar = nullptr;
272 const int32_t refCount = 1;
273
274 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
275 napi_get_undefined(env, &result);
276 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
277 "Prepare: Failed to retrieve details about the callback");
278
279 NAPI_ASSERT(env, argc <= ARGS_ONE, "Prepare: requires 1 parameter maximum");
280 std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
281 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
282 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
283 if (argc == ARGS_ONE) {
284 napi_valuetype valueType = napi_undefined;
285 napi_typeof(env, argv[PARAM0], &valueType);
286 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
287 "Prepare: the param type is not napi_function");
288 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
289 } else {
290 napi_create_promise(env, &asyncContext->deferred, &result);
291 }
292
293 napi_create_string_utf8(env, "Prepare", NAPI_AUTO_LENGTH, &resource);
294 status = napi_create_async_work(env, nullptr, resource,
295 [](napi_env env, void* data) {
296 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
297 auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
298 ObjectRefMap objectGuard(obj);
299 auto *napiSystemTonePlayer = objectGuard.GetPtr();
300 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
301 MEDIA_LOGE("The system tone player is nullptr!");
302 context->status = MSERR_INVALID_STATE;
303 return;
304 }
305 context->status = napiSystemTonePlayer->systemTonePlayer_->Prepare();
306 },
307 CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
308 if (status != napi_ok) {
309 MEDIA_LOGE("Prepare: Failed to get create async work");
310 napi_get_undefined(env, &result);
311 } else {
312 napi_queue_async_work(env, asyncContext->work);
313 asyncContext.release();
314 }
315 }
316
317 return result;
318 }
319
StartAsyncCallbackComplete(napi_env env,napi_status status,void * data)320 void SystemTonePlayerNapi::StartAsyncCallbackComplete(napi_env env, napi_status status, void *data)
321 {
322 auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
323 napi_value getTitleCallback = nullptr;
324 napi_value retVal = nullptr;
325 napi_value result[2] = {};
326
327 if (!context->status) {
328 napi_get_undefined(env, &result[PARAM0]);
329 napi_create_int32(env, context->streamID, &result[PARAM1]);
330 } else {
331 napi_value message = nullptr;
332 napi_create_string_utf8(env, "GetTitle Error: Operation is not supported or failed",
333 NAPI_AUTO_LENGTH, &message);
334 napi_create_error(env, nullptr, message, &result[PARAM0]);
335 napi_get_undefined(env, &result[PARAM1]);
336 }
337
338 if (context->deferred) {
339 if (!context->status) {
340 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
341 } else {
342 napi_reject_deferred(env, context->deferred, result[PARAM0]);
343 }
344 } else {
345 napi_get_reference_value(env, context->callbackRef, &getTitleCallback);
346 napi_call_function(env, nullptr, getTitleCallback, ARGS_TWO, result, &retVal);
347 napi_delete_reference(env, context->callbackRef);
348 }
349 napi_delete_async_work(env, context->work);
350
351 delete context;
352 context = nullptr;
353 }
354
Start(napi_env env,napi_callback_info info)355 napi_value SystemTonePlayerNapi::Start(napi_env env, napi_callback_info info)
356 {
357 napi_value result = nullptr;
358 napi_value resource = nullptr;
359 napi_value property = nullptr;
360 size_t argc = ARGS_ONE;
361 napi_value argv[ARGS_TWO] = {0};
362 napi_value thisVar = nullptr;
363 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
364 napi_get_undefined(env, &result);
365 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result, "Start: napi_get_cb_info failed");
366 NAPI_ASSERT(env, argc <= ARGS_TWO, "Start: requires 2 parameter maximum");
367
368 std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
369 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
370 CHECK_AND_RETURN_RET_LOG(status == napi_ok && asyncContext->objectInfo != nullptr, result,
371 "Start: napi_unwrap failed or objectInfo is nullptr.");
372
373 if (argc == 0) {
374 napi_create_promise(env, &asyncContext->deferred, &result);
375 }
376 for (size_t i = PARAM0; i < argc; i++) {
377 napi_valuetype valueType = napi_undefined;
378 napi_typeof(env, argv[i], &valueType);
379 if (i == PARAM0 && valueType == napi_object) {
380 if (napi_get_named_property(env, argv[PARAM0], "muteAudio", &property) == napi_ok) {
381 napi_get_value_bool(env, property, &(asyncContext->systemToneOptions.muteAudio));
382 }
383 if (napi_get_named_property(env, argv[PARAM0], "muteHaptics", &property) == napi_ok) {
384 napi_get_value_bool(env, property, &(asyncContext->systemToneOptions.muteHaptics));
385 }
386 if (argc == ARGS_ONE) {
387 napi_create_promise(env, &asyncContext->deferred, &result);
388 }
389 } else if ((i == PARAM0 || i == PARAM1) && valueType == napi_function) {
390 napi_create_reference(env, argv[PARAM0], 1, &asyncContext->callbackRef);
391 } else {
392 NAPI_ASSERT(env, false, "Start: type mismatch");
393 }
394 }
395
396 napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
397 status = napi_create_async_work(env, nullptr, resource, AsyncStart,
398 StartAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
399 if (status != napi_ok) {
400 napi_get_undefined(env, &result);
401 } else {
402 napi_queue_async_work(env, asyncContext->work);
403 asyncContext.release();
404 }
405 return result;
406 }
407
AsyncStart(napi_env env,void * data)408 void SystemTonePlayerNapi::AsyncStart(napi_env env, void *data)
409 {
410 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
411 auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
412 ObjectRefMap objectGuard(obj);
413 auto *napiSystemTonePlayer = objectGuard.GetPtr();
414 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
415 MEDIA_LOGE("The system tone player is nullptr!");
416 context->status = MSERR_INVALID_STATE;
417 return;
418 }
419 context->streamID = napiSystemTonePlayer->systemTonePlayer_->Start(context->systemToneOptions);
420 context->status = MSERR_OK;
421 }
422
Stop(napi_env env,napi_callback_info info)423 napi_value SystemTonePlayerNapi::Stop(napi_env env, napi_callback_info info)
424 {
425 napi_status status;
426 napi_value result = nullptr;
427 napi_value resource = nullptr;
428 size_t argc = ARGS_ONE;
429 napi_value argv[ARGS_TWO] = {0};
430 napi_value thisVar = nullptr;
431 const int32_t refCount = 1;
432
433 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
434 napi_get_undefined(env, &result);
435 if (status != napi_ok || thisVar == nullptr) {
436 MEDIA_LOGE("Stop: Failed to retrieve details about the callback");
437 return result;
438 }
439
440 NAPI_ASSERT(env, argc == ARGS_ONE || argc == ARGS_TWO, "Stop: requires 1 or 2 parameter");
441 std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
442 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
443 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
444 napi_valuetype valueType = napi_undefined;
445 napi_typeof(env, argv[PARAM0], &valueType);
446 if (valueType == napi_number) {
447 napi_get_value_int32(env, argv[PARAM0], &(asyncContext->streamID));
448 napi_create_promise(env, &asyncContext->deferred, &result);
449 } else {
450 NAPI_ASSERT(env, false, "Stop: type mismatch");
451 }
452 if (argc == ARGS_TWO) {
453 napi_typeof(env, argv[PARAM1], &valueType);
454 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result, "Stop: the param type is not napi_function");
455 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
456 } else {
457 napi_create_promise(env, &asyncContext->deferred, &result);
458 }
459
460 napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
461 status = napi_create_async_work(env, nullptr, resource, AsyncStop,
462 CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
463 if (status != napi_ok) {
464 MEDIA_LOGE("Stop: Failed to get create async work");
465 napi_get_undefined(env, &result);
466 } else {
467 napi_queue_async_work(env, asyncContext->work);
468 asyncContext.release();
469 }
470 }
471
472 return result;
473 }
474
AsyncStop(napi_env env,void * data)475 void SystemTonePlayerNapi::AsyncStop(napi_env env, void *data)
476 {
477 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
478 auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
479 ObjectRefMap objectGuard(obj);
480 auto *napiSystemTonePlayer = objectGuard.GetPtr();
481 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
482 MEDIA_LOGE("The system tone player is nullptr!");
483 context->status = MSERR_INVALID_STATE;
484 return;
485 }
486 context->status = napiSystemTonePlayer->systemTonePlayer_->Stop(context->streamID);
487 }
488
Release(napi_env env,napi_callback_info info)489 napi_value SystemTonePlayerNapi::Release(napi_env env, napi_callback_info info)
490 {
491 napi_status status;
492 napi_value result = nullptr;
493 napi_value resource = nullptr;
494 size_t argc = ARGS_ONE;
495 napi_value argv[ARGS_ONE] = {0};
496 napi_value thisVar = nullptr;
497 const int32_t refCount = 1;
498
499 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
500 napi_get_undefined(env, &result);
501 if (status != napi_ok || thisVar == nullptr) {
502 MEDIA_LOGE("Release: Failed to retrieve details about the callback");
503 return result;
504 }
505
506 NAPI_ASSERT(env, argc <= ARGS_ONE, "Release: requires 1 parameter maximum");
507 std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
508 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
509 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
510 if (argc == ARGS_ONE) {
511 napi_valuetype valueType = napi_undefined;
512 napi_typeof(env, argv[PARAM0], &valueType);
513 CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
514 "Release: the param type is not napi_function");
515 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
516 } else {
517 napi_create_promise(env, &asyncContext->deferred, &result);
518 }
519
520 napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
521 status = napi_create_async_work(env, nullptr, resource, AsyncRelease,
522 CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
523 if (status != napi_ok) {
524 MEDIA_LOGE("Release: Failed to get create async work");
525 napi_get_undefined(env, &result);
526 } else {
527 napi_queue_async_work(env, asyncContext->work);
528 asyncContext.release();
529 }
530 }
531
532 return result;
533 }
534
AsyncRelease(napi_env env,void * data)535 void SystemTonePlayerNapi::AsyncRelease(napi_env env, void *data)
536 {
537 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
538 auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
539 ObjectRefMap objectGuard(obj);
540 auto *napiSystemTonePlayer = objectGuard.GetPtr();
541 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
542 MEDIA_LOGE("The system tone player is nullptr!");
543 context->status = MSERR_INVALID_STATE;
544 return;
545 }
546 context->status = napiSystemTonePlayer->systemTonePlayer_->Release();
547 }
548
SetAudioVolumeScale(napi_env env,napi_callback_info info)549 napi_value SystemTonePlayerNapi::SetAudioVolumeScale(napi_env env, napi_callback_info info)
550 {
551 napi_status status;
552 napi_value result = nullptr;
553 size_t argc = ARGS_ONE;
554 napi_value argv[ARGS_TWO] = {0};
555 napi_value thisVar = nullptr;
556
557 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
558 napi_get_undefined(env, &result);
559 if (status != napi_ok || thisVar == nullptr) {
560 MEDIA_LOGE("SetAudioVolumeScale: Failed to retrieve details about the callback");
561 return result;
562 }
563
564 NAPI_ASSERT(env, argc >= ARGS_ONE, "SetAudioVolumeScale: requires 1 parameter");
565 std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
566 SystemTonePlayerNapi *objectInfo = nullptr;
567 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&objectInfo));
568 if (status == napi_ok && objectInfo != nullptr) {
569 napi_valuetype valueType = napi_undefined;
570 napi_typeof(env, argv[PARAM0], &valueType);
571 NAPI_ASSERT(env, valueType == napi_number, "SetAudioVolumeScale: type mismatch");
572 double value;
573 napi_get_value_double(env, argv[PARAM0], &value);
574 float volume = static_cast<float>(value);
575 ObjectRefMap objectGuard(objectInfo);
576 auto *napiSystemTonePlayer = objectGuard.GetPtr();
577 int32_t ret = napiSystemTonePlayer->systemTonePlayer_->SetAudioVolume(volume);
578 if (ret != MSERR_OK) {
579 napi_throw_error(env, std::to_string(ret).c_str(),
580 "SetAudioVolumeScale: Operation is not supported or failed");
581 }
582 }
583 return result;
584 }
585
GetAudioVolumeScale(napi_env env,napi_callback_info info)586 napi_value SystemTonePlayerNapi::GetAudioVolumeScale(napi_env env, napi_callback_info info)
587 {
588 napi_value result = nullptr;
589 size_t argc = ARGS_ONE;
590 napi_value argv[ARGS_ONE] = {0};
591 napi_value thisVar = nullptr;
592
593 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
594 napi_get_undefined(env, &result);
595 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
596 "GetAudioVolume: napi_get_cb_info failed");
597
598 SystemTonePlayerNapi* objectInfo = nullptr;
599 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&objectInfo));
600 if (status == napi_ok && objectInfo != nullptr) {
601 ObjectRefMap objectGuard(objectInfo);
602 auto *napiSystemTonePlayer = objectGuard.GetPtr();
603 float volume;
604 int32_t ret = napiSystemTonePlayer->systemTonePlayer_->GetAudioVolume(volume);
605 if (ret != MSERR_OK) {
606 napi_throw_error(env, std::to_string(ret).c_str(),
607 "SetAudioVolumeScale: Operation is not supported or failed");
608 } else {
609 napi_create_double(env, static_cast<double>(volume), &result);
610 }
611 }
612 return result;
613 }
614
GetSupportHapticsFeaturesComplete(napi_env env,napi_status status,void * data)615 static void GetSupportHapticsFeaturesComplete(napi_env env, napi_status status, void *data)
616 {
617 auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
618 napi_value result[2] = {};
619 napi_status curStatus;
620
621 if (!context->status) {
622 napi_get_undefined(env, &result[PARAM0]);
623 napi_create_array_with_length(env, context->toneHapticsFeatures.size(), &result[PARAM1]);
624 napi_value value;
625 for (size_t i = 0; i < context->toneHapticsFeatures.size(); i++) {
626 value = nullptr;
627 curStatus = napi_create_int32(env, static_cast<int32_t>(context->toneHapticsFeatures[i]), &value);
628 if (curStatus != napi_ok || value == nullptr||
629 napi_set_element(env, result[PARAM1], i, value) != napi_ok) {
630 MEDIA_LOGE("GetSupportHapticsFeatures error : Failed to create number or add number to array");
631 napi_value message = nullptr;
632 napi_create_string_utf8(env,
633 "GetSupportHapticsFeatures Error: Failed to create number or add number to array",
634 NAPI_AUTO_LENGTH, &message);
635 napi_create_error(env, nullptr, message, &result[PARAM0]);
636 napi_get_undefined(env, &result[PARAM1]);
637 context->status = MSERR_NO_MEMORY;
638 break;
639 }
640 }
641 } else {
642 napi_value message = nullptr;
643 napi_create_string_utf8(env, "GetSupportHapticsFeatures Error: Operation is not supported or failed",
644 NAPI_AUTO_LENGTH, &message);
645 napi_create_error(env, nullptr, message, &result[PARAM0]);
646 napi_get_undefined(env, &result[PARAM1]);
647 }
648
649 if (context->deferred) {
650 if (!context->status) {
651 napi_resolve_deferred(env, context->deferred, result[PARAM1]);
652 } else {
653 napi_reject_deferred(env, context->deferred, result[PARAM0]);
654 }
655 }
656 napi_delete_async_work(env, context->work);
657
658 delete context;
659 context = nullptr;
660 }
661
GetSupportedHapticsFeatures(napi_env env,napi_callback_info info)662 napi_value SystemTonePlayerNapi::GetSupportedHapticsFeatures(napi_env env, napi_callback_info info)
663 {
664 napi_value result = nullptr;
665 napi_value resource = nullptr;
666 size_t argc = ARGS_ONE;
667 napi_value argv[ARGS_ONE] = {0};
668 napi_value thisVar = nullptr;
669
670 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
671 napi_get_undefined(env, &result);
672 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
673 "GetSupportHapticsFeatures: napi_get_cb_info failed");
674
675 std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
676 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
677 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
678 napi_create_promise(env, &asyncContext->deferred, &result);
679 napi_create_string_utf8(env, "GetSupportHapticsFeatures", NAPI_AUTO_LENGTH, &resource);
680 status = napi_create_async_work(env, nullptr, resource,
681 [](napi_env env, void *data) {
682 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
683 auto obj = reinterpret_cast<SystemTonePlayerNapi*>(context->objectInfo);
684 ObjectRefMap objectGuard(obj);
685 auto *napiSystemTonePlayer = objectGuard.GetPtr();
686 context->status = napiSystemTonePlayer->systemTonePlayer_->GetSupportHapticsFeatures(
687 context->toneHapticsFeatures);
688 },
689 GetSupportHapticsFeaturesComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
690 if (status != napi_ok) {
691 MEDIA_LOGE("GetSupportHapticsFeatures: Failed to get create async work");
692 napi_get_undefined(env, &result);
693 } else {
694 napi_queue_async_work(env, asyncContext->work);
695 asyncContext.release();
696 }
697 }
698 return result;
699 }
700
SetHapticsFeature(napi_env env,napi_callback_info info)701 napi_value SystemTonePlayerNapi::SetHapticsFeature(napi_env env, napi_callback_info info)
702 {
703 napi_status status;
704 napi_value result = nullptr;
705 size_t argc = ARGS_ONE;
706 napi_value argv[ARGS_TWO] = {0};
707 napi_value thisVar = nullptr;
708
709 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
710 napi_get_undefined(env, &result);
711 if (status != napi_ok || thisVar == nullptr) {
712 MEDIA_LOGE("SetHapticsFeature: Failed to retrieve details about the callback");
713 return result;
714 }
715
716 NAPI_ASSERT(env, argc >= ARGS_ONE, "SetHapticsFeature: requires 1 parameter");
717 SystemTonePlayerNapi* objectInfo = nullptr;
718 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&objectInfo));
719 if (status == napi_ok && objectInfo != nullptr) {
720 napi_valuetype valueType = napi_undefined;
721 napi_typeof(env, argv[PARAM0], &valueType);
722 NAPI_ASSERT(env, valueType == napi_number, "SetHapticsFeature: type mismatch");
723 ToneHapticsFeature toneHapticsFeature;
724 napi_get_value_int32(env, argv[PARAM0], reinterpret_cast<int32_t*>(&toneHapticsFeature));
725 ObjectRefMap objectGuard(objectInfo);
726 auto *napiSystemTonePlayer = objectGuard.GetPtr();
727 int32_t ret = napiSystemTonePlayer->systemTonePlayer_->SetHapticsFeature(
728 toneHapticsFeature);
729 if (ret != MSERR_OK) {
730 napi_throw_error(env, std::to_string(ret).c_str(),
731 "SetHapticsFeature: Operation is not supported or failed");
732 }
733 }
734 return result;
735 }
736
GetHapticsFeature(napi_env env,napi_callback_info info)737 napi_value SystemTonePlayerNapi::GetHapticsFeature(napi_env env, napi_callback_info info)
738 {
739 napi_value result = nullptr;
740 size_t argc = ARGS_ONE;
741 napi_value argv[ARGS_ONE] = {0};
742 napi_value thisVar = nullptr;
743
744 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
745 napi_get_undefined(env, &result);
746 CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
747 "GetHapticsFeature: napi_get_cb_info failed");
748
749 SystemTonePlayerNapi* objectInfo = nullptr;
750 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&objectInfo));
751 if (status == napi_ok && objectInfo != nullptr) {
752 ObjectRefMap objectGuard(objectInfo);
753 auto *napiSystemTonePlayer = objectGuard.GetPtr();
754 ToneHapticsFeature toneHapticsFeature;
755 int32_t ret = napiSystemTonePlayer->systemTonePlayer_->GetHapticsFeature(toneHapticsFeature);
756 if (ret != MSERR_OK) {
757 napi_throw_error(env, std::to_string(ret).c_str(),
758 "GetHapticsFeature: Operation is not supported or failed");
759 } else {
760 napi_create_int32(env, static_cast<int32_t>(toneHapticsFeature), &result);
761 }
762 }
763 return result;
764 }
765 } // namespace Media
766 } // namespace OHOS