1 /*
2 * Copyright (c) 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 "ability.h"
17 #include "audio_common_napi.h"
18 #include "audio_errors.h"
19 #include "audio_info.h"
20 #include "audio_log.h"
21 #include "audio_manager_napi.h"
22 #include "audio_parameters_napi.h"
23 #include "hilog/log.h"
24 #include "napi_base_context.h"
25 #include "securec.h"
26 #include "tone_player.h"
27 #include "toneplayer_napi.h"
28
29 using namespace std;
30 using OHOS::HiviewDFX::HiLog;
31 using OHOS::HiviewDFX::HiLogLabel;
32
33 namespace OHOS {
34 namespace AudioStandard {
35 static __thread napi_ref g_tonePlayerConstructor = nullptr;
36 std::unique_ptr<AudioRendererInfo> TonePlayerNapi::sRendererInfo_ = nullptr;
37 napi_ref TonePlayerNapi::toneType_ = nullptr;
38 mutex TonePlayerNapi::createMutex_;
39 namespace {
40 const int ARGS_ONE = 1;
41 const int ARGS_TWO = 2;
42
43 const int PARAM0 = 0;
44 const int PARAM1 = 1;
45
46 constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "TonePlayerNapi"};
47
48 #define GET_PARAMS(env, info, num) \
49 size_t argc = num; \
50 napi_value argv[num] = {0}; \
51 napi_value thisVar = nullptr; \
52 void *data; \
53 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)
54 }
TonePlayerNapi()55 TonePlayerNapi::TonePlayerNapi()
56 : env_(nullptr), tonePlayer_(nullptr) {}
57
58 TonePlayerNapi::~TonePlayerNapi() = default;
59
Destructor(napi_env env,void * nativeObject,void * finalize_hint)60 void TonePlayerNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
61 {
62 if (nativeObject != nullptr) {
63 auto obj = static_cast<TonePlayerNapi *>(nativeObject);
64 delete obj;
65 obj = nullptr;
66 }
67 }
68
AddNamedProperty(napi_env env,napi_value object,const std::string name,int32_t enumValue)69 napi_status TonePlayerNapi::AddNamedProperty(napi_env env, napi_value object,
70 const std::string name, int32_t enumValue)
71 {
72 napi_status status;
73 napi_value enumNapiValue;
74
75 status = napi_create_int32(env, enumValue, &enumNapiValue);
76 if (status == napi_ok) {
77 status = napi_set_named_property(env, object, name.c_str(), enumNapiValue);
78 }
79 return status;
80 }
81
CreateToneTypeObject(napi_env env)82 napi_value TonePlayerNapi::CreateToneTypeObject(napi_env env)
83 {
84 napi_value result = nullptr;
85 napi_status status;
86 AUDIO_DEBUG_LOG("CreateToneTypeObject start");
87 status = napi_create_object(env, &result);
88 if (status == napi_ok) {
89 AUDIO_DEBUG_LOG("CreateToneTypeObject: napi_create_object");
90 std::string propName;
91 for (auto &iter: toneTypeMap) {
92 propName = iter.first;
93 status = AddNamedProperty(env, result, propName, iter.second);
94 if (status != napi_ok) {
95 HiLog::Error(LABEL, "Failed to add named prop in CreateToneTypeObject!");
96 break;
97 }
98 propName.clear();
99 }
100 int32_t refCount = 1;
101 if (status == napi_ok) {
102 AUDIO_DEBUG_LOG("CreateToneTypeObject: AddNamedProperty");
103 status = napi_create_reference(env, result, refCount, &toneType_);
104 if (status == napi_ok) {
105 return result;
106 }
107 }
108 }
109 HiLog::Error(LABEL, "CreateToneTypeObject is Failed!");
110 napi_get_undefined(env, &result);
111
112 return result;
113 }
114
ParseRendererInfo(napi_env env,napi_value root,AudioRendererInfo * rendererInfo)115 bool TonePlayerNapi::ParseRendererInfo(napi_env env, napi_value root, AudioRendererInfo *rendererInfo)
116 {
117 napi_value tempValue = nullptr;
118 int32_t intValue = {0};
119 AUDIO_DEBUG_LOG("ParseRendererInfo::Init");
120 if (napi_get_named_property(env, root, "content", &tempValue) == napi_ok) {
121 napi_get_value_int32(env, tempValue, &intValue);
122 rendererInfo->contentType = static_cast<ContentType>(intValue);
123 }
124
125 if (napi_get_named_property(env, root, "usage", &tempValue) == napi_ok) {
126 napi_get_value_int32(env, tempValue, &intValue);
127 rendererInfo->streamUsage = static_cast<StreamUsage>(intValue);
128 }
129
130 if (napi_get_named_property(env, root, "rendererFlags", &tempValue) == napi_ok) {
131 napi_get_value_int32(env, tempValue, &(rendererInfo->rendererFlags));
132 }
133 return true;
134 }
135
CreateTonePlayerWrapper(napi_env env,unique_ptr<AudioRendererInfo> & rendererInfo)136 napi_value TonePlayerNapi::CreateTonePlayerWrapper(napi_env env, unique_ptr<AudioRendererInfo> &rendererInfo)
137 {
138 lock_guard<mutex> lock(createMutex_);
139 napi_status status;
140 napi_value result = nullptr;
141 napi_value constructor;
142
143 if (rendererInfo != nullptr) {
144 status = napi_get_reference_value(env, g_tonePlayerConstructor, &constructor);
145 if (status == napi_ok) {
146 sRendererInfo_ = move(rendererInfo);
147 status = napi_new_instance(env, constructor, 0, nullptr, &result);
148 sRendererInfo_.release();
149 if (status == napi_ok) {
150 return result;
151 }
152 }
153 HiLog::Error(LABEL, "Failed in CreateAudioRendererWrapper, %{public}d", status);
154 }
155
156 napi_get_undefined(env, &result);
157 return result;
158 }
159
CommonCallbackRoutine(napi_env env,TonePlayerAsyncContext * & asyncContext,const napi_value & valueParam)160 void TonePlayerNapi::CommonCallbackRoutine(napi_env env, TonePlayerAsyncContext* &asyncContext,
161 const napi_value &valueParam)
162 {
163 napi_value result[ARGS_TWO] = {0};
164 napi_value retVal;
165
166 if (!asyncContext->status) {
167 napi_get_undefined(env, &result[PARAM0]);
168 result[PARAM1] = valueParam;
169 } else {
170 napi_value message = nullptr;
171 std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
172 napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
173
174 napi_value code = nullptr;
175 napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
176
177 napi_create_error(env, code, message, &result[PARAM0]);
178 napi_get_undefined(env, &result[PARAM1]);
179 }
180
181 if (asyncContext->deferred) {
182 if (!asyncContext->status) {
183 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
184 } else {
185 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
186 }
187 } else {
188 napi_value callback = nullptr;
189 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
190 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
191 napi_delete_reference(env, asyncContext->callbackRef);
192 }
193 napi_delete_async_work(env, asyncContext->work);
194
195 delete asyncContext;
196 asyncContext = nullptr;
197 }
198
GetTonePlayerAsyncCallbackComplete(napi_env env,napi_status status,void * data)199 void TonePlayerNapi::GetTonePlayerAsyncCallbackComplete(napi_env env, napi_status status, void *data)
200 {
201 napi_value valueParam = nullptr;
202 auto asyncContext = static_cast<TonePlayerAsyncContext *>(data);
203
204 if (asyncContext != nullptr) {
205 if (!asyncContext->status) {
206 unique_ptr<AudioRendererInfo> rendererInfo = make_unique<AudioRendererInfo>();
207 rendererInfo->contentType = asyncContext->rendererInfo.contentType;
208 rendererInfo->streamUsage = asyncContext->rendererInfo.streamUsage;
209 rendererInfo->rendererFlags = asyncContext->rendererInfo.rendererFlags;
210
211 valueParam = CreateTonePlayerWrapper(env, rendererInfo);
212 }
213 CommonCallbackRoutine(env, asyncContext, valueParam);
214 } else {
215 HiLog::Error(LABEL, "ERROR: GetTonePlayerAsyncCallbackComplete asyncContext is Null!");
216 }
217 }
218
CreateTonePlayer(napi_env env,napi_callback_info info)219 napi_value TonePlayerNapi::CreateTonePlayer(napi_env env, napi_callback_info info)
220 {
221 HiLog::Info(LABEL, "%{public}s IN", __func__);
222 napi_status status;
223 napi_value result = nullptr;
224 bool inputRight = true;
225
226 GET_PARAMS(env, info, ARGS_TWO);
227
228 unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
229 CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "TonePlayerAsyncContext object creation failed");
230 if (argc < ARGS_ONE) {
231 asyncContext->status = NAPI_ERR_INVALID_PARAM;
232 }
233
234 for (size_t i = PARAM0; i < argc; i++) {
235 napi_valuetype valueType = napi_undefined;
236 napi_typeof(env, argv[i], &valueType);
237 if (i == PARAM0 && valueType == napi_object) {
238 if (!ParseRendererInfo(env, argv[i], &(asyncContext->rendererInfo))) {
239 HiLog::Error(LABEL, "Parsing of renderer options failed");
240 inputRight = false;
241 }
242 } else if (i == PARAM1) {
243 if (valueType == napi_function) {
244 napi_create_reference(env, argv[i], REFERENCE_CREATION_COUNT, &asyncContext->callbackRef);
245 }
246 break;
247 } else {
248 HiLog::Error(LABEL, "type mismatch");
249 inputRight = false;
250 }
251 }
252
253 if (asyncContext->callbackRef == nullptr) {
254 napi_create_promise(env, &asyncContext->deferred, &result);
255 } else {
256 napi_get_undefined(env, &result);
257 }
258 AUDIO_DEBUG_LOG("CreateTonePlayer::CreateAsyncWork");
259 napi_value resource = nullptr;
260 napi_create_string_utf8(env, "CreateTonePlayer", NAPI_AUTO_LENGTH, &resource);
261
262 if (!inputRight) {
263 status = napi_create_async_work(
264 env, nullptr, resource,
265 [](napi_env env, void *data) {
266 auto context = static_cast<TonePlayerAsyncContext *>(data);
267 context->status = NAPI_ERR_INVALID_PARAM;
268 HiLog::Error(LABEL, "CreateTonePlayer fail, invalid param!");
269 },
270 GetTonePlayerAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
271 } else {
272 status = napi_create_async_work(
273 env, nullptr, resource,
274 [](napi_env env, void *data) {
275 auto context = static_cast<TonePlayerAsyncContext *>(data);
276 context->status = SUCCESS;
277 },
278 GetTonePlayerAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
279 }
280 if (status != napi_ok) {
281 napi_delete_reference(env, asyncContext->callbackRef);
282 result = nullptr;
283 } else {
284 status = napi_queue_async_work(env, asyncContext->work);
285 if (status == napi_ok) {
286 asyncContext.release();
287 } else {
288 result = nullptr;
289 }
290 }
291 AUDIO_DEBUG_LOG("CreateTonePlayer::finished");
292 return result;
293 }
294
GetAbilityContext(napi_env env)295 static shared_ptr<AbilityRuntime::Context> GetAbilityContext(napi_env env)
296 {
297 HiLog::Info(LABEL, "Getting context with FA model");
298 auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
299 if (ability == nullptr) {
300 HiLog::Error(LABEL, "Failed to obtain ability in FA mode");
301 return nullptr;
302 }
303
304 auto faContext = ability->GetAbilityContext();
305 if (faContext == nullptr) {
306 HiLog::Error(LABEL, "GetAbilityContext returned null in FA model");
307 return nullptr;
308 }
309 return faContext;
310 }
311
Construct(napi_env env,napi_callback_info info)312 napi_value TonePlayerNapi::Construct(napi_env env, napi_callback_info info)
313 {
314 napi_status status;
315 napi_value result = nullptr;
316 napi_get_undefined(env, &result);
317
318 GET_PARAMS(env, info, ARGS_TWO);
319
320 unique_ptr<TonePlayerNapi> tonePlayerNapi = make_unique<TonePlayerNapi>();
321 CHECK_AND_RETURN_RET_LOG(tonePlayerNapi != nullptr, result, "No memory");
322
323 tonePlayerNapi->env_ = env;
324 AudioRendererInfo rendererInfo = {};
325 CHECK_AND_RETURN_RET_LOG(sRendererInfo_ != nullptr, result, "Construct sRendererInfo_ is null");
326 rendererInfo.contentType = sRendererInfo_->contentType;
327 rendererInfo.streamUsage = sRendererInfo_->streamUsage;
328 rendererInfo.rendererFlags = sRendererInfo_->rendererFlags;
329 std::shared_ptr<AbilityRuntime::Context> abilityContext = GetAbilityContext(env);
330 std::string cacheDir = "";
331 if (abilityContext != nullptr) {
332 cacheDir = abilityContext->GetCacheDir();
333 } else {
334 cacheDir = "/data/storage/el2/base/haps/entry/files";
335 }
336 tonePlayerNapi->tonePlayer_ = TonePlayer::Create(cacheDir, rendererInfo);
337
338 CHECK_AND_RETURN_RET_LOG(tonePlayerNapi->tonePlayer_ != nullptr, result, "Toneplayer Create failed");
339
340 status = napi_wrap(env, thisVar, static_cast<void*>(tonePlayerNapi.get()),
341 TonePlayerNapi::Destructor, nullptr, nullptr);
342 if (status == napi_ok) {
343 tonePlayerNapi.release();
344 return thisVar;
345 }
346
347 HiLog::Error(LABEL, "Failed in TonePlayerNapi::Construct()!");
348 return result;
349 }
350
toneTypeCheck(napi_env env,int32_t type)351 bool TonePlayerNapi::toneTypeCheck(napi_env env, int32_t type)
352 {
353 int32_t len = sizeof(toneTypeArr) / sizeof(toneTypeArr[0]);
354 for (int32_t i = 0; i < len; i++) {
355 if (toneTypeArr[i] == type) {
356 return true;
357 }
358 }
359 return false;
360 }
361
Load(napi_env env,napi_callback_info info)362 napi_value TonePlayerNapi::Load(napi_env env, napi_callback_info info)
363 {
364 napi_status status;
365 const int32_t refCount = 1;
366 napi_value result = nullptr;
367 bool inputRight = true;
368
369 GET_PARAMS(env, info, ARGS_TWO);
370
371 unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
372 CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, result, "Load TonePlayerAsyncContext object creation failed");
373 if (argc < ARGS_ONE) {
374 asyncContext->status = NAPI_ERR_INVALID_PARAM;
375 }
376
377 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
378 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
379 for (size_t i = PARAM0; i < argc; i++) {
380 napi_valuetype valueType = napi_undefined;
381 napi_typeof(env, argv[i], &valueType);
382
383 if (i == PARAM0 && valueType == napi_number) {
384 napi_get_value_int32(env, argv[PARAM0], &asyncContext->toneType);
385 if (!toneTypeCheck(env, asyncContext->toneType)) {
386 HiLog::Error(LABEL, "The Load parameter is invalid");
387 inputRight = false;
388 }
389 } else if (i == PARAM1) {
390 if (valueType == napi_function) {
391 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
392 }
393 break;
394 } else {
395 HiLog::Error(LABEL, "type mismatch");
396 inputRight = false;
397 }
398 }
399
400 if (asyncContext->callbackRef == nullptr) {
401 napi_create_promise(env, &asyncContext->deferred, &result);
402 } else {
403 napi_get_undefined(env, &result);
404 }
405
406 napi_value resource = nullptr;
407 napi_create_string_utf8(env, "Load", NAPI_AUTO_LENGTH, &resource);
408
409 if (!inputRight) {
410 status = napi_create_async_work(
411 env, nullptr, resource,
412 [](napi_env env, void *data) {
413 auto context = static_cast<TonePlayerAsyncContext *>(data);
414 context->status = NAPI_ERR_INVALID_PARAM;
415 HiLog::Error(LABEL, "The Load parameter is invalid");
416 },
417 VoidAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
418 } else {
419 status = napi_create_async_work(
420 env, nullptr, resource,
421 [](napi_env env, void *data) {
422 auto context = static_cast<TonePlayerAsyncContext *>(data);
423 if (context->status == SUCCESS) {
424 ToneType toneType = static_cast<ToneType>(context->toneType);
425 context->intValue = context->objectInfo->tonePlayer_->LoadTone(toneType);
426 if (context->intValue) {
427 context->status = SUCCESS;
428 } else {
429 context->status = NAPI_ERR_SYSTEM;
430 }
431 }
432 },
433 VoidAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
434 }
435 if (status != napi_ok) {
436 result = nullptr;
437 } else {
438 status = napi_queue_async_work(env, asyncContext->work);
439 if (status == napi_ok) {
440 asyncContext.release();
441 } else {
442 result = nullptr;
443 }
444 }
445 }
446 return result;
447 }
448
Start(napi_env env,napi_callback_info info)449 napi_value TonePlayerNapi::Start(napi_env env, napi_callback_info info)
450 {
451 napi_status status;
452 const int32_t refCount = 1;
453 napi_value result = nullptr;
454
455 GET_PARAMS(env, info, ARGS_ONE);
456
457 unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
458 CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "Start TonePlayerAsyncContext object creation failed");
459
460 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
461 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
462 if (argc > PARAM0) {
463 napi_valuetype valueType = napi_undefined;
464 napi_typeof(env, argv[PARAM0], &valueType);
465 if (valueType == napi_function) {
466 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
467 }
468 }
469
470 if (asyncContext->callbackRef == nullptr) {
471 napi_create_promise(env, &asyncContext->deferred, &result);
472 } else {
473 napi_get_undefined(env, &result);
474 }
475
476 napi_value resource = nullptr;
477 napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
478
479 status = napi_create_async_work(
480 env, nullptr, resource,
481 [](napi_env env, void *data) {
482 auto context = static_cast<TonePlayerAsyncContext *>(data);
483 context->isTrue = context->objectInfo->tonePlayer_->StartTone();
484 if (context->isTrue) {
485 context->status = SUCCESS;
486 } else {
487 HiLog::Error(LABEL, "Start call failed, wrong timing!");
488 context->status = NAPI_ERR_SYSTEM;
489 }
490 },
491 VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
492 if (status != napi_ok) {
493 result = nullptr;
494 } else {
495 status = napi_queue_async_work(env, asyncContext->work);
496 if (status == napi_ok) {
497 asyncContext.release();
498 } else {
499 result = nullptr;
500 }
501 }
502 }
503 return result;
504 }
505
Stop(napi_env env,napi_callback_info info)506 napi_value TonePlayerNapi::Stop(napi_env env, napi_callback_info info)
507 {
508 napi_status status;
509 const int32_t refCount = 1;
510 napi_value result = nullptr;
511
512 GET_PARAMS(env, info, ARGS_ONE);
513
514 unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
515 CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "Stop TonePlayerAsyncContext object creation failed");
516
517 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
518 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
519 if (argc > PARAM0) {
520 napi_valuetype valueType = napi_undefined;
521 napi_typeof(env, argv[PARAM0], &valueType);
522 if (valueType == napi_function) {
523 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
524 }
525 }
526
527 if (asyncContext->callbackRef == nullptr) {
528 napi_create_promise(env, &asyncContext->deferred, &result);
529 } else {
530 napi_get_undefined(env, &result);
531 }
532
533 napi_value resource = nullptr;
534 napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
535
536 status = napi_create_async_work(
537 env, nullptr, resource,
538 [](napi_env env, void *data) {
539 auto context = static_cast<TonePlayerAsyncContext *>(data);
540 context->isTrue = context->objectInfo->tonePlayer_->StopTone();
541 if (context->isTrue) {
542 context->status = SUCCESS;
543 } else {
544 HiLog::Error(LABEL, "Stop call failed, wrong timing");
545 context->status = NAPI_ERR_SYSTEM;
546 }
547 },
548 VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
549 if (status != napi_ok) {
550 result = nullptr;
551 } else {
552 status = napi_queue_async_work(env, asyncContext->work);
553 if (status == napi_ok) {
554 asyncContext.release();
555 } else {
556 result = nullptr;
557 }
558 }
559 }
560 return result;
561 }
562
Release(napi_env env,napi_callback_info info)563 napi_value TonePlayerNapi::Release(napi_env env, napi_callback_info info)
564 {
565 napi_status status;
566 const int32_t refCount = 1;
567 napi_value result = nullptr;
568
569 GET_PARAMS(env, info, ARGS_ONE);
570
571 unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
572 CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "Release TonePlayerAsyncContext object creation failed");
573
574 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
575 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
576 if (argc > PARAM0) {
577 napi_valuetype valueType = napi_undefined;
578 napi_typeof(env, argv[PARAM0], &valueType);
579 if (valueType == napi_function) {
580 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
581 }
582 }
583
584 if (asyncContext->callbackRef == nullptr) {
585 napi_create_promise(env, &asyncContext->deferred, &result);
586 } else {
587 napi_get_undefined(env, &result);
588 }
589
590 napi_value resource = nullptr;
591 napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
592
593 status = napi_create_async_work(
594 env, nullptr, resource,
595 [](napi_env env, void *data) {
596 auto context = static_cast<TonePlayerAsyncContext *>(data);
597 context->isTrue = context->objectInfo->tonePlayer_->Release();
598 if (context->isTrue) {
599 context->status = SUCCESS;
600 } else {
601 HiLog::Error(LABEL, "Release call failed, wrong timing");
602 context->status = NAPI_ERR_SYSTEM;
603 }
604 },
605 VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
606 if (status != napi_ok) {
607 result = nullptr;
608 } else {
609 status = napi_queue_async_work(env, asyncContext->work);
610 if (status == napi_ok) {
611 asyncContext.release();
612 } else {
613 result = nullptr;
614 }
615 }
616 }
617 return result;
618 }
619
VoidAsyncCallbackComplete(napi_env env,napi_status status,void * data)620 void TonePlayerNapi::VoidAsyncCallbackComplete(napi_env env, napi_status status, void *data)
621 {
622 auto asyncContext = static_cast<TonePlayerAsyncContext*>(data);
623 napi_value valueParam = nullptr;
624
625 if (asyncContext != nullptr) {
626 if (!asyncContext->status) {
627 napi_get_undefined(env, &valueParam);
628 }
629 CommonCallbackRoutine(env, asyncContext, valueParam);
630 } else {
631 HiLog::Error(LABEL, "ERROR: VoidAsyncCallbackComplete* is Null!");
632 }
633 }
634
Init(napi_env env,napi_value exports)635 napi_value TonePlayerNapi::Init(napi_env env, napi_value exports)
636 {
637 napi_status status;
638 napi_value constructor;
639 napi_value result = nullptr;
640 const int32_t refCount = 1;
641 napi_get_undefined(env, &result);
642 AUDIO_DEBUG_LOG("TonePlayerNapi::Init");
643 napi_property_descriptor audio_toneplayer_properties[] = {
644 DECLARE_NAPI_FUNCTION("load", Load),
645 DECLARE_NAPI_FUNCTION("start", Start),
646 DECLARE_NAPI_FUNCTION("stop", Stop),
647 DECLARE_NAPI_FUNCTION("release", Release),
648 };
649
650 napi_property_descriptor static_prop[] = {
651 DECLARE_NAPI_STATIC_FUNCTION("createTonePlayer", CreateTonePlayer),
652 DECLARE_NAPI_PROPERTY("ToneType", CreateToneTypeObject(env)),
653 };
654
655 status = napi_define_class(env, TONE_PLAYER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
656 sizeof(audio_toneplayer_properties) / sizeof(audio_toneplayer_properties[PARAM0]),
657 audio_toneplayer_properties, &constructor);
658 if (status != napi_ok) {
659 return result;
660 }
661
662 status = napi_create_reference(env, constructor, refCount, &g_tonePlayerConstructor);
663 if (status == napi_ok) {
664 AUDIO_DEBUG_LOG("TonePlayerNapi::Init napi_create_reference");
665 status = napi_set_named_property(env, exports, TONE_PLAYER_NAPI_CLASS_NAME.c_str(), constructor);
666 if (status == napi_ok) {
667 AUDIO_DEBUG_LOG("TonePlayerNapi::Init napi_set_named_property");
668 status = napi_define_properties(env, exports,
669 sizeof(static_prop) / sizeof(static_prop[PARAM0]), static_prop);
670 if (status == napi_ok) {
671 AUDIO_DEBUG_LOG("TonePlayerNapi::Init napi_define_properties");
672 return exports;
673 }
674 }
675 }
676
677 HiLog::Error(LABEL, "Failure in TonePlayerNapi::Init()");
678 return result;
679 }
680 }
681 } //