• 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         JudgeFuncDrain(env, result, asyncContext);
1331     }
1332 
1333     return result;
1334 }
1335 
JudgeFuncDrain(napi_env & env,napi_value & result,unique_ptr<AudioRendererAsyncContext> & asyncContext)1336 void AudioRendererNapi::JudgeFuncDrain(napi_env &env, napi_value &result,
1337     unique_ptr<AudioRendererAsyncContext> &asyncContext)
1338 {
1339     napi_status status;
1340     napi_value resource = nullptr;
1341     napi_create_string_utf8(env, "Drain", NAPI_AUTO_LENGTH, &resource);
1342     status = napi_create_async_work(
1343         env, nullptr, resource,
1344         [](napi_env env, void *data) {
1345             auto context = static_cast<AudioRendererAsyncContext *>(data);
1346             if (!CheckContextStatus(context)) {
1347                 return;
1348             }
1349             context->isTrue = context->objectInfo->audioRenderer_->Drain();
1350             context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1351         },
1352         VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1353     if (status != napi_ok) {
1354         result = nullptr;
1355     } else {
1356         if (!asyncContext->objectInfo->doNotScheduleWrite_) {
1357             asyncContext->objectInfo->isDrainWriteQInProgress_ = true;
1358             while (!asyncContext->objectInfo->writeRequestQ_.empty()) {
1359                 napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
1360                 asyncContext->objectInfo->writeRequestQ_.pop();
1361             }
1362             asyncContext->objectInfo->isDrainWriteQInProgress_ = false;
1363         }
1364         status = napi_queue_async_work(env, asyncContext->work);
1365         if (status == napi_ok) {
1366             asyncContext.release();
1367         } else {
1368             result = nullptr;
1369         }
1370     }
1371 }
1372 
Pause(napi_env env,napi_callback_info info)1373 napi_value AudioRendererNapi::Pause(napi_env env, napi_callback_info info)
1374 {
1375     napi_status status;
1376     const int32_t refCount = 1;
1377     napi_value result = nullptr;
1378 
1379     GET_PARAMS(env, info, ARGS_ONE);
1380 
1381     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1382 
1383     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1384     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1385         if (argc > PARAM0) {
1386             napi_valuetype valueType = napi_undefined;
1387             napi_typeof(env, argv[PARAM0], &valueType);
1388             if (valueType == napi_function) {
1389                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1390             }
1391         }
1392 
1393         if (asyncContext->callbackRef == nullptr) {
1394             napi_create_promise(env, &asyncContext->deferred, &result);
1395         } else {
1396             napi_get_undefined(env, &result);
1397         }
1398 
1399         napi_value resource = nullptr;
1400         napi_create_string_utf8(env, "Pause", NAPI_AUTO_LENGTH, &resource);
1401 
1402         status = napi_create_async_work(
1403             env, nullptr, resource,
1404             [](napi_env env, void *data) {
1405                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1406                 if (!CheckContextStatus(context)) {
1407                     return;
1408                 }
1409                 context->isTrue = context->objectInfo->audioRenderer_->Pause();
1410                 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1411             },
1412             PauseAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1413         if (status != napi_ok) {
1414             result = nullptr;
1415         } else {
1416             status = napi_queue_async_work(env, asyncContext->work);
1417             if (status == napi_ok) {
1418                 asyncContext->objectInfo->doNotScheduleWrite_ = true;
1419                 asyncContext.release();
1420             } else {
1421                 result = nullptr;
1422             }
1423         }
1424     }
1425 
1426     return result;
1427 }
1428 
Stop(napi_env env,napi_callback_info info)1429 napi_value AudioRendererNapi::Stop(napi_env env, napi_callback_info info)
1430 {
1431     napi_status status;
1432     const int32_t refCount = 1;
1433     napi_value result = nullptr;
1434 
1435     GET_PARAMS(env, info, ARGS_ONE);
1436 
1437     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1438 
1439     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1440     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1441         if (argc > PARAM0) {
1442             napi_valuetype valueType = napi_undefined;
1443             napi_typeof(env, argv[PARAM0], &valueType);
1444             if (valueType == napi_function) {
1445                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1446             }
1447         }
1448 
1449         if (asyncContext->callbackRef == nullptr) {
1450             napi_create_promise(env, &asyncContext->deferred, &result);
1451         } else {
1452             napi_get_undefined(env, &result);
1453         }
1454 
1455         napi_value resource = nullptr;
1456         napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
1457 
1458         status = napi_create_async_work(
1459             env, nullptr, resource,
1460             [](napi_env env, void *data) {
1461                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1462                 if (!CheckContextStatus(context)) {
1463                     return;
1464                 }
1465                 context->isTrue = context->objectInfo->audioRenderer_->Stop();
1466                 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1467             },
1468             StopAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1469         if (status != napi_ok) {
1470             result = nullptr;
1471         } else {
1472             status = napi_queue_async_work(env, asyncContext->work);
1473             if (status == napi_ok) {
1474                 asyncContext.release();
1475             } else {
1476                 result = nullptr;
1477             }
1478         }
1479     }
1480 
1481     return result;
1482 }
1483 
Release(napi_env env,napi_callback_info info)1484 napi_value AudioRendererNapi::Release(napi_env env, napi_callback_info info)
1485 {
1486     napi_status status;
1487     const int32_t refCount = 1;
1488     napi_value result = nullptr;
1489 
1490     GET_PARAMS(env, info, ARGS_ONE);
1491 
1492     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1493 
1494     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1495     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1496         if (argc > PARAM0) {
1497             napi_valuetype valueType = napi_undefined;
1498             napi_typeof(env, argv[PARAM0], &valueType);
1499             if (valueType == napi_function) {
1500                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1501             }
1502         }
1503 
1504         if (asyncContext->callbackRef == nullptr) {
1505             napi_create_promise(env, &asyncContext->deferred, &result);
1506         } else {
1507             napi_get_undefined(env, &result);
1508         }
1509 
1510         napi_value resource = nullptr;
1511         napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
1512 
1513         status = napi_create_async_work(
1514             env, nullptr, resource,
1515             [](napi_env env, void *data) {
1516                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1517                 if (!CheckContextStatus(context)) {
1518                     return;
1519                 }
1520                 context->isTrue = context->objectInfo->audioRenderer_->Release();
1521                 if (context->isTrue) {
1522                     context->status = SUCCESS;
1523                 } else {
1524                     context->status = NAPI_ERR_SYSTEM;
1525                 }
1526             },
1527             VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1528         if (status != napi_ok) {
1529             result = nullptr;
1530         } else {
1531             status = napi_queue_async_work(env, asyncContext->work);
1532             if (status == napi_ok) {
1533                 asyncContext.release();
1534             } else {
1535                 result = nullptr;
1536             }
1537         }
1538     }
1539 
1540     return result;
1541 }
1542 
GetBufferSize(napi_env env,napi_callback_info info)1543 napi_value AudioRendererNapi::GetBufferSize(napi_env env, napi_callback_info info)
1544 {
1545     napi_status status;
1546     const int32_t refCount = 1;
1547     napi_value result = nullptr;
1548 
1549     GET_PARAMS(env, info, ARGS_ONE);
1550 
1551     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1552 
1553     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1554     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1555         if (argc > PARAM0) {
1556             napi_valuetype valueType = napi_undefined;
1557             napi_typeof(env, argv[PARAM0], &valueType);
1558             if (valueType == napi_function) {
1559                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1560             }
1561         }
1562 
1563         if (asyncContext->callbackRef == nullptr) {
1564             napi_create_promise(env, &asyncContext->deferred, &result);
1565         } else {
1566             napi_get_undefined(env, &result);
1567         }
1568 
1569         napi_value resource = nullptr;
1570         napi_create_string_utf8(env, "GetBufferSize", NAPI_AUTO_LENGTH, &resource);
1571 
1572         status = napi_create_async_work(
1573             env, nullptr, resource,
1574             [](napi_env env, void *data) {
1575                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1576                 if (!CheckContextStatus(context)) {
1577                     return;
1578                 }
1579                 size_t bufferSize;
1580                 context->status = context->objectInfo->audioRenderer_->GetBufferSize(bufferSize);
1581                 if (context->status == SUCCESS) {
1582                     context->bufferSize = bufferSize;
1583                 }
1584             },
1585             GetBufferSizeAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1586         if (status != napi_ok) {
1587             result = nullptr;
1588         } else {
1589             status = napi_queue_async_work(env, asyncContext->work);
1590             if (status == napi_ok) {
1591                 asyncContext.release();
1592             } else {
1593                 result = nullptr;
1594             }
1595         }
1596     }
1597 
1598     return result;
1599 }
1600 
GetAudioStreamId(napi_env env,napi_callback_info info)1601 napi_value AudioRendererNapi::GetAudioStreamId(napi_env env, napi_callback_info info)
1602 {
1603     napi_status status;
1604     const int32_t refCount = 1;
1605     napi_value result = nullptr;
1606 
1607     GET_PARAMS(env, info, ARGS_ONE);
1608 
1609     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1610 
1611     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1612     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1613         if (argc > PARAM0) {
1614             napi_valuetype valueType = napi_undefined;
1615             napi_typeof(env, argv[PARAM0], &valueType);
1616             if (valueType == napi_function) {
1617                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1618             }
1619         }
1620 
1621         if (asyncContext->callbackRef == nullptr) {
1622             napi_create_promise(env, &asyncContext->deferred, &result);
1623         } else {
1624             napi_get_undefined(env, &result);
1625         }
1626         JudgeFuncGetAudioStreamId(env, result, asyncContext);
1627     }
1628 
1629     return result;
1630 }
1631 
JudgeFuncGetAudioStreamId(napi_env & env,napi_value & result,unique_ptr<AudioRendererAsyncContext> & asyncContext)1632 void AudioRendererNapi::JudgeFuncGetAudioStreamId(napi_env &env, napi_value &result,
1633     unique_ptr<AudioRendererAsyncContext> &asyncContext)
1634 {
1635     napi_status status;
1636     napi_value resource = nullptr;
1637     napi_create_string_utf8(env, "GetAudioStreamId", NAPI_AUTO_LENGTH, &resource);
1638 
1639     status = napi_create_async_work(
1640         env, nullptr, resource,
1641         [](napi_env env, void *data) {
1642             auto context = static_cast<AudioRendererAsyncContext *>(data);
1643             if (!CheckContextStatus(context)) {
1644                 return;
1645             }
1646             int32_t streamIdStatus;
1647             streamIdStatus = context->objectInfo->audioRenderer_->
1648                 GetAudioStreamId(context->audioStreamId);
1649             if (streamIdStatus == ERR_ILLEGAL_STATE) {
1650                 context->status = NAPI_ERR_ILLEGAL_STATE;
1651             } else if (streamIdStatus == ERR_INVALID_INDEX) {
1652                 context->status = NAPI_ERR_SYSTEM;
1653             } else {
1654                 context->status = SUCCESS;
1655             }
1656         },
1657         GetAudioStreamIdCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1658     if (status != napi_ok) {
1659         result = nullptr;
1660     } else {
1661         status = napi_queue_async_work(env, asyncContext->work);
1662         if (status == napi_ok) {
1663             asyncContext.release();
1664         } else {
1665             result = nullptr;
1666         }
1667     }
1668 }
1669 
SetVolume(napi_env env,napi_callback_info info)1670 napi_value AudioRendererNapi::SetVolume(napi_env env, napi_callback_info info)
1671 {
1672     napi_status status;
1673     const int32_t refCount = 1;
1674     napi_value result = nullptr;
1675 
1676     GET_PARAMS(env, info, ARGS_THREE);
1677 
1678     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1679     if (argc < ARGS_ONE) {
1680         asyncContext->status = NAPI_ERR_INVALID_PARAM;
1681     }
1682 
1683     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1684     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1685         for (size_t i = PARAM0; i < argc; i++) {
1686             napi_valuetype valueType = napi_undefined;
1687             napi_typeof(env, argv[i], &valueType);
1688             if (i == PARAM0 && valueType == napi_number) {
1689                 napi_get_value_double(env, argv[i], &asyncContext->volLevel);
1690             } else if (i == PARAM1) {
1691                 if (valueType == napi_function) {
1692                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1693                 }
1694                 break;
1695             } else {
1696                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1697             }
1698         }
1699 
1700         if (asyncContext->callbackRef == nullptr) {
1701             napi_create_promise(env, &asyncContext->deferred, &result);
1702         } else {
1703             napi_get_undefined(env, &result);
1704         }
1705 
1706         napi_value resource = nullptr;
1707         napi_create_string_utf8(env, "SetVolume", NAPI_AUTO_LENGTH, &resource);
1708 
1709         status = napi_create_async_work(
1710             env, nullptr, resource,
1711             [](napi_env env, void *data) {
1712                 auto context = static_cast<AudioRendererAsyncContext*>(data);
1713                 if (!CheckContextStatus(context)) {
1714                     return;
1715                 }
1716                 if (context->status == SUCCESS) {
1717                     if (context->volLevel < MIN_VOLUME_IN_DOUBLE || context->volLevel > MAX_VOLUME_IN_DOUBLE) {
1718                         context->status = NAPI_ERR_UNSUPPORTED;
1719                     } else {
1720                         context->status = context->objectInfo->audioRenderer_->
1721                             SetVolume(static_cast<float>(context->volLevel));
1722                     }
1723                 }
1724             },
1725             SetFunctionAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1726         if (status != napi_ok) {
1727             result = nullptr;
1728         } else {
1729             status = napi_queue_async_work(env, asyncContext->work);
1730             if (status == napi_ok) {
1731                 asyncContext.release();
1732             } else {
1733                 result = nullptr;
1734             }
1735         }
1736     }
1737 
1738     return result;
1739 }
1740 
1741 
GetRendererInfo(napi_env env,napi_callback_info info)1742 napi_value AudioRendererNapi::GetRendererInfo(napi_env env, napi_callback_info info)
1743 {
1744     HiLog::Info(LABEL, "Entered GetRendererInfo");
1745     napi_status status;
1746     const int32_t refCount = 1;
1747     napi_value result = nullptr;
1748 
1749     GET_PARAMS(env, info, ARGS_ONE);
1750 
1751     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1752 
1753     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1754     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1755         if (argc > PARAM0) {
1756             napi_valuetype valueType = napi_undefined;
1757             napi_typeof(env, argv[PARAM0], &valueType);
1758             if (valueType == napi_function) {
1759                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1760             }
1761         }
1762 
1763         if (asyncContext->callbackRef == nullptr) {
1764             napi_create_promise(env, &asyncContext->deferred, &result);
1765         } else {
1766             napi_get_undefined(env, &result);
1767         }
1768 
1769         napi_value resource = nullptr;
1770         napi_create_string_utf8(env, "GetRendererInfo", NAPI_AUTO_LENGTH, &resource);
1771 
1772         status = napi_create_async_work(
1773             env, nullptr, resource,
1774             [](napi_env env, void *data) {
1775                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1776                 if (!CheckContextStatus(context)) {
1777                     return;
1778                 }
1779                 AudioRendererInfo rendererInfo = {};
1780                 context->status = context->objectInfo->audioRenderer_->GetRendererInfo(rendererInfo);
1781                 if (context->status == SUCCESS) {
1782                     context->contentType = rendererInfo.contentType;
1783                     context->usage = rendererInfo.streamUsage;
1784                     context->rendererFlags = rendererInfo.rendererFlags;
1785                 }
1786             },
1787             AudioRendererInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1788         if (status != napi_ok) {
1789             result = nullptr;
1790         } else {
1791             status = napi_queue_async_work(env, asyncContext->work);
1792             if (status == napi_ok) {
1793                 asyncContext.release();
1794             } else {
1795                 result = nullptr;
1796             }
1797         }
1798     }
1799 
1800     return result;
1801 }
1802 
GetStreamInfo(napi_env env,napi_callback_info info)1803 napi_value AudioRendererNapi::GetStreamInfo(napi_env env, napi_callback_info info)
1804 {
1805     napi_status status;
1806     const int32_t refCount = 1;
1807     napi_value result = nullptr;
1808 
1809     GET_PARAMS(env, info, ARGS_ONE);
1810 
1811     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1812 
1813     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1814     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1815         if (argc > PARAM0) {
1816             napi_valuetype valueType = napi_undefined;
1817             napi_typeof(env, argv[PARAM0], &valueType);
1818             if (valueType == napi_function) {
1819                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1820             }
1821         }
1822 
1823         if (asyncContext->callbackRef == nullptr) {
1824             napi_create_promise(env, &asyncContext->deferred, &result);
1825         } else {
1826             napi_get_undefined(env, &result);
1827         }
1828 
1829         napi_value resource = nullptr;
1830         napi_create_string_utf8(env, "GetStreamInfo", NAPI_AUTO_LENGTH, &resource);
1831 
1832         status = napi_create_async_work(
1833             env, nullptr, resource,
1834             [](napi_env env, void *data) {
1835                 auto context = static_cast<AudioRendererAsyncContext *>(data);
1836                 if (!CheckContextStatus(context)) {
1837                     return;
1838                 }
1839                 AudioStreamInfo streamInfo;
1840                 context->status = context->objectInfo->audioRenderer_->GetStreamInfo(streamInfo);
1841                 if (context->status == SUCCESS) {
1842                     context->sampleFormat = static_cast<AudioSampleFormat>(streamInfo.format);
1843                     context->samplingRate = streamInfo.samplingRate;
1844                     context->channelCount = streamInfo.channels;
1845                     context->encodingType = streamInfo.encoding;
1846                 }
1847             },
1848             AudioStreamInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1849         if (status != napi_ok) {
1850             result = nullptr;
1851         } else {
1852             status = napi_queue_async_work(env, asyncContext->work);
1853             if (status == napi_ok) {
1854                 asyncContext.release();
1855             } else {
1856                 result = nullptr;
1857             }
1858         }
1859     }
1860 
1861     return result;
1862 }
1863 
GetState(napi_env env,napi_callback_info info)1864 napi_value AudioRendererNapi::GetState(napi_env env, napi_callback_info info)
1865 {
1866     napi_value jsThis = nullptr;
1867     napi_value undefinedResult = nullptr;
1868     napi_get_undefined(env, &undefinedResult);
1869 
1870     size_t argCount = 0;
1871     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1872     if (status != napi_ok || jsThis == nullptr) {
1873         AUDIO_INFO_LOG("Failed to retrieve details about the callback");
1874         return undefinedResult;
1875     }
1876 
1877     AudioRendererNapi *rendererNapi = nullptr;
1878     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
1879     CHECK_AND_RETURN_RET_LOG(status == napi_ok && rendererNapi != nullptr, undefinedResult, "Failed to get instance");
1880 
1881     CHECK_AND_RETURN_RET_LOG(rendererNapi->audioRenderer_ != nullptr, undefinedResult, "No memory");
1882     int32_t rendererState = rendererNapi->audioRenderer_->GetStatus();
1883 
1884     napi_value jsResult = nullptr;
1885     status = napi_create_int32(env, rendererState, &jsResult);
1886     CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
1887 
1888     AUDIO_INFO_LOG("AudioRendererNapi: GetState Complete, Current state: %{public}d", rendererState);
1889     return jsResult;
1890 }
1891 
RegisterPeriodPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)1892 napi_value AudioRendererNapi::RegisterPeriodPositionCallback(napi_env env, napi_value* argv, const std::string& cbName,
1893                                                              AudioRendererNapi *rendererNapi)
1894 {
1895     int64_t frameCount = 0;
1896     napi_get_value_int64(env, argv[PARAM1], &frameCount);
1897 
1898     if (frameCount > 0) {
1899         if (rendererNapi->periodPositionCBNapi_ == nullptr) {
1900             rendererNapi->periodPositionCBNapi_ = std::make_shared<RendererPeriodPositionCallbackNapi>(env);
1901             THROW_ERROR_ASSERT(env, rendererNapi->periodPositionCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1902 
1903             int32_t ret = rendererNapi->audioRenderer_->SetRendererPeriodPositionCallback(frameCount,
1904                 rendererNapi->periodPositionCBNapi_);
1905             THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
1906 
1907             std::shared_ptr<RendererPeriodPositionCallbackNapi> cb =
1908                 std::static_pointer_cast<RendererPeriodPositionCallbackNapi>(rendererNapi->periodPositionCBNapi_);
1909             cb->SaveCallbackReference(cbName, argv[PARAM2]);
1910         } else {
1911             AUDIO_DEBUG_LOG("AudioRendererNapi: periodReach already subscribed.");
1912         }
1913     } else {
1914         AUDIO_ERR_LOG("AudioRendererNapi: frameCount value not supported!!");
1915     }
1916 
1917     napi_value result = nullptr;
1918     napi_get_undefined(env, &result);
1919     return result;
1920 }
1921 
RegisterPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)1922 napi_value AudioRendererNapi::RegisterPositionCallback(napi_env env, napi_value* argv,
1923                                                        const std::string& cbName, AudioRendererNapi *rendererNapi)
1924 {
1925     int64_t markPosition = 0;
1926     napi_get_value_int64(env, argv[PARAM1], &markPosition);
1927 
1928     if (markPosition > 0) {
1929         rendererNapi->positionCBNapi_ = std::make_shared<RendererPositionCallbackNapi>(env);
1930         THROW_ERROR_ASSERT(env, rendererNapi->positionCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1931         int32_t ret = rendererNapi->audioRenderer_->SetRendererPositionCallback(markPosition,
1932             rendererNapi->positionCBNapi_);
1933         THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
1934 
1935         std::shared_ptr<RendererPositionCallbackNapi> cb =
1936             std::static_pointer_cast<RendererPositionCallbackNapi>(rendererNapi->positionCBNapi_);
1937         cb->SaveCallbackReference(cbName, argv[PARAM2]);
1938     } else {
1939         AUDIO_ERR_LOG("AudioRendererNapi: Mark Position value not supported!!");
1940         THROW_ERROR_ASSERT(env, false, NAPI_ERR_INPUT_INVALID);
1941     }
1942 
1943     napi_value result = nullptr;
1944     napi_get_undefined(env, &result);
1945     return result;
1946 }
1947 
RegisterRendererCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)1948 napi_value AudioRendererNapi::RegisterRendererCallback(napi_env env, napi_value* argv,
1949                                                        const std::string& cbName, AudioRendererNapi *rendererNapi)
1950 {
1951     THROW_ERROR_ASSERT(env, rendererNapi->callbackNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1952 
1953     std::shared_ptr<AudioRendererCallbackNapi> cb =
1954         std::static_pointer_cast<AudioRendererCallbackNapi>(rendererNapi->callbackNapi_);
1955     cb->SaveCallbackReference(cbName, argv[PARAM1]);
1956 
1957     napi_value result = nullptr;
1958     napi_get_undefined(env, &result);
1959     return result;
1960 }
1961 
RegisterDataRequestCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)1962 napi_value AudioRendererNapi::RegisterDataRequestCallback(napi_env env, napi_value* argv,
1963     const std::string& cbName, AudioRendererNapi *rendererNapi)
1964 {
1965     if (rendererNapi->dataRequestCBNapi_ == nullptr) {
1966         rendererNapi->dataRequestCBNapi_ = std::make_shared<RendererDataRequestCallbackNapi>(env, rendererNapi);
1967         rendererNapi->audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK);
1968         THROW_ERROR_ASSERT(env, rendererNapi->dataRequestCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
1969         int32_t ret = rendererNapi->audioRenderer_->SetRendererWriteCallback(rendererNapi->dataRequestCBNapi_);
1970         THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
1971         std::shared_ptr<RendererDataRequestCallbackNapi> cb =
1972             std::static_pointer_cast<RendererDataRequestCallbackNapi>(rendererNapi->dataRequestCBNapi_);
1973         cb->SaveCallbackReference(cbName, argv[PARAM1]);
1974     } else {
1975         AUDIO_DEBUG_LOG("AudioRendererNapi:dataRequest already subscribed.");
1976         THROW_ERROR_ASSERT(env, false, NAPI_ERR_ILLEGAL_STATE);
1977     }
1978     napi_value result = nullptr;
1979     napi_get_undefined(env, &result);
1980     return result;
1981 }
1982 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * argv,const std::string & cbName)1983 napi_value AudioRendererNapi::RegisterCallback(napi_env env, napi_value jsThis,
1984                                                napi_value* argv, const std::string& cbName)
1985 {
1986     AudioRendererNapi *rendererNapi = nullptr;
1987     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
1988     THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
1989     THROW_ERROR_ASSERT(env, rendererNapi != nullptr, NAPI_ERR_NO_MEMORY);
1990 
1991     THROW_ERROR_ASSERT(env, rendererNapi->audioRenderer_ != nullptr, NAPI_ERR_NO_MEMORY);
1992 
1993     napi_value result = nullptr;
1994     napi_get_undefined(env, &result);
1995 
1996     if (!cbName.compare(INTERRUPT_CALLBACK_NAME) ||
1997         !cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME) ||
1998         !cbName.compare(STATE_CHANGE_CALLBACK_NAME)) {
1999         result = RegisterRendererCallback(env, argv, cbName, rendererNapi);
2000     } else if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
2001         result = RegisterPositionCallback(env, argv, cbName, rendererNapi);
2002     } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
2003         result = RegisterPeriodPositionCallback(env, argv, cbName, rendererNapi);
2004     } else if (!cbName.compare(DATA_REQUEST_CALLBACK_NAME)) {
2005         result = RegisterDataRequestCallback(env, argv, cbName, rendererNapi);
2006     } else {
2007         bool unknownCallback = true;
2008         THROW_ERROR_ASSERT(env, !unknownCallback, NAPI_ERROR_INVALID_PARAM);
2009     }
2010 
2011     return result;
2012 }
2013 
On(napi_env env,napi_callback_info info)2014 napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
2015 {
2016     const size_t requireArgc = 2;
2017     size_t argc = 3;
2018 
2019     napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
2020     napi_value jsThis = nullptr;
2021     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
2022     THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2023     THROW_ERROR_ASSERT(env, argc >= requireArgc, NAPI_ERR_INPUT_INVALID);
2024 
2025     napi_valuetype eventType = napi_undefined;
2026     napi_typeof(env, argv[0], &eventType);
2027     THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INPUT_INVALID);
2028 
2029     std::string callbackName = AudioCommonNapi::GetStringArgument(env, argv[0]);
2030     AUDIO_DEBUG_LOG("AudioRendererNapi: On callbackName: %{public}s", callbackName.c_str());
2031 
2032     napi_valuetype handler = napi_undefined;
2033     if (argc == requireArgc) {
2034         napi_typeof(env, argv[1], &handler);
2035         THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
2036     } else {
2037         napi_valuetype paramArg1 = napi_undefined;
2038         napi_typeof(env, argv[1], &paramArg1);
2039         napi_valuetype expectedValType = napi_number;  // Default. Reset it with 'callbackName' if check, if required.
2040         THROW_ERROR_ASSERT(env, paramArg1 == expectedValType, NAPI_ERR_INPUT_INVALID);
2041 
2042         const int32_t arg2 = 2;
2043         napi_typeof(env, argv[arg2], &handler);
2044         THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
2045     }
2046 
2047     return RegisterCallback(env, jsThis, argv, callbackName);
2048 }
2049 
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & cbName)2050 napi_value AudioRendererNapi::UnregisterCallback(napi_env env, napi_value jsThis, const std::string& cbName)
2051 {
2052     AudioRendererNapi *rendererNapi = nullptr;
2053     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
2054     THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2055     THROW_ERROR_ASSERT(env, rendererNapi != nullptr, NAPI_ERR_NO_MEMORY);
2056     THROW_ERROR_ASSERT(env, rendererNapi->audioRenderer_ != nullptr, NAPI_ERR_NO_MEMORY);
2057 
2058     if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
2059         rendererNapi->audioRenderer_->UnsetRendererPositionCallback();
2060         rendererNapi->positionCBNapi_ = nullptr;
2061     } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
2062         rendererNapi->audioRenderer_->UnsetRendererPeriodPositionCallback();
2063         rendererNapi->periodPositionCBNapi_ = nullptr;
2064     } else {
2065         bool unknownCallback = true;
2066         THROW_ERROR_ASSERT(env, !unknownCallback, NAPI_ERR_UNSUPPORTED);
2067     }
2068 
2069     napi_value result = nullptr;
2070     napi_get_undefined(env, &result);
2071     return result;
2072 }
2073 
Off(napi_env env,napi_callback_info info)2074 napi_value AudioRendererNapi::Off(napi_env env, napi_callback_info info)
2075 {
2076     const size_t requireArgc = 1;
2077     size_t argc = 1;
2078 
2079     napi_value argv[requireArgc] = {nullptr};
2080     napi_value jsThis = nullptr;
2081     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
2082     THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2083     THROW_ERROR_ASSERT(env, argc >= requireArgc, NAPI_ERR_INVALID_PARAM);
2084 
2085     napi_valuetype eventType = napi_undefined;
2086     napi_typeof(env, argv[0], &eventType);
2087     THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INVALID_PARAM);
2088 
2089     std::string callbackName = AudioCommonNapi::GetStringArgument(env, argv[0]);
2090     AUDIO_DEBUG_LOG("AudioRendererNapi: Off callbackName: %{public}s", callbackName.c_str());
2091 
2092     return UnregisterCallback(env, jsThis, callbackName);
2093 }
2094 
ParseRendererOptions(napi_env env,napi_value root,AudioRendererOptions * opts)2095 bool AudioRendererNapi::ParseRendererOptions(napi_env env, napi_value root, AudioRendererOptions *opts)
2096 {
2097     napi_value res = nullptr;
2098 
2099     if (napi_get_named_property(env, root, "rendererInfo", &res) == napi_ok) {
2100         ParseRendererInfo(env, res, &(opts->rendererInfo));
2101     }
2102 
2103     if (napi_get_named_property(env, root, "streamInfo", &res) == napi_ok) {
2104         ParseStreamInfo(env, res, &(opts->streamInfo));
2105     }
2106 
2107     return true;
2108 }
2109 
ParseRendererInfo(napi_env env,napi_value root,AudioRendererInfo * rendererInfo)2110 bool AudioRendererNapi::ParseRendererInfo(napi_env env, napi_value root, AudioRendererInfo *rendererInfo)
2111 {
2112     napi_value tempValue = nullptr;
2113     int32_t intValue = {0};
2114 
2115     if (napi_get_named_property(env, root, "content", &tempValue) == napi_ok) {
2116         napi_get_value_int32(env, tempValue, &intValue);
2117         rendererInfo->contentType = static_cast<ContentType>(intValue);
2118     }
2119 
2120     if (napi_get_named_property(env, root, "usage", &tempValue) == napi_ok) {
2121         napi_get_value_int32(env, tempValue, &intValue);
2122         rendererInfo->streamUsage = static_cast<StreamUsage>(intValue);
2123     }
2124 
2125     if (napi_get_named_property(env, root, "rendererFlags", &tempValue) == napi_ok) {
2126         napi_get_value_int32(env, tempValue, &(rendererInfo->rendererFlags));
2127     }
2128 
2129     return true;
2130 }
2131 
ParseStreamInfo(napi_env env,napi_value root,AudioStreamInfo * streamInfo)2132 bool AudioRendererNapi::ParseStreamInfo(napi_env env, napi_value root, AudioStreamInfo* streamInfo)
2133 {
2134     napi_value tempValue = nullptr;
2135     int32_t intValue = {0};
2136 
2137     if (napi_get_named_property(env, root, "samplingRate", &tempValue) == napi_ok) {
2138         napi_get_value_int32(env, tempValue, &intValue);
2139         streamInfo->samplingRate = static_cast<AudioSamplingRate>(intValue);
2140     }
2141 
2142     if (napi_get_named_property(env, root, "channels", &tempValue) == napi_ok) {
2143         napi_get_value_int32(env, tempValue, &intValue);
2144         streamInfo->channels = static_cast<AudioChannel>(intValue);
2145     }
2146 
2147     if (napi_get_named_property(env, root, "sampleFormat", &tempValue) == napi_ok) {
2148         napi_get_value_int32(env, tempValue, &intValue);
2149         streamInfo->format = static_cast<OHOS::AudioStandard::AudioSampleFormat>(intValue);
2150     }
2151 
2152     if (napi_get_named_property(env, root, "encodingType", &tempValue) == napi_ok) {
2153         napi_get_value_int32(env, tempValue, &intValue);
2154         streamInfo->encoding = static_cast<AudioEncodingType>(intValue);
2155     }
2156 
2157     return true;
2158 }
2159 
CheckContextStatus(AudioRendererAsyncContext * context)2160 bool AudioRendererNapi::CheckContextStatus(AudioRendererAsyncContext *context)
2161 {
2162     if (context == nullptr) {
2163         AUDIO_ERR_LOG("context object is nullptr.");
2164         return false;
2165     }
2166     if (context->objectInfo == nullptr || context->objectInfo->audioRenderer_ == nullptr) {
2167         context->status = NAPI_ERR_SYSTEM;
2168         AUDIO_ERR_LOG("context object state is error.");
2169         return false;
2170     }
2171     return true;
2172 }
2173 
CreateAudioRendererWrapper(napi_env env,unique_ptr<AudioRendererOptions> & renderOptions)2174 napi_value AudioRendererNapi::CreateAudioRendererWrapper(napi_env env, unique_ptr<AudioRendererOptions> &renderOptions)
2175 {
2176     lock_guard<mutex> lock(createMutex_);
2177     napi_status status;
2178     napi_value result = nullptr;
2179     napi_value constructor;
2180 
2181     if (renderOptions != nullptr) {
2182         status = napi_get_reference_value(env, g_rendererConstructor, &constructor);
2183         if (status == napi_ok) {
2184             sRendererOptions_ = move(renderOptions);
2185             status = napi_new_instance(env, constructor, 0, nullptr, &result);
2186             sRendererOptions_.release();
2187             if (status == napi_ok) {
2188                 return result;
2189             }
2190         }
2191         HiLog::Error(LABEL, "Failed in CreateAudioRendererWrapper, %{public}d", status);
2192     }
2193 
2194     napi_get_undefined(env, &result);
2195 
2196     return result;
2197 }
2198 
SetInterruptMode(napi_env env,napi_callback_info info)2199 napi_value AudioRendererNapi::SetInterruptMode(napi_env env, napi_callback_info info)
2200 {
2201     napi_status status;
2202     const int32_t refCount = 1;
2203     napi_value result = nullptr;
2204 
2205     GET_PARAMS(env, info, ARGS_TWO);
2206 
2207     unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2208     CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "AudioRendererAsyncContext object creation failed");
2209     if (argc < ARGS_ONE) {
2210         asyncContext->status = NAPI_ERR_INVALID_PARAM;
2211     }
2212 
2213     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2214     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2215         for (size_t i = PARAM0; i < argc; i++) {
2216             napi_valuetype valueType = napi_undefined;
2217             napi_typeof(env, argv[i], &valueType);
2218             if (i == PARAM0 && valueType == napi_number) {
2219                 napi_get_value_int32(env, argv[i], &asyncContext->interruptMode);
2220             } else if (i == PARAM1) {
2221                 if (valueType == napi_function) {
2222                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
2223                 }
2224                 break;
2225             } else {
2226                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
2227             }
2228         }
2229 
2230         if (asyncContext->callbackRef == nullptr) {
2231             napi_create_promise(env, &asyncContext->deferred, &result);
2232         } else {
2233             napi_get_undefined(env, &result);
2234         }
2235 
2236         napi_value resource = nullptr;
2237         napi_create_string_utf8(env, "SetInterruptMode", NAPI_AUTO_LENGTH, &resource);
2238 
2239         status = napi_create_async_work(
2240             env, nullptr, resource,
2241             [](napi_env env, void *data) {
2242                 auto context = static_cast<AudioRendererAsyncContext*>(data);
2243                 if (!CheckContextStatus(context)) {
2244                     return;
2245                 }
2246                 if (context->status == SUCCESS) {
2247                     AudioStandard::InterruptMode interruptMode_ = GetNativeInterruptMode(context->interruptMode);
2248                     context->objectInfo->audioRenderer_->SetInterruptMode(interruptMode_);
2249                     context->status = SUCCESS;
2250                     context->intValue = SUCCESS;
2251                 }
2252             },
2253             GetIntValueAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
2254         if (status != napi_ok) {
2255             result = nullptr;
2256         } else {
2257             status = napi_queue_async_work(env, asyncContext->work);
2258             if (status == napi_ok) {
2259                 asyncContext.release();
2260             } else {
2261                 result = nullptr;
2262             }
2263         }
2264     }
2265 
2266     return result;
2267 }
2268 } // namespace AudioStandard
2269 } // namespace OHOS
2270