• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "audio_renderer_napi.h"
17 #include "ability.h"
18 #include "audio_renderer_callback_napi.h"
19 #include "renderer_data_request_callback_napi.h"
20 #include "renderer_period_position_callback_napi.h"
21 #include "renderer_position_callback_napi.h"
22 
23 #include "audio_common_napi.h"
24 #include "audio_errors.h"
25 #include "audio_log.h"
26 #include "audio_manager_napi.h"
27 #include "audio_parameters_napi.h"
28 #include "hilog/log.h"
29 #include "napi_base_context.h"
30 #include "securec.h"
31 
32 using namespace std;
33 using OHOS::HiviewDFX::HiLog;
34 using OHOS::HiviewDFX::HiLogLabel;
35 
36 namespace OHOS {
37 namespace AudioStandard {
38 static __thread napi_ref g_rendererConstructor = nullptr;
39 std::unique_ptr<AudioParameters> AudioRendererNapi::sAudioParameters_ = nullptr;
40 std::unique_ptr<AudioRendererOptions> AudioRendererNapi::sRendererOptions_ = nullptr;
41 napi_ref AudioRendererNapi::audioRendererRate_ = nullptr;
42 napi_ref AudioRendererNapi::interruptEventType_ = nullptr;
43 napi_ref AudioRendererNapi::interruptHintType_ = nullptr;
44 napi_ref AudioRendererNapi::interruptForceType_ = nullptr;
45 napi_ref AudioRendererNapi::audioState_ = nullptr;
46 napi_ref AudioRendererNapi::sampleFormat_ = nullptr;
47 mutex AudioRendererNapi::createMutex_;
48 int32_t AudioRendererNapi::isConstructSuccess_ = SUCCESS;
49 
50 namespace {
51     const int ARGS_ONE = 1;
52     const int ARGS_TWO = 2;
53     const int ARGS_THREE = 3;
54 
55     const int PARAM0 = 0;
56     const int PARAM1 = 1;
57     const int PARAM2 = 2;
58 
59     constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioRendererNapi"};
60 
61     const std::string MARK_REACH_CALLBACK_NAME = "markReach";
62     const std::string PERIOD_REACH_CALLBACK_NAME = "periodReach";
63     const std::string DATA_REQUEST_CALLBACK_NAME = "dataRequest";
64 
65 #define GET_PARAMS(env, info, num) \
66     size_t argc = num;             \
67     napi_value argv[num] = {0};    \
68     napi_value thisVar = nullptr;  \
69     void *data;                    \
70     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)
71 }
72 
AudioRendererNapi()73 AudioRendererNapi::AudioRendererNapi()
74     : audioRenderer_(nullptr), contentType_(CONTENT_TYPE_MUSIC), streamUsage_(STREAM_USAGE_MEDIA),
75       deviceRole_(OUTPUT_DEVICE), deviceType_(DEVICE_TYPE_SPEAKER), env_(nullptr),
76       scheduleFromApiCall_(true), doNotScheduleWrite_(false), isDrainWriteQInProgress_(false) {}
77 
78 AudioRendererNapi::~AudioRendererNapi() = default;
79 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)80 void AudioRendererNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
81 {
82     if (nativeObject != nullptr) {
83         auto obj = static_cast<AudioRendererNapi *>(nativeObject);
84         delete obj;
85         obj = nullptr;
86     }
87 }
88 
AddNamedProperty(napi_env env,napi_value object,const std::string name,int32_t enumValue)89 napi_status AudioRendererNapi::AddNamedProperty(napi_env env, napi_value object,
90                                                 const std::string name, int32_t enumValue)
91 {
92     napi_status status;
93     napi_value enumNapiValue;
94 
95     status = napi_create_int32(env, enumValue, &enumNapiValue);
96     if (status == napi_ok) {
97         status = napi_set_named_property(env, object, name.c_str(), enumNapiValue);
98     }
99 
100     return status;
101 }
102 
SetValueInt32(const napi_env & env,const std::string & fieldStr,const int intValue,napi_value & result)103 static void SetValueInt32(const napi_env& env, const std::string& fieldStr, const int intValue, napi_value &result)
104 {
105     napi_value value = nullptr;
106     napi_create_int32(env, intValue, &value);
107     napi_set_named_property(env, result, fieldStr.c_str(), value);
108 }
109 
GetNativeInterruptMode(int32_t interruptMode)110 static AudioStandard::InterruptMode  GetNativeInterruptMode(int32_t interruptMode)
111 {
112     AudioStandard::InterruptMode result;
113     switch (interruptMode) {
114         case AudioManagerNapi::InterruptMode::SHARE_MODE:
115             result = AudioStandard::InterruptMode::SHARE_MODE;
116             break;
117         case AudioManagerNapi::InterruptMode::INDEPENDENT_MODE:
118             result = AudioStandard::InterruptMode::INDEPENDENT_MODE;
119             break;
120         default:
121             result = AudioStandard::InterruptMode::SHARE_MODE;
122             HiLog::Error(LABEL, "Unknown interruptMode type, Set it to default SHARE_MODE!");
123             break;
124     }
125     return result;
126 }
127 
CreateAudioSampleFormatObject(napi_env env)128 napi_value AudioRendererNapi::CreateAudioSampleFormatObject(napi_env env)
129 {
130     napi_value result = nullptr;
131     napi_status status;
132     string propName;
133 
134     status = napi_create_object(env, &result);
135     if (status == napi_ok) {
136         for (int i = AudioRendererNapi::SAMPLE_FORMAT_INVALID; i <= AudioRendererNapi::SAMPLE_FORMAT_F32LE; i++) {
137             switch (i) {
138                 case AudioRendererNapi::SAMPLE_FORMAT_INVALID:
139                     propName = "SAMPLE_FORMAT_INVALID";
140                     break;
141                 case AudioRendererNapi::SAMPLE_FORMAT_U8:
142                     propName = "SAMPLE_FORMAT_U8";
143                     break;
144                 case AudioRendererNapi::SAMPLE_FORMAT_S16LE:
145                     propName = "SAMPLE_FORMAT_S16LE";
146                     break;
147                 case AudioRendererNapi::SAMPLE_FORMAT_S24LE:
148                     propName = "SAMPLE_FORMAT_S24LE";
149                     break;
150                 case AudioRendererNapi::SAMPLE_FORMAT_S32LE:
151                     propName = "SAMPLE_FORMAT_S32LE";
152                     break;
153                 case AudioRendererNapi::SAMPLE_FORMAT_F32LE:
154                     propName = "SAMPLE_FORMAT_F32LE";
155                     break;
156                 default:
157                     HiLog::Error(LABEL, "CreateAudioSampleFormatObject: No prop with this value try next value!");
158                     continue;
159             }
160             status = AddNamedProperty(env, result, propName, i);
161             if (status != napi_ok) {
162                 HiLog::Error(LABEL, "Failed to add named prop!");
163                 break;
164             }
165             propName.clear();
166         }
167         if (status == napi_ok) {
168             status = napi_create_reference(env, result, REFERENCE_CREATION_COUNT, &sampleFormat_);
169             if (status == napi_ok) {
170                 return result;
171             }
172         }
173     }
174     HiLog::Error(LABEL, "CreateAudioSampleFormatObject is Failed!");
175     napi_get_undefined(env, &result);
176 
177     return result;
178 }
179 
CreateAudioRendererRateObject(napi_env env)180 napi_value AudioRendererNapi::CreateAudioRendererRateObject(napi_env env)
181 {
182     napi_value result = nullptr;
183     napi_status status;
184     std::string propName;
185 
186     status = napi_create_object(env, &result);
187     if (status == napi_ok) {
188         for (auto &iter: rendererRateMap) {
189             propName = iter.first;
190             status = AddNamedProperty(env, result, propName, iter.second);
191             if (status != napi_ok) {
192                 HiLog::Error(LABEL, "Failed to add named prop!");
193                 break;
194             }
195             propName.clear();
196         }
197         if (status == napi_ok) {
198             status = napi_create_reference(env, result, REFERENCE_CREATION_COUNT, &audioRendererRate_);
199             if (status == napi_ok) {
200                 return result;
201             }
202         }
203     }
204     HiLog::Error(LABEL, "CreateAudioRendererRateObject is Failed!");
205     napi_get_undefined(env, &result);
206 
207     return result;
208 }
209 
CreateAudioStateObject(napi_env env)210 napi_value AudioRendererNapi::CreateAudioStateObject(napi_env env)
211 {
212     napi_value result = nullptr;
213     napi_status status;
214     std::string propName;
215     int32_t refCount = 1;
216 
217     status = napi_create_object(env, &result);
218     if (status == napi_ok) {
219         for (auto &iter: audioStateMap) {
220             propName = iter.first;
221             status = AddNamedProperty(env, result, propName, iter.second);
222             if (status != napi_ok) {
223                 HiLog::Error(LABEL, "Failed to add named prop in CreateAudioStateObject!");
224                 break;
225             }
226             propName.clear();
227         }
228         if (status == napi_ok) {
229             status = napi_create_reference(env, result, refCount, &audioState_);
230             if (status == napi_ok) {
231                 return result;
232             }
233         }
234     }
235     HiLog::Error(LABEL, "CreateAudioStateObject is Failed!");
236     napi_get_undefined(env, &result);
237 
238     return result;
239 }
240 
CreateInterruptEventTypeObject(napi_env env)241 napi_value AudioRendererNapi::CreateInterruptEventTypeObject(napi_env env)
242 {
243     napi_value result = nullptr;
244     napi_status status;
245     std::string propName;
246     int32_t refCount = 1;
247 
248     status = napi_create_object(env, &result);
249     if (status == napi_ok) {
250         for (auto &iter: interruptEventTypeMap) {
251             propName = iter.first;
252             status = AddNamedProperty(env, result, propName, iter.second);
253             if (status != napi_ok) {
254                 HiLog::Error(LABEL, "Failed to add named prop in CreateInterruptEventTypeObject!");
255                 break;
256             }
257             propName.clear();
258         }
259         if (status == napi_ok) {
260             status = napi_create_reference(env, result, refCount, &interruptEventType_);
261             if (status == napi_ok) {
262                 return result;
263             }
264         }
265     }
266     HiLog::Error(LABEL, "CreateInterruptEventTypeObject is Failed!");
267     napi_get_undefined(env, &result);
268 
269     return result;
270 }
271 
CreateInterruptForceTypeObject(napi_env env)272 napi_value AudioRendererNapi::CreateInterruptForceTypeObject(napi_env env)
273 {
274     napi_value result = nullptr;
275     napi_status status;
276     std::string propName;
277     int32_t refCount = 1;
278 
279     status = napi_create_object(env, &result);
280     if (status == napi_ok) {
281         for (auto &iter: interruptForceTypeMap) {
282             propName = iter.first;
283             status = AddNamedProperty(env, result, propName, iter.second);
284             if (status != napi_ok) {
285                 HiLog::Error(LABEL, "Failed to add named prop in CreateInterruptTypeObject!");
286                 break;
287             }
288             propName.clear();
289         }
290         if (status == napi_ok) {
291             status = napi_create_reference(env, result, refCount, &interruptForceType_);
292             if (status == napi_ok) {
293                 return result;
294             }
295         }
296     }
297     HiLog::Error(LABEL, "CreateInterruptForceTypeObject is Failed!");
298     napi_get_undefined(env, &result);
299 
300     return result;
301 }
302 
CreateInterruptHintTypeObject(napi_env env)303 napi_value AudioRendererNapi::CreateInterruptHintTypeObject(napi_env env)
304 {
305     napi_value result = nullptr;
306     napi_status status;
307     std::string propName;
308     int32_t refCount = 1;
309 
310     status = napi_create_object(env, &result);
311     if (status == napi_ok) {
312         for (auto &iter: interruptHintTypeMap) {
313             propName = iter.first;
314             status = AddNamedProperty(env, result, propName, iter.second);
315             if (status != napi_ok) {
316                 HiLog::Error(LABEL, "Failed to add named prop in CreateInterruptHintTypeObject!");
317                 break;
318             }
319             propName.clear();
320         }
321         if (status == napi_ok) {
322             status = napi_create_reference(env, result, refCount, &interruptHintType_);
323             if (status == napi_ok) {
324                 return result;
325             }
326         }
327     }
328     HiLog::Error(LABEL, "CreateInterruptHintTypeObject is Failed!");
329     napi_get_undefined(env, &result);
330 
331     return result;
332 }
333 
Init(napi_env env,napi_value exports)334 napi_value AudioRendererNapi::Init(napi_env env, napi_value exports)
335 {
336     napi_status status;
337     napi_value constructor;
338     napi_value result = nullptr;
339     const int32_t refCount = 1;
340     napi_get_undefined(env, &result);
341 
342     napi_property_descriptor audio_renderer_properties[] = {
343         DECLARE_NAPI_FUNCTION("setRenderRate", SetRenderRate),
344         DECLARE_NAPI_FUNCTION("getRenderRate", GetRenderRate),
345         DECLARE_NAPI_FUNCTION("start", Start),
346         DECLARE_NAPI_FUNCTION("write", Write),
347         DECLARE_NAPI_FUNCTION("getAudioTime", GetAudioTime),
348         DECLARE_NAPI_FUNCTION("drain", Drain),
349         DECLARE_NAPI_FUNCTION("pause", Pause),
350         DECLARE_NAPI_FUNCTION("stop", Stop),
351         DECLARE_NAPI_FUNCTION("release", Release),
352         DECLARE_NAPI_FUNCTION("getBufferSize", GetBufferSize),
353         DECLARE_NAPI_FUNCTION("getAudioStreamId", GetAudioStreamId),
354         DECLARE_NAPI_FUNCTION("setVolume", SetVolume),
355         DECLARE_NAPI_FUNCTION("on", On),
356         DECLARE_NAPI_FUNCTION("off", Off),
357         DECLARE_NAPI_FUNCTION("getRendererInfo", GetRendererInfo),
358         DECLARE_NAPI_FUNCTION("getStreamInfo", GetStreamInfo),
359         DECLARE_NAPI_FUNCTION("setInterruptMode", SetInterruptMode),
360         DECLARE_NAPI_GETTER("state", GetState)
361     };
362 
363     napi_property_descriptor static_prop[] = {
364         DECLARE_NAPI_STATIC_FUNCTION("createAudioRenderer", CreateAudioRenderer),
365         DECLARE_NAPI_PROPERTY("AudioRendererRate", CreateAudioRendererRateObject(env)),
366         DECLARE_NAPI_PROPERTY("InterruptType", CreateInterruptEventTypeObject(env)),
367         DECLARE_NAPI_PROPERTY("InterruptForceType", CreateInterruptForceTypeObject(env)),
368         DECLARE_NAPI_PROPERTY("InterruptHint", CreateInterruptHintTypeObject(env)),
369         DECLARE_NAPI_PROPERTY("AudioState", CreateAudioStateObject(env)),
370         DECLARE_NAPI_PROPERTY("AudioSampleFormat", CreateAudioSampleFormatObject(env)),
371     };
372 
373     status = napi_define_class(env, AUDIO_RENDERER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
374         sizeof(audio_renderer_properties) / sizeof(audio_renderer_properties[PARAM0]),
375         audio_renderer_properties, &constructor);
376     if (status != napi_ok) {
377         return result;
378     }
379 
380     status = napi_create_reference(env, constructor, refCount, &g_rendererConstructor);
381     if (status == napi_ok) {
382         status = napi_set_named_property(env, exports, AUDIO_RENDERER_NAPI_CLASS_NAME.c_str(), constructor);
383         if (status == napi_ok) {
384             status = napi_define_properties(env, exports,
385                                             sizeof(static_prop) / sizeof(static_prop[PARAM0]), static_prop);
386             if (status == napi_ok) {
387                 return exports;
388             }
389         }
390     }
391 
392     HiLog::Error(LABEL, "Failure in AudioRendererNapi::Init()");
393     return result;
394 }
395 
GetAbilityContext(napi_env env)396 static shared_ptr<AbilityRuntime::Context> GetAbilityContext(napi_env env)
397 {
398     HiLog::Info(LABEL, "Getting context with FA model");
399     auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
400     if (ability == nullptr) {
401         HiLog::Error(LABEL, "Failed to obtain ability in FA mode");
402         return nullptr;
403     }
404 
405     auto faContext = ability->GetAbilityContext();
406     if (faContext == nullptr) {
407         HiLog::Error(LABEL, "GetAbilityContext returned null in FA model");
408         return nullptr;
409     }
410 
411     return faContext;
412 }
413 
Construct(napi_env env,napi_callback_info info)414 napi_value AudioRendererNapi::Construct(napi_env env, napi_callback_info info)
415 {
416     napi_status status;
417     napi_value result = nullptr;
418     napi_get_undefined(env, &result);
419 
420     GET_PARAMS(env, info, ARGS_TWO);
421 
422     unique_ptr<AudioRendererNapi> rendererNapi = make_unique<AudioRendererNapi>();
423     CHECK_AND_RETURN_RET_LOG(rendererNapi != nullptr, result, "No memory");
424 
425     rendererNapi->env_ = env;
426     rendererNapi->contentType_ = sRendererOptions_->rendererInfo.contentType;
427     rendererNapi->streamUsage_ = sRendererOptions_->rendererInfo.streamUsage;
428     rendererNapi->rendererFlags_ = sRendererOptions_->rendererInfo.rendererFlags;
429 
430     AudioRendererOptions rendererOptions = {};
431     rendererOptions.streamInfo.samplingRate = sRendererOptions_->streamInfo.samplingRate;
432     rendererOptions.streamInfo.encoding = sRendererOptions_->streamInfo.encoding;
433     rendererOptions.streamInfo.format = sRendererOptions_->streamInfo.format;
434     rendererOptions.streamInfo.channels = sRendererOptions_->streamInfo.channels;
435     rendererOptions.rendererInfo.contentType = sRendererOptions_->rendererInfo.contentType;
436     rendererOptions.rendererInfo.streamUsage = sRendererOptions_->rendererInfo.streamUsage;
437     rendererOptions.rendererInfo.rendererFlags = sRendererOptions_->rendererInfo.rendererFlags;
438 
439     std::shared_ptr<AbilityRuntime::Context> abilityContext = GetAbilityContext(env);
440     std::string cacheDir = "";
441     if (abilityContext != nullptr) {
442         cacheDir = abilityContext->GetCacheDir();
443     } else {
444         cacheDir = "/data/storage/el2/base/haps/entry/files";
445     }
446     rendererNapi->audioRenderer_ = AudioRenderer::Create(cacheDir, rendererOptions);
447 
448     if (rendererNapi->audioRenderer_ == nullptr) {
449         HiLog::Error(LABEL, "Renderer Create failed");
450         unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
451         AudioRendererNapi::isConstructSuccess_ = NAPI_ERR_SYSTEM;
452     }
453 
454     if (rendererNapi->audioRenderer_ != nullptr && rendererNapi->callbackNapi_ == nullptr) {
455         rendererNapi->callbackNapi_ = std::make_shared<AudioRendererCallbackNapi>(env);
456         CHECK_AND_RETURN_RET_LOG(rendererNapi->callbackNapi_ != nullptr, result, "No memory");
457         int32_t ret = rendererNapi->audioRenderer_->SetRendererCallback(rendererNapi->callbackNapi_);
458         if (ret) {
459             AUDIO_DEBUG_LOG("AudioRendererNapi::Construct SetRendererCallback failed");
460         }
461     }
462 
463     status = napi_wrap(env, thisVar, static_cast<void*>(rendererNapi.get()),
464                        AudioRendererNapi::Destructor, nullptr, nullptr);
465     if (status == napi_ok) {
466         rendererNapi.release();
467         return thisVar;
468     }
469 
470     HiLog::Error(LABEL, "Failed in AudioRendererNapi::Construct()!");
471     return result;
472 }
473 
CreateAudioRenderer(napi_env env,napi_callback_info info)474 napi_value AudioRendererNapi::CreateAudioRenderer(napi_env env, napi_callback_info info)
475 {
476     HiLog::Info(LABEL, "%{public}s IN", __func__);
477     napi_status status;
478     napi_value result = nullptr;
479 
480     GET_PARAMS(env, info, ARGS_TWO);
481 
482     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
483     CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "AudioRendererAsyncContext object creation failed");
484     if (argc < ARGS_ONE) {
485         asyncContext->status = NAPI_ERR_INVALID_PARAM;
486     }
487 
488     for (size_t i = PARAM0; i < argc; i++) {
489         napi_valuetype valueType = napi_undefined;
490         napi_typeof(env, argv[i], &valueType);
491         if (i == PARAM0 && valueType == napi_object) {
492             if (!ParseRendererOptions(env, argv[i], &(asyncContext->rendererOptions))) {
493                 HiLog::Error(LABEL, "Parsing of renderer options failed");
494                 return result;
495             }
496         } else if (i == PARAM1) {
497             if (valueType == napi_function) {
498                 napi_create_reference(env, argv[i], REFERENCE_CREATION_COUNT, &asyncContext->callbackRef);
499             }
500             break;
501         } else {
502             asyncContext->status = NAPI_ERR_INVALID_PARAM;
503         }
504     }
505 
506     if (asyncContext->callbackRef == nullptr) {
507         napi_create_promise(env, &asyncContext->deferred, &result);
508     } else {
509         napi_get_undefined(env, &result);
510     }
511 
512     napi_value resource = nullptr;
513     napi_create_string_utf8(env, "CreateAudioRenderer", NAPI_AUTO_LENGTH, &resource);
514 
515     status = napi_create_async_work(
516         env, nullptr, resource,
517         [](napi_env env, void *data) {
518             auto context = static_cast<AudioRendererAsyncContext *>(data);
519             context->status = SUCCESS;
520         },
521         GetRendererAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
522     if (status != napi_ok) {
523         result = nullptr;
524     } else {
525         status = napi_queue_async_work(env, asyncContext->work);
526         if (status == napi_ok) {
527             asyncContext.release();
528         } else {
529             result = nullptr;
530         }
531     }
532     return result;
533 }
534 
CommonCallbackRoutine(napi_env env,AudioRendererAsyncContext * & asyncContext,const napi_value & valueParam)535 void AudioRendererNapi::CommonCallbackRoutine(napi_env env, AudioRendererAsyncContext* &asyncContext,
536                                               const napi_value &valueParam)
537 {
538     napi_value result[ARGS_TWO] = {0};
539     napi_value retVal;
540 
541     if (!asyncContext->status) {
542         napi_get_undefined(env, &result[PARAM0]);
543         result[PARAM1] = valueParam;
544     } else {
545         napi_value message = nullptr;
546         std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
547         napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
548 
549         napi_value code = nullptr;
550         napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
551 
552         napi_create_error(env, code, message, &result[PARAM0]);
553         napi_get_undefined(env, &result[PARAM1]);
554     }
555 
556     if (asyncContext->deferred) {
557         if (!asyncContext->status) {
558             napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
559         } else {
560             napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
561         }
562     } else {
563         napi_value callback = nullptr;
564         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
565         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
566         napi_delete_reference(env, asyncContext->callbackRef);
567     }
568     napi_delete_async_work(env, asyncContext->work);
569 
570     delete asyncContext;
571     asyncContext = nullptr;
572 }
573 
WriteAsyncCallbackComplete(napi_env env,napi_status status,void * data)574 void AudioRendererNapi::WriteAsyncCallbackComplete(napi_env env, napi_status status, void *data)
575 {
576     napi_value result[ARGS_TWO] = {0};
577     napi_value retVal;
578 
579     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
580 
581     if (asyncContext != nullptr) {
582         if (!asyncContext->status) {
583             napi_get_undefined(env, &result[PARAM0]);
584             napi_create_uint32(env, asyncContext->totalBytesWritten, &result[PARAM1]);
585         } else {
586             napi_value message = nullptr;
587             std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
588             napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
589 
590             napi_value code = nullptr;
591             napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
592 
593             napi_create_error(env, code, message, &result[PARAM0]);
594             napi_get_undefined(env, &result[PARAM1]);
595         }
596 
597         if (asyncContext->deferred) {
598             if (!asyncContext->status) {
599                 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
600             } else {
601                 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
602             }
603         } else {
604             napi_value callback = nullptr;
605             napi_get_reference_value(env, asyncContext->callbackRef, &callback);
606             napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
607             napi_delete_reference(env, asyncContext->callbackRef);
608         }
609         napi_delete_async_work(env, asyncContext->work);
610         // queue the next write request from internal queue to napi queue
611         if (!asyncContext->objectInfo->doNotScheduleWrite_ && !asyncContext->objectInfo->isDrainWriteQInProgress_) {
612             if (!asyncContext->objectInfo->writeRequestQ_.empty()) {
613                 napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
614                 asyncContext->objectInfo->writeRequestQ_.pop();
615             } else {
616                 asyncContext->objectInfo->scheduleFromApiCall_ = true;
617             }
618         }
619 
620         delete asyncContext;
621         asyncContext = nullptr;
622     } else {
623             HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
624     }
625 }
626 
PauseAsyncCallbackComplete(napi_env env,napi_status status,void * data)627 void AudioRendererNapi::PauseAsyncCallbackComplete(napi_env env, napi_status status, void *data)
628 {
629     napi_value result[ARGS_TWO] = {0};
630     napi_value retVal;
631 
632     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
633     napi_value valueParam = nullptr;
634 
635     if (asyncContext != nullptr) {
636         if (!asyncContext->status) {
637             // set pause result to doNotScheduleWrite_
638             asyncContext->objectInfo->doNotScheduleWrite_ = asyncContext->isTrue;
639             napi_get_undefined(env, &valueParam);
640         }
641         if (!asyncContext->status) {
642             napi_get_undefined(env, &result[PARAM0]);
643             result[PARAM1] = valueParam;
644         } else {
645             napi_value message = nullptr;
646             std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
647             napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
648 
649             napi_value code = nullptr;
650             napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
651 
652             napi_create_error(env, code, message, &result[PARAM0]);
653             napi_get_undefined(env, &result[PARAM1]);
654         }
655 
656         if (asyncContext->deferred) {
657             if (!asyncContext->status) {
658                 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
659             } else {
660                 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
661             }
662         } else {
663             napi_value callback = nullptr;
664             napi_get_reference_value(env, asyncContext->callbackRef, &callback);
665             napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
666             napi_delete_reference(env, asyncContext->callbackRef);
667         }
668         napi_delete_async_work(env, asyncContext->work);
669         // Pause failed . Continue Write
670         if (!asyncContext->isTrue) {
671             HiLog::Info(LABEL, "PauseAsyncCallbackComplete: Pasue failed, Continue Write");
672             if (!asyncContext->objectInfo->writeRequestQ_.empty()) {
673                 napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
674                 asyncContext->objectInfo->writeRequestQ_.pop();
675             } else {
676                 asyncContext->objectInfo->scheduleFromApiCall_ = true;
677             }
678         }
679 
680         delete asyncContext;
681         asyncContext = nullptr;
682     } else {
683             HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
684     }
685 }
686 
StartAsyncCallbackComplete(napi_env env,napi_status status,void * data)687 void AudioRendererNapi::StartAsyncCallbackComplete(napi_env env, napi_status status, void *data)
688 {
689     napi_value result[ARGS_TWO] = {0};
690     napi_value retVal;
691 
692     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
693     napi_value valueParam = nullptr;
694 
695     if (asyncContext != nullptr) {
696         if (!asyncContext->status) {
697             napi_get_undefined(env, &valueParam);
698         }
699         if (!asyncContext->status) {
700             napi_get_undefined(env, &result[PARAM0]);
701             result[PARAM1] = valueParam;
702         } else {
703             napi_value message = nullptr;
704             std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
705             napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
706 
707             napi_value code = nullptr;
708             napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
709 
710             napi_create_error(env, code, message, &result[PARAM0]);
711             napi_get_undefined(env, &result[PARAM1]);
712         }
713 
714         if (asyncContext->deferred) {
715             if (!asyncContext->status) {
716                 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
717             } else {
718                 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
719             }
720         } else {
721             napi_value callback = nullptr;
722             napi_get_reference_value(env, asyncContext->callbackRef, &callback);
723             napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
724             napi_delete_reference(env, asyncContext->callbackRef);
725         }
726         napi_delete_async_work(env, asyncContext->work);
727         // If start success , set doNotScheduleWrite_ = false and queue write request
728         if (asyncContext->isTrue) {
729             asyncContext->objectInfo->doNotScheduleWrite_ = false;
730             if (!asyncContext->objectInfo->writeRequestQ_.empty()) {
731                 napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
732                 asyncContext->objectInfo->writeRequestQ_.pop();
733             } else {
734                 asyncContext->objectInfo->scheduleFromApiCall_ = true;
735             }
736         }
737 
738         delete asyncContext;
739         asyncContext = nullptr;
740     } else {
741             HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
742     }
743 }
744 
StopAsyncCallbackComplete(napi_env env,napi_status status,void * data)745 void AudioRendererNapi::StopAsyncCallbackComplete(napi_env env, napi_status status, void *data)
746 {
747     napi_value result[ARGS_TWO] = {0};
748     napi_value retVal;
749 
750     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
751     napi_value valueParam = nullptr;
752 
753     if (asyncContext != nullptr) {
754         if (!asyncContext->status) {
755             // set pause result to doNotScheduleWrite_
756             asyncContext->objectInfo->doNotScheduleWrite_ = asyncContext->isTrue;
757             napi_get_undefined(env, &valueParam);
758         }
759         if (!asyncContext->status) {
760             napi_get_undefined(env, &result[PARAM0]);
761             result[PARAM1] = valueParam;
762         } else {
763             napi_value message = nullptr;
764             std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
765             napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
766 
767             napi_value code = nullptr;
768             napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
769 
770             napi_create_error(env, code, message, &result[PARAM0]);
771             napi_get_undefined(env, &result[PARAM1]);
772         }
773 
774         if (asyncContext->deferred) {
775             if (!asyncContext->status) {
776                 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
777             } else {
778                 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
779             }
780         } else {
781             napi_value callback = nullptr;
782             napi_get_reference_value(env, asyncContext->callbackRef, &callback);
783             napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
784             napi_delete_reference(env, asyncContext->callbackRef);
785         }
786         napi_delete_async_work(env, asyncContext->work);
787 
788         delete asyncContext;
789         asyncContext = nullptr;
790     } else {
791             HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
792     }
793 }
794 
SetFunctionAsyncCallbackComplete(napi_env env,napi_status status,void * data)795 void AudioRendererNapi::SetFunctionAsyncCallbackComplete(napi_env env, napi_status status, void *data)
796 {
797     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
798     napi_value valueParam = nullptr;
799 
800     if (asyncContext != nullptr) {
801         if (!asyncContext->status) {
802             napi_get_undefined(env, &valueParam);
803         }
804         CommonCallbackRoutine(env, asyncContext, valueParam);
805     } else {
806         HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
807     }
808 }
809 
IsTrueAsyncCallbackComplete(napi_env env,napi_status status,void * data)810 void AudioRendererNapi::IsTrueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
811 {
812     auto asyncContext = static_cast<AudioRendererAsyncContext*>(data);
813     napi_value valueParam = nullptr;
814 
815     if (asyncContext != nullptr) {
816         if (!asyncContext->status) {
817             napi_get_boolean(env, asyncContext->isTrue, &valueParam);
818         }
819         CommonCallbackRoutine(env, asyncContext, valueParam);
820     } else {
821         HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
822     }
823 }
824 
VoidAsyncCallbackComplete(napi_env env,napi_status status,void * data)825 void AudioRendererNapi::VoidAsyncCallbackComplete(napi_env env, napi_status status, void *data)
826 {
827     auto asyncContext = static_cast<AudioRendererAsyncContext*>(data);
828     napi_value valueParam = nullptr;
829 
830     if (asyncContext != nullptr) {
831         if (!asyncContext->status) {
832             napi_get_undefined(env, &valueParam);
833         }
834         CommonCallbackRoutine(env, asyncContext, valueParam);
835     } else {
836         HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
837     }
838 }
839 
GetBufferSizeAsyncCallbackComplete(napi_env env,napi_status status,void * data)840 void AudioRendererNapi::GetBufferSizeAsyncCallbackComplete(napi_env env, napi_status status, void *data)
841 {
842     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
843     napi_value valueParam = nullptr;
844 
845     if (asyncContext != nullptr) {
846         if (!asyncContext->status) {
847             napi_create_uint32(env, asyncContext->bufferSize, &valueParam);
848         }
849         CommonCallbackRoutine(env, asyncContext, valueParam);
850     } else {
851         HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
852     }
853 }
854 
GetAudioStreamIdCallbackComplete(napi_env env,napi_status status,void * data)855 void AudioRendererNapi::GetAudioStreamIdCallbackComplete(napi_env env, napi_status status, void *data)
856 {
857     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
858     napi_value valueParam = nullptr;
859 
860     if (asyncContext != nullptr) {
861         if (!asyncContext->status) {
862             napi_create_uint32(env, asyncContext->audioStreamId, &valueParam);
863         }
864         CommonCallbackRoutine(env, asyncContext, valueParam);
865     } else {
866         HiLog::Error(LABEL, "ERROR::GetAudioStreamIdCallbackComplete* is Null!");
867     }
868 }
869 
GetIntValueAsyncCallbackComplete(napi_env env,napi_status status,void * data)870 void AudioRendererNapi::GetIntValueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
871 {
872     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
873     napi_value valueParam = nullptr;
874 
875     if (asyncContext != nullptr) {
876         if (!asyncContext->status) {
877             napi_create_int32(env, asyncContext->intValue, &valueParam);
878         }
879         CommonCallbackRoutine(env, asyncContext, valueParam);
880     } else {
881         HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
882     }
883 }
884 
GetRendererAsyncCallbackComplete(napi_env env,napi_status status,void * data)885 void AudioRendererNapi::GetRendererAsyncCallbackComplete(napi_env env, napi_status status, void *data)
886 {
887     napi_value valueParam = nullptr;
888     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
889 
890     if (asyncContext != nullptr) {
891         if (!asyncContext->status) {
892             unique_ptr<AudioRendererOptions> rendererOptions = make_unique<AudioRendererOptions>();
893             rendererOptions->streamInfo.samplingRate = asyncContext->rendererOptions.streamInfo.samplingRate;
894             rendererOptions->streamInfo.encoding = asyncContext->rendererOptions.streamInfo.encoding;
895             rendererOptions->streamInfo.format = asyncContext->rendererOptions.streamInfo.format;
896             rendererOptions->streamInfo.channels = asyncContext->rendererOptions.streamInfo.channels;
897             rendererOptions->rendererInfo.contentType = asyncContext->rendererOptions.rendererInfo.contentType;
898             rendererOptions->rendererInfo.streamUsage = asyncContext->rendererOptions.rendererInfo.streamUsage;
899             rendererOptions->rendererInfo.rendererFlags = asyncContext->rendererOptions.rendererInfo.rendererFlags;
900 
901             valueParam = CreateAudioRendererWrapper(env, rendererOptions);
902             asyncContext->status = AudioRendererNapi::isConstructSuccess_;
903             AudioRendererNapi::isConstructSuccess_ = SUCCESS;
904         }
905         CommonCallbackRoutine(env, asyncContext, valueParam);
906     } else {
907         HiLog::Error(LABEL, "ERROR: GetRendererAsyncCallbackComplete asyncContext is Null!");
908     }
909 }
910 
GetInt64ValueAsyncCallbackComplete(napi_env env,napi_status status,void * data)911 void AudioRendererNapi::GetInt64ValueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
912 {
913     auto asyncContext = static_cast<AudioRendererAsyncContext*>(data);
914     napi_value valueParam = nullptr;
915 
916     if (asyncContext != nullptr) {
917         if (!asyncContext->status) {
918             napi_create_int64(env, asyncContext->time, &valueParam);
919         }
920         CommonCallbackRoutine(env, asyncContext, valueParam);
921     } else {
922         HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
923     }
924 }
925 
AudioRendererInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)926 void AudioRendererNapi::AudioRendererInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
927 {
928     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
929     napi_value valueParam = nullptr;
930 
931     if (asyncContext != nullptr) {
932         if (asyncContext->status == SUCCESS) {
933             (void)napi_create_object(env, &valueParam);
934             SetValueInt32(env, "content", static_cast<int32_t>(asyncContext->contentType), valueParam);
935             SetValueInt32(env, "usage", static_cast<int32_t>(asyncContext->usage), valueParam);
936             SetValueInt32(env, "rendererFlags", asyncContext->rendererFlags, valueParam);
937         }
938         CommonCallbackRoutine(env, asyncContext, valueParam);
939     } else {
940         HiLog::Error(LABEL, "ERROR: asyncContext is Null!");
941     }
942 }
943 
AudioStreamInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)944 void AudioRendererNapi::AudioStreamInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
945 {
946     auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
947     napi_value valueParam = nullptr;
948 
949     if (asyncContext != nullptr) {
950         if (asyncContext->status == SUCCESS) {
951             (void)napi_create_object(env, &valueParam);
952             SetValueInt32(env, "samplingRate", static_cast<int32_t>(asyncContext->samplingRate), valueParam);
953             SetValueInt32(env, "channels", static_cast<int32_t>(asyncContext->channelCount), valueParam);
954             SetValueInt32(env, "sampleFormat", static_cast<int32_t>(asyncContext->sampleFormat), valueParam);
955             SetValueInt32(env, "encodingType", static_cast<int32_t>(asyncContext->encodingType), valueParam);
956         }
957         CommonCallbackRoutine(env, asyncContext, valueParam);
958     } else {
959         HiLog::Error(LABEL, "ERROR: AudioStreamInfoAsyncCallbackComplete* is Null!");
960     }
961 }
962 
SetRenderRate(napi_env env,napi_callback_info info)963 napi_value AudioRendererNapi::SetRenderRate(napi_env env, napi_callback_info info)
964 {
965     napi_status status;
966     const int32_t refCount = 1;
967     napi_value result = nullptr;
968 
969     GET_PARAMS(env, info, ARGS_TWO);
970     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
971     if (argc < ARGS_ONE) {
972         asyncContext->status = NAPI_ERR_INVALID_PARAM;
973     }
974 
975     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
976     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
977         for (size_t i = PARAM0; i < argc; i++) {
978             napi_valuetype valueType = napi_undefined;
979             napi_typeof(env, argv[i], &valueType);
980 
981             if (i == PARAM0 && valueType == napi_number) {
982                 napi_get_value_int32(env, argv[PARAM0], &asyncContext->audioRendererRate);
983             } else if (i == PARAM1) {
984                 if (valueType == napi_function) {
985                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
986                 }
987                 break;
988             } else {
989                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
990             }
991         }
992 
993         if (asyncContext->callbackRef == nullptr) {
994             napi_create_promise(env, &asyncContext->deferred, &result);
995         } else {
996             napi_get_undefined(env, &result);
997         }
998 
999         napi_value resource = nullptr;
1000         napi_create_string_utf8(env, "SetRenderRate", NAPI_AUTO_LENGTH, &resource);
1001 
1002         status = napi_create_async_work(
1003             env, nullptr, resource,
1004             [](napi_env env, void *data) {
1005                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1006                 if (!CheckContextStatus(context)) {
1007                     return;
1008                 }
1009                 if (context->status == SUCCESS) {
1010                     AudioRendererRate audioRenderRate = static_cast<AudioRendererRate>(context->audioRendererRate);
1011                     int32_t audioClientInvalidParamsErr = -2;
1012                     context->intValue = context->objectInfo->audioRenderer_->SetRenderRate(audioRenderRate);
1013                     if (context->intValue == SUCCESS) {
1014                         context->status = SUCCESS;
1015                     } else if (context->intValue == audioClientInvalidParamsErr) {
1016                         context->status = NAPI_ERR_UNSUPPORTED;
1017                     } else {
1018                         context->status = NAPI_ERR_SYSTEM;
1019                     }
1020                 }
1021             },
1022             VoidAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1023         if (status != napi_ok) {
1024             result = nullptr;
1025         } else {
1026             status = napi_queue_async_work(env, asyncContext->work);
1027             if (status == napi_ok) {
1028                 asyncContext.release();
1029             } else {
1030                 result = nullptr;
1031             }
1032         }
1033     }
1034 
1035     return result;
1036 }
1037 
GetRenderRate(napi_env env,napi_callback_info info)1038 napi_value AudioRendererNapi::GetRenderRate(napi_env env, napi_callback_info info)
1039 {
1040     napi_status status;
1041     const int32_t refCount = 1;
1042     napi_value result = nullptr;
1043 
1044     GET_PARAMS(env, info, ARGS_ONE);
1045 
1046     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1047     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1048     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1049         if (argc > PARAM0) {
1050             napi_valuetype valueType = napi_undefined;
1051             napi_typeof(env, argv[PARAM0], &valueType);
1052             if (valueType == napi_function) {
1053                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1054             }
1055         }
1056 
1057         if (asyncContext->callbackRef == nullptr) {
1058             napi_create_promise(env, &asyncContext->deferred, &result);
1059         } else {
1060             napi_get_undefined(env, &result);
1061         }
1062 
1063         napi_value resource = nullptr;
1064         napi_create_string_utf8(env, "GetRenderRate", NAPI_AUTO_LENGTH, &resource);
1065 
1066         status = napi_create_async_work(
1067             env, nullptr, resource,
1068             [](napi_env env, void *data) {
1069                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1070                 if (!CheckContextStatus(context)) {
1071                     return;
1072                 }
1073                 context->intValue = context->objectInfo->audioRenderer_->GetRenderRate();
1074                 context->status = SUCCESS;
1075             },
1076             GetIntValueAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1077         if (status != napi_ok) {
1078             result = nullptr;
1079         } else {
1080             status = napi_queue_async_work(env, asyncContext->work);
1081             if (status == napi_ok) {
1082                 asyncContext.release();
1083             } else {
1084                 result = nullptr;
1085             }
1086         }
1087     }
1088 
1089     return result;
1090 }
1091 
Start(napi_env env,napi_callback_info info)1092 napi_value AudioRendererNapi::Start(napi_env env, napi_callback_info info)
1093 {
1094     napi_status status;
1095     const int32_t refCount = 1;
1096     napi_value result = nullptr;
1097 
1098     GET_PARAMS(env, info, ARGS_ONE);
1099 
1100     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1101 
1102     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1103     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1104         if (argc > PARAM0) {
1105             napi_valuetype valueType = napi_undefined;
1106             napi_typeof(env, argv[PARAM0], &valueType);
1107             if (valueType == napi_function) {
1108                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1109             }
1110         }
1111 
1112         if (asyncContext->callbackRef == nullptr) {
1113             napi_create_promise(env, &asyncContext->deferred, &result);
1114         } else {
1115             napi_get_undefined(env, &result);
1116         }
1117 
1118         napi_value resource = nullptr;
1119         napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
1120 
1121         status = napi_create_async_work(
1122             env, nullptr, resource,
1123             [](napi_env env, void *data) {
1124                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1125                 if (!CheckContextStatus(context)) {
1126                     return;
1127                 }
1128                 context->isTrue = context->objectInfo->audioRenderer_->Start();
1129                 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1130             },
1131             StartAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1132         if (status != napi_ok) {
1133             result = nullptr;
1134         } else {
1135             status = napi_queue_async_work(env, asyncContext->work);
1136             if (status == napi_ok) {
1137                 asyncContext.release();
1138             } else {
1139                 result = nullptr;
1140             }
1141         }
1142     }
1143 
1144     return result;
1145 }
1146 
Write(napi_env env,napi_callback_info info)1147 napi_value AudioRendererNapi::Write(napi_env env, napi_callback_info info)
1148 {
1149     napi_status status;
1150     const int32_t refCount = 1;
1151     napi_value result = nullptr;
1152 
1153     GET_PARAMS(env, info, ARGS_TWO);
1154     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1155     if (argc < ARGS_ONE) {
1156         asyncContext->status = NAPI_ERR_INVALID_PARAM;
1157     }
1158 
1159     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1160     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1161         for (size_t i = PARAM0; i < argc; i++) {
1162             napi_valuetype valueType = napi_undefined;
1163             napi_typeof(env, argv[i], &valueType);
1164 
1165             if ((i == PARAM0) && (valueType == napi_object)) {
1166                 napi_get_arraybuffer_info(env, argv[i], &asyncContext->data, &asyncContext->bufferLen);
1167             } else if (i == PARAM1) {
1168                 if (valueType == napi_function) {
1169                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1170                 }
1171                 break;
1172             } else {
1173                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1174             }
1175         }
1176 
1177         if (asyncContext->callbackRef == nullptr) {
1178             napi_create_promise(env, &asyncContext->deferred, &result);
1179         } else {
1180             napi_get_undefined(env, &result);
1181         }
1182 
1183         napi_value resource = nullptr;
1184         napi_create_string_utf8(env, "Write", NAPI_AUTO_LENGTH, &resource);
1185 
1186         status = napi_create_async_work(
1187             env, nullptr, resource,
1188             [](napi_env env, void *data) {
1189                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1190                 if (!CheckContextStatus(context)) {
1191                     return;
1192                 }
1193                 if (context->status == SUCCESS) {
1194                     context->status = NAPI_ERR_SYSTEM;
1195                     size_t bufferLen = context->bufferLen;
1196                     auto buffer = std::make_unique<uint8_t[]>(bufferLen);
1197                     if (buffer == nullptr) {
1198                         HiLog::Error(LABEL, "Renderer write buffer allocation failed");
1199                         return;
1200                     }
1201 
1202                     if (memcpy_s(buffer.get(), bufferLen, context->data, bufferLen)) {
1203                         HiLog::Info(LABEL, "Renderer mem copy failed");
1204                         return;
1205                     }
1206 
1207                     int32_t bytesWritten = 0;
1208                     size_t totalBytesWritten = 0;
1209                     size_t minBytes = 4;
1210                     while ((totalBytesWritten < bufferLen) && ((bufferLen - totalBytesWritten) > minBytes)) {
1211                         bytesWritten = context->objectInfo->audioRenderer_->Write(buffer.get() + totalBytesWritten,
1212                             bufferLen - totalBytesWritten);
1213                         if (bytesWritten < 0) {
1214                             break;
1215                         }
1216 
1217                         totalBytesWritten += bytesWritten;
1218                     }
1219 
1220                     context->status = SUCCESS;
1221                     context->totalBytesWritten = totalBytesWritten;
1222                 }
1223             },
1224             WriteAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1225         if (status != napi_ok) {
1226             result = nullptr;
1227         } else if (asyncContext->objectInfo->scheduleFromApiCall_) {
1228             status = napi_queue_async_work(env, asyncContext->work);
1229             if (status == napi_ok) {
1230                 asyncContext->objectInfo->scheduleFromApiCall_ = false;
1231                 asyncContext.release();
1232             } else {
1233                 result = nullptr;
1234             }
1235         } else {
1236             asyncContext->objectInfo->writeRequestQ_.push(asyncContext->work);
1237             asyncContext.release();
1238         }
1239     }
1240 
1241     return result;
1242 }
1243 
GetAudioTime(napi_env env,napi_callback_info info)1244 napi_value AudioRendererNapi::GetAudioTime(napi_env env, napi_callback_info info)
1245 {
1246     napi_status status;
1247     const int32_t refCount = 1;
1248     napi_value result = nullptr;
1249 
1250     GET_PARAMS(env, info, ARGS_ONE);
1251 
1252     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1253 
1254     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1255     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1256         if (argc > PARAM0) {
1257             napi_valuetype valueType = napi_undefined;
1258             napi_typeof(env, argv[PARAM0], &valueType);
1259             if (valueType == napi_function) {
1260                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1261             }
1262         }
1263 
1264         if (asyncContext->callbackRef == nullptr) {
1265             napi_create_promise(env, &asyncContext->deferred, &result);
1266         } else {
1267             napi_get_undefined(env, &result);
1268         }
1269 
1270         napi_value resource = nullptr;
1271         napi_create_string_utf8(env, "GetAudioTime", NAPI_AUTO_LENGTH, &resource);
1272 
1273         status = napi_create_async_work(
1274             env, nullptr, resource,
1275             [](napi_env env, void *data) {
1276                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1277                 if (!CheckContextStatus(context)) {
1278                     return;
1279                 }
1280                 Timestamp timestamp;
1281                 if (context->objectInfo->audioRenderer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC)) {
1282                     const uint64_t secToNanosecond = 1000000000;
1283                     context->time = timestamp.time.tv_nsec + timestamp.time.tv_sec * secToNanosecond;
1284                     context->status = SUCCESS;
1285                 } else {
1286                     context->status = NAPI_ERR_SYSTEM;
1287                 }
1288             },
1289             GetInt64ValueAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1290         if (status != napi_ok) {
1291             result = nullptr;
1292         } else {
1293             status = napi_queue_async_work(env, asyncContext->work);
1294             if (status == napi_ok) {
1295                 asyncContext.release();
1296             } else {
1297                 result = nullptr;
1298             }
1299         }
1300     }
1301 
1302     return result;
1303 }
1304 
Drain(napi_env env,napi_callback_info info)1305 napi_value AudioRendererNapi::Drain(napi_env env, napi_callback_info info)
1306 {
1307     napi_status status;
1308     const int32_t refCount = 1;
1309     napi_value result = nullptr;
1310 
1311     GET_PARAMS(env, info, ARGS_ONE);
1312 
1313     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1314 
1315     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1316     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1317         if (argc > PARAM0) {
1318             napi_valuetype valueType = napi_undefined;
1319             napi_typeof(env, argv[PARAM0], &valueType);
1320             if (valueType == napi_function) {
1321                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1322             }
1323         }
1324 
1325         if (asyncContext->callbackRef == nullptr) {
1326             napi_create_promise(env, &asyncContext->deferred, &result);
1327         } else {
1328             napi_get_undefined(env, &result);
1329         }
1330 
1331         napi_value resource = nullptr;
1332         napi_create_string_utf8(env, "Drain", NAPI_AUTO_LENGTH, &resource);
1333 
1334         status = napi_create_async_work(
1335             env, nullptr, resource,
1336             [](napi_env env, void *data) {
1337                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1338                 if (!CheckContextStatus(context)) {
1339                     return;
1340                 }
1341                 context->isTrue = context->objectInfo->audioRenderer_->Drain();
1342                 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1343             },
1344             VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1345         if (status != napi_ok) {
1346             result = nullptr;
1347         } else {
1348             if (!asyncContext->objectInfo->doNotScheduleWrite_) {
1349                 asyncContext->objectInfo->isDrainWriteQInProgress_ = true;
1350                 while (!asyncContext->objectInfo->writeRequestQ_.empty()) {
1351                     napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
1352                     asyncContext->objectInfo->writeRequestQ_.pop();
1353                 }
1354                 asyncContext->objectInfo->isDrainWriteQInProgress_ = false;
1355             }
1356             status = napi_queue_async_work(env, asyncContext->work);
1357             if (status == napi_ok) {
1358                 asyncContext.release();
1359             } else {
1360                 result = nullptr;
1361             }
1362         }
1363     }
1364 
1365     return result;
1366 }
1367 
Pause(napi_env env,napi_callback_info info)1368 napi_value AudioRendererNapi::Pause(napi_env env, napi_callback_info info)
1369 {
1370     napi_status status;
1371     const int32_t refCount = 1;
1372     napi_value result = nullptr;
1373 
1374     GET_PARAMS(env, info, ARGS_ONE);
1375 
1376     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1377 
1378     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1379     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1380         if (argc > PARAM0) {
1381             napi_valuetype valueType = napi_undefined;
1382             napi_typeof(env, argv[PARAM0], &valueType);
1383             if (valueType == napi_function) {
1384                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1385             }
1386         }
1387 
1388         if (asyncContext->callbackRef == nullptr) {
1389             napi_create_promise(env, &asyncContext->deferred, &result);
1390         } else {
1391             napi_get_undefined(env, &result);
1392         }
1393 
1394         napi_value resource = nullptr;
1395         napi_create_string_utf8(env, "Pause", NAPI_AUTO_LENGTH, &resource);
1396 
1397         status = napi_create_async_work(
1398             env, nullptr, resource,
1399             [](napi_env env, void *data) {
1400                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1401                 if (!CheckContextStatus(context)) {
1402                     return;
1403                 }
1404                 context->isTrue = context->objectInfo->audioRenderer_->Pause();
1405                 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1406             },
1407             PauseAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1408         if (status != napi_ok) {
1409             result = nullptr;
1410         } else {
1411             status = napi_queue_async_work(env, asyncContext->work);
1412             if (status == napi_ok) {
1413                 asyncContext->objectInfo->doNotScheduleWrite_ = true;
1414                 asyncContext.release();
1415             } else {
1416                 result = nullptr;
1417             }
1418         }
1419     }
1420 
1421     return result;
1422 }
1423 
Stop(napi_env env,napi_callback_info info)1424 napi_value AudioRendererNapi::Stop(napi_env env, napi_callback_info info)
1425 {
1426     napi_status status;
1427     const int32_t refCount = 1;
1428     napi_value result = nullptr;
1429 
1430     GET_PARAMS(env, info, ARGS_ONE);
1431 
1432     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1433 
1434     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1435     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1436         if (argc > PARAM0) {
1437             napi_valuetype valueType = napi_undefined;
1438             napi_typeof(env, argv[PARAM0], &valueType);
1439             if (valueType == napi_function) {
1440                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1441             }
1442         }
1443 
1444         if (asyncContext->callbackRef == nullptr) {
1445             napi_create_promise(env, &asyncContext->deferred, &result);
1446         } else {
1447             napi_get_undefined(env, &result);
1448         }
1449 
1450         napi_value resource = nullptr;
1451         napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
1452 
1453         status = napi_create_async_work(
1454             env, nullptr, resource,
1455             [](napi_env env, void *data) {
1456                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1457                 if (!CheckContextStatus(context)) {
1458                     return;
1459                 }
1460                 context->isTrue = context->objectInfo->audioRenderer_->Stop();
1461                 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1462             },
1463             StopAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1464         if (status != napi_ok) {
1465             result = nullptr;
1466         } else {
1467             status = napi_queue_async_work(env, asyncContext->work);
1468             if (status == napi_ok) {
1469                 asyncContext.release();
1470             } else {
1471                 result = nullptr;
1472             }
1473         }
1474     }
1475 
1476     return result;
1477 }
1478 
Release(napi_env env,napi_callback_info info)1479 napi_value AudioRendererNapi::Release(napi_env env, napi_callback_info info)
1480 {
1481     napi_status status;
1482     const int32_t refCount = 1;
1483     napi_value result = nullptr;
1484 
1485     GET_PARAMS(env, info, ARGS_ONE);
1486 
1487     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1488 
1489     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1490     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1491         if (argc > PARAM0) {
1492             napi_valuetype valueType = napi_undefined;
1493             napi_typeof(env, argv[PARAM0], &valueType);
1494             if (valueType == napi_function) {
1495                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1496             }
1497         }
1498 
1499         if (asyncContext->callbackRef == nullptr) {
1500             napi_create_promise(env, &asyncContext->deferred, &result);
1501         } else {
1502             napi_get_undefined(env, &result);
1503         }
1504 
1505         napi_value resource = nullptr;
1506         napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
1507 
1508         status = napi_create_async_work(
1509             env, nullptr, resource,
1510             [](napi_env env, void *data) {
1511                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1512                 if (!CheckContextStatus(context)) {
1513                     return;
1514                 }
1515                 context->isTrue = context->objectInfo->audioRenderer_->Release();
1516                 if (context->isTrue) {
1517                     context->status = SUCCESS;
1518                 } else {
1519                     context->status = NAPI_ERR_SYSTEM;
1520                 }
1521             },
1522             VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1523         if (status != napi_ok) {
1524             result = nullptr;
1525         } else {
1526             status = napi_queue_async_work(env, asyncContext->work);
1527             if (status == napi_ok) {
1528                 asyncContext.release();
1529             } else {
1530                 result = nullptr;
1531             }
1532         }
1533     }
1534 
1535     return result;
1536 }
1537 
GetBufferSize(napi_env env,napi_callback_info info)1538 napi_value AudioRendererNapi::GetBufferSize(napi_env env, napi_callback_info info)
1539 {
1540     napi_status status;
1541     const int32_t refCount = 1;
1542     napi_value result = nullptr;
1543 
1544     GET_PARAMS(env, info, ARGS_ONE);
1545 
1546     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1547 
1548     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1549     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1550         if (argc > PARAM0) {
1551             napi_valuetype valueType = napi_undefined;
1552             napi_typeof(env, argv[PARAM0], &valueType);
1553             if (valueType == napi_function) {
1554                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1555             }
1556         }
1557 
1558         if (asyncContext->callbackRef == nullptr) {
1559             napi_create_promise(env, &asyncContext->deferred, &result);
1560         } else {
1561             napi_get_undefined(env, &result);
1562         }
1563 
1564         napi_value resource = nullptr;
1565         napi_create_string_utf8(env, "GetBufferSize", NAPI_AUTO_LENGTH, &resource);
1566 
1567         status = napi_create_async_work(
1568             env, nullptr, resource,
1569             [](napi_env env, void *data) {
1570                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1571                 if (!CheckContextStatus(context)) {
1572                     return;
1573                 }
1574                 size_t bufferSize;
1575                 context->status = context->objectInfo->audioRenderer_->GetBufferSize(bufferSize);
1576                 if (context->status == SUCCESS) {
1577                     context->bufferSize = bufferSize;
1578                 }
1579             },
1580             GetBufferSizeAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1581         if (status != napi_ok) {
1582             result = nullptr;
1583         } else {
1584             status = napi_queue_async_work(env, asyncContext->work);
1585             if (status == napi_ok) {
1586                 asyncContext.release();
1587             } else {
1588                 result = nullptr;
1589             }
1590         }
1591     }
1592 
1593     return result;
1594 }
1595 
GetAudioStreamId(napi_env env,napi_callback_info info)1596 napi_value AudioRendererNapi::GetAudioStreamId(napi_env env, napi_callback_info info)
1597 {
1598     napi_status status;
1599     const int32_t refCount = 1;
1600     napi_value result = nullptr;
1601 
1602     GET_PARAMS(env, info, ARGS_ONE);
1603 
1604     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1605 
1606     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1607     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1608         if (argc > PARAM0) {
1609             napi_valuetype valueType = napi_undefined;
1610             napi_typeof(env, argv[PARAM0], &valueType);
1611             if (valueType == napi_function) {
1612                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1613             }
1614         }
1615 
1616         if (asyncContext->callbackRef == nullptr) {
1617             napi_create_promise(env, &asyncContext->deferred, &result);
1618         } else {
1619             napi_get_undefined(env, &result);
1620         }
1621 
1622         napi_value resource = nullptr;
1623         napi_create_string_utf8(env, "GetAudioStreamId", NAPI_AUTO_LENGTH, &resource);
1624 
1625         status = napi_create_async_work(
1626             env, nullptr, resource,
1627             [](napi_env env, void *data) {
1628                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1629                 if (!CheckContextStatus(context)) {
1630                     return;
1631                 }
1632                 int32_t streamIdStatus;
1633                 streamIdStatus = context->objectInfo->audioRenderer_->
1634                     GetAudioStreamId(context->audioStreamId);
1635                 if (streamIdStatus == ERR_ILLEGAL_STATE) {
1636                     context->status = NAPI_ERR_ILLEGAL_STATE;
1637                 } else if (streamIdStatus == ERR_INVALID_INDEX) {
1638                     context->status = NAPI_ERR_SYSTEM;
1639                 } else {
1640                     context->status = SUCCESS;
1641                 }
1642             },
1643             GetAudioStreamIdCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1644         if (status != napi_ok) {
1645             result = nullptr;
1646         } else {
1647             status = napi_queue_async_work(env, asyncContext->work);
1648             if (status == napi_ok) {
1649                 asyncContext.release();
1650             } else {
1651                 result = nullptr;
1652             }
1653         }
1654     }
1655 
1656     return result;
1657 }
1658 
SetVolume(napi_env env,napi_callback_info info)1659 napi_value AudioRendererNapi::SetVolume(napi_env env, napi_callback_info info)
1660 {
1661     napi_status status;
1662     const int32_t refCount = 1;
1663     napi_value result = nullptr;
1664 
1665     GET_PARAMS(env, info, ARGS_THREE);
1666 
1667     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1668     if (argc < ARGS_ONE) {
1669         asyncContext->status = NAPI_ERR_INVALID_PARAM;
1670     }
1671 
1672     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1673     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1674         for (size_t i = PARAM0; i < argc; i++) {
1675             napi_valuetype valueType = napi_undefined;
1676             napi_typeof(env, argv[i], &valueType);
1677             if (i == PARAM0 && valueType == napi_number) {
1678                 napi_get_value_double(env, argv[i], &asyncContext->volLevel);
1679             } else if (i == PARAM1) {
1680                 if (valueType == napi_function) {
1681                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1682                 }
1683                 break;
1684             } else {
1685                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1686             }
1687         }
1688 
1689         if (asyncContext->callbackRef == nullptr) {
1690             napi_create_promise(env, &asyncContext->deferred, &result);
1691         } else {
1692             napi_get_undefined(env, &result);
1693         }
1694 
1695         napi_value resource = nullptr;
1696         napi_create_string_utf8(env, "SetVolume", NAPI_AUTO_LENGTH, &resource);
1697 
1698         status = napi_create_async_work(
1699             env, nullptr, resource,
1700             [](napi_env env, void *data) {
1701                 auto context = static_cast<AudioRendererAsyncContext*>(data);
1702                 if (!CheckContextStatus(context)) {
1703                     return;
1704                 }
1705                 if (context->status == SUCCESS) {
1706                     if (context->volLevel < MIN_VOLUME_IN_DOUBLE || context->volLevel > MAX_VOLUME_IN_DOUBLE) {
1707                         context->status = NAPI_ERR_UNSUPPORTED;
1708                     } else {
1709                         context->status = context->objectInfo->audioRenderer_->
1710                             SetVolume(static_cast<float>(context->volLevel));
1711                     }
1712                 }
1713             },
1714             SetFunctionAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1715         if (status != napi_ok) {
1716             result = nullptr;
1717         } else {
1718             status = napi_queue_async_work(env, asyncContext->work);
1719             if (status == napi_ok) {
1720                 asyncContext.release();
1721             } else {
1722                 result = nullptr;
1723             }
1724         }
1725     }
1726 
1727     return result;
1728 }
1729 
1730 
GetRendererInfo(napi_env env,napi_callback_info info)1731 napi_value AudioRendererNapi::GetRendererInfo(napi_env env, napi_callback_info info)
1732 {
1733     HiLog::Info(LABEL, "Entered GetRendererInfo");
1734     napi_status status;
1735     const int32_t refCount = 1;
1736     napi_value result = nullptr;
1737 
1738     GET_PARAMS(env, info, ARGS_ONE);
1739 
1740     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1741 
1742     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1743     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1744         if (argc > PARAM0) {
1745             napi_valuetype valueType = napi_undefined;
1746             napi_typeof(env, argv[PARAM0], &valueType);
1747             if (valueType == napi_function) {
1748                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1749             }
1750         }
1751 
1752         if (asyncContext->callbackRef == nullptr) {
1753             napi_create_promise(env, &asyncContext->deferred, &result);
1754         } else {
1755             napi_get_undefined(env, &result);
1756         }
1757 
1758         napi_value resource = nullptr;
1759         napi_create_string_utf8(env, "GetRendererInfo", NAPI_AUTO_LENGTH, &resource);
1760 
1761         status = napi_create_async_work(
1762             env, nullptr, resource,
1763             [](napi_env env, void *data) {
1764                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1765                 if (!CheckContextStatus(context)) {
1766                     return;
1767                 }
1768                 AudioRendererInfo rendererInfo = {};
1769                 context->status = context->objectInfo->audioRenderer_->GetRendererInfo(rendererInfo);
1770                 if (context->status == SUCCESS) {
1771                     context->contentType = rendererInfo.contentType;
1772                     context->usage = rendererInfo.streamUsage;
1773                     context->rendererFlags = rendererInfo.rendererFlags;
1774                 }
1775             },
1776             AudioRendererInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1777         if (status != napi_ok) {
1778             result = nullptr;
1779         } else {
1780             status = napi_queue_async_work(env, asyncContext->work);
1781             if (status == napi_ok) {
1782                 asyncContext.release();
1783             } else {
1784                 result = nullptr;
1785             }
1786         }
1787     }
1788 
1789     return result;
1790 }
1791 
GetStreamInfo(napi_env env,napi_callback_info info)1792 napi_value AudioRendererNapi::GetStreamInfo(napi_env env, napi_callback_info info)
1793 {
1794     napi_status status;
1795     const int32_t refCount = 1;
1796     napi_value result = nullptr;
1797 
1798     GET_PARAMS(env, info, ARGS_ONE);
1799 
1800     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1801 
1802     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1803     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1804         if (argc > PARAM0) {
1805             napi_valuetype valueType = napi_undefined;
1806             napi_typeof(env, argv[PARAM0], &valueType);
1807             if (valueType == napi_function) {
1808                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1809             }
1810         }
1811 
1812         if (asyncContext->callbackRef == nullptr) {
1813             napi_create_promise(env, &asyncContext->deferred, &result);
1814         } else {
1815             napi_get_undefined(env, &result);
1816         }
1817 
1818         napi_value resource = nullptr;
1819         napi_create_string_utf8(env, "GetStreamInfo", NAPI_AUTO_LENGTH, &resource);
1820 
1821         status = napi_create_async_work(
1822             env, nullptr, resource,
1823             [](napi_env env, void *data) {
1824                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1825                 if (!CheckContextStatus(context)) {
1826                     return;
1827                 }
1828                 AudioStreamInfo streamInfo;
1829                 context->status = context->objectInfo->audioRenderer_->GetStreamInfo(streamInfo);
1830                 if (context->status == SUCCESS) {
1831                     context->sampleFormat = static_cast<AudioSampleFormat>(streamInfo.format);
1832                     context->samplingRate = streamInfo.samplingRate;
1833                     context->channelCount = streamInfo.channels;
1834                     context->encodingType = streamInfo.encoding;
1835                 }
1836             },
1837             AudioStreamInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1838         if (status != napi_ok) {
1839             result = nullptr;
1840         } else {
1841             status = napi_queue_async_work(env, asyncContext->work);
1842             if (status == napi_ok) {
1843                 asyncContext.release();
1844             } else {
1845                 result = nullptr;
1846             }
1847         }
1848     }
1849 
1850     return result;
1851 }
1852 
GetState(napi_env env,napi_callback_info info)1853 napi_value AudioRendererNapi::GetState(napi_env env, napi_callback_info info)
1854 {
1855     napi_value jsThis = nullptr;
1856     napi_value undefinedResult = nullptr;
1857     napi_get_undefined(env, &undefinedResult);
1858 
1859     size_t argCount = 0;
1860     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1861     if (status != napi_ok || jsThis == nullptr) {
1862         AUDIO_INFO_LOG("Failed to retrieve details about the callback");
1863         return undefinedResult;
1864     }
1865 
1866     AudioRendererNapi *rendererNapi = nullptr;
1867     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
1868     CHECK_AND_RETURN_RET_LOG(status == napi_ok && rendererNapi != nullptr, undefinedResult, "Failed to get instance");
1869 
1870     CHECK_AND_RETURN_RET_LOG(rendererNapi->audioRenderer_ != nullptr, undefinedResult, "No memory");
1871     int32_t rendererState = rendererNapi->audioRenderer_->GetStatus();
1872 
1873     napi_value jsResult = nullptr;
1874     status = napi_create_int32(env, rendererState, &jsResult);
1875     CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
1876 
1877     AUDIO_INFO_LOG("AudioRendererNapi: GetState Complete, Current state: %{public}d", rendererState);
1878     return jsResult;
1879 }
1880 
RegisterPeriodPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)1881 napi_value AudioRendererNapi::RegisterPeriodPositionCallback(napi_env env, napi_value* argv, const std::string& cbName,
1882                                                              AudioRendererNapi *rendererNapi)
1883 {
1884     int64_t frameCount = 0;
1885     napi_get_value_int64(env, argv[PARAM1], &frameCount);
1886 
1887     if (frameCount > 0) {
1888         if (rendererNapi->periodPositionCBNapi_ == nullptr) {
1889             rendererNapi->periodPositionCBNapi_ = std::make_shared<RendererPeriodPositionCallbackNapi>(env);
1890             THROW_ERROR_ASSERT(env, rendererNapi->periodPositionCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1891 
1892             int32_t ret = rendererNapi->audioRenderer_->SetRendererPeriodPositionCallback(frameCount,
1893                 rendererNapi->periodPositionCBNapi_);
1894             THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
1895 
1896             std::shared_ptr<RendererPeriodPositionCallbackNapi> cb =
1897                 std::static_pointer_cast<RendererPeriodPositionCallbackNapi>(rendererNapi->periodPositionCBNapi_);
1898             cb->SaveCallbackReference(cbName, argv[PARAM2]);
1899         } else {
1900             AUDIO_DEBUG_LOG("AudioRendererNapi: periodReach already subscribed.");
1901         }
1902     } else {
1903         AUDIO_ERR_LOG("AudioRendererNapi: frameCount value not supported!!");
1904     }
1905 
1906     napi_value result = nullptr;
1907     napi_get_undefined(env, &result);
1908     return result;
1909 }
1910 
RegisterPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)1911 napi_value AudioRendererNapi::RegisterPositionCallback(napi_env env, napi_value* argv,
1912                                                        const std::string& cbName, AudioRendererNapi *rendererNapi)
1913 {
1914     int64_t markPosition = 0;
1915     napi_get_value_int64(env, argv[PARAM1], &markPosition);
1916 
1917     if (markPosition > 0) {
1918         rendererNapi->positionCBNapi_ = std::make_shared<RendererPositionCallbackNapi>(env);
1919         THROW_ERROR_ASSERT(env, rendererNapi->positionCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1920         int32_t ret = rendererNapi->audioRenderer_->SetRendererPositionCallback(markPosition,
1921             rendererNapi->positionCBNapi_);
1922         THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
1923 
1924         std::shared_ptr<RendererPositionCallbackNapi> cb =
1925             std::static_pointer_cast<RendererPositionCallbackNapi>(rendererNapi->positionCBNapi_);
1926         cb->SaveCallbackReference(cbName, argv[PARAM2]);
1927     } else {
1928         AUDIO_ERR_LOG("AudioRendererNapi: Mark Position value not supported!!");
1929         THROW_ERROR_ASSERT(env, false, NAPI_ERR_INPUT_INVALID);
1930     }
1931 
1932     napi_value result = nullptr;
1933     napi_get_undefined(env, &result);
1934     return result;
1935 }
1936 
RegisterRendererCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)1937 napi_value AudioRendererNapi::RegisterRendererCallback(napi_env env, napi_value* argv,
1938                                                        const std::string& cbName, AudioRendererNapi *rendererNapi)
1939 {
1940     THROW_ERROR_ASSERT(env, rendererNapi->callbackNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1941 
1942     std::shared_ptr<AudioRendererCallbackNapi> cb =
1943         std::static_pointer_cast<AudioRendererCallbackNapi>(rendererNapi->callbackNapi_);
1944     cb->SaveCallbackReference(cbName, argv[PARAM1]);
1945 
1946     napi_value result = nullptr;
1947     napi_get_undefined(env, &result);
1948     return result;
1949 }
1950 
RegisterDataRequestCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)1951 napi_value AudioRendererNapi::RegisterDataRequestCallback(napi_env env, napi_value* argv,
1952     const std::string& cbName, AudioRendererNapi *rendererNapi)
1953 {
1954     if (rendererNapi->dataRequestCBNapi_ == nullptr) {
1955         rendererNapi->dataRequestCBNapi_ = std::make_shared<RendererDataRequestCallbackNapi>(env, rendererNapi);
1956         rendererNapi->audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK);
1957         THROW_ERROR_ASSERT(env, rendererNapi->dataRequestCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1958         int32_t ret = rendererNapi->audioRenderer_->SetRendererWriteCallback(rendererNapi->dataRequestCBNapi_);
1959         THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
1960         std::shared_ptr<RendererDataRequestCallbackNapi> cb =
1961             std::static_pointer_cast<RendererDataRequestCallbackNapi>(rendererNapi->dataRequestCBNapi_);
1962         cb->SaveCallbackReference(cbName, argv[PARAM1]);
1963     } else {
1964         AUDIO_DEBUG_LOG("AudioRendererNapi:dataRequest already subscribed.");
1965         THROW_ERROR_ASSERT(env, false, NAPI_ERR_ILLEGAL_STATE);
1966     }
1967     napi_value result = nullptr;
1968     napi_get_undefined(env, &result);
1969     return result;
1970 }
1971 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * argv,const std::string & cbName)1972 napi_value AudioRendererNapi::RegisterCallback(napi_env env, napi_value jsThis,
1973                                                napi_value* argv, const std::string& cbName)
1974 {
1975     AudioRendererNapi *rendererNapi = nullptr;
1976     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
1977     THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
1978     THROW_ERROR_ASSERT(env, rendererNapi != nullptr, NAPI_ERR_NO_MEMORY);
1979 
1980     THROW_ERROR_ASSERT(env, rendererNapi->audioRenderer_ != nullptr, NAPI_ERR_NO_MEMORY);
1981 
1982     napi_value result = nullptr;
1983     napi_get_undefined(env, &result);
1984 
1985     if (!cbName.compare(INTERRUPT_CALLBACK_NAME) ||
1986         !cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME) ||
1987         !cbName.compare(STATE_CHANGE_CALLBACK_NAME)) {
1988         result = RegisterRendererCallback(env, argv, cbName, rendererNapi);
1989     } else if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
1990         result = RegisterPositionCallback(env, argv, cbName, rendererNapi);
1991     } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
1992         result = RegisterPeriodPositionCallback(env, argv, cbName, rendererNapi);
1993     } else if (!cbName.compare(DATA_REQUEST_CALLBACK_NAME)) {
1994         result = RegisterDataRequestCallback(env, argv, cbName, rendererNapi);
1995     } else {
1996         bool unknownCallback = true;
1997         THROW_ERROR_ASSERT(env, !unknownCallback, NAPI_ERROR_INVALID_PARAM);
1998     }
1999 
2000     return result;
2001 }
2002 
On(napi_env env,napi_callback_info info)2003 napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
2004 {
2005     const size_t requireArgc = 2;
2006     size_t argc = 3;
2007 
2008     napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
2009     napi_value jsThis = nullptr;
2010     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
2011     THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2012     THROW_ERROR_ASSERT(env, argc >= requireArgc, NAPI_ERR_INPUT_INVALID);
2013 
2014     napi_valuetype eventType = napi_undefined;
2015     napi_typeof(env, argv[0], &eventType);
2016     THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INPUT_INVALID);
2017 
2018     std::string callbackName = AudioCommonNapi::GetStringArgument(env, argv[0]);
2019     AUDIO_DEBUG_LOG("AudioRendererNapi: On callbackName: %{public}s", callbackName.c_str());
2020 
2021     napi_valuetype handler = napi_undefined;
2022     if (argc == requireArgc) {
2023         napi_typeof(env, argv[1], &handler);
2024         THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
2025     } else {
2026         napi_valuetype paramArg1 = napi_undefined;
2027         napi_typeof(env, argv[1], &paramArg1);
2028         napi_valuetype expectedValType = napi_number;  // Default. Reset it with 'callbackName' if check, if required.
2029         THROW_ERROR_ASSERT(env, paramArg1 == expectedValType, NAPI_ERR_INPUT_INVALID);
2030 
2031         const int32_t arg2 = 2;
2032         napi_typeof(env, argv[arg2], &handler);
2033         THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
2034     }
2035 
2036     return RegisterCallback(env, jsThis, argv, callbackName);
2037 }
2038 
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & cbName)2039 napi_value AudioRendererNapi::UnregisterCallback(napi_env env, napi_value jsThis, const std::string& cbName)
2040 {
2041     AudioRendererNapi *rendererNapi = nullptr;
2042     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
2043     THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2044     THROW_ERROR_ASSERT(env, rendererNapi != nullptr, NAPI_ERR_NO_MEMORY);
2045     THROW_ERROR_ASSERT(env, rendererNapi->audioRenderer_ != nullptr, NAPI_ERR_NO_MEMORY);
2046 
2047     if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
2048         rendererNapi->audioRenderer_->UnsetRendererPositionCallback();
2049         rendererNapi->positionCBNapi_ = nullptr;
2050     } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
2051         rendererNapi->audioRenderer_->UnsetRendererPeriodPositionCallback();
2052         rendererNapi->periodPositionCBNapi_ = nullptr;
2053     } else {
2054         bool unknownCallback = true;
2055         THROW_ERROR_ASSERT(env, !unknownCallback, NAPI_ERR_UNSUPPORTED);
2056     }
2057 
2058     napi_value result = nullptr;
2059     napi_get_undefined(env, &result);
2060     return result;
2061 }
2062 
Off(napi_env env,napi_callback_info info)2063 napi_value AudioRendererNapi::Off(napi_env env, napi_callback_info info)
2064 {
2065     const size_t requireArgc = 1;
2066     size_t argc = 1;
2067 
2068     napi_value argv[requireArgc] = {nullptr};
2069     napi_value jsThis = nullptr;
2070     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
2071     THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2072     THROW_ERROR_ASSERT(env, argc >= requireArgc, NAPI_ERR_INVALID_PARAM);
2073 
2074     napi_valuetype eventType = napi_undefined;
2075     napi_typeof(env, argv[0], &eventType);
2076     THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INVALID_PARAM);
2077 
2078     std::string callbackName = AudioCommonNapi::GetStringArgument(env, argv[0]);
2079     AUDIO_DEBUG_LOG("AudioRendererNapi: Off callbackName: %{public}s", callbackName.c_str());
2080 
2081     return UnregisterCallback(env, jsThis, callbackName);
2082 }
2083 
ParseRendererOptions(napi_env env,napi_value root,AudioRendererOptions * opts)2084 bool AudioRendererNapi::ParseRendererOptions(napi_env env, napi_value root, AudioRendererOptions *opts)
2085 {
2086     napi_value res = nullptr;
2087 
2088     if (napi_get_named_property(env, root, "rendererInfo", &res) == napi_ok) {
2089         ParseRendererInfo(env, res, &(opts->rendererInfo));
2090     }
2091 
2092     if (napi_get_named_property(env, root, "streamInfo", &res) == napi_ok) {
2093         ParseStreamInfo(env, res, &(opts->streamInfo));
2094     }
2095 
2096     return true;
2097 }
2098 
ParseRendererInfo(napi_env env,napi_value root,AudioRendererInfo * rendererInfo)2099 bool AudioRendererNapi::ParseRendererInfo(napi_env env, napi_value root, AudioRendererInfo *rendererInfo)
2100 {
2101     napi_value tempValue = nullptr;
2102     int32_t intValue = {0};
2103 
2104     if (napi_get_named_property(env, root, "content", &tempValue) == napi_ok) {
2105         napi_get_value_int32(env, tempValue, &intValue);
2106         rendererInfo->contentType = static_cast<ContentType>(intValue);
2107     }
2108 
2109     if (napi_get_named_property(env, root, "usage", &tempValue) == napi_ok) {
2110         napi_get_value_int32(env, tempValue, &intValue);
2111         rendererInfo->streamUsage = static_cast<StreamUsage>(intValue);
2112     }
2113 
2114     if (napi_get_named_property(env, root, "rendererFlags", &tempValue) == napi_ok) {
2115         napi_get_value_int32(env, tempValue, &(rendererInfo->rendererFlags));
2116     }
2117 
2118     return true;
2119 }
2120 
ParseStreamInfo(napi_env env,napi_value root,AudioStreamInfo * streamInfo)2121 bool AudioRendererNapi::ParseStreamInfo(napi_env env, napi_value root, AudioStreamInfo* streamInfo)
2122 {
2123     napi_value tempValue = nullptr;
2124     int32_t intValue = {0};
2125 
2126     if (napi_get_named_property(env, root, "samplingRate", &tempValue) == napi_ok) {
2127         napi_get_value_int32(env, tempValue, &intValue);
2128         streamInfo->samplingRate = static_cast<AudioSamplingRate>(intValue);
2129     }
2130 
2131     if (napi_get_named_property(env, root, "channels", &tempValue) == napi_ok) {
2132         napi_get_value_int32(env, tempValue, &intValue);
2133         streamInfo->channels = static_cast<AudioChannel>(intValue);
2134     }
2135 
2136     if (napi_get_named_property(env, root, "sampleFormat", &tempValue) == napi_ok) {
2137         napi_get_value_int32(env, tempValue, &intValue);
2138         streamInfo->format = static_cast<OHOS::AudioStandard::AudioSampleFormat>(intValue);
2139     }
2140 
2141     if (napi_get_named_property(env, root, "encodingType", &tempValue) == napi_ok) {
2142         napi_get_value_int32(env, tempValue, &intValue);
2143         streamInfo->encoding = static_cast<AudioEncodingType>(intValue);
2144     }
2145 
2146     return true;
2147 }
2148 
CheckContextStatus(AudioRendererAsyncContext * context)2149 bool AudioRendererNapi::CheckContextStatus(AudioRendererAsyncContext *context)
2150 {
2151     if (context == nullptr) {
2152         AUDIO_ERR_LOG("context object is nullptr.");
2153         return false;
2154     }
2155     if (context->objectInfo == nullptr || context->objectInfo->audioRenderer_ == nullptr) {
2156         context->status = NAPI_ERR_SYSTEM;
2157         AUDIO_ERR_LOG("context object state is error.");
2158         return false;
2159     }
2160     return true;
2161 }
2162 
CreateAudioRendererWrapper(napi_env env,unique_ptr<AudioRendererOptions> & renderOptions)2163 napi_value AudioRendererNapi::CreateAudioRendererWrapper(napi_env env, unique_ptr<AudioRendererOptions> &renderOptions)
2164 {
2165     lock_guard<mutex> lock(createMutex_);
2166     napi_status status;
2167     napi_value result = nullptr;
2168     napi_value constructor;
2169 
2170     if (renderOptions != nullptr) {
2171         status = napi_get_reference_value(env, g_rendererConstructor, &constructor);
2172         if (status == napi_ok) {
2173             sRendererOptions_ = move(renderOptions);
2174             status = napi_new_instance(env, constructor, 0, nullptr, &result);
2175             sRendererOptions_.release();
2176             if (status == napi_ok) {
2177                 return result;
2178             }
2179         }
2180         HiLog::Error(LABEL, "Failed in CreateAudioRendererWrapper, %{public}d", status);
2181     }
2182 
2183     napi_get_undefined(env, &result);
2184 
2185     return result;
2186 }
2187 
SetInterruptMode(napi_env env,napi_callback_info info)2188 napi_value AudioRendererNapi::SetInterruptMode(napi_env env, napi_callback_info info)
2189 {
2190     napi_status status;
2191     const int32_t refCount = 1;
2192     napi_value result = nullptr;
2193 
2194     GET_PARAMS(env, info, ARGS_TWO);
2195 
2196     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2197     CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "AudioRendererAsyncContext object creation failed");
2198     if (argc < ARGS_ONE) {
2199         asyncContext->status = NAPI_ERR_INVALID_PARAM;
2200     }
2201 
2202     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2203     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2204         for (size_t i = PARAM0; i < argc; i++) {
2205             napi_valuetype valueType = napi_undefined;
2206             napi_typeof(env, argv[i], &valueType);
2207             if (i == PARAM0 && valueType == napi_number) {
2208                 napi_get_value_int32(env, argv[i], &asyncContext->interruptMode);
2209             } else if (i == PARAM1) {
2210                 if (valueType == napi_function) {
2211                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
2212                 }
2213                 break;
2214             } else {
2215                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
2216             }
2217         }
2218 
2219         if (asyncContext->callbackRef == nullptr) {
2220             napi_create_promise(env, &asyncContext->deferred, &result);
2221         } else {
2222             napi_get_undefined(env, &result);
2223         }
2224 
2225         napi_value resource = nullptr;
2226         napi_create_string_utf8(env, "SetInterruptMode", NAPI_AUTO_LENGTH, &resource);
2227 
2228         status = napi_create_async_work(
2229             env, nullptr, resource,
2230             [](napi_env env, void *data) {
2231                 auto context = static_cast<AudioRendererAsyncContext*>(data);
2232                 if (!CheckContextStatus(context)) {
2233                     return;
2234                 }
2235                 if (context->status == SUCCESS) {
2236                     AudioStandard::InterruptMode interruptMode_ = GetNativeInterruptMode(context->interruptMode);
2237                     context->objectInfo->audioRenderer_->SetInterruptMode(interruptMode_);
2238                     context->status = SUCCESS;
2239                     context->intValue = SUCCESS;
2240                 }
2241             },
2242             GetIntValueAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
2243         if (status != napi_ok) {
2244             result = nullptr;
2245         } else {
2246             status = napi_queue_async_work(env, asyncContext->work);
2247             if (status == napi_ok) {
2248                 asyncContext.release();
2249             } else {
2250                 result = nullptr;
2251             }
2252         }
2253     }
2254 
2255     return result;
2256 }
2257 } // namespace AudioStandard
2258 } // namespace OHOS
2259