• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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