• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "audio_renderer_napi.h"
17 #include "ability.h"
18 #include "audio_renderer_callback_napi.h"
19 #include "renderer_data_request_callback_napi.h"
20 #include "renderer_period_position_callback_napi.h"
21 #include "renderer_position_callback_napi.h"
22 
23 #include "audio_common_napi.h"
24 #include "audio_errors.h"
25 #include "audio_log.h"
26 #include "audio_manager_napi.h"
27 #include "audio_parameters_napi.h"
28 #include "hilog/log.h"
29 #include "napi_base_context.h"
30 #include "securec.h"
31 #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], &paramArg1);
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