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