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], ¶mArg1);
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