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