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 #include "xpower_event_js.h"
32 #include "audio_renderer_device_change_callback_napi.h"
33 #include "audio_renderer_policy_service_died_callback_napi.h"
34
35 using namespace std;
36 using OHOS::HiviewDFX::HiLog;
37 using OHOS::HiviewDFX::HiLogLabel;
38
39 namespace OHOS {
40 namespace AudioStandard {
41 static __thread napi_ref g_rendererConstructor = nullptr;
42 std::unique_ptr<AudioParameters> AudioRendererNapi::sAudioParameters_ = nullptr;
43 std::unique_ptr<AudioRendererOptions> AudioRendererNapi::sRendererOptions_ = nullptr;
44 napi_ref AudioRendererNapi::audioRendererRate_ = nullptr;
45 napi_ref AudioRendererNapi::interruptEventType_ = nullptr;
46 napi_ref AudioRendererNapi::interruptHintType_ = nullptr;
47 napi_ref AudioRendererNapi::interruptForceType_ = nullptr;
48 napi_ref AudioRendererNapi::audioState_ = nullptr;
49 napi_ref AudioRendererNapi::sampleFormat_ = nullptr;
50 napi_ref AudioRendererNapi::audioEffectMode_ = nullptr;
51 napi_ref AudioRendererNapi::audioPrivacyType_ = nullptr;
52 mutex AudioRendererNapi::createMutex_;
53 int32_t AudioRendererNapi::isConstructSuccess_ = SUCCESS;
54
55 namespace {
56 const int ARGS_ONE = 1;
57 const int ARGS_TWO = 2;
58 const int ARGS_THREE = 3;
59
60 const int PARAM0 = 0;
61 const int PARAM1 = 1;
62 const int PARAM2 = 2;
63
64 constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioRendererNapi"};
65
66 const std::string MARK_REACH_CALLBACK_NAME = "markReach";
67 const std::string PERIOD_REACH_CALLBACK_NAME = "periodReach";
68 const std::string DATA_REQUEST_CALLBACK_NAME = "dataRequest";
69 const std::string DEVICECHANGE_CALLBACK_NAME = "outputDeviceChange";
70
71 #define GET_PARAMS(env, info, num) \
72 size_t argc = num; \
73 napi_value argv[num] = {0}; \
74 napi_value thisVar = nullptr; \
75 void *data; \
76 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)
77 }
78
AudioRendererNapi()79 AudioRendererNapi::AudioRendererNapi()
80 : audioRenderer_(nullptr), contentType_(CONTENT_TYPE_MUSIC), streamUsage_(STREAM_USAGE_MEDIA),
81 deviceRole_(OUTPUT_DEVICE), deviceType_(DEVICE_TYPE_SPEAKER), env_(nullptr),
82 scheduleFromApiCall_(true), doNotScheduleWrite_(false), isDrainWriteQInProgress_(false) {}
83
84 AudioRendererNapi::~AudioRendererNapi() = default;
85
Destructor(napi_env env,void * nativeObject,void * finalize_hint)86 void AudioRendererNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
87 {
88 if (nativeObject != nullptr) {
89 auto obj = static_cast<AudioRendererNapi *>(nativeObject);
90 delete obj;
91 obj = nullptr;
92 }
93 AUDIO_INFO_LOG("Destructor is successful");
94 }
95
AddNamedProperty(napi_env env,napi_value object,const std::string name,int32_t enumValue)96 napi_status AudioRendererNapi::AddNamedProperty(napi_env env, napi_value object,
97 const std::string name, int32_t enumValue)
98 {
99 napi_status status;
100 napi_value enumNapiValue;
101
102 status = napi_create_int32(env, enumValue, &enumNapiValue);
103 if (status == napi_ok) {
104 status = napi_set_named_property(env, object, name.c_str(), enumNapiValue);
105 }
106
107 return status;
108 }
109
SetValueInt32(const napi_env & env,const std::string & fieldStr,const int intValue,napi_value & result)110 static void SetValueInt32(const napi_env& env, const std::string& fieldStr, const int intValue, napi_value &result)
111 {
112 napi_value value = nullptr;
113 napi_create_int32(env, intValue, &value);
114 napi_set_named_property(env, result, fieldStr.c_str(), value);
115 }
116
SetValueString(const napi_env & env,const std::string & fieldStr,const std::string stringValue,napi_value & result)117 static void SetValueString(const napi_env &env, const std::string &fieldStr, const std::string stringValue,
118 napi_value &result)
119 {
120 napi_value value = nullptr;
121 napi_create_string_utf8(env, stringValue.c_str(), NAPI_AUTO_LENGTH, &value);
122 napi_set_named_property(env, result, fieldStr.c_str(), value);
123 }
124
GetNativeInterruptMode(int32_t interruptMode)125 static AudioStandard::InterruptMode GetNativeInterruptMode(int32_t interruptMode)
126 {
127 AudioStandard::InterruptMode result;
128 switch (interruptMode) {
129 case AudioManagerNapi::InterruptMode::SHARE_MODE:
130 result = AudioStandard::InterruptMode::SHARE_MODE;
131 break;
132 case AudioManagerNapi::InterruptMode::INDEPENDENT_MODE:
133 result = AudioStandard::InterruptMode::INDEPENDENT_MODE;
134 break;
135 default:
136 result = AudioStandard::InterruptMode::SHARE_MODE;
137 HiLog::Error(LABEL, "Unknown interruptMode type, Set it to default SHARE_MODE!");
138 break;
139 }
140 return result;
141 }
142
CreateAudioSampleFormatObject(napi_env env)143 napi_value AudioRendererNapi::CreateAudioSampleFormatObject(napi_env env)
144 {
145 napi_value result = nullptr;
146 napi_status status;
147 string propName;
148
149 status = napi_create_object(env, &result);
150 if (status == napi_ok) {
151 for (int i = AudioRendererNapi::SAMPLE_FORMAT_INVALID; i <= AudioRendererNapi::SAMPLE_FORMAT_F32LE; i++) {
152 switch (i) {
153 case AudioRendererNapi::SAMPLE_FORMAT_INVALID:
154 propName = "SAMPLE_FORMAT_INVALID";
155 break;
156 case AudioRendererNapi::SAMPLE_FORMAT_U8:
157 propName = "SAMPLE_FORMAT_U8";
158 break;
159 case AudioRendererNapi::SAMPLE_FORMAT_S16LE:
160 propName = "SAMPLE_FORMAT_S16LE";
161 break;
162 case AudioRendererNapi::SAMPLE_FORMAT_S24LE:
163 propName = "SAMPLE_FORMAT_S24LE";
164 break;
165 case AudioRendererNapi::SAMPLE_FORMAT_S32LE:
166 propName = "SAMPLE_FORMAT_S32LE";
167 break;
168 case AudioRendererNapi::SAMPLE_FORMAT_F32LE:
169 propName = "SAMPLE_FORMAT_F32LE";
170 break;
171 default:
172 HiLog::Error(LABEL, "CreateAudioSampleFormatObject: No prop with this value try next value!");
173 continue;
174 }
175 status = AddNamedProperty(env, result, propName, i);
176 if (status != napi_ok) {
177 HiLog::Error(LABEL, "Failed to add named prop!");
178 break;
179 }
180 propName.clear();
181 }
182 if (status == napi_ok) {
183 status = napi_create_reference(env, result, REFERENCE_CREATION_COUNT, &sampleFormat_);
184 if (status == napi_ok) {
185 return result;
186 }
187 }
188 }
189 HiLog::Error(LABEL, "CreateAudioSampleFormatObject is Failed!");
190 napi_get_undefined(env, &result);
191
192 return result;
193 }
194
CreateAudioRendererRateObject(napi_env env)195 napi_value AudioRendererNapi::CreateAudioRendererRateObject(napi_env env)
196 {
197 napi_value result = nullptr;
198 napi_status status;
199 std::string propName;
200
201 status = napi_create_object(env, &result);
202 if (status == napi_ok) {
203 for (auto &iter: rendererRateMap) {
204 propName = iter.first;
205 status = AddNamedProperty(env, result, propName, iter.second);
206 if (status != napi_ok) {
207 HiLog::Error(LABEL, "Failed to add named prop!");
208 break;
209 }
210 propName.clear();
211 }
212 if (status == napi_ok) {
213 status = napi_create_reference(env, result, REFERENCE_CREATION_COUNT, &audioRendererRate_);
214 if (status == napi_ok) {
215 return result;
216 }
217 }
218 }
219 HiLog::Error(LABEL, "CreateAudioRendererRateObject is Failed!");
220 napi_get_undefined(env, &result);
221
222 return result;
223 }
224
CreateAudioStateObject(napi_env env)225 napi_value AudioRendererNapi::CreateAudioStateObject(napi_env env)
226 {
227 napi_value result = nullptr;
228 napi_status status;
229 std::string propName;
230 int32_t refCount = 1;
231
232 status = napi_create_object(env, &result);
233 if (status == napi_ok) {
234 for (auto &iter: audioStateMap) {
235 propName = iter.first;
236 status = AddNamedProperty(env, result, propName, iter.second);
237 if (status != napi_ok) {
238 HiLog::Error(LABEL, "Failed to add named prop in CreateAudioStateObject!");
239 break;
240 }
241 propName.clear();
242 }
243 if (status == napi_ok) {
244 status = napi_create_reference(env, result, refCount, &audioState_);
245 if (status == napi_ok) {
246 return result;
247 }
248 }
249 }
250 HiLog::Error(LABEL, "CreateAudioStateObject is Failed!");
251 napi_get_undefined(env, &result);
252
253 return result;
254 }
255
CreateInterruptEventTypeObject(napi_env env)256 napi_value AudioRendererNapi::CreateInterruptEventTypeObject(napi_env env)
257 {
258 napi_value result = nullptr;
259 napi_status status;
260 std::string propName;
261 int32_t refCount = 1;
262
263 status = napi_create_object(env, &result);
264 if (status == napi_ok) {
265 for (auto &iter: interruptEventTypeMap) {
266 propName = iter.first;
267 status = AddNamedProperty(env, result, propName, iter.second);
268 if (status != napi_ok) {
269 HiLog::Error(LABEL, "Failed to add named prop in CreateInterruptEventTypeObject!");
270 break;
271 }
272 propName.clear();
273 }
274 if (status == napi_ok) {
275 status = napi_create_reference(env, result, refCount, &interruptEventType_);
276 if (status == napi_ok) {
277 return result;
278 }
279 }
280 }
281 HiLog::Error(LABEL, "CreateInterruptEventTypeObject is Failed!");
282 napi_get_undefined(env, &result);
283
284 return result;
285 }
286
CreateInterruptForceTypeObject(napi_env env)287 napi_value AudioRendererNapi::CreateInterruptForceTypeObject(napi_env env)
288 {
289 napi_value result = nullptr;
290 napi_status status;
291 std::string propName;
292 int32_t refCount = 1;
293
294 status = napi_create_object(env, &result);
295 if (status == napi_ok) {
296 for (auto &iter: interruptForceTypeMap) {
297 propName = iter.first;
298 status = AddNamedProperty(env, result, propName, iter.second);
299 if (status != napi_ok) {
300 HiLog::Error(LABEL, "Failed to add named prop in CreateInterruptTypeObject!");
301 break;
302 }
303 propName.clear();
304 }
305 if (status == napi_ok) {
306 status = napi_create_reference(env, result, refCount, &interruptForceType_);
307 if (status == napi_ok) {
308 return result;
309 }
310 }
311 }
312 HiLog::Error(LABEL, "CreateInterruptForceTypeObject is Failed!");
313 napi_get_undefined(env, &result);
314
315 return result;
316 }
317
CreateInterruptHintTypeObject(napi_env env)318 napi_value AudioRendererNapi::CreateInterruptHintTypeObject(napi_env env)
319 {
320 napi_value result = nullptr;
321 napi_status status;
322 std::string propName;
323 int32_t refCount = 1;
324
325 status = napi_create_object(env, &result);
326 if (status == napi_ok) {
327 for (auto &iter: interruptHintTypeMap) {
328 propName = iter.first;
329 status = AddNamedProperty(env, result, propName, iter.second);
330 if (status != napi_ok) {
331 HiLog::Error(LABEL, "Failed to add named prop in CreateInterruptHintTypeObject!");
332 break;
333 }
334 propName.clear();
335 }
336 if (status == napi_ok) {
337 status = napi_create_reference(env, result, refCount, &interruptHintType_);
338 if (status == napi_ok) {
339 return result;
340 }
341 }
342 }
343 HiLog::Error(LABEL, "CreateInterruptHintTypeObject is Failed!");
344 napi_get_undefined(env, &result);
345
346 return result;
347 }
348
CreateAudioEffectModeObject(napi_env env)349 napi_value AudioRendererNapi::CreateAudioEffectModeObject(napi_env env)
350 {
351 napi_value result = nullptr;
352 napi_status status;
353 std::string propName;
354
355 status = napi_create_object(env, &result);
356 if (status == napi_ok) {
357 for (auto &iter: effectModeMap) {
358 propName = iter.first;
359 status = AddNamedProperty(env, result, propName, iter.second);
360 if (status != napi_ok) {
361 HiLog::Error(LABEL, "Failed to add named prop!");
362 break;
363 }
364 propName.clear();
365 }
366 if (status == napi_ok) {
367 status = napi_create_reference(env, result, REFERENCE_CREATION_COUNT, &audioEffectMode_);
368 if (status == napi_ok) {
369 return result;
370 }
371 }
372 }
373 HiLog::Error(LABEL, "CreateAudioEffectModeObject is Failed!");
374 napi_get_undefined(env, &result);
375
376 return result;
377 }
378
CreateAudioPrivacyTypeObject(napi_env env)379 napi_value AudioRendererNapi::CreateAudioPrivacyTypeObject(napi_env env)
380 {
381 napi_value result = nullptr;
382 napi_status status;
383 std::string propName;
384
385 status = napi_create_object(env, &result);
386 if (status == napi_ok) {
387 for (auto &iter: audioPrivacyTypeMap) {
388 propName = iter.first;
389 status = AddNamedProperty(env, result, propName, iter.second);
390 if (status != napi_ok) {
391 HiLog::Error(LABEL, "Failed to add named prop in CreateAudioPrivacyTypeObject!");
392 break;
393 }
394 propName.clear();
395 }
396 if (status == napi_ok) {
397 status = napi_create_reference(env, result, REFERENCE_CREATION_COUNT, &audioPrivacyType_);
398 if (status == napi_ok) {
399 return result;
400 }
401 }
402 }
403 HiLog::Error(LABEL, "CreateAudioPrivacyTypeObject is Failed!");
404 napi_get_undefined(env, &result);
405
406 return result;
407 }
408
SetDeviceDescriptors(const napi_env & env,napi_value & valueParam,const DeviceInfo & deviceInfo)409 static void SetDeviceDescriptors(const napi_env& env, napi_value &valueParam, const DeviceInfo &deviceInfo)
410 {
411 (void)napi_create_object(env, &valueParam);
412 SetValueInt32(env, "deviceRole", static_cast<int32_t>(deviceInfo.deviceRole), valueParam);
413 SetValueInt32(env, "deviceType", static_cast<int32_t>(deviceInfo.deviceType), valueParam);
414 SetValueInt32(env, "id", static_cast<int32_t>(deviceInfo.deviceId), valueParam);
415 SetValueString(env, "name", deviceInfo.deviceName, valueParam);
416 SetValueString(env, "address", deviceInfo.macAddress, valueParam);
417 SetValueString(env, "networkId", deviceInfo.networkId, valueParam);
418 SetValueString(env, "displayName", deviceInfo.displayName, valueParam);
419 SetValueInt32(env, "interruptGroupId", static_cast<int32_t>(deviceInfo.interruptGroupId), valueParam);
420 SetValueInt32(env, "volumeGroupId", static_cast<int32_t>(deviceInfo.volumeGroupId), valueParam);
421
422 napi_value value = nullptr;
423 napi_value sampleRates;
424 napi_create_array_with_length(env, 1, &sampleRates);
425 napi_create_int32(env, deviceInfo.audioStreamInfo.samplingRate, &value);
426 napi_set_element(env, sampleRates, 0, value);
427 napi_set_named_property(env, valueParam, "sampleRates", sampleRates);
428
429 napi_value channelCounts;
430 napi_create_array_with_length(env, 1, &channelCounts);
431 napi_create_int32(env, deviceInfo.audioStreamInfo.channels, &value);
432 napi_set_element(env, channelCounts, 0, value);
433 napi_set_named_property(env, valueParam, "channelCounts", channelCounts);
434
435 napi_value channelMasks;
436 napi_create_array_with_length(env, 1, &channelMasks);
437 napi_create_int32(env, deviceInfo.channelMasks, &value);
438 napi_set_element(env, channelMasks, 0, value);
439 napi_set_named_property(env, valueParam, "channelMasks", channelMasks);
440 }
441
Init(napi_env env,napi_value exports)442 napi_value AudioRendererNapi::Init(napi_env env, napi_value exports)
443 {
444 napi_status status;
445 napi_value constructor;
446 napi_value result = nullptr;
447 const int32_t refCount = 1;
448 napi_get_undefined(env, &result);
449
450 napi_property_descriptor audio_renderer_properties[] = {
451 DECLARE_NAPI_FUNCTION("setRenderRate", SetRenderRate),
452 DECLARE_NAPI_FUNCTION("getRenderRate", GetRenderRate),
453 DECLARE_NAPI_FUNCTION("getRenderRateSync", GetRenderRateSync),
454 DECLARE_NAPI_FUNCTION("setRendererSamplingRate", SetRendererSamplingRate),
455 DECLARE_NAPI_FUNCTION("getRendererSamplingRate", GetRendererSamplingRate),
456 DECLARE_NAPI_FUNCTION("start", Start),
457 DECLARE_NAPI_FUNCTION("write", Write),
458 DECLARE_NAPI_FUNCTION("getAudioTime", GetAudioTime),
459 DECLARE_NAPI_FUNCTION("getAudioTimeSync", GetAudioTimeSync),
460 DECLARE_NAPI_FUNCTION("drain", Drain),
461 DECLARE_NAPI_FUNCTION("pause", Pause),
462 DECLARE_NAPI_FUNCTION("stop", Stop),
463 DECLARE_NAPI_FUNCTION("release", Release),
464 DECLARE_NAPI_FUNCTION("getBufferSize", GetBufferSize),
465 DECLARE_NAPI_FUNCTION("getBufferSizeSync", GetBufferSizeSync),
466 DECLARE_NAPI_FUNCTION("getAudioStreamId", GetAudioStreamId),
467 DECLARE_NAPI_FUNCTION("getAudioStreamIdSync", GetAudioStreamIdSync),
468 DECLARE_NAPI_FUNCTION("setVolume", SetVolume),
469 DECLARE_NAPI_FUNCTION("on", On),
470 DECLARE_NAPI_FUNCTION("off", Off),
471 DECLARE_NAPI_FUNCTION("getRendererInfo", GetRendererInfo),
472 DECLARE_NAPI_FUNCTION("getRendererInfoSync", GetRendererInfoSync),
473 DECLARE_NAPI_FUNCTION("getStreamInfo", GetStreamInfo),
474 DECLARE_NAPI_FUNCTION("getStreamInfoSync", GetStreamInfoSync),
475 DECLARE_NAPI_FUNCTION("setInterruptMode", SetInterruptMode),
476 DECLARE_NAPI_FUNCTION("setInterruptModeSync", SetInterruptModeSync),
477 DECLARE_NAPI_FUNCTION("getMinStreamVolume", GetMinStreamVolume),
478 DECLARE_NAPI_FUNCTION("getMinStreamVolumeSync", GetMinStreamVolumeSync),
479 DECLARE_NAPI_FUNCTION("getMaxStreamVolume", GetMaxStreamVolume),
480 DECLARE_NAPI_FUNCTION("getMaxStreamVolumeSync", GetMaxStreamVolumeSync),
481 DECLARE_NAPI_FUNCTION("getCurrentOutputDevices", GetCurrentOutputDevices),
482 DECLARE_NAPI_FUNCTION("getCurrentOutputDevicesSync", GetCurrentOutputDevicesSync),
483 DECLARE_NAPI_FUNCTION("getUnderflowCount", GetUnderflowCount),
484 DECLARE_NAPI_FUNCTION("getUnderflowCountSync", GetUnderflowCountSync),
485 DECLARE_NAPI_FUNCTION("getAudioEffectMode", GetAudioEffectMode),
486 DECLARE_NAPI_FUNCTION("setAudioEffectMode", SetAudioEffectMode),
487 DECLARE_NAPI_GETTER("state", GetState)
488 };
489
490 napi_property_descriptor static_prop[] = {
491 DECLARE_NAPI_STATIC_FUNCTION("createAudioRenderer", CreateAudioRenderer),
492 DECLARE_NAPI_STATIC_FUNCTION("createAudioRendererSync", CreateAudioRendererSync),
493 DECLARE_NAPI_PROPERTY("AudioRendererRate", CreateAudioRendererRateObject(env)),
494 DECLARE_NAPI_PROPERTY("InterruptType", CreateInterruptEventTypeObject(env)),
495 DECLARE_NAPI_PROPERTY("InterruptForceType", CreateInterruptForceTypeObject(env)),
496 DECLARE_NAPI_PROPERTY("InterruptHint", CreateInterruptHintTypeObject(env)),
497 DECLARE_NAPI_PROPERTY("AudioState", CreateAudioStateObject(env)),
498 DECLARE_NAPI_PROPERTY("AudioSampleFormat", CreateAudioSampleFormatObject(env)),
499 DECLARE_NAPI_PROPERTY("AudioEffectMode", CreateAudioEffectModeObject(env)),
500 DECLARE_NAPI_PROPERTY("AudioPrivacyType", CreateAudioPrivacyTypeObject(env)),
501 };
502
503 status = napi_define_class(env, AUDIO_RENDERER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
504 sizeof(audio_renderer_properties) / sizeof(audio_renderer_properties[PARAM0]),
505 audio_renderer_properties, &constructor);
506 if (status != napi_ok) {
507 return result;
508 }
509
510 status = napi_create_reference(env, constructor, refCount, &g_rendererConstructor);
511 if (status == napi_ok) {
512 status = napi_set_named_property(env, exports, AUDIO_RENDERER_NAPI_CLASS_NAME.c_str(), constructor);
513 if (status == napi_ok) {
514 status = napi_define_properties(env, exports,
515 sizeof(static_prop) / sizeof(static_prop[PARAM0]), static_prop);
516 if (status == napi_ok) {
517 return exports;
518 }
519 }
520 }
521
522 HiLog::Error(LABEL, "Failure in AudioRendererNapi::Init()");
523 return result;
524 }
525
GetAbilityContext(napi_env env)526 static shared_ptr<AbilityRuntime::Context> GetAbilityContext(napi_env env)
527 {
528 HiLog::Info(LABEL, "Getting context with FA model");
529 auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
530 if (ability == nullptr) {
531 HiLog::Error(LABEL, "Failed to obtain ability in FA mode");
532 return nullptr;
533 }
534
535 auto faContext = ability->GetAbilityContext();
536 if (faContext == nullptr) {
537 HiLog::Error(LABEL, "GetAbilityContext returned null in FA model");
538 return nullptr;
539 }
540
541 return faContext;
542 }
543
CreateRendererFailed()544 void AudioRendererNapi::CreateRendererFailed()
545 {
546 HiLog::Error(LABEL, "Renderer Create failed");
547 AudioRendererNapi::isConstructSuccess_ = NAPI_ERR_SYSTEM;
548 if (AudioRenderer::CheckMaxRendererInstances() == ERR_OVERFLOW) {
549 AudioRendererNapi::isConstructSuccess_ = NAPI_ERR_STREAM_LIMIT;
550 }
551 }
552
Construct(napi_env env,napi_callback_info info)553 napi_value AudioRendererNapi::Construct(napi_env env, napi_callback_info info)
554 {
555 napi_status status;
556 napi_value result = nullptr;
557 napi_get_undefined(env, &result);
558
559 GET_PARAMS(env, info, ARGS_TWO);
560
561 unique_ptr<AudioRendererNapi> rendererNapi = make_unique<AudioRendererNapi>();
562 CHECK_AND_RETURN_RET_LOG(rendererNapi != nullptr, result, "No memory");
563
564 rendererNapi->env_ = env;
565 rendererNapi->contentType_ = sRendererOptions_->rendererInfo.contentType;
566 rendererNapi->streamUsage_ = sRendererOptions_->rendererInfo.streamUsage;
567
568 AudioRendererOptions rendererOptions = {};
569 rendererOptions.streamInfo.samplingRate = sRendererOptions_->streamInfo.samplingRate;
570 rendererOptions.streamInfo.encoding = sRendererOptions_->streamInfo.encoding;
571 rendererOptions.streamInfo.format = sRendererOptions_->streamInfo.format;
572 rendererOptions.streamInfo.channels = sRendererOptions_->streamInfo.channels;
573 rendererOptions.rendererInfo.contentType = sRendererOptions_->rendererInfo.contentType;
574 rendererOptions.rendererInfo.streamUsage = sRendererOptions_->rendererInfo.streamUsage;
575 rendererOptions.privacyType = sRendererOptions_->privacyType;
576
577 std::shared_ptr<AbilityRuntime::Context> abilityContext = GetAbilityContext(env);
578 std::string cacheDir = "";
579 if (abilityContext != nullptr) {
580 cacheDir = abilityContext->GetCacheDir();
581 } else {
582 cacheDir = "/data/storage/el2/base/haps/entry/files";
583 }
584 rendererNapi->audioRenderer_ = AudioRenderer::Create(cacheDir, rendererOptions);
585
586 if (rendererNapi->audioRenderer_ == nullptr) {
587 CreateRendererFailed();
588 }
589
590 if (rendererNapi->audioRenderer_ != nullptr && rendererNapi->callbackNapi_ == nullptr) {
591 rendererNapi->callbackNapi_ = std::make_shared<AudioRendererCallbackNapi>(env);
592 CHECK_AND_RETURN_RET_LOG(rendererNapi->callbackNapi_ != nullptr, result, "No memory");
593 int32_t ret = rendererNapi->audioRenderer_->SetRendererCallback(rendererNapi->callbackNapi_);
594 if (ret) {
595 AUDIO_DEBUG_LOG("Construct SetRendererCallback failed");
596 }
597 }
598
599 status = napi_wrap(env, thisVar, static_cast<void*>(rendererNapi.get()),
600 AudioRendererNapi::Destructor, nullptr, nullptr);
601 if (status == napi_ok) {
602 rendererNapi.release();
603 return thisVar;
604 }
605
606 HiLog::Error(LABEL, "Failed in AudioRendererNapi::Construct()!");
607 return result;
608 }
609
CreateAudioRenderer(napi_env env,napi_callback_info info)610 napi_value AudioRendererNapi::CreateAudioRenderer(napi_env env, napi_callback_info info)
611 {
612 HiLog::Info(LABEL, "%{public}s IN", __func__);
613 napi_status status;
614 napi_value result = nullptr;
615
616 GET_PARAMS(env, info, ARGS_TWO);
617
618 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
619 CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "AudioRendererAsyncContext object creation failed");
620 if (argc < ARGS_ONE) {
621 asyncContext->status = NAPI_ERR_INVALID_PARAM;
622 }
623
624 for (size_t i = PARAM0; i < argc; i++) {
625 napi_valuetype valueType = napi_undefined;
626 napi_typeof(env, argv[i], &valueType);
627 if (i == PARAM0 && valueType == napi_object) {
628 if (!ParseRendererOptions(env, argv[i], &(asyncContext->rendererOptions))) {
629 HiLog::Error(LABEL, "Parsing of renderer options failed");
630 return result;
631 }
632 } else if (i == PARAM1) {
633 if (valueType == napi_function) {
634 napi_create_reference(env, argv[i], REFERENCE_CREATION_COUNT, &asyncContext->callbackRef);
635 }
636 break;
637 } else {
638 asyncContext->status = NAPI_ERR_INVALID_PARAM;
639 }
640 }
641
642 if (asyncContext->callbackRef == nullptr) {
643 napi_create_promise(env, &asyncContext->deferred, &result);
644 } else {
645 napi_get_undefined(env, &result);
646 }
647
648 napi_value resource = nullptr;
649 napi_create_string_utf8(env, "CreateAudioRenderer", NAPI_AUTO_LENGTH, &resource);
650
651 status = napi_create_async_work(
652 env, nullptr, resource,
653 [](napi_env env, void *data) {
654 auto context = static_cast<AudioRendererAsyncContext *>(data);
655 context->status = SUCCESS;
656 },
657 GetRendererAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
658 if (status != napi_ok) {
659 result = nullptr;
660 } else {
661 status = napi_queue_async_work(env, asyncContext->work);
662 if (status == napi_ok) {
663 asyncContext.release();
664 } else {
665 result = nullptr;
666 }
667 }
668 return result;
669 }
670
CreateAudioRendererSync(napi_env env,napi_callback_info info)671 napi_value AudioRendererNapi::CreateAudioRendererSync(napi_env env, napi_callback_info info)
672 {
673 HiLog::Info(LABEL, "%{public}s IN", __func__);
674 napi_value result = nullptr;
675
676 GET_PARAMS(env, info, ARGS_ONE);
677
678 if (argc < ARGS_ONE) {
679 AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
680 return result;
681 }
682
683 napi_valuetype valueType = napi_undefined;
684 napi_typeof(env, argv[PARAM0], &valueType);
685 if (valueType != napi_object) {
686 AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
687 return result;
688 }
689
690 AudioRendererOptions rendererOptions;
691 if (!ParseRendererOptions(env, argv[PARAM0], &rendererOptions)) {
692 AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
693 return result;
694 }
695
696 unique_ptr<AudioRendererOptions> audioRendererOptions = make_unique<AudioRendererOptions>();
697 audioRendererOptions->streamInfo.samplingRate = rendererOptions.streamInfo.samplingRate;
698 audioRendererOptions->streamInfo.encoding = rendererOptions.streamInfo.encoding;
699 audioRendererOptions->streamInfo.format = rendererOptions.streamInfo.format;
700 audioRendererOptions->streamInfo.channels = rendererOptions.streamInfo.channels;
701 audioRendererOptions->rendererInfo.contentType = rendererOptions.rendererInfo.contentType;
702 audioRendererOptions->rendererInfo.streamUsage = rendererOptions.rendererInfo.streamUsage;
703 audioRendererOptions->rendererInfo.rendererFlags = rendererOptions.rendererInfo.rendererFlags;
704 audioRendererOptions->privacyType = rendererOptions.privacyType;
705
706 return AudioRendererNapi::CreateAudioRendererWrapper(env, audioRendererOptions);
707 }
708
CommonCallbackRoutine(napi_env env,AudioRendererAsyncContext * & asyncContext,const napi_value & valueParam)709 void AudioRendererNapi::CommonCallbackRoutine(napi_env env, AudioRendererAsyncContext* &asyncContext,
710 const napi_value &valueParam)
711 {
712 napi_value result[ARGS_TWO] = {0};
713 napi_value retVal;
714
715 if (!asyncContext->status) {
716 napi_get_undefined(env, &result[PARAM0]);
717 result[PARAM1] = valueParam;
718 } else {
719 napi_value message = nullptr;
720 std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
721 napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
722
723 napi_value code = nullptr;
724 napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
725
726 napi_create_error(env, code, message, &result[PARAM0]);
727 napi_get_undefined(env, &result[PARAM1]);
728 }
729
730 if (asyncContext->deferred) {
731 if (!asyncContext->status) {
732 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
733 } else {
734 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
735 }
736 } else {
737 napi_value callback = nullptr;
738 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
739 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
740 napi_delete_reference(env, asyncContext->callbackRef);
741 }
742 napi_delete_async_work(env, asyncContext->work);
743
744 delete asyncContext;
745 asyncContext = nullptr;
746 }
747
WriteAsyncCallbackComplete(napi_env env,napi_status status,void * data)748 void AudioRendererNapi::WriteAsyncCallbackComplete(napi_env env, napi_status status, void *data)
749 {
750 napi_value result[ARGS_TWO] = {0};
751 napi_value retVal;
752
753 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
754
755 if (asyncContext != nullptr) {
756 if (!asyncContext->status) {
757 napi_get_undefined(env, &result[PARAM0]);
758 napi_create_uint32(env, asyncContext->totalBytesWritten, &result[PARAM1]);
759 } else {
760 napi_value message = nullptr;
761 std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
762 napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
763
764 napi_value code = nullptr;
765 napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
766
767 napi_create_error(env, code, message, &result[PARAM0]);
768 napi_get_undefined(env, &result[PARAM1]);
769 }
770
771 if (asyncContext->deferred) {
772 if (!asyncContext->status) {
773 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
774 } else {
775 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
776 }
777 } else {
778 napi_value callback = nullptr;
779 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
780 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
781 napi_delete_reference(env, asyncContext->callbackRef);
782 }
783 napi_delete_async_work(env, asyncContext->work);
784 // queue the next write request from internal queue to napi queue
785 if (!asyncContext->objectInfo->doNotScheduleWrite_ && !asyncContext->objectInfo->isDrainWriteQInProgress_) {
786 if (!asyncContext->objectInfo->writeRequestQ_.empty()) {
787 napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
788 asyncContext->objectInfo->writeRequestQ_.pop();
789 } else {
790 asyncContext->objectInfo->scheduleFromApiCall_ = true;
791 }
792 }
793
794 delete asyncContext;
795 asyncContext = nullptr;
796 } else {
797 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
798 }
799 }
800
PauseAsyncCallbackComplete(napi_env env,napi_status status,void * data)801 void AudioRendererNapi::PauseAsyncCallbackComplete(napi_env env, napi_status status, void *data)
802 {
803 napi_value result[ARGS_TWO] = {0};
804 napi_value retVal;
805
806 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
807 napi_value valueParam = nullptr;
808
809 if (asyncContext != nullptr) {
810 if (!asyncContext->status) {
811 // set pause result to doNotScheduleWrite_
812 asyncContext->objectInfo->doNotScheduleWrite_ = asyncContext->isTrue;
813 napi_get_undefined(env, &valueParam);
814 }
815 if (!asyncContext->status) {
816 napi_get_undefined(env, &result[PARAM0]);
817 result[PARAM1] = valueParam;
818 } else {
819 napi_value message = nullptr;
820 std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
821 napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
822
823 napi_value code = nullptr;
824 napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
825
826 napi_create_error(env, code, message, &result[PARAM0]);
827 napi_get_undefined(env, &result[PARAM1]);
828 }
829
830 if (asyncContext->deferred) {
831 if (!asyncContext->status) {
832 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
833 } else {
834 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
835 }
836 } else {
837 napi_value callback = nullptr;
838 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
839 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
840 napi_delete_reference(env, asyncContext->callbackRef);
841 }
842 napi_delete_async_work(env, asyncContext->work);
843 // Pause failed . Continue Write
844 if (!asyncContext->isTrue) {
845 HiLog::Info(LABEL, "PauseAsyncCallbackComplete: Pasue failed, Continue Write");
846 if (!asyncContext->objectInfo->writeRequestQ_.empty()) {
847 napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
848 asyncContext->objectInfo->writeRequestQ_.pop();
849 } else {
850 asyncContext->objectInfo->scheduleFromApiCall_ = true;
851 }
852 }
853
854 delete asyncContext;
855 asyncContext = nullptr;
856 } else {
857 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
858 }
859 }
860
StartAsyncCallbackComplete(napi_env env,napi_status status,void * data)861 void AudioRendererNapi::StartAsyncCallbackComplete(napi_env env, napi_status status, void *data)
862 {
863 napi_value result[ARGS_TWO] = {0};
864 napi_value retVal;
865
866 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
867 napi_value valueParam = nullptr;
868
869 if (asyncContext != nullptr) {
870 if (!asyncContext->status) {
871 napi_get_undefined(env, &valueParam);
872 }
873 if (!asyncContext->status) {
874 napi_get_undefined(env, &result[PARAM0]);
875 result[PARAM1] = valueParam;
876 } else {
877 napi_value message = nullptr;
878 std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
879 napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
880
881 napi_value code = nullptr;
882 napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
883
884 napi_create_error(env, code, message, &result[PARAM0]);
885 napi_get_undefined(env, &result[PARAM1]);
886 }
887
888 if (asyncContext->deferred) {
889 if (!asyncContext->status) {
890 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
891 } else {
892 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
893 }
894 } else {
895 napi_value callback = nullptr;
896 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
897 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
898 napi_delete_reference(env, asyncContext->callbackRef);
899 }
900 napi_delete_async_work(env, asyncContext->work);
901 // If start success , set doNotScheduleWrite_ = false and queue write request
902 if (asyncContext->isTrue) {
903 asyncContext->objectInfo->doNotScheduleWrite_ = false;
904 if (!asyncContext->objectInfo->writeRequestQ_.empty()) {
905 napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
906 asyncContext->objectInfo->writeRequestQ_.pop();
907 } else {
908 asyncContext->objectInfo->scheduleFromApiCall_ = true;
909 }
910 }
911
912 delete asyncContext;
913 asyncContext = nullptr;
914 } else {
915 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
916 }
917 }
918
StopAsyncCallbackComplete(napi_env env,napi_status status,void * data)919 void AudioRendererNapi::StopAsyncCallbackComplete(napi_env env, napi_status status, void *data)
920 {
921 napi_value result[ARGS_TWO] = {0};
922 napi_value retVal;
923
924 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
925 napi_value valueParam = nullptr;
926
927 if (asyncContext != nullptr) {
928 if (!asyncContext->status) {
929 // set pause result to doNotScheduleWrite_
930 asyncContext->objectInfo->doNotScheduleWrite_ = asyncContext->isTrue;
931 napi_get_undefined(env, &valueParam);
932 }
933 if (!asyncContext->status) {
934 napi_get_undefined(env, &result[PARAM0]);
935 result[PARAM1] = valueParam;
936 } else {
937 napi_value message = nullptr;
938 std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
939 napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
940
941 napi_value code = nullptr;
942 napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
943
944 napi_create_error(env, code, message, &result[PARAM0]);
945 napi_get_undefined(env, &result[PARAM1]);
946 }
947
948 if (asyncContext->deferred) {
949 if (!asyncContext->status) {
950 napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
951 } else {
952 napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
953 }
954 } else {
955 napi_value callback = nullptr;
956 napi_get_reference_value(env, asyncContext->callbackRef, &callback);
957 napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
958 napi_delete_reference(env, asyncContext->callbackRef);
959 }
960 napi_delete_async_work(env, asyncContext->work);
961
962 delete asyncContext;
963 asyncContext = nullptr;
964 } else {
965 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
966 }
967 }
968
SetFunctionAsyncCallbackComplete(napi_env env,napi_status status,void * data)969 void AudioRendererNapi::SetFunctionAsyncCallbackComplete(napi_env env, napi_status status, void *data)
970 {
971 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
972 napi_value valueParam = nullptr;
973
974 if (asyncContext != nullptr) {
975 if (!asyncContext->status) {
976 napi_get_undefined(env, &valueParam);
977 }
978 CommonCallbackRoutine(env, asyncContext, valueParam);
979 } else {
980 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
981 }
982 }
983
IsTrueAsyncCallbackComplete(napi_env env,napi_status status,void * data)984 void AudioRendererNapi::IsTrueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
985 {
986 auto asyncContext = static_cast<AudioRendererAsyncContext*>(data);
987 napi_value valueParam = nullptr;
988
989 if (asyncContext != nullptr) {
990 if (!asyncContext->status) {
991 napi_get_boolean(env, asyncContext->isTrue, &valueParam);
992 }
993 CommonCallbackRoutine(env, asyncContext, valueParam);
994 } else {
995 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
996 }
997 }
998
VoidAsyncCallbackComplete(napi_env env,napi_status status,void * data)999 void AudioRendererNapi::VoidAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1000 {
1001 auto asyncContext = static_cast<AudioRendererAsyncContext*>(data);
1002 napi_value valueParam = nullptr;
1003
1004 if (asyncContext != nullptr) {
1005 if (!asyncContext->status) {
1006 napi_get_undefined(env, &valueParam);
1007 }
1008 CommonCallbackRoutine(env, asyncContext, valueParam);
1009 } else {
1010 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
1011 }
1012 }
1013
GetBufferSizeAsyncCallbackComplete(napi_env env,napi_status status,void * data)1014 void AudioRendererNapi::GetBufferSizeAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1015 {
1016 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1017 napi_value valueParam = nullptr;
1018
1019 if (asyncContext != nullptr) {
1020 if (!asyncContext->status) {
1021 napi_create_uint32(env, asyncContext->bufferSize, &valueParam);
1022 }
1023 CommonCallbackRoutine(env, asyncContext, valueParam);
1024 } else {
1025 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
1026 }
1027 }
1028
GetAudioStreamIdCallbackComplete(napi_env env,napi_status status,void * data)1029 void AudioRendererNapi::GetAudioStreamIdCallbackComplete(napi_env env, napi_status status, void *data)
1030 {
1031 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1032 napi_value valueParam = nullptr;
1033
1034 if (asyncContext != nullptr) {
1035 if (!asyncContext->status) {
1036 napi_create_uint32(env, asyncContext->audioStreamId, &valueParam);
1037 }
1038 CommonCallbackRoutine(env, asyncContext, valueParam);
1039 } else {
1040 HiLog::Error(LABEL, "ERROR::GetAudioStreamIdCallbackComplete* is Null!");
1041 }
1042 }
1043
GetIntValueAsyncCallbackComplete(napi_env env,napi_status status,void * data)1044 void AudioRendererNapi::GetIntValueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1045 {
1046 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1047 napi_value valueParam = nullptr;
1048
1049 if (asyncContext != nullptr) {
1050 if (!asyncContext->status) {
1051 napi_create_int32(env, asyncContext->intValue, &valueParam);
1052 }
1053 CommonCallbackRoutine(env, asyncContext, valueParam);
1054 } else {
1055 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
1056 }
1057 }
1058
GetStreamVolumeAsyncCallbackComplete(napi_env env,napi_status status,void * data)1059 void AudioRendererNapi::GetStreamVolumeAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1060 {
1061 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1062 napi_value valueParam = nullptr;
1063
1064 if (asyncContext != nullptr) {
1065 if (!asyncContext->status) {
1066 napi_create_double(env, asyncContext->volLevel, &valueParam);
1067 }
1068 CommonCallbackRoutine(env, asyncContext, valueParam);
1069 } else {
1070 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
1071 }
1072 }
1073
GetRendererSampleRateAsyncCallbackComplete(napi_env env,napi_status,void * data)1074 void AudioRendererNapi::GetRendererSampleRateAsyncCallbackComplete(napi_env env, napi_status, void *data)
1075 {
1076 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1077 napi_value valueParam = nullptr;
1078
1079 if (asyncContext != nullptr) {
1080 if (!asyncContext->status) {
1081 napi_create_uint32(env, asyncContext->rendererSampleRate, &valueParam);
1082 }
1083 CommonCallbackRoutine(env, asyncContext, valueParam);
1084 } else {
1085 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
1086 }
1087 }
1088
GetRendererAsyncCallbackComplete(napi_env env,napi_status status,void * data)1089 void AudioRendererNapi::GetRendererAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1090 {
1091 napi_value valueParam = nullptr;
1092 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1093
1094 if (asyncContext != nullptr) {
1095 if (!asyncContext->status) {
1096 unique_ptr<AudioRendererOptions> rendererOptions = make_unique<AudioRendererOptions>();
1097 rendererOptions->streamInfo.samplingRate = asyncContext->rendererOptions.streamInfo.samplingRate;
1098 rendererOptions->streamInfo.encoding = asyncContext->rendererOptions.streamInfo.encoding;
1099 rendererOptions->streamInfo.format = asyncContext->rendererOptions.streamInfo.format;
1100 rendererOptions->streamInfo.channels = asyncContext->rendererOptions.streamInfo.channels;
1101 rendererOptions->rendererInfo.contentType = asyncContext->rendererOptions.rendererInfo.contentType;
1102 rendererOptions->rendererInfo.streamUsage = asyncContext->rendererOptions.rendererInfo.streamUsage;
1103 rendererOptions->rendererInfo.rendererFlags = asyncContext->rendererOptions.rendererInfo.rendererFlags;
1104 rendererOptions->privacyType = asyncContext->rendererOptions.privacyType;
1105
1106 valueParam = CreateAudioRendererWrapper(env, rendererOptions);
1107 asyncContext->status = AudioRendererNapi::isConstructSuccess_;
1108 AudioRendererNapi::isConstructSuccess_ = SUCCESS;
1109 }
1110 CommonCallbackRoutine(env, asyncContext, valueParam);
1111 } else {
1112 HiLog::Error(LABEL, "ERROR: GetRendererAsyncCallbackComplete asyncContext is Null!");
1113 }
1114 }
1115
GetDeviceInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)1116 void AudioRendererNapi::GetDeviceInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1117 {
1118 napi_value valueParam = nullptr;
1119 napi_value deviceDescriptors = nullptr;
1120 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1121
1122 if (asyncContext != nullptr) {
1123 if (!asyncContext->status) {
1124 napi_create_array_with_length(env, 1, &deviceDescriptors);
1125 SetDeviceDescriptors(env, valueParam, asyncContext->deviceInfo);
1126 napi_set_element(env, deviceDescriptors, 0, valueParam);
1127 asyncContext->status = AudioRendererNapi::isConstructSuccess_;
1128 AudioRendererNapi::isConstructSuccess_ = SUCCESS;
1129 }
1130 CommonCallbackRoutine(env, asyncContext, deviceDescriptors);
1131 } else {
1132 HiLog::Error(LABEL, "ERROR: GetDeviceInfoAsyncCallbackComplete asyncContext is Null!");
1133 }
1134 }
1135
GetInt64ValueAsyncCallbackComplete(napi_env env,napi_status status,void * data)1136 void AudioRendererNapi::GetInt64ValueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1137 {
1138 auto asyncContext = static_cast<AudioRendererAsyncContext*>(data);
1139 napi_value valueParam = nullptr;
1140
1141 if (asyncContext != nullptr) {
1142 if (!asyncContext->status) {
1143 napi_create_int64(env, asyncContext->time, &valueParam);
1144 }
1145 CommonCallbackRoutine(env, asyncContext, valueParam);
1146 } else {
1147 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
1148 }
1149 }
1150
AudioRendererInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)1151 void AudioRendererNapi::AudioRendererInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1152 {
1153 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1154 napi_value valueParam = nullptr;
1155
1156 if (asyncContext != nullptr) {
1157 if (asyncContext->status == SUCCESS) {
1158 (void)napi_create_object(env, &valueParam);
1159 SetValueInt32(env, "content", static_cast<int32_t>(asyncContext->contentType), valueParam);
1160 SetValueInt32(env, "usage", static_cast<int32_t>(asyncContext->usage), valueParam);
1161 SetValueInt32(env, "rendererFlags", asyncContext->rendererFlags, valueParam);
1162 }
1163 CommonCallbackRoutine(env, asyncContext, valueParam);
1164 } else {
1165 HiLog::Error(LABEL, "ERROR: asyncContext is Null!");
1166 }
1167 }
1168
AudioStreamInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)1169 void AudioRendererNapi::AudioStreamInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1170 {
1171 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1172 napi_value valueParam = nullptr;
1173
1174 if (asyncContext != nullptr) {
1175 if (asyncContext->status == SUCCESS) {
1176 (void)napi_create_object(env, &valueParam);
1177 SetValueInt32(env, "samplingRate", static_cast<int32_t>(asyncContext->samplingRate), valueParam);
1178 SetValueInt32(env, "channels", static_cast<int32_t>(asyncContext->channelCount), valueParam);
1179 SetValueInt32(env, "sampleFormat", static_cast<int32_t>(asyncContext->sampleFormat), valueParam);
1180 SetValueInt32(env, "encodingType", static_cast<int32_t>(asyncContext->encodingType), valueParam);
1181 }
1182 CommonCallbackRoutine(env, asyncContext, valueParam);
1183 } else {
1184 HiLog::Error(LABEL, "ERROR: AudioStreamInfoAsyncCallbackComplete* is Null!");
1185 }
1186 }
1187
GetUnderflowCountAsyncCallbackComplete(napi_env env,napi_status status,void * data)1188 void AudioRendererNapi::GetUnderflowCountAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1189 {
1190 auto asyncContext = static_cast<AudioRendererAsyncContext *>(data);
1191 napi_value valueParam = nullptr;
1192
1193 if (asyncContext != nullptr) {
1194 if (!asyncContext->status) {
1195 napi_create_uint32(env, asyncContext->underflowCount, &valueParam);
1196 }
1197 CommonCallbackRoutine(env, asyncContext, valueParam);
1198 } else {
1199 HiLog::Error(LABEL, "ERROR: AudioRendererAsyncContext* is Null!");
1200 }
1201 }
1202
SetRenderRate(napi_env env,napi_callback_info info)1203 napi_value AudioRendererNapi::SetRenderRate(napi_env env, napi_callback_info info)
1204 {
1205 napi_status status;
1206 const int32_t refCount = 1;
1207 napi_value result = nullptr;
1208
1209 GET_PARAMS(env, info, ARGS_TWO);
1210 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1211 if (argc < ARGS_ONE) {
1212 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1213 }
1214
1215 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1216 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1217 for (size_t i = PARAM0; i < argc; i++) {
1218 napi_valuetype valueType = napi_undefined;
1219 napi_typeof(env, argv[i], &valueType);
1220
1221 if (i == PARAM0 && valueType == napi_number) {
1222 napi_get_value_int32(env, argv[PARAM0], &asyncContext->audioRendererRate);
1223 } else if (i == PARAM1) {
1224 if (valueType == napi_function) {
1225 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1226 }
1227 break;
1228 } else {
1229 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1230 }
1231 }
1232
1233 if (asyncContext->callbackRef == nullptr) {
1234 napi_create_promise(env, &asyncContext->deferred, &result);
1235 } else {
1236 napi_get_undefined(env, &result);
1237 }
1238
1239 napi_value resource = nullptr;
1240 napi_create_string_utf8(env, "SetRenderRate", NAPI_AUTO_LENGTH, &resource);
1241
1242 status = napi_create_async_work(
1243 env, nullptr, resource,
1244 [](napi_env env, void *data) {
1245 auto context = static_cast<AudioRendererAsyncContext *>(data);
1246 if (!CheckContextStatus(context)) {
1247 return;
1248 }
1249 if (context->status == SUCCESS) {
1250 AudioRendererRate audioRenderRate = static_cast<AudioRendererRate>(context->audioRendererRate);
1251 int32_t audioClientInvalidParamsErr = -2;
1252 context->intValue = context->objectInfo->audioRenderer_->SetRenderRate(audioRenderRate);
1253 if (context->intValue == SUCCESS) {
1254 context->status = SUCCESS;
1255 } else if (context->intValue == audioClientInvalidParamsErr) {
1256 context->status = NAPI_ERR_UNSUPPORTED;
1257 } else {
1258 context->status = NAPI_ERR_SYSTEM;
1259 }
1260 }
1261 },
1262 VoidAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1263 if (status != napi_ok) {
1264 result = nullptr;
1265 } else {
1266 status = napi_queue_async_work(env, asyncContext->work);
1267 if (status == napi_ok) {
1268 asyncContext.release();
1269 } else {
1270 result = nullptr;
1271 }
1272 }
1273 }
1274
1275 return result;
1276 }
1277
AsyncSetSamplingRate(napi_env env,void * data)1278 void AudioRendererNapi::AsyncSetSamplingRate(napi_env env, void *data)
1279 {
1280 auto context = static_cast<AudioRendererAsyncContext*>(data);
1281 if (!CheckContextStatus(context)) {
1282 return;
1283 }
1284 if (context->status == SUCCESS) {
1285 if (context->rendererSampleRate <= 0) {
1286 context->status = NAPI_ERR_UNSUPPORTED;
1287 } else {
1288 context->status = context->objectInfo->audioRenderer_->
1289 SetRendererSamplingRate(context->rendererSampleRate);
1290 }
1291 }
1292 }
1293
SetRendererSamplingRate(napi_env env,napi_callback_info info)1294 napi_value AudioRendererNapi::SetRendererSamplingRate(napi_env env, napi_callback_info info)
1295 {
1296 napi_status status;
1297 const int32_t refCount = 1;
1298 napi_value result = nullptr;
1299
1300 GET_PARAMS(env, info, ARGS_TWO);
1301 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1302 THROW_ERROR_ASSERT(env, argc >= ARGS_ONE, NAPI_ERR_INVALID_PARAM);
1303
1304 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1305 if (status != napi_ok || asyncContext->objectInfo == nullptr) {
1306 return result;
1307 }
1308
1309 for (size_t i = PARAM0; i < argc; i++) {
1310 napi_valuetype valueType = napi_undefined;
1311 napi_typeof(env, argv[i], &valueType);
1312
1313 if (i == PARAM0 && valueType == napi_number) {
1314 napi_get_value_uint32(env, argv[PARAM0], &asyncContext->rendererSampleRate);
1315 } else if (i == PARAM1) {
1316 if (valueType == napi_function) {
1317 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1318 }
1319 break;
1320 } else {
1321 asyncContext->status = NAPI_ERR_INVALID_PARAM;
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, "SetRendererSamplingRate", NAPI_AUTO_LENGTH, &resource);
1333
1334 status = napi_create_async_work(
1335 env, nullptr, resource, AsyncSetSamplingRate, SetFunctionAsyncCallbackComplete,
1336 static_cast<void*>(asyncContext.get()), &asyncContext->work);
1337 if (status != napi_ok) {
1338 result = nullptr;
1339 } else {
1340 status = napi_queue_async_work(env, asyncContext->work);
1341 if (status == napi_ok) {
1342 asyncContext.release();
1343 } else {
1344 result = nullptr;
1345 }
1346 }
1347
1348 return result;
1349 }
1350
GetRenderRate(napi_env env,napi_callback_info info)1351 napi_value AudioRendererNapi::GetRenderRate(napi_env env, napi_callback_info info)
1352 {
1353 napi_status status;
1354 const int32_t refCount = 1;
1355 napi_value result = nullptr;
1356
1357 GET_PARAMS(env, info, ARGS_ONE);
1358
1359 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1360 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1361 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1362 if (argc > PARAM0) {
1363 napi_valuetype valueType = napi_undefined;
1364 napi_typeof(env, argv[PARAM0], &valueType);
1365 if (valueType == napi_function) {
1366 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1367 }
1368 }
1369
1370 if (asyncContext->callbackRef == nullptr) {
1371 napi_create_promise(env, &asyncContext->deferred, &result);
1372 } else {
1373 napi_get_undefined(env, &result);
1374 }
1375
1376 napi_value resource = nullptr;
1377 napi_create_string_utf8(env, "GetRenderRate", NAPI_AUTO_LENGTH, &resource);
1378
1379 status = napi_create_async_work(
1380 env, nullptr, resource,
1381 [](napi_env env, void *data) {
1382 auto context = static_cast<AudioRendererAsyncContext *>(data);
1383 if (!CheckContextStatus(context)) {
1384 return;
1385 }
1386 context->intValue = context->objectInfo->audioRenderer_->GetRenderRate();
1387 context->status = SUCCESS;
1388 },
1389 GetIntValueAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1390 if (status != napi_ok) {
1391 result = nullptr;
1392 } else {
1393 status = napi_queue_async_work(env, asyncContext->work);
1394 if (status == napi_ok) {
1395 asyncContext.release();
1396 } else {
1397 result = nullptr;
1398 }
1399 }
1400 }
1401
1402 return result;
1403 }
1404
GetRenderRateSync(napi_env env,napi_callback_info info)1405 napi_value AudioRendererNapi::GetRenderRateSync(napi_env env, napi_callback_info info)
1406 {
1407 napi_status status;
1408 napi_value thisVar = nullptr;
1409 napi_value result = nullptr;
1410 size_t argCount = 0;
1411 void *native = nullptr;
1412
1413 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
1414 if (status != napi_ok) {
1415 AUDIO_ERR_LOG("Invalid parameters!");
1416 return result;
1417 }
1418
1419 status = napi_unwrap(env, thisVar, &native);
1420 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
1421 if (status != napi_ok || audioRendererNapi == nullptr) {
1422 AUDIO_ERR_LOG("GetRenderRateSync unwrap failure!");
1423 return result;
1424 }
1425
1426 AudioRendererRate rendererRate = audioRendererNapi->audioRenderer_->GetRenderRate();
1427 napi_create_int32(env, rendererRate, &result);
1428
1429 return result;
1430 }
1431
GetRendererSamplingRate(napi_env env,napi_callback_info info)1432 napi_value AudioRendererNapi::GetRendererSamplingRate(napi_env env, napi_callback_info info)
1433 {
1434 napi_status status;
1435 const int32_t refCount = 1;
1436 napi_value result = nullptr;
1437
1438 GET_PARAMS(env, info, ARGS_ONE);
1439
1440 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1441 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1442 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1443 if (argc > PARAM0) {
1444 napi_valuetype valueType = napi_undefined;
1445 napi_typeof(env, argv[PARAM0], &valueType);
1446 if (valueType == napi_function) {
1447 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1448 }
1449 }
1450
1451 if (asyncContext->callbackRef == nullptr) {
1452 napi_create_promise(env, &asyncContext->deferred, &result);
1453 } else {
1454 napi_get_undefined(env, &result);
1455 }
1456
1457 napi_value resource = nullptr;
1458 napi_create_string_utf8(env, "GetRendererSamplingRate", NAPI_AUTO_LENGTH, &resource);
1459
1460 status = napi_create_async_work(
1461 env, nullptr, resource,
1462 [](napi_env env, void *data) {
1463 auto context = static_cast<AudioRendererAsyncContext *>(data);
1464 if (!CheckContextStatus(context)) {
1465 return;
1466 }
1467 context->rendererSampleRate = context->objectInfo->audioRenderer_->GetRendererSamplingRate();
1468 context->status = SUCCESS;
1469 },
1470 GetRendererSampleRateAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1471 if (status != napi_ok) {
1472 result = nullptr;
1473 } else {
1474 status = napi_queue_async_work(env, asyncContext->work);
1475 if (status == napi_ok) {
1476 asyncContext.release();
1477 } else {
1478 result = nullptr;
1479 }
1480 }
1481 }
1482
1483 return result;
1484 }
1485
Start(napi_env env,napi_callback_info info)1486 napi_value AudioRendererNapi::Start(napi_env env, napi_callback_info info)
1487 {
1488 napi_status status;
1489 const int32_t refCount = 1;
1490 napi_value result = nullptr;
1491
1492 GET_PARAMS(env, info, ARGS_ONE);
1493
1494 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1495
1496 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1497 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1498 if (argc > PARAM0) {
1499 napi_valuetype valueType = napi_undefined;
1500 napi_typeof(env, argv[PARAM0], &valueType);
1501 if (valueType == napi_function) {
1502 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1503 }
1504 }
1505
1506 if (asyncContext->callbackRef == nullptr) {
1507 napi_create_promise(env, &asyncContext->deferred, &result);
1508 } else {
1509 napi_get_undefined(env, &result);
1510 }
1511
1512 HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Audio");
1513 napi_value resource = nullptr;
1514 napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
1515
1516 status = napi_create_async_work(
1517 env, nullptr, resource,
1518 [](napi_env env, void *data) {
1519 auto context = static_cast<AudioRendererAsyncContext *>(data);
1520 if (!CheckContextStatus(context)) {
1521 return;
1522 }
1523 context->isTrue = context->objectInfo->audioRenderer_->Start();
1524 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1525 },
1526 StartAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1527 if (status != napi_ok) {
1528 result = nullptr;
1529 } else {
1530 status = napi_queue_async_work(env, asyncContext->work);
1531 if (status == napi_ok) {
1532 asyncContext.release();
1533 } else {
1534 result = nullptr;
1535 }
1536 }
1537 }
1538
1539 return result;
1540 }
1541
Write(napi_env env,napi_callback_info info)1542 napi_value AudioRendererNapi::Write(napi_env env, napi_callback_info info)
1543 {
1544 napi_status status;
1545 const int32_t refCount = 1;
1546 napi_value result = nullptr;
1547
1548 GET_PARAMS(env, info, ARGS_TWO);
1549 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1550 if (argc < ARGS_ONE) {
1551 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1552 }
1553
1554 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1555 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1556 for (size_t i = PARAM0; i < argc; i++) {
1557 napi_valuetype valueType = napi_undefined;
1558 napi_typeof(env, argv[i], &valueType);
1559
1560 if ((i == PARAM0) && (valueType == napi_object)) {
1561 napi_get_arraybuffer_info(env, argv[i], &asyncContext->data, &asyncContext->bufferLen);
1562 } else if (i == PARAM1) {
1563 if (valueType == napi_function) {
1564 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1565 }
1566 break;
1567 } else {
1568 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1569 }
1570 }
1571
1572 if (asyncContext->callbackRef == nullptr) {
1573 napi_create_promise(env, &asyncContext->deferred, &result);
1574 } else {
1575 napi_get_undefined(env, &result);
1576 }
1577
1578 napi_value resource = nullptr;
1579 napi_create_string_utf8(env, "Write", NAPI_AUTO_LENGTH, &resource);
1580
1581 status = napi_create_async_work(
1582 env, nullptr, resource,
1583 [](napi_env env, void *data) {
1584 auto context = static_cast<AudioRendererAsyncContext *>(data);
1585 if (!CheckContextStatus(context)) {
1586 return;
1587 }
1588 if (context->status == SUCCESS) {
1589 context->status = NAPI_ERR_SYSTEM;
1590 size_t bufferLen = context->bufferLen;
1591 auto buffer = std::make_unique<uint8_t[]>(bufferLen);
1592 if (buffer == nullptr) {
1593 HiLog::Error(LABEL, "Renderer write buffer allocation failed");
1594 return;
1595 }
1596
1597 if (memcpy_s(buffer.get(), bufferLen, context->data, bufferLen)) {
1598 HiLog::Info(LABEL, "Renderer mem copy failed");
1599 return;
1600 }
1601
1602 int32_t bytesWritten = 0;
1603 size_t totalBytesWritten = 0;
1604 size_t minBytes = 4;
1605 while ((totalBytesWritten < bufferLen) && ((bufferLen - totalBytesWritten) > minBytes)) {
1606 bytesWritten = context->objectInfo->audioRenderer_->Write(buffer.get() + totalBytesWritten,
1607 bufferLen - totalBytesWritten);
1608 if (bytesWritten < 0) {
1609 break;
1610 }
1611
1612 totalBytesWritten += bytesWritten;
1613 }
1614
1615 context->status = SUCCESS;
1616 context->totalBytesWritten = totalBytesWritten;
1617 }
1618 },
1619 WriteAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
1620 if (status != napi_ok) {
1621 result = nullptr;
1622 } else if (asyncContext->objectInfo->scheduleFromApiCall_) {
1623 status = napi_queue_async_work(env, asyncContext->work);
1624 if (status == napi_ok) {
1625 asyncContext->objectInfo->scheduleFromApiCall_ = false;
1626 asyncContext.release();
1627 } else {
1628 result = nullptr;
1629 }
1630 } else {
1631 asyncContext->objectInfo->writeRequestQ_.push(asyncContext->work);
1632 asyncContext.release();
1633 }
1634 }
1635
1636 return result;
1637 }
1638
GetAudioTime(napi_env env,napi_callback_info info)1639 napi_value AudioRendererNapi::GetAudioTime(napi_env env, napi_callback_info info)
1640 {
1641 napi_status status;
1642 const int32_t refCount = 1;
1643 napi_value result = nullptr;
1644
1645 GET_PARAMS(env, info, ARGS_ONE);
1646
1647 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1648
1649 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
1650 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1651 if (argc > PARAM0) {
1652 napi_valuetype valueType = napi_undefined;
1653 napi_typeof(env, argv[PARAM0], &valueType);
1654 if (valueType == napi_function) {
1655 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1656 }
1657 }
1658
1659 if (asyncContext->callbackRef == nullptr) {
1660 napi_create_promise(env, &asyncContext->deferred, &result);
1661 } else {
1662 napi_get_undefined(env, &result);
1663 }
1664
1665 napi_value resource = nullptr;
1666 napi_create_string_utf8(env, "GetAudioTime", NAPI_AUTO_LENGTH, &resource);
1667
1668 status = napi_create_async_work(
1669 env, nullptr, resource,
1670 [](napi_env env, void *data) {
1671 auto context = static_cast<AudioRendererAsyncContext *>(data);
1672 if (!CheckContextStatus(context)) {
1673 return;
1674 }
1675 Timestamp timestamp;
1676 if (context->objectInfo->audioRenderer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC)) {
1677 const uint64_t secToNanosecond = 1000000000;
1678 context->time = timestamp.time.tv_nsec + timestamp.time.tv_sec * secToNanosecond;
1679 context->status = SUCCESS;
1680 } else {
1681 context->status = NAPI_ERR_SYSTEM;
1682 }
1683 },
1684 GetInt64ValueAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1685 if (status != napi_ok) {
1686 result = nullptr;
1687 } else {
1688 status = napi_queue_async_work(env, asyncContext->work);
1689 if (status == napi_ok) {
1690 asyncContext.release();
1691 } else {
1692 result = nullptr;
1693 }
1694 }
1695 }
1696
1697 return result;
1698 }
1699
GetAudioTimeSync(napi_env env,napi_callback_info info)1700 napi_value AudioRendererNapi::GetAudioTimeSync(napi_env env, napi_callback_info info)
1701 {
1702 napi_status status;
1703 napi_value thisVar = nullptr;
1704 napi_value result = nullptr;
1705 size_t argCount = 0;
1706 void *native = nullptr;
1707
1708 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
1709 if (status != napi_ok) {
1710 AUDIO_ERR_LOG("Invalid parameters!");
1711 return result;
1712 }
1713
1714 status = napi_unwrap(env, thisVar, &native);
1715 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
1716 if (status != napi_ok || audioRendererNapi == nullptr) {
1717 AUDIO_ERR_LOG("GetAudioTimeSync unwrap failure!");
1718 return result;
1719 }
1720
1721 Timestamp timestamp;
1722 bool ret = audioRendererNapi->audioRenderer_->GetAudioTime(timestamp, Timestamp::Timestampbase::MONOTONIC);
1723 if (!ret) {
1724 AUDIO_ERR_LOG("GetAudioTime failure!");
1725 return result;
1726 }
1727 const uint64_t secToNanosecond = 1000000000;
1728 uint64_t time = timestamp.time.tv_nsec + timestamp.time.tv_sec * secToNanosecond;
1729
1730 napi_create_int64(env, time, &result);
1731
1732 return result;
1733 }
1734
Drain(napi_env env,napi_callback_info info)1735 napi_value AudioRendererNapi::Drain(napi_env env, napi_callback_info info)
1736 {
1737 napi_status status;
1738 const int32_t refCount = 1;
1739 napi_value result = nullptr;
1740
1741 GET_PARAMS(env, info, ARGS_ONE);
1742
1743 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1744
1745 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1746 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1747 if (argc > PARAM0) {
1748 napi_valuetype valueType = napi_undefined;
1749 napi_typeof(env, argv[PARAM0], &valueType);
1750 if (valueType == napi_function) {
1751 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1752 }
1753 }
1754
1755 if (asyncContext->callbackRef == nullptr) {
1756 napi_create_promise(env, &asyncContext->deferred, &result);
1757 } else {
1758 napi_get_undefined(env, &result);
1759 }
1760 JudgeFuncDrain(env, result, asyncContext);
1761 }
1762
1763 return result;
1764 }
1765
JudgeFuncDrain(napi_env & env,napi_value & result,unique_ptr<AudioRendererAsyncContext> & asyncContext)1766 void AudioRendererNapi::JudgeFuncDrain(napi_env &env, napi_value &result,
1767 unique_ptr<AudioRendererAsyncContext> &asyncContext)
1768 {
1769 napi_status status;
1770 napi_value resource = nullptr;
1771 napi_create_string_utf8(env, "Drain", NAPI_AUTO_LENGTH, &resource);
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 context->isTrue = context->objectInfo->audioRenderer_->Drain();
1780 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1781 },
1782 VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1783 if (status != napi_ok) {
1784 result = nullptr;
1785 } else {
1786 if (!asyncContext->objectInfo->doNotScheduleWrite_) {
1787 asyncContext->objectInfo->isDrainWriteQInProgress_ = true;
1788 while (!asyncContext->objectInfo->writeRequestQ_.empty()) {
1789 napi_queue_async_work(env, asyncContext->objectInfo->writeRequestQ_.front());
1790 asyncContext->objectInfo->writeRequestQ_.pop();
1791 }
1792 asyncContext->objectInfo->isDrainWriteQInProgress_ = false;
1793 }
1794 status = napi_queue_async_work(env, asyncContext->work);
1795 if (status == napi_ok) {
1796 asyncContext.release();
1797 } else {
1798 result = nullptr;
1799 }
1800 }
1801 }
1802
Pause(napi_env env,napi_callback_info info)1803 napi_value AudioRendererNapi::Pause(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, "Pause", 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 context->isTrue = context->objectInfo->audioRenderer_->Pause();
1840 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1841 },
1842 PauseAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1843 if (status != napi_ok) {
1844 result = nullptr;
1845 } else {
1846 status = napi_queue_async_work(env, asyncContext->work);
1847 if (status == napi_ok) {
1848 asyncContext->objectInfo->doNotScheduleWrite_ = true;
1849 asyncContext.release();
1850 } else {
1851 result = nullptr;
1852 }
1853 }
1854 }
1855
1856 return result;
1857 }
1858
Stop(napi_env env,napi_callback_info info)1859 napi_value AudioRendererNapi::Stop(napi_env env, napi_callback_info info)
1860 {
1861 napi_status status;
1862 const int32_t refCount = 1;
1863 napi_value result = nullptr;
1864
1865 GET_PARAMS(env, info, ARGS_ONE);
1866
1867 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1868
1869 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1870 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1871 if (argc > PARAM0) {
1872 napi_valuetype valueType = napi_undefined;
1873 napi_typeof(env, argv[PARAM0], &valueType);
1874 if (valueType == napi_function) {
1875 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1876 }
1877 }
1878
1879 if (asyncContext->callbackRef == nullptr) {
1880 napi_create_promise(env, &asyncContext->deferred, &result);
1881 } else {
1882 napi_get_undefined(env, &result);
1883 }
1884
1885 napi_value resource = nullptr;
1886 napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
1887
1888 status = napi_create_async_work(
1889 env, nullptr, resource,
1890 [](napi_env env, void *data) {
1891 auto context = static_cast<AudioRendererAsyncContext *>(data);
1892 if (!CheckContextStatus(context)) {
1893 return;
1894 }
1895 context->isTrue = context->objectInfo->audioRenderer_->Stop();
1896 context->status = context->isTrue ? SUCCESS : NAPI_ERR_SYSTEM;
1897 },
1898 StopAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1899 if (status != napi_ok) {
1900 result = nullptr;
1901 } else {
1902 status = napi_queue_async_work(env, asyncContext->work);
1903 if (status == napi_ok) {
1904 asyncContext.release();
1905 } else {
1906 result = nullptr;
1907 }
1908 }
1909 }
1910
1911 return result;
1912 }
1913
Release(napi_env env,napi_callback_info info)1914 napi_value AudioRendererNapi::Release(napi_env env, napi_callback_info info)
1915 {
1916 napi_status status;
1917 const int32_t refCount = 1;
1918 napi_value result = nullptr;
1919
1920 GET_PARAMS(env, info, ARGS_ONE);
1921
1922 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1923
1924 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1925 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1926 if (argc > PARAM0) {
1927 napi_valuetype valueType = napi_undefined;
1928 napi_typeof(env, argv[PARAM0], &valueType);
1929 if (valueType == napi_function) {
1930 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1931 }
1932 }
1933
1934 if (asyncContext->callbackRef == nullptr) {
1935 napi_create_promise(env, &asyncContext->deferred, &result);
1936 } else {
1937 napi_get_undefined(env, &result);
1938 }
1939
1940 napi_value resource = nullptr;
1941 napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
1942
1943 status = napi_create_async_work(
1944 env, nullptr, resource,
1945 [](napi_env env, void *data) {
1946 auto context = static_cast<AudioRendererAsyncContext *>(data);
1947 if (!CheckContextStatus(context)) {
1948 return;
1949 }
1950 context->isTrue = context->objectInfo->audioRenderer_->Release();
1951 if (context->isTrue) {
1952 context->status = SUCCESS;
1953 } else {
1954 context->status = NAPI_ERR_SYSTEM;
1955 }
1956 },
1957 VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1958 if (status != napi_ok) {
1959 result = nullptr;
1960 } else {
1961 status = napi_queue_async_work(env, asyncContext->work);
1962 if (status == napi_ok) {
1963 asyncContext.release();
1964 } else {
1965 result = nullptr;
1966 }
1967 }
1968 }
1969
1970 return result;
1971 }
1972
GetBufferSize(napi_env env,napi_callback_info info)1973 napi_value AudioRendererNapi::GetBufferSize(napi_env env, napi_callback_info info)
1974 {
1975 napi_status status;
1976 const int32_t refCount = 1;
1977 napi_value result = nullptr;
1978
1979 GET_PARAMS(env, info, ARGS_ONE);
1980
1981 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
1982
1983 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1984 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1985 if (argc > PARAM0) {
1986 napi_valuetype valueType = napi_undefined;
1987 napi_typeof(env, argv[PARAM0], &valueType);
1988 if (valueType == napi_function) {
1989 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
1990 }
1991 }
1992
1993 if (asyncContext->callbackRef == nullptr) {
1994 napi_create_promise(env, &asyncContext->deferred, &result);
1995 } else {
1996 napi_get_undefined(env, &result);
1997 }
1998
1999 napi_value resource = nullptr;
2000 napi_create_string_utf8(env, "GetBufferSize", NAPI_AUTO_LENGTH, &resource);
2001
2002 status = napi_create_async_work(
2003 env, nullptr, resource,
2004 [](napi_env env, void *data) {
2005 auto context = static_cast<AudioRendererAsyncContext *>(data);
2006 if (!CheckContextStatus(context)) {
2007 return;
2008 }
2009 size_t bufferSize;
2010 context->status = context->objectInfo->audioRenderer_->GetBufferSize(bufferSize);
2011 if (context->status == SUCCESS) {
2012 context->bufferSize = bufferSize;
2013 }
2014 },
2015 GetBufferSizeAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
2016 if (status != napi_ok) {
2017 result = nullptr;
2018 } else {
2019 status = napi_queue_async_work(env, asyncContext->work);
2020 if (status == napi_ok) {
2021 asyncContext.release();
2022 } else {
2023 result = nullptr;
2024 }
2025 }
2026 }
2027
2028 return result;
2029 }
2030
GetBufferSizeSync(napi_env env,napi_callback_info info)2031 napi_value AudioRendererNapi::GetBufferSizeSync(napi_env env, napi_callback_info info)
2032 {
2033 napi_status status;
2034 napi_value thisVar = nullptr;
2035 napi_value result = nullptr;
2036 size_t argCount = 0;
2037 void *native = nullptr;
2038
2039 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
2040 if (status != napi_ok) {
2041 AUDIO_ERR_LOG("Invalid parameters!");
2042 return result;
2043 }
2044
2045 status = napi_unwrap(env, thisVar, &native);
2046 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
2047 if (status != napi_ok || audioRendererNapi == nullptr) {
2048 AUDIO_ERR_LOG("GetBufferSizeSync unwrap failure!");
2049 return result;
2050 }
2051
2052 size_t bufferSize;
2053 int32_t ret = audioRendererNapi->audioRenderer_->GetBufferSize(bufferSize);
2054 if (ret != SUCCESS) {
2055 AUDIO_ERR_LOG("GetBufferSize failure!");
2056 return result;
2057 }
2058 napi_create_uint32(env, bufferSize, &result);
2059
2060 return result;
2061 }
2062
GetAudioStreamId(napi_env env,napi_callback_info info)2063 napi_value AudioRendererNapi::GetAudioStreamId(napi_env env, napi_callback_info info)
2064 {
2065 napi_status status;
2066 const int32_t refCount = 1;
2067 napi_value result = nullptr;
2068
2069 GET_PARAMS(env, info, ARGS_ONE);
2070
2071 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2072
2073 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2074 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2075 if (argc > PARAM0) {
2076 napi_valuetype valueType = napi_undefined;
2077 napi_typeof(env, argv[PARAM0], &valueType);
2078 if (valueType == napi_function) {
2079 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
2080 }
2081 }
2082
2083 if (asyncContext->callbackRef == nullptr) {
2084 napi_create_promise(env, &asyncContext->deferred, &result);
2085 } else {
2086 napi_get_undefined(env, &result);
2087 }
2088 JudgeFuncGetAudioStreamId(env, result, asyncContext);
2089 }
2090
2091 return result;
2092 }
2093
GetAudioStreamIdSync(napi_env env,napi_callback_info info)2094 napi_value AudioRendererNapi::GetAudioStreamIdSync(napi_env env, napi_callback_info info)
2095 {
2096 napi_status status;
2097 napi_value thisVar = nullptr;
2098 napi_value result = nullptr;
2099 size_t argCount = 0;
2100 void *native = nullptr;
2101
2102 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
2103 if (status != napi_ok) {
2104 AUDIO_ERR_LOG("Invalid parameters!");
2105 return result;
2106 }
2107
2108 status = napi_unwrap(env, thisVar, &native);
2109 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
2110 if (status != napi_ok || audioRendererNapi == nullptr) {
2111 AUDIO_ERR_LOG("GetAudioStreamIdSync unwrap failure!");
2112 return result;
2113 }
2114
2115 uint32_t audioStreamId;
2116 int32_t streamIdStatus = audioRendererNapi->audioRenderer_->GetAudioStreamId(audioStreamId);
2117 if (streamIdStatus != SUCCESS) {
2118 AUDIO_ERR_LOG("GetAudioStreamId failure!");
2119 return result;
2120 }
2121 napi_create_uint32(env, audioStreamId, &result);
2122
2123 return result;
2124 }
2125
JudgeFuncGetAudioStreamId(napi_env & env,napi_value & result,unique_ptr<AudioRendererAsyncContext> & asyncContext)2126 void AudioRendererNapi::JudgeFuncGetAudioStreamId(napi_env &env, napi_value &result,
2127 unique_ptr<AudioRendererAsyncContext> &asyncContext)
2128 {
2129 napi_status status;
2130 napi_value resource = nullptr;
2131 napi_create_string_utf8(env, "GetAudioStreamId", NAPI_AUTO_LENGTH, &resource);
2132
2133 status = napi_create_async_work(
2134 env, nullptr, resource,
2135 [](napi_env env, void *data) {
2136 auto context = static_cast<AudioRendererAsyncContext *>(data);
2137 if (!CheckContextStatus(context)) {
2138 return;
2139 }
2140 int32_t streamIdStatus;
2141 streamIdStatus = context->objectInfo->audioRenderer_->
2142 GetAudioStreamId(context->audioStreamId);
2143 if (streamIdStatus == ERR_ILLEGAL_STATE) {
2144 context->status = NAPI_ERR_ILLEGAL_STATE;
2145 } else if (streamIdStatus == ERR_INVALID_INDEX) {
2146 context->status = NAPI_ERR_SYSTEM;
2147 } else {
2148 context->status = SUCCESS;
2149 }
2150 },
2151 GetAudioStreamIdCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
2152 if (status != napi_ok) {
2153 result = nullptr;
2154 } else {
2155 status = napi_queue_async_work(env, asyncContext->work);
2156 if (status == napi_ok) {
2157 asyncContext.release();
2158 } else {
2159 result = nullptr;
2160 }
2161 }
2162 }
2163
SetVolume(napi_env env,napi_callback_info info)2164 napi_value AudioRendererNapi::SetVolume(napi_env env, napi_callback_info info)
2165 {
2166 napi_status status;
2167 const int32_t refCount = 1;
2168 napi_value result = nullptr;
2169
2170 GET_PARAMS(env, info, ARGS_THREE);
2171
2172 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2173 if (argc < ARGS_ONE) {
2174 asyncContext->status = NAPI_ERR_INVALID_PARAM;
2175 }
2176
2177 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2178 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2179 for (size_t i = PARAM0; i < argc; i++) {
2180 napi_valuetype valueType = napi_undefined;
2181 napi_typeof(env, argv[i], &valueType);
2182 if (i == PARAM0 && valueType == napi_number) {
2183 napi_get_value_double(env, argv[i], &asyncContext->volLevel);
2184 } else if (i == PARAM1) {
2185 if (valueType == napi_function) {
2186 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
2187 }
2188 break;
2189 } else {
2190 asyncContext->status = NAPI_ERR_INVALID_PARAM;
2191 }
2192 }
2193
2194 if (asyncContext->callbackRef == nullptr) {
2195 napi_create_promise(env, &asyncContext->deferred, &result);
2196 } else {
2197 napi_get_undefined(env, &result);
2198 }
2199
2200 HiviewDFX::ReportXPowerJsStackSysEvent(env, "VOLUME_CHANGE", "SRC=Audio");
2201 napi_value resource = nullptr;
2202 napi_create_string_utf8(env, "SetVolume", NAPI_AUTO_LENGTH, &resource);
2203
2204 status = napi_create_async_work(
2205 env, nullptr, resource,
2206 [](napi_env env, void *data) {
2207 auto context = static_cast<AudioRendererAsyncContext*>(data);
2208 if (!CheckContextStatus(context)) {
2209 return;
2210 }
2211 if (context->status == SUCCESS) {
2212 if (context->volLevel < MIN_VOLUME_IN_DOUBLE || context->volLevel > MAX_VOLUME_IN_DOUBLE) {
2213 context->status = NAPI_ERR_UNSUPPORTED;
2214 } else {
2215 context->status = context->objectInfo->audioRenderer_->
2216 SetVolume(static_cast<float>(context->volLevel));
2217 }
2218 }
2219 },
2220 SetFunctionAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
2221 if (status != napi_ok) {
2222 result = nullptr;
2223 } else {
2224 status = napi_queue_async_work(env, asyncContext->work);
2225 if (status == napi_ok) {
2226 asyncContext.release();
2227 } else {
2228 result = nullptr;
2229 }
2230 }
2231 }
2232
2233 return result;
2234 }
2235
2236
GetRendererInfo(napi_env env,napi_callback_info info)2237 napi_value AudioRendererNapi::GetRendererInfo(napi_env env, napi_callback_info info)
2238 {
2239 HiLog::Info(LABEL, "Entered GetRendererInfo");
2240 napi_status status;
2241 const int32_t refCount = 1;
2242 napi_value result = nullptr;
2243
2244 GET_PARAMS(env, info, ARGS_ONE);
2245
2246 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2247
2248 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2249 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2250 if (argc > PARAM0) {
2251 napi_valuetype valueType = napi_undefined;
2252 napi_typeof(env, argv[PARAM0], &valueType);
2253 if (valueType == napi_function) {
2254 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
2255 }
2256 }
2257
2258 if (asyncContext->callbackRef == nullptr) {
2259 napi_create_promise(env, &asyncContext->deferred, &result);
2260 } else {
2261 napi_get_undefined(env, &result);
2262 }
2263
2264 napi_value resource = nullptr;
2265 napi_create_string_utf8(env, "GetRendererInfo", NAPI_AUTO_LENGTH, &resource);
2266
2267 status = napi_create_async_work(
2268 env, nullptr, resource,
2269 [](napi_env env, void *data) {
2270 auto context = static_cast<AudioRendererAsyncContext *>(data);
2271 if (!CheckContextStatus(context)) {
2272 return;
2273 }
2274 AudioRendererInfo rendererInfo = {};
2275 context->status = context->objectInfo->audioRenderer_->GetRendererInfo(rendererInfo);
2276 if (context->status == SUCCESS) {
2277 context->contentType = rendererInfo.contentType;
2278 context->usage = rendererInfo.streamUsage;
2279 context->rendererFlags = rendererInfo.rendererFlags;
2280 }
2281 },
2282 AudioRendererInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
2283 if (status != napi_ok) {
2284 result = nullptr;
2285 } else {
2286 status = napi_queue_async_work(env, asyncContext->work);
2287 if (status == napi_ok) {
2288 asyncContext.release();
2289 } else {
2290 result = nullptr;
2291 }
2292 }
2293 }
2294
2295 return result;
2296 }
2297
GetRendererInfoSync(napi_env env,napi_callback_info info)2298 napi_value AudioRendererNapi::GetRendererInfoSync(napi_env env, napi_callback_info info)
2299 {
2300 HiLog::Info(LABEL, "Entered GetRendererInfoSync");
2301 napi_status status;
2302 napi_value thisVar = nullptr;
2303 napi_value result = nullptr;
2304 size_t argCount = 0;
2305 void *native = nullptr;
2306
2307 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
2308 if (status != napi_ok) {
2309 AUDIO_ERR_LOG("Invalid parameters!");
2310 return result;
2311 }
2312
2313 status = napi_unwrap(env, thisVar, &native);
2314 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
2315 if (status != napi_ok || audioRendererNapi == nullptr) {
2316 AUDIO_ERR_LOG("GetRendererInfoSync unwrap failure!");
2317 return result;
2318 }
2319
2320 AudioRendererInfo rendererInfo;
2321 int32_t ret = audioRendererNapi->audioRenderer_->GetRendererInfo(rendererInfo);
2322 if (ret != SUCCESS) {
2323 AUDIO_ERR_LOG("GetRendererInfo failure!");
2324 return result;
2325 }
2326
2327 (void)napi_create_object(env, &result);
2328 SetValueInt32(env, "content", static_cast<int32_t>(rendererInfo.contentType), result);
2329 SetValueInt32(env, "usage", static_cast<int32_t>(rendererInfo.streamUsage), result);
2330 SetValueInt32(env, "rendererFlags", rendererInfo.rendererFlags, result);
2331
2332 return result;
2333 }
2334
GetStreamInfo(napi_env env,napi_callback_info info)2335 napi_value AudioRendererNapi::GetStreamInfo(napi_env env, napi_callback_info info)
2336 {
2337 napi_status status;
2338 const int32_t refCount = 1;
2339 napi_value result = nullptr;
2340
2341 GET_PARAMS(env, info, ARGS_ONE);
2342
2343 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2344
2345 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2346 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2347 if (argc > PARAM0) {
2348 napi_valuetype valueType = napi_undefined;
2349 napi_typeof(env, argv[PARAM0], &valueType);
2350 if (valueType == napi_function) {
2351 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
2352 }
2353 }
2354
2355 if (asyncContext->callbackRef == nullptr) {
2356 napi_create_promise(env, &asyncContext->deferred, &result);
2357 } else {
2358 napi_get_undefined(env, &result);
2359 }
2360
2361 napi_value resource = nullptr;
2362 napi_create_string_utf8(env, "GetStreamInfo", NAPI_AUTO_LENGTH, &resource);
2363
2364 status = napi_create_async_work(
2365 env, nullptr, resource,
2366 [](napi_env env, void *data) {
2367 auto context = static_cast<AudioRendererAsyncContext *>(data);
2368 if (!CheckContextStatus(context)) {
2369 return;
2370 }
2371 AudioStreamInfo streamInfo;
2372 context->status = context->objectInfo->audioRenderer_->GetStreamInfo(streamInfo);
2373 if (context->status == SUCCESS) {
2374 context->sampleFormat = static_cast<AudioSampleFormat>(streamInfo.format);
2375 context->samplingRate = streamInfo.samplingRate;
2376 context->channelCount = streamInfo.channels;
2377 context->encodingType = streamInfo.encoding;
2378 }
2379 },
2380 AudioStreamInfoAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
2381 if (status != napi_ok) {
2382 result = nullptr;
2383 } else {
2384 status = napi_queue_async_work(env, asyncContext->work);
2385 if (status == napi_ok) {
2386 asyncContext.release();
2387 } else {
2388 result = nullptr;
2389 }
2390 }
2391 }
2392
2393 return result;
2394 }
2395
GetStreamInfoSync(napi_env env,napi_callback_info info)2396 napi_value AudioRendererNapi::GetStreamInfoSync(napi_env env, napi_callback_info info)
2397 {
2398 napi_status status;
2399 napi_value thisVar = nullptr;
2400 napi_value result = nullptr;
2401 size_t argCount = 0;
2402 void *native = nullptr;
2403
2404 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
2405 if (status != napi_ok) {
2406 AUDIO_ERR_LOG("Invalid parameters!");
2407 return result;
2408 }
2409
2410 status = napi_unwrap(env, thisVar, &native);
2411 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
2412 if (status != napi_ok || audioRendererNapi == nullptr) {
2413 AUDIO_ERR_LOG("GetStreamInfoSync unwrap failure!");
2414 return result;
2415 }
2416
2417 AudioStreamInfo streamInfo;
2418 int32_t ret = audioRendererNapi->audioRenderer_->GetStreamInfo(streamInfo);
2419 if (ret != SUCCESS) {
2420 AUDIO_ERR_LOG("GetStreamInfo failure!");
2421 return result;
2422 }
2423
2424 (void)napi_create_object(env, &result);
2425 SetValueInt32(env, "samplingRate", static_cast<int32_t>(streamInfo.samplingRate), result);
2426 SetValueInt32(env, "channels", static_cast<int32_t>(streamInfo.channels), result);
2427 SetValueInt32(env, "sampleFormat", static_cast<int32_t>(streamInfo.format), result);
2428 SetValueInt32(env, "encodingType", static_cast<int32_t>(streamInfo.encoding), result);
2429
2430 return result;
2431 }
2432
GetAudioEffectMode(napi_env env,napi_callback_info info)2433 napi_value AudioRendererNapi::GetAudioEffectMode(napi_env env, napi_callback_info info)
2434 {
2435 napi_status status;
2436 const int32_t refCount = 1;
2437 napi_value result = nullptr;
2438
2439 GET_PARAMS(env, info, ARGS_ONE);
2440
2441 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2442 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2443 if (status != napi_ok || asyncContext->objectInfo == nullptr) {
2444 return result;
2445 }
2446
2447 if (argc > PARAM0) {
2448 napi_valuetype valueType = napi_undefined;
2449 napi_typeof(env, argv[PARAM0], &valueType);
2450 if (valueType == napi_function) {
2451 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
2452 }
2453 }
2454
2455 if (asyncContext->callbackRef == nullptr) {
2456 napi_create_promise(env, &asyncContext->deferred, &result);
2457 } else {
2458 napi_get_undefined(env, &result);
2459 }
2460
2461 napi_value resource = nullptr;
2462 napi_create_string_utf8(env, "GetAudioEffectMode", NAPI_AUTO_LENGTH, &resource);
2463
2464 status = napi_create_async_work(
2465 env, nullptr, resource, AsyncGetAudioEffectMode,
2466 GetIntValueAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
2467 if (status != napi_ok) {
2468 result = nullptr;
2469 } else {
2470 status = napi_queue_async_work(env, asyncContext->work);
2471 if (status == napi_ok) {
2472 asyncContext.release();
2473 } else {
2474 result = nullptr;
2475 }
2476 }
2477 return result;
2478 }
2479
AsyncGetAudioEffectMode(napi_env env,void * data)2480 void AudioRendererNapi::AsyncGetAudioEffectMode(napi_env env, void *data)
2481 {
2482 auto context = static_cast<AudioRendererAsyncContext *>(data);
2483 if (!CheckContextStatus(context)) {
2484 return;
2485 }
2486 context->intValue = context->objectInfo->audioRenderer_->GetAudioEffectMode();
2487 context->status = SUCCESS;
2488 }
2489
AsyncSetAudioEffectMode(napi_env env,void * data)2490 void AudioRendererNapi::AsyncSetAudioEffectMode(napi_env env, void *data)
2491 {
2492 auto context = static_cast<AudioRendererAsyncContext *>(data);
2493 if (!CheckContextStatus(context)) {
2494 return;
2495 }
2496 if (context->status == SUCCESS) {
2497 AudioEffectMode audioEffectMode = static_cast<AudioEffectMode>(context->audioEffectMode);
2498 context->intValue = context->objectInfo->audioRenderer_->SetAudioEffectMode(audioEffectMode);
2499 if (context->intValue == SUCCESS) {
2500 context->status = SUCCESS;
2501 } else {
2502 context->status = NAPI_ERR_SYSTEM;
2503 }
2504 }
2505 }
2506
GetArgvForSetAudioEffectMode(napi_env env,size_t argc,napi_value * argv,unique_ptr<AudioRendererAsyncContext> & asyncContext)2507 bool AudioRendererNapi::GetArgvForSetAudioEffectMode(napi_env env, size_t argc, napi_value *argv,
2508 unique_ptr<AudioRendererAsyncContext> &asyncContext)
2509 {
2510 const int32_t refCount = 1;
2511 for (size_t i = PARAM0; i < argc; i++) {
2512 napi_valuetype valueType = napi_undefined;
2513 napi_typeof(env, argv[i], &valueType);
2514
2515 if (i == PARAM0 && valueType == napi_number) {
2516 napi_get_value_int32(env, argv[PARAM0], &asyncContext->audioEffectMode);
2517 if (!AudioCommonNapi::IsLegalInputArgumentAudioEffectMode(asyncContext->audioEffectMode)) {
2518 asyncContext->status = asyncContext->status ==
2519 NAPI_ERR_INVALID_PARAM ? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
2520 }
2521 } else if (i == PARAM1) {
2522 if (valueType == napi_function) {
2523 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
2524 }
2525 break;
2526 } else {
2527 AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
2528 return false;
2529 }
2530 }
2531 return true;
2532 }
2533
SetAudioEffectMode(napi_env env,napi_callback_info info)2534 napi_value AudioRendererNapi::SetAudioEffectMode(napi_env env, napi_callback_info info)
2535 {
2536 napi_status status;
2537 napi_value result = nullptr;
2538
2539 GET_PARAMS(env, info, ARGS_TWO);
2540 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2541 THROW_ERROR_ASSERT(env, argc >= ARGS_ONE, NAPI_ERR_INPUT_INVALID);
2542
2543 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
2544 if (status != napi_ok || asyncContext->objectInfo == nullptr) {
2545 return result;
2546 }
2547
2548 if (!GetArgvForSetAudioEffectMode(env, argc, argv, asyncContext)) {
2549 return nullptr;
2550 }
2551
2552 if (asyncContext->callbackRef == nullptr) {
2553 napi_create_promise(env, &asyncContext->deferred, &result);
2554 } else {
2555 napi_get_undefined(env, &result);
2556 }
2557
2558 napi_value resource = nullptr;
2559 napi_create_string_utf8(env, "SetAudioEffectMode", NAPI_AUTO_LENGTH, &resource);
2560
2561 status = napi_create_async_work(env, nullptr, resource, AsyncSetAudioEffectMode,
2562 VoidAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
2563 if (status != napi_ok) {
2564 result = nullptr;
2565 } else {
2566 status = napi_queue_async_work(env, asyncContext->work);
2567 if (status == napi_ok) {
2568 asyncContext.release();
2569 } else {
2570 result = nullptr;
2571 }
2572 }
2573
2574 return result;
2575 }
2576
GetState(napi_env env,napi_callback_info info)2577 napi_value AudioRendererNapi::GetState(napi_env env, napi_callback_info info)
2578 {
2579 napi_value jsThis = nullptr;
2580 napi_value undefinedResult = nullptr;
2581 napi_get_undefined(env, &undefinedResult);
2582
2583 size_t argCount = 0;
2584 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
2585 if (status != napi_ok || jsThis == nullptr) {
2586 AUDIO_INFO_LOG("Failed to retrieve details about the callback");
2587 return undefinedResult;
2588 }
2589
2590 AudioRendererNapi *rendererNapi = nullptr;
2591 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
2592 CHECK_AND_RETURN_RET_LOG(status == napi_ok && rendererNapi != nullptr, undefinedResult, "Failed to get instance");
2593
2594 CHECK_AND_RETURN_RET_LOG(rendererNapi->audioRenderer_ != nullptr, undefinedResult, "No memory");
2595 int32_t rendererState = rendererNapi->audioRenderer_->GetStatus();
2596
2597 napi_value jsResult = nullptr;
2598 status = napi_create_int32(env, rendererState, &jsResult);
2599 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
2600
2601 AUDIO_DEBUG_LOG("GetState Complete, Current state: %{public}d", rendererState);
2602 return jsResult;
2603 }
2604
RegisterPeriodPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)2605 napi_value AudioRendererNapi::RegisterPeriodPositionCallback(napi_env env, napi_value* argv, const std::string& cbName,
2606 AudioRendererNapi *rendererNapi)
2607 {
2608 int64_t frameCount = 0;
2609 napi_get_value_int64(env, argv[PARAM1], &frameCount);
2610
2611 if (frameCount > 0) {
2612 if (rendererNapi->periodPositionCBNapi_ == nullptr) {
2613 rendererNapi->periodPositionCBNapi_ = std::make_shared<RendererPeriodPositionCallbackNapi>(env);
2614 THROW_ERROR_ASSERT(env, rendererNapi->periodPositionCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
2615
2616 int32_t ret = rendererNapi->audioRenderer_->SetRendererPeriodPositionCallback(frameCount,
2617 rendererNapi->periodPositionCBNapi_);
2618 THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
2619
2620 std::shared_ptr<RendererPeriodPositionCallbackNapi> cb =
2621 std::static_pointer_cast<RendererPeriodPositionCallbackNapi>(rendererNapi->periodPositionCBNapi_);
2622 cb->SaveCallbackReference(cbName, argv[PARAM2]);
2623 } else {
2624 AUDIO_DEBUG_LOG("AudioRendererNapi: periodReach already subscribed.");
2625 }
2626 } else {
2627 AUDIO_ERR_LOG("AudioRendererNapi: frameCount value not supported!!");
2628 }
2629
2630 napi_value result = nullptr;
2631 napi_get_undefined(env, &result);
2632 return result;
2633 }
2634
RegisterPositionCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)2635 napi_value AudioRendererNapi::RegisterPositionCallback(napi_env env, napi_value* argv,
2636 const std::string& cbName, AudioRendererNapi *rendererNapi)
2637 {
2638 int64_t markPosition = 0;
2639 napi_get_value_int64(env, argv[PARAM1], &markPosition);
2640
2641 if (markPosition > 0) {
2642 rendererNapi->positionCBNapi_ = std::make_shared<RendererPositionCallbackNapi>(env);
2643 THROW_ERROR_ASSERT(env, rendererNapi->positionCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
2644 int32_t ret = rendererNapi->audioRenderer_->SetRendererPositionCallback(markPosition,
2645 rendererNapi->positionCBNapi_);
2646 THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
2647
2648 std::shared_ptr<RendererPositionCallbackNapi> cb =
2649 std::static_pointer_cast<RendererPositionCallbackNapi>(rendererNapi->positionCBNapi_);
2650 cb->SaveCallbackReference(cbName, argv[PARAM2]);
2651 } else {
2652 AUDIO_ERR_LOG("AudioRendererNapi: Mark Position value not supported!!");
2653 THROW_ERROR_ASSERT(env, false, NAPI_ERR_INPUT_INVALID);
2654 }
2655
2656 napi_value result = nullptr;
2657 napi_get_undefined(env, &result);
2658 return result;
2659 }
2660
RegisterRendererCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)2661 napi_value AudioRendererNapi::RegisterRendererCallback(napi_env env, napi_value* argv,
2662 const std::string& cbName, AudioRendererNapi *rendererNapi)
2663 {
2664 THROW_ERROR_ASSERT(env, rendererNapi->callbackNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
2665
2666 std::shared_ptr<AudioRendererCallbackNapi> cb =
2667 std::static_pointer_cast<AudioRendererCallbackNapi>(rendererNapi->callbackNapi_);
2668 cb->SaveCallbackReference(cbName, argv[PARAM1]);
2669
2670 napi_value result = nullptr;
2671 napi_get_undefined(env, &result);
2672 return result;
2673 }
2674
RegisterDataRequestCallback(napi_env env,napi_value * argv,const std::string & cbName,AudioRendererNapi * rendererNapi)2675 napi_value AudioRendererNapi::RegisterDataRequestCallback(napi_env env, napi_value* argv,
2676 const std::string& cbName, AudioRendererNapi *rendererNapi)
2677 {
2678 if (rendererNapi->dataRequestCBNapi_ == nullptr) {
2679 rendererNapi->dataRequestCBNapi_ = std::make_shared<RendererDataRequestCallbackNapi>(env, rendererNapi);
2680 rendererNapi->audioRenderer_->SetRenderMode(RENDER_MODE_CALLBACK);
2681 THROW_ERROR_ASSERT(env, rendererNapi->dataRequestCBNapi_ != nullptr, NAPI_ERR_NO_MEMORY);
2682 int32_t ret = rendererNapi->audioRenderer_->SetRendererWriteCallback(rendererNapi->dataRequestCBNapi_);
2683 THROW_ERROR_ASSERT(env, ret == SUCCESS, NAPI_ERR_SYSTEM);
2684 std::shared_ptr<RendererDataRequestCallbackNapi> cb =
2685 std::static_pointer_cast<RendererDataRequestCallbackNapi>(rendererNapi->dataRequestCBNapi_);
2686 cb->SaveCallbackReference(cbName, argv[PARAM1]);
2687 } else {
2688 AUDIO_DEBUG_LOG("AudioRendererNapi:dataRequest already subscribed.");
2689 THROW_ERROR_ASSERT(env, false, NAPI_ERR_ILLEGAL_STATE);
2690 }
2691 napi_value result = nullptr;
2692 napi_get_undefined(env, &result);
2693 return result;
2694 }
2695
RegisterCallback(napi_env env,napi_value jsThis,napi_value * argv,const std::string & cbName)2696 napi_value AudioRendererNapi::RegisterCallback(napi_env env, napi_value jsThis,
2697 napi_value* argv, const std::string& cbName)
2698 {
2699 AudioRendererNapi *rendererNapi = nullptr;
2700 napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
2701 THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2702 THROW_ERROR_ASSERT(env, rendererNapi != nullptr, NAPI_ERR_NO_MEMORY);
2703
2704 THROW_ERROR_ASSERT(env, rendererNapi->audioRenderer_ != nullptr, NAPI_ERR_NO_MEMORY);
2705
2706 napi_value result = nullptr;
2707 napi_get_undefined(env, &result);
2708
2709 if (!cbName.compare(INTERRUPT_CALLBACK_NAME) ||
2710 !cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME) ||
2711 !cbName.compare(STATE_CHANGE_CALLBACK_NAME)) {
2712 result = RegisterRendererCallback(env, argv, cbName, rendererNapi);
2713 } else if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
2714 result = RegisterPositionCallback(env, argv, cbName, rendererNapi);
2715 } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
2716 result = RegisterPeriodPositionCallback(env, argv, cbName, rendererNapi);
2717 } else if (!cbName.compare(DATA_REQUEST_CALLBACK_NAME)) {
2718 result = RegisterDataRequestCallback(env, argv, cbName, rendererNapi);
2719 } else if (!cbName.compare(DEVICECHANGE_CALLBACK_NAME)) {
2720 RegisterRendererDeviceChangeCallback(env, argv, rendererNapi);
2721 } else {
2722 bool unknownCallback = true;
2723 THROW_ERROR_ASSERT(env, !unknownCallback, NAPI_ERROR_INVALID_PARAM);
2724 }
2725
2726 return result;
2727 }
2728
On(napi_env env,napi_callback_info info)2729 napi_value AudioRendererNapi::On(napi_env env, napi_callback_info info)
2730 {
2731 const size_t requireArgc = 2;
2732 size_t argc = 3;
2733
2734 napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
2735 napi_value jsThis = nullptr;
2736 napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
2737 THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2738 THROW_ERROR_ASSERT(env, argc >= requireArgc, NAPI_ERR_INPUT_INVALID);
2739
2740 napi_valuetype eventType = napi_undefined;
2741 napi_typeof(env, argv[0], &eventType);
2742 THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INPUT_INVALID);
2743
2744 std::string callbackName = AudioCommonNapi::GetStringArgument(env, argv[0]);
2745 AUDIO_DEBUG_LOG("AudioRendererNapi: On callbackName: %{public}s", callbackName.c_str());
2746
2747 napi_valuetype handler = napi_undefined;
2748 if (argc == requireArgc) {
2749 napi_typeof(env, argv[1], &handler);
2750 THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
2751 } else {
2752 napi_valuetype paramArg1 = napi_undefined;
2753 napi_typeof(env, argv[1], ¶mArg1);
2754 napi_valuetype expectedValType = napi_number; // Default. Reset it with 'callbackName' if check, if required.
2755 THROW_ERROR_ASSERT(env, paramArg1 == expectedValType, NAPI_ERR_INPUT_INVALID);
2756
2757 const int32_t arg2 = 2;
2758 napi_typeof(env, argv[arg2], &handler);
2759 THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
2760 }
2761
2762 return RegisterCallback(env, jsThis, argv, callbackName);
2763 }
2764
UnregisterCallback(napi_env env,napi_value jsThis,size_t argc,napi_value * argv,const std::string & cbName)2765 napi_value AudioRendererNapi::UnregisterCallback(napi_env env, napi_value jsThis, size_t argc, napi_value* argv,
2766 const std::string& cbName)
2767 {
2768 AudioRendererNapi *rendererNapi = nullptr;
2769 napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&rendererNapi));
2770 THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2771 THROW_ERROR_ASSERT(env, rendererNapi != nullptr, NAPI_ERR_NO_MEMORY);
2772 THROW_ERROR_ASSERT(env, rendererNapi->audioRenderer_ != nullptr, NAPI_ERR_NO_MEMORY);
2773
2774 if (!cbName.compare(MARK_REACH_CALLBACK_NAME)) {
2775 rendererNapi->audioRenderer_->UnsetRendererPositionCallback();
2776 rendererNapi->positionCBNapi_ = nullptr;
2777 } else if (!cbName.compare(PERIOD_REACH_CALLBACK_NAME)) {
2778 rendererNapi->audioRenderer_->UnsetRendererPeriodPositionCallback();
2779 rendererNapi->periodPositionCBNapi_ = nullptr;
2780 } else if (!cbName.compare(DEVICECHANGE_CALLBACK_NAME)) {
2781 UnregisterRendererDeviceChangeCallback(env, argc, argv, rendererNapi);
2782 } else if (!cbName.compare(AUDIO_INTERRUPT_CALLBACK_NAME)) {
2783 UnregisterRendererCallback(env, argv, cbName, rendererNapi);
2784 } else {
2785 bool unknownCallback = true;
2786 THROW_ERROR_ASSERT(env, !unknownCallback, NAPI_ERR_UNSUPPORTED);
2787 }
2788
2789 napi_value result = nullptr;
2790 napi_get_undefined(env, &result);
2791 return result;
2792 }
2793
UnregisterRendererCallback(napi_env env,napi_value *,const std::string & cbName,AudioRendererNapi * rendererNapi)2794 void AudioRendererNapi::UnregisterRendererCallback(napi_env env, napi_value* /* argv */,
2795 const std::string& cbName, AudioRendererNapi *rendererNapi)
2796 {
2797 CHECK_AND_RETURN_LOG(rendererNapi->callbackNapi_ != nullptr, "rendererCallbackNapi is nullptr");
2798
2799 std::shared_ptr<AudioRendererCallbackNapi> cb =
2800 std::static_pointer_cast<AudioRendererCallbackNapi>(rendererNapi->callbackNapi_);
2801 cb->RemoveCallbackReference(cbName);
2802 }
2803
Off(napi_env env,napi_callback_info info)2804 napi_value AudioRendererNapi::Off(napi_env env, napi_callback_info info)
2805 {
2806 const size_t requireArgc = 2;
2807 size_t argc = 3;
2808
2809 napi_value argv[requireArgc + 1] = {nullptr, nullptr, nullptr};
2810 napi_value jsThis = nullptr;
2811 napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
2812 THROW_ERROR_ASSERT(env, status == napi_ok, NAPI_ERR_SYSTEM);
2813 THROW_ERROR_ASSERT(env, argc <= requireArgc, NAPI_ERR_INVALID_PARAM);
2814
2815 napi_valuetype eventType = napi_undefined;
2816 napi_typeof(env, argv[0], &eventType);
2817 THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INVALID_PARAM);
2818
2819 std::string callbackName = AudioCommonNapi::GetStringArgument(env, argv[0]);
2820 AUDIO_DEBUG_LOG("AudioRendererNapi: Off callbackName: %{public}s", callbackName.c_str());
2821
2822 return UnregisterCallback(env, jsThis, argc, argv, callbackName);
2823 }
2824
ParseRendererOptions(napi_env env,napi_value root,AudioRendererOptions * opts)2825 bool AudioRendererNapi::ParseRendererOptions(napi_env env, napi_value root, AudioRendererOptions *opts)
2826 {
2827 napi_value res = nullptr;
2828
2829 if (napi_get_named_property(env, root, "rendererInfo", &res) == napi_ok) {
2830 ParseRendererInfo(env, res, &(opts->rendererInfo));
2831 }
2832
2833 if (napi_get_named_property(env, root, "streamInfo", &res) == napi_ok) {
2834 ParseStreamInfo(env, res, &(opts->streamInfo));
2835 }
2836
2837 if (napi_get_named_property(env, root, "privacyType", &res) == napi_ok) {
2838 int32_t intValue = {0};
2839 napi_get_value_int32(env, res, &intValue);
2840 opts->privacyType = static_cast<AudioPrivacyType>(intValue);
2841 }
2842
2843 return true;
2844 }
2845
ParseRendererInfo(napi_env env,napi_value root,AudioRendererInfo * rendererInfo)2846 bool AudioRendererNapi::ParseRendererInfo(napi_env env, napi_value root, AudioRendererInfo *rendererInfo)
2847 {
2848 napi_value tempValue = nullptr;
2849 int32_t intValue = {0};
2850
2851 if (napi_get_named_property(env, root, "content", &tempValue) == napi_ok) {
2852 napi_get_value_int32(env, tempValue, &intValue);
2853 rendererInfo->contentType = static_cast<ContentType>(intValue);
2854 }
2855
2856 if (napi_get_named_property(env, root, "usage", &tempValue) == napi_ok) {
2857 napi_get_value_int32(env, tempValue, &intValue);
2858 rendererInfo->streamUsage = static_cast<StreamUsage>(intValue);
2859 }
2860
2861 if (napi_get_named_property(env, root, "rendererFlags", &tempValue) == napi_ok) {
2862 napi_get_value_int32(env, tempValue, &(rendererInfo->rendererFlags));
2863 }
2864
2865 return true;
2866 }
2867
ParseStreamInfo(napi_env env,napi_value root,AudioStreamInfo * streamInfo)2868 bool AudioRendererNapi::ParseStreamInfo(napi_env env, napi_value root, AudioStreamInfo* streamInfo)
2869 {
2870 napi_value tempValue = nullptr;
2871 int32_t intValue = {0};
2872
2873 if (napi_get_named_property(env, root, "samplingRate", &tempValue) == napi_ok) {
2874 napi_get_value_int32(env, tempValue, &intValue);
2875 streamInfo->samplingRate = static_cast<AudioSamplingRate>(intValue);
2876 }
2877
2878 if (napi_get_named_property(env, root, "channels", &tempValue) == napi_ok) {
2879 napi_get_value_int32(env, tempValue, &intValue);
2880 streamInfo->channels = static_cast<AudioChannel>(intValue);
2881 }
2882
2883 if (napi_get_named_property(env, root, "sampleFormat", &tempValue) == napi_ok) {
2884 napi_get_value_int32(env, tempValue, &intValue);
2885 streamInfo->format = static_cast<OHOS::AudioStandard::AudioSampleFormat>(intValue);
2886 }
2887
2888 if (napi_get_named_property(env, root, "encodingType", &tempValue) == napi_ok) {
2889 napi_get_value_int32(env, tempValue, &intValue);
2890 streamInfo->encoding = static_cast<AudioEncodingType>(intValue);
2891 }
2892
2893 return true;
2894 }
2895
CheckContextStatus(AudioRendererAsyncContext * context)2896 bool AudioRendererNapi::CheckContextStatus(AudioRendererAsyncContext *context)
2897 {
2898 if (context == nullptr) {
2899 AUDIO_ERR_LOG("context object is nullptr.");
2900 return false;
2901 }
2902 if (context->objectInfo == nullptr || context->objectInfo->audioRenderer_ == nullptr) {
2903 context->status = NAPI_ERR_SYSTEM;
2904 AUDIO_ERR_LOG("context object state is error.");
2905 return false;
2906 }
2907 return true;
2908 }
2909
CreateAudioRendererWrapper(napi_env env,unique_ptr<AudioRendererOptions> & renderOptions)2910 napi_value AudioRendererNapi::CreateAudioRendererWrapper(napi_env env, unique_ptr<AudioRendererOptions> &renderOptions)
2911 {
2912 lock_guard<mutex> lock(createMutex_);
2913 napi_status status;
2914 napi_value result = nullptr;
2915 napi_value constructor;
2916
2917 if (renderOptions != nullptr) {
2918 status = napi_get_reference_value(env, g_rendererConstructor, &constructor);
2919 if (status == napi_ok) {
2920 sRendererOptions_ = move(renderOptions);
2921 status = napi_new_instance(env, constructor, 0, nullptr, &result);
2922 sRendererOptions_.release();
2923 if (status == napi_ok) {
2924 return result;
2925 }
2926 }
2927 HiLog::Error(LABEL, "Failed in CreateAudioRendererWrapper, %{public}d", status);
2928 }
2929
2930 napi_get_undefined(env, &result);
2931
2932 return result;
2933 }
2934
SetInterruptMode(napi_env env,napi_callback_info info)2935 napi_value AudioRendererNapi::SetInterruptMode(napi_env env, napi_callback_info info)
2936 {
2937 napi_status status;
2938 const int32_t refCount = 1;
2939 napi_value result = nullptr;
2940
2941 GET_PARAMS(env, info, ARGS_TWO);
2942
2943 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
2944 CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "AudioRendererAsyncContext object creation failed");
2945 if (argc < ARGS_ONE) {
2946 asyncContext->status = NAPI_ERR_INVALID_PARAM;
2947 }
2948
2949 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
2950 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
2951 for (size_t i = PARAM0; i < argc; i++) {
2952 napi_valuetype valueType = napi_undefined;
2953 napi_typeof(env, argv[i], &valueType);
2954 if (i == PARAM0 && valueType == napi_number) {
2955 napi_get_value_int32(env, argv[i], &asyncContext->interruptMode);
2956 } else if (i == PARAM1) {
2957 if (valueType == napi_function) {
2958 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
2959 }
2960 break;
2961 } else {
2962 asyncContext->status = NAPI_ERR_INVALID_PARAM;
2963 }
2964 }
2965
2966 if (asyncContext->callbackRef == nullptr) {
2967 napi_create_promise(env, &asyncContext->deferred, &result);
2968 } else {
2969 napi_get_undefined(env, &result);
2970 }
2971
2972 napi_value resource = nullptr;
2973 napi_create_string_utf8(env, "SetInterruptMode", NAPI_AUTO_LENGTH, &resource);
2974
2975 status = napi_create_async_work(
2976 env, nullptr, resource,
2977 [](napi_env env, void *data) {
2978 auto context = static_cast<AudioRendererAsyncContext*>(data);
2979 if (!CheckContextStatus(context)) {
2980 return;
2981 }
2982 if (context->status == SUCCESS) {
2983 AudioStandard::InterruptMode interruptMode_ = GetNativeInterruptMode(context->interruptMode);
2984 context->objectInfo->audioRenderer_->SetInterruptMode(interruptMode_);
2985 context->status = SUCCESS;
2986 context->intValue = SUCCESS;
2987 }
2988 },
2989 GetIntValueAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
2990 if (status != napi_ok) {
2991 result = nullptr;
2992 } else {
2993 status = napi_queue_async_work(env, asyncContext->work);
2994 if (status == napi_ok) {
2995 asyncContext.release();
2996 } else {
2997 result = nullptr;
2998 }
2999 }
3000 }
3001
3002 return result;
3003 }
3004
SetInterruptModeSync(napi_env env,napi_callback_info info)3005 napi_value AudioRendererNapi::SetInterruptModeSync(napi_env env, napi_callback_info info)
3006 {
3007 napi_status status;
3008 napi_value result = nullptr;
3009 void *native = nullptr;
3010
3011 GET_PARAMS(env, info, ARGS_ONE);
3012
3013 if (argc < ARGS_ONE) {
3014 AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
3015 return result;
3016 }
3017
3018 status = napi_unwrap(env, thisVar, &native);
3019 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
3020 if (status != napi_ok || audioRendererNapi == nullptr) {
3021 AUDIO_ERR_LOG("SetInterruptModeSync unwrap failure!");
3022 return result;
3023 }
3024
3025 napi_valuetype valueType = napi_undefined;
3026 napi_typeof(env, argv[PARAM0], &valueType);
3027 if (valueType != napi_number) {
3028 AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
3029 return result;
3030 }
3031
3032 int32_t interruptMode;
3033 napi_get_value_int32(env, argv[PARAM0], &interruptMode);
3034 if (!AudioCommonNapi::IsLegalInputArgumentInterruptMode(interruptMode)) {
3035 AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
3036 return result;
3037 }
3038
3039 audioRendererNapi->audioRenderer_->SetInterruptMode(GetNativeInterruptMode(interruptMode));
3040
3041 return result;
3042 }
3043
GetMinStreamVolume(napi_env env,napi_callback_info info)3044 napi_value AudioRendererNapi::GetMinStreamVolume(napi_env env, napi_callback_info info)
3045 {
3046 napi_status status;
3047 const int32_t refCount = 1;
3048 napi_value result = nullptr;
3049
3050 GET_PARAMS(env, info, ARGS_ONE);
3051
3052 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
3053 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
3054 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
3055 if (argc > PARAM0) {
3056 napi_valuetype valueType = napi_undefined;
3057 napi_typeof(env, argv[PARAM0], &valueType);
3058 if (valueType == napi_function) {
3059 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
3060 }
3061 }
3062
3063 if (asyncContext->callbackRef == nullptr) {
3064 napi_create_promise(env, &asyncContext->deferred, &result);
3065 } else {
3066 napi_get_undefined(env, &result);
3067 }
3068
3069 napi_value resource = nullptr;
3070 napi_create_string_utf8(env, "GetMinStreamVolume", NAPI_AUTO_LENGTH, &resource);
3071
3072 status = napi_create_async_work(
3073 env, nullptr, resource,
3074 [](napi_env env, void *data) {
3075 auto context = static_cast<AudioRendererAsyncContext *>(data);
3076 if (!CheckContextStatus(context)) {
3077 return;
3078 }
3079 context->volLevel = context->objectInfo->audioRenderer_->GetMinStreamVolume();
3080 context->status = SUCCESS;
3081 },
3082 GetStreamVolumeAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
3083 if (status != napi_ok) {
3084 result = nullptr;
3085 } else {
3086 status = napi_queue_async_work(env, asyncContext->work);
3087 if (status == napi_ok) {
3088 asyncContext.release();
3089 } else {
3090 result = nullptr;
3091 }
3092 }
3093 }
3094 return result;
3095 }
3096
GetMinStreamVolumeSync(napi_env env,napi_callback_info info)3097 napi_value AudioRendererNapi::GetMinStreamVolumeSync(napi_env env, napi_callback_info info)
3098 {
3099 napi_status status;
3100 napi_value thisVar = nullptr;
3101 napi_value result = nullptr;
3102 size_t argCount = 0;
3103 void *native = nullptr;
3104
3105 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
3106 if (status != napi_ok) {
3107 AUDIO_ERR_LOG("Invalid parameters!");
3108 return result;
3109 }
3110
3111 status = napi_unwrap(env, thisVar, &native);
3112 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
3113 if (status != napi_ok || audioRendererNapi == nullptr) {
3114 AUDIO_ERR_LOG("GetMinStreamVolumeSync unwrap failure!");
3115 return result;
3116 }
3117
3118 double volLevel = audioRendererNapi->audioRenderer_->GetMinStreamVolume();
3119 napi_create_double(env, volLevel, &result);
3120
3121 return result;
3122 }
3123
GetMaxStreamVolume(napi_env env,napi_callback_info info)3124 napi_value AudioRendererNapi::GetMaxStreamVolume(napi_env env, napi_callback_info info)
3125 {
3126 napi_status status;
3127 const int32_t refCount = 1;
3128 napi_value result = nullptr;
3129
3130 GET_PARAMS(env, info, ARGS_ONE);
3131
3132 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
3133 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
3134 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
3135 if (argc > PARAM0) {
3136 napi_valuetype valueType = napi_undefined;
3137 napi_typeof(env, argv[PARAM0], &valueType);
3138 if (valueType == napi_function) {
3139 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
3140 }
3141 }
3142
3143 if (asyncContext->callbackRef == nullptr) {
3144 napi_create_promise(env, &asyncContext->deferred, &result);
3145 } else {
3146 napi_get_undefined(env, &result);
3147 }
3148
3149 napi_value resource = nullptr;
3150 napi_create_string_utf8(env, "GetMaxStreamVolume", NAPI_AUTO_LENGTH, &resource);
3151
3152 status = napi_create_async_work(
3153 env, nullptr, resource,
3154 [](napi_env env, void *data) {
3155 auto context = static_cast<AudioRendererAsyncContext *>(data);
3156 if (!CheckContextStatus(context)) {
3157 return;
3158 }
3159 context->volLevel = context->objectInfo->audioRenderer_->GetMaxStreamVolume();
3160 context->status = SUCCESS;
3161 },
3162 GetStreamVolumeAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
3163 if (status != napi_ok) {
3164 result = nullptr;
3165 } else {
3166 status = napi_queue_async_work(env, asyncContext->work);
3167 if (status == napi_ok) {
3168 asyncContext.release();
3169 } else {
3170 result = nullptr;
3171 }
3172 }
3173 }
3174 return result;
3175 }
3176
GetMaxStreamVolumeSync(napi_env env,napi_callback_info info)3177 napi_value AudioRendererNapi::GetMaxStreamVolumeSync(napi_env env, napi_callback_info info)
3178 {
3179 napi_status status;
3180 napi_value thisVar = nullptr;
3181 napi_value result = nullptr;
3182 size_t argCount = 0;
3183 void *native = nullptr;
3184
3185 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
3186 if (status != napi_ok) {
3187 AUDIO_ERR_LOG("Invalid parameters!");
3188 return result;
3189 }
3190
3191 status = napi_unwrap(env, thisVar, &native);
3192 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
3193 if (status != napi_ok || audioRendererNapi == nullptr) {
3194 AUDIO_ERR_LOG("GetMaxStreamVolumeSync unwrap failure!");
3195 return result;
3196 }
3197
3198 double volLevel = audioRendererNapi->audioRenderer_->GetMaxStreamVolume();
3199 napi_create_double(env, volLevel, &result);
3200
3201 return result;
3202 }
3203
AsyncGetCurrentOutputDevices(napi_env env,void * data)3204 void AudioRendererNapi::AsyncGetCurrentOutputDevices(napi_env env, void *data)
3205 {
3206 auto context = static_cast<AudioRendererAsyncContext *>(data);
3207 if (!CheckContextStatus(context)) {
3208 return;
3209 }
3210 DeviceInfo deviceInfo;
3211 context->status = context->objectInfo->audioRenderer_->GetCurrentOutputDevices(deviceInfo);
3212 if (context->status == ERR_INVALID_PARAM) {
3213 context->status = NAPI_ERROR_INVALID_PARAM;
3214 } else if (context->status == SUCCESS) {
3215 context->deviceInfo = deviceInfo;
3216 }
3217 }
3218
GetCurrentOutputDevices(napi_env env,napi_callback_info info)3219 napi_value AudioRendererNapi::GetCurrentOutputDevices(napi_env env, napi_callback_info info)
3220 {
3221 napi_status status;
3222 const int32_t refCount = 1;
3223 napi_value result = nullptr;
3224
3225 GET_PARAMS(env, info, ARGS_ONE);
3226
3227 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
3228 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
3229 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
3230 if (argc > PARAM0) {
3231 napi_valuetype valueType = napi_undefined;
3232 napi_typeof(env, argv[PARAM0], &valueType);
3233 if (valueType == napi_function) {
3234 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
3235 }
3236 }
3237
3238 if (asyncContext->callbackRef == nullptr) {
3239 napi_create_promise(env, &asyncContext->deferred, &result);
3240 } else {
3241 napi_get_undefined(env, &result);
3242 }
3243
3244 napi_value resource = nullptr;
3245 napi_create_string_utf8(env, "GetCurrentOutputDevices", NAPI_AUTO_LENGTH, &resource);
3246
3247 status = napi_create_async_work(
3248 env, nullptr, resource, AsyncGetCurrentOutputDevices, GetDeviceInfoAsyncCallbackComplete,
3249 static_cast<void *>(asyncContext.get()), &asyncContext->work);
3250 if (status != napi_ok) {
3251 result = nullptr;
3252 } else {
3253 status = napi_queue_async_work(env, asyncContext->work);
3254 if (status == napi_ok) {
3255 asyncContext.release();
3256 } else {
3257 result = nullptr;
3258 }
3259 }
3260 }
3261 return result;
3262 }
3263
GetCurrentOutputDevicesSync(napi_env env,napi_callback_info info)3264 napi_value AudioRendererNapi::GetCurrentOutputDevicesSync(napi_env env, napi_callback_info info)
3265 {
3266 napi_status status;
3267 napi_value thisVar = nullptr;
3268 napi_value result = nullptr;
3269 size_t argCount = 0;
3270 void *native = nullptr;
3271
3272 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
3273 if (status != napi_ok) {
3274 AUDIO_ERR_LOG("Invalid parameters!");
3275 return result;
3276 }
3277
3278 status = napi_unwrap(env, thisVar, &native);
3279 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
3280 if (status != napi_ok || audioRendererNapi == nullptr) {
3281 AUDIO_ERR_LOG("GetCurrentOutputDevicesSync unwrap failure!");
3282 return result;
3283 }
3284
3285 DeviceInfo deviceInfo;
3286 int32_t ret = audioRendererNapi->audioRenderer_->GetCurrentOutputDevices(deviceInfo);
3287 if (ret != SUCCESS) {
3288 AUDIO_ERR_LOG("GetCurrentOutputDevices failure!");
3289 return result;
3290 }
3291 napi_create_array_with_length(env, 1, &result);
3292 napi_value valueParam;
3293 SetDeviceDescriptors(env, valueParam, deviceInfo);
3294 napi_set_element(env, result, 0, valueParam);
3295
3296 return result;
3297 }
3298
GetUnderflowCount(napi_env env,napi_callback_info info)3299 napi_value AudioRendererNapi::GetUnderflowCount(napi_env env, napi_callback_info info)
3300 {
3301 napi_status status;
3302 const int32_t refCount = 1;
3303 napi_value result = nullptr;
3304
3305 GET_PARAMS(env, info, ARGS_ONE);
3306
3307 unique_ptr<AudioRendererAsyncContext> asyncContext = make_unique<AudioRendererAsyncContext>();
3308 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
3309 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
3310 if (argc > PARAM0) {
3311 napi_valuetype valueType = napi_undefined;
3312 napi_typeof(env, argv[PARAM0], &valueType);
3313 if (valueType == napi_function) {
3314 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
3315 }
3316 }
3317
3318 if (asyncContext->callbackRef == nullptr) {
3319 napi_create_promise(env, &asyncContext->deferred, &result);
3320 } else {
3321 napi_get_undefined(env, &result);
3322 }
3323
3324 napi_value resource = nullptr;
3325 napi_create_string_utf8(env, "GetUnderflowCount", NAPI_AUTO_LENGTH, &resource);
3326
3327 status = napi_create_async_work(
3328 env, nullptr, resource,
3329 [](napi_env env, void *data) {
3330 auto context = static_cast<AudioRendererAsyncContext *>(data);
3331 if (!CheckContextStatus(context)) {
3332 return;
3333 }
3334 context->underflowCount = context->objectInfo->audioRenderer_->GetUnderflowCount();
3335 context->status = SUCCESS;
3336 },
3337 GetUnderflowCountAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
3338 if (status != napi_ok) {
3339 result = nullptr;
3340 } else {
3341 status = napi_queue_async_work(env, asyncContext->work);
3342 if (status == napi_ok) {
3343 asyncContext.release();
3344 } else {
3345 result = nullptr;
3346 }
3347 }
3348 }
3349
3350 return result;
3351 }
3352
GetUnderflowCountSync(napi_env env,napi_callback_info info)3353 napi_value AudioRendererNapi::GetUnderflowCountSync(napi_env env, napi_callback_info info)
3354 {
3355 napi_status status;
3356 napi_value thisVar = nullptr;
3357 napi_value result = nullptr;
3358 size_t argCount = 0;
3359 void *native = nullptr;
3360
3361 status = napi_get_cb_info(env, info, &argCount, nullptr, &thisVar, nullptr);
3362 if (status != napi_ok) {
3363 AUDIO_ERR_LOG("Invalid parameters!");
3364 return result;
3365 }
3366
3367 status = napi_unwrap(env, thisVar, &native);
3368 auto *audioRendererNapi = reinterpret_cast<AudioRendererNapi *>(native);
3369 if (status != napi_ok || audioRendererNapi == nullptr) {
3370 AUDIO_ERR_LOG("GetUnderflowCountSync unwrap failure!");
3371 return result;
3372 }
3373
3374 uint32_t underflowCount = audioRendererNapi->audioRenderer_->GetUnderflowCount();
3375 napi_create_uint32(env, underflowCount, &result);
3376
3377 return result;
3378 }
3379
RegisterRendererDeviceChangeCallback(napi_env env,napi_value * argv,AudioRendererNapi * rendererNapi)3380 void AudioRendererNapi::RegisterRendererDeviceChangeCallback(napi_env env, napi_value* argv,
3381 AudioRendererNapi *rendererNapi)
3382 {
3383 if (!rendererNapi->rendererDeviceChangeCallbackNapi_) {
3384 rendererNapi->rendererDeviceChangeCallbackNapi_ = std::make_shared<AudioRendererDeviceChangeCallbackNapi>(env);
3385 if (!rendererNapi->rendererDeviceChangeCallbackNapi_) {
3386 AUDIO_ERR_LOG("AudioRendererNapi: Memory Allocation Failed !!");
3387 return;
3388 }
3389
3390 int32_t ret =
3391 rendererNapi->audioRenderer_->RegisterAudioRendererEventListener(getpid(),
3392 rendererNapi->rendererDeviceChangeCallbackNapi_);
3393 if (ret) {
3394 AUDIO_ERR_LOG("AudioRendererNapi: Registering of Renderer Device Change Callback Failed");
3395 return;
3396 }
3397 }
3398
3399 if (!rendererNapi->rendererPolicyServiceDiedCallbackNapi_) {
3400 rendererNapi->rendererPolicyServiceDiedCallbackNapi_ =
3401 std::make_shared<AudioRendererPolicyServiceDiedCallbackNapi>(rendererNapi);
3402 if (!rendererNapi->rendererPolicyServiceDiedCallbackNapi_) {
3403 AUDIO_ERR_LOG("Memory Allocation Failed !!");
3404 return;
3405 }
3406
3407 int32_t ret =
3408 rendererNapi->audioRenderer_->RegisterAudioPolicyServerDiedCb(getpid(),
3409 rendererNapi->rendererPolicyServiceDiedCallbackNapi_);
3410 if (ret) {
3411 AUDIO_ERR_LOG("Registering of AudioPolicyService Died Change Callback Failed");
3412 return;
3413 }
3414 }
3415
3416 std::shared_ptr<AudioRendererDeviceChangeCallbackNapi> cb =
3417 std::static_pointer_cast<AudioRendererDeviceChangeCallbackNapi>(
3418 rendererNapi->rendererDeviceChangeCallbackNapi_);
3419 cb->AddCallbackReference(argv[PARAM1]);
3420 AUDIO_INFO_LOG("RegisterRendererStateChangeCallback is successful");
3421 }
3422
UnregisterRendererDeviceChangeCallback(napi_env env,size_t argc,napi_value * argv,AudioRendererNapi * rendererNapi)3423 void AudioRendererNapi::UnregisterRendererDeviceChangeCallback(napi_env env, size_t argc,
3424 napi_value* argv, AudioRendererNapi *rendererNapi)
3425 {
3426 napi_value callback = nullptr;
3427
3428 if (argc == ARGS_TWO) {
3429 callback = argv[PARAM1];
3430 }
3431
3432 if (rendererNapi->rendererDeviceChangeCallbackNapi_ == nullptr) {
3433 AUDIO_ERR_LOG("rendererDeviceChangeCallbackNapi_ is nullptr, return");
3434 return;
3435 }
3436
3437 if (rendererNapi->rendererPolicyServiceDiedCallbackNapi_ == nullptr) {
3438 AUDIO_ERR_LOG("rendererPolicyServiceDiedCallbackNapi_ is nullptr, return");
3439 return;
3440 }
3441
3442 std::shared_ptr<AudioRendererDeviceChangeCallbackNapi> cb =
3443 std::static_pointer_cast<AudioRendererDeviceChangeCallbackNapi>(
3444 rendererNapi->rendererDeviceChangeCallbackNapi_);
3445 cb->RemoveCallbackReference(env, callback);
3446
3447 if (callback == nullptr || cb->GetCallbackListSize() == 0) {
3448 int32_t ret = rendererNapi->audioRenderer_->UnregisterAudioRendererEventListener(getpid());
3449 if (ret) {
3450 AUDIO_ERR_LOG("Unregistering of Renderer devuce Change Callback Failed");
3451 return;
3452 }
3453
3454 ret = rendererNapi->audioRenderer_->UnregisterAudioPolicyServerDiedCb(getpid());
3455 if (ret) {
3456 AUDIO_ERR_LOG("UnregisterAudioPolicyServerDiedCb Failed");
3457 return;
3458 }
3459 rendererNapi->DestroyNAPICallbacks();
3460 }
3461 AUDIO_INFO_LOG("UnegisterRendererDeviceChangeCallback is successful");
3462 }
3463
DestroyNAPICallbacks()3464 void AudioRendererNapi::DestroyNAPICallbacks()
3465 {
3466 if (rendererDeviceChangeCallbackNapi_ != nullptr) {
3467 rendererDeviceChangeCallbackNapi_.reset();
3468 rendererDeviceChangeCallbackNapi_ = nullptr;
3469 }
3470
3471 if (rendererPolicyServiceDiedCallbackNapi_ != nullptr) {
3472 rendererPolicyServiceDiedCallbackNapi_.reset();
3473 rendererPolicyServiceDiedCallbackNapi_ = nullptr;
3474 }
3475 }
3476
DestroyCallbacks()3477 void AudioRendererNapi::DestroyCallbacks()
3478 {
3479 rendererDeviceChangeCallbackNapi_->RemoveAllCallbacks();
3480 audioRenderer_->DestroyAudioRendererStateCallback();
3481 DestroyNAPICallbacks();
3482 }
3483 } // namespace AudioStandard
3484 } // namespace OHOS
3485